a lot of changes and support languages

This commit is contained in:
Ondřej Novák 2025-02-07 20:26:54 +01:00
parent 185a6e5382
commit f55f92a88b
38 changed files with 1221 additions and 467 deletions

View file

@ -1,10 +1,9 @@
SET(files error.cpp
)
# Základní knihovna mylib
add_library(skeldal_platform STATIC)
add_executable(skeldal)
# Přidejte soubory společné pro všechny platformy
target_sources(skeldal_platform PRIVATE
legacy_coroutines.cpp
platform.cpp
@ -17,7 +16,6 @@ target_sources(skeldal_platform PRIVATE
getopt.c
)
# Podmínky pro platformu Windows
if(WIN32)
target_sources(skeldal_platform PRIVATE
windows/save_folder.cpp
@ -25,20 +23,25 @@ if(WIN32)
target_compile_definitions(skeldal_platform PRIVATE PLATFORM_WINDOWS)
message(STATUS "Building for Windows")
# Podmínky pro platformu Linux
elseif(UNIX AND NOT APPLE)
target_sources(skeldal_platform PRIVATE
linux/save_folder.cpp
linux/map_file.cpp
)
target_sources(skeldal PRIVATE
linux/app_start.cpp
)
target_compile_definitions(skeldal_platform PRIVATE PLATFORM_LINUX)
message(STATUS "Building for Linux")
# Podmínky pro platformu macOS
elseif(APPLE)
target_sources(skeldal_platform PRIVATE
mac_os/save_folder.cpp
)
target_sources(skeldal PRIVATE
linux/app_start.cpp
)
target_compile_definitions(mylib PRIVATE PLATFORM_MACOS)
message(STATUS "Building for macOS")
else()
@ -47,3 +50,11 @@ endif()
set_property(TARGET skeldal_platform PROPERTY CXX_STANDARD 20)
add_subdirectory(sdl)
target_link_libraries(skeldal
skeldal_main
skeldal_libs
skeldal_platform
skeldal_sdl
skeldal_libs
${SDL2_LIBRARIES} pthread)

View file

@ -8,10 +8,6 @@
#include "platform.h"
void display_error(const char *text) {
std::cerr << "ERROR:" << text << std::endl;
abort();
}
static std::uint32_t gtick = get_game_tick_count();

View file

@ -6,7 +6,6 @@ extern "C" {
#endif
void display_error(const char *text);
void send_log_impl(const char *format, ...);
#ifdef __cplusplus

View file

@ -1,7 +1,12 @@
#ifndef GETOPT_H
#define GETOPT_H
#ifdef __cplusplus
extern "C" {
#endif
extern int opterr; /* if error message should be printed */
extern int optind; /* index into parent argv vector */
extern int optopt; /* character checked for validity */
@ -10,4 +15,9 @@ extern char *optarg; /* argument associated with option */
int getopt(int nargc, char * const nargv[], const char *ostr);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -40,8 +40,8 @@ struct MsgQueue {
};
static std::queue<MsgQueue> msg_queue;
static int recursion_count = 0;
static void flush_message_queue();
static void task_after_wakeup(TaskInfo *info) {
info->wake_up_msg = -1;
@ -67,7 +67,6 @@ static void switch_to_task(TaskInfo *task) {
task->resume_flag.notify_all();
resume_master_flag.wait(false);
resume_master_flag = false;
flush_message_queue();
} else {
if (task->exited) return ;
TaskInfo *me = current_task_inst;
@ -81,6 +80,7 @@ static void switch_to_task(TaskInfo *task) {
}
static void clean_task_table() {
if (recursion_count) return;
for (auto iter = task_list.begin(); iter != task_list.end();) {
if (iter->second->exited) {
iter = task_list.erase(iter);
@ -100,26 +100,24 @@ static void clean_up_current_task() {
resume_master_flag.notify_all();
}
static void flush_message_queue() {
while (!msg_queue.empty()) {
auto m = msg_queue.front();
msg_queue.pop();
for (auto &[id, task]: task_list) {
if (task->wake_up_msg == m.msg->msg && task.get() != m.sender) {
EVENT_MSG cpy;
cpy.msg = m.msg->msg;
va_copy(cpy.data, m.msg->data);
cur_message = &cpy;
switch_to_task(task.get());
va_end(cpy.data);
cur_message = NULL;
}
static void broadcast_message(EVENT_MSG *msg) {
++recursion_count;
for (auto &[id, task]: task_list) {
if (task->wake_up_msg == msg->msg && task.get() != current_task_inst) {
EVENT_MSG cpy;
cpy.msg = msg->msg;
va_copy(cpy.data, msg->data);
cur_message = &cpy;
switch_to_task(task.get());
va_end(cpy.data);
cur_message = NULL;
}
clean_task_table();
}
--recursion_count;
clean_task_table();
}
int add_task(int stack,TaskerFunctionName fcname,...) {
int id = get_new_task_id();
auto st = task_list.emplace(id, std::make_unique<TaskInfo>(id));
@ -150,21 +148,21 @@ char is_running(int id_num) {
return !iter->second->exited;
}
void unsuspend_task(EVENT_MSG *msg) {
if (current_task_inst) return;
msg_queue.push({msg, current_task_inst});
flush_message_queue();
broadcast_message(msg);
}
void task_sleep(void) {
if (current_task_inst) {
switch_to_task(NULL);
} else {
auto now = std::chrono::system_clock::now();
recursion_count++;
for (auto &[id, task]: task_list) {
if (task->_wake_up_after < now && task->wake_up_msg == -1) {
switch_to_task(task.get());
}
}
recursion_count--;
clean_task_table();
}
}

View file

@ -0,0 +1,73 @@
#include "../../game/skeldal.h"
#include "../getopt.h"
#include "../platform.h"
#include <iostream>
#include <string>
void show_help(const char *arg0) {
printf(
"Brany Skeldalu (Gates of Skeldal) portable game player\n"
"Copyright (c) 2025 Ondrej Novak. All rights reserved.\n\n"
"This work is licensed under the terms of the MIT license.\n"
"For a copy, see <https://opensource.org/licenses/MIT>.\n"
"\n"
"Usage:"
);
printf("%s [-f <file>] [-a <file>] [-l <lang>] [-s <dir>] [-h]\n\n", arg0);
printf("-f <file> path to configuration file\n"
"-a <adv> path for adventure file (.adv)\n"
"-l <lang> set language (cz|en)"
"-s <directory> generate string-tables (for localization) and exit\n"
"-h this help\n");
exit(0);
}
void show_help_short() {
printf("Use -h for help\n");
}
int main(int argc, char **argv) {
std::string config_name = SKELDALINI;
std::string adv_config_file;
std::string gen_stringtable_path;
std::string lang;
for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:s:l:")) != -1; ) {
switch (optchr) {
case 'f': config_name = optarg;break;
case 'a': adv_config_file = optarg;break;
case 'h': show_help(argv[0]);break;
case 'l': lang = optarg;break;
case 's': gen_stringtable_path = optarg;break;
default: show_help_short();
return 1;
}
}
SKELDAL_CONFIG cfg;
cfg.short_help = show_help_short;
cfg.show_error = [](const char *txt) {
std::cerr << "ERROR: " << txt << std::endl;
};
cfg.adventure_path = adv_config_file.empty()?NULL:adv_config_file.c_str();
cfg.config_path = config_name.c_str();
cfg.lang_path = lang.c_str();
try {
if (!gen_stringtable_path.empty()) {
skeldal_gen_string_table_entry_point(&cfg, gen_stringtable_path.c_str());
return 0;
} else {
return skeldal_entry_point(&cfg);
}
} catch (const std::exception &e) {
std::cerr << "ERROR: " << e.what() << std::endl;
return 1;
}
return 0;
}

View file

@ -9,7 +9,7 @@ static std::string get_default_savegame_dir() {
if (home) {
return std::filesystem::path(home) / ".local/share/" SAVEGAME_FOLDERNAME;
} else {
display_error("$HOME has no value (user with no home)");
throw std::runtime_error("$HOME has no value (user with no home)");
abort();
}
}

View file

@ -66,7 +66,7 @@ void SetWheelMapping(char up, char down);
char get_control_key_state(void);
char get_shift_key_state(void);
char get_capslock_state(void);
void display_error(const char *text);
void display_error(const char *text,...);
///returns -1 if doesn't exists
char check_file_exists(const char *pathname);
FILE *fopen_icase(const char *pathname, const char *mode);

View file

@ -259,19 +259,21 @@ void SDLContext::event_loop(std::stop_token stp) {
if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
_crt_effect.reset();
}
} else if (e.type == SDL_KEYDOWN) {
} else if (e.type == SDL_KEYDOWN || e.type == SDL_KEYUP) {
_key_capslock = e.key.keysym.mod & KMOD_CAPS;
_key_shift =e.key.keysym.mod & KMOD_SHIFT;
_key_control =e.key.keysym.mod & KMOD_CTRL;
if (e.key.keysym.sym == SDLK_RETURN && (e.key.keysym.mod & KMOD_ALT)) {
_fullscreen_mode = !_fullscreen_mode;
SDL_SetWindowFullscreen(_window.get(), _fullscreen_mode ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
} else {
auto code =sdl_keycode_map.get_bios_code(e.key.keysym.scancode,
e.key.keysym.mod & KMOD_SHIFT, e.key.keysym.mod & KMOD_CTRL);
if (code) {
std::lock_guard _(_mx);
_keyboard_queue.push(code);
if (e.type == SDL_KEYDOWN) {
if (e.key.keysym.sym == SDLK_RETURN && (e.key.keysym.mod & KMOD_ALT)) {
_fullscreen_mode = !_fullscreen_mode;
SDL_SetWindowFullscreen(_window.get(), _fullscreen_mode ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
} else {
auto code =sdl_keycode_map.get_bios_code(e.key.keysym.scancode,
e.key.keysym.mod & KMOD_SHIFT, e.key.keysym.mod & KMOD_CTRL);
if (code) {
std::lock_guard _(_mx);
_keyboard_queue.push(code);
}
}
}
} else if (e.type == SDL_MOUSEMOTION) {