From 3152a44d3572222f7a43d5175d7459b2aa4c1c90 Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Tue, 22 Apr 2025 20:42:13 +0200 Subject: [PATCH 01/24] fix sound balance during battle --- game/souboje.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/game/souboje.c b/game/souboje.c index a9370a9..fdf925a 100644 --- a/game/souboje.c +++ b/game/souboje.c @@ -678,6 +678,7 @@ void zacatek_kola() viewsector=postavy[select_player].sektor; viewdir=postavy[select_player].direction; redraw_scene(); + recalc_volumes(viewsector,viewdir); } char check_end_game() @@ -905,6 +906,7 @@ void prejdi_na_pohled(THUMAN *p) { viewsector=p->sektor; viewdir=p->direction; + recalc_volumes(viewsector,viewdir); pozdrz_akci(); hold_timer(TM_SCENE,1); redraw_scene(); @@ -1440,6 +1442,7 @@ void jadro_souboje(EVENT_MSG *msg,void **unused) //!!!! Jadro souboje viewsector=postavy[i].sektor; viewdir=postavy[i].direction; build_player_map(); + recalc_volumes(viewsector,viewdir); GlobEvent(MAGLOB_AFTERBATTLE,viewsector,viewdir); autosave(); } @@ -1924,6 +1927,7 @@ static void souboje_dalsi() while ((!postavy[select_player].used || postavy[select_player].inmaphash != current_map_hash || !postavy[select_player].actions || (postavy[select_player].groupnum!=cd && j>6)) && j); viewsector=postavy[select_player].sektor; viewdir=postavy[select_player].direction; + recalc_volumes(viewsector,viewdir); cur_group=postavy[select_player].groupnum; } @@ -1944,6 +1948,7 @@ static void souboje_dalsi_user() { viewsector=postavy[select_player].sektor; viewdir=postavy[select_player].direction; cur_group=postavy[select_player].groupnum; + recalc_volumes(viewsector,viewdir); } void souboje_vybrano(int d) From 54d7d2273472088179bdd7d192e499bae64ffb07 Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Wed, 30 Apr 2025 23:00:46 +0200 Subject: [PATCH 02/24] FIx detection of drive letter in windows path, use utf-8 for path #2 --- game/gamesave.c | 11 +++++----- platform/file_access.cpp | 37 +++++++++++++++++++++++--------- platform/windows/save_folder.cpp | 10 ++++++--- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/game/gamesave.c b/game/gamesave.c index 6a7f969..388835d 100644 --- a/game/gamesave.c +++ b/game/gamesave.c @@ -776,11 +776,12 @@ int save_game(long game_time,char *gamename, char is_autosave) temp_storage_store("playtime",&new_play_time, sizeof(new_play_time)); svf=fopen_icase(sn,"wb"); - if (svf==NULL) - { - char buff[256]; - sprintf(buff,"Nelze ulozit pozici na cestu: %s", sn); - display_error(buff); + if (svf==NULL){ + if (!is_autosave) { + char buff[256]; + sprintf(buff,"Failed to create savegame at path %s", sn); + message(1,0,0,"",buff,texty[80]); + } } else { diff --git a/platform/file_access.cpp b/platform/file_access.cpp index b6d1f15..71d13d7 100644 --- a/platform/file_access.cpp +++ b/platform/file_access.cpp @@ -7,23 +7,35 @@ #include "../libs/logfile.h" -std::filesystem::path break_and_compose_path(const std::string_view &pathname, char sep) { + +std::filesystem::path break_and_compose_path(std::string_view pathname, char sep) { + auto utf8_to_path = [](std::string_view sv) -> std::filesystem::path { + return std::filesystem::path(std::u8string(reinterpret_cast(sv.data()), sv.size())); + }; + auto p = pathname.rfind(sep); + if (p == pathname.npos) { if (pathname == "." || pathname == "..") { return std::filesystem::canonical("."); - } else if (pathname.empty()) { - return std::filesystem::current_path().root_path(); - } else if (pathname == std::filesystem::current_path().root_name()) { - return std::filesystem::current_path().root_path(); - } else { - return std::filesystem::current_path()/pathname; } - } - return break_and_compose_path(pathname.substr(0,p), sep) / pathname.substr(p+1); -} + // Detekce Windows drive letter jako "C:" + if (pathname.size() == 2 && std::isalpha(static_cast(pathname[0])) && pathname[1] == ':') { + return utf8_to_path(std::string(pathname) + "\\"); // vždy konstruujeme s \ pro root disku + } + // Kontrola na root (např. "/") – musíme převést pro porovnání + if (utf8_to_path(pathname) == std::filesystem::current_path().root_path()) { + return std::filesystem::current_path().root_path(); + } + + // Vše ostatní relativně vůči current_path + return std::filesystem::current_path() / utf8_to_path(pathname); + } + + return break_and_compose_path(pathname.substr(0, p), sep) / utf8_to_path(pathname.substr(p + 1)); +} std::filesystem::path convert_pathname_to_path(const std::string_view &pathname) { auto p = pathname.find('\\'); @@ -81,7 +93,12 @@ const char *file_icase_find(const char *pathname) { FILE *fopen_icase(const char *pathname, const char *mode) { std::filesystem::path path = try_to_find_file(convert_pathname_to_path(pathname)); +#ifdef _WIN32 + std::wstring wmode(mode, mode + std::strlen(mode)); // bezpečnější převod + return _wfopen(path.wstring().c_str(), wmode.c_str()); +#else return fopen(path.string().c_str(), mode); +#endif } static thread_local std::string build_pathname_buffer; diff --git a/platform/windows/save_folder.cpp b/platform/windows/save_folder.cpp index c0b53c9..5b002a3 100644 --- a/platform/windows/save_folder.cpp +++ b/platform/windows/save_folder.cpp @@ -15,13 +15,17 @@ std::string getSavedGamesDirectory() { PWSTR path = nullptr; if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_SavedGames, 0, NULL, &path))) { fs::path savedGamesPath(path); - CoTaskMemFree(path); - return (savedGamesPath / SAVEGAME_FOLDERNAME).string(); + CoTaskMemFree(path); + + // Převod na UTF-8 std::string + std::u8string utf8 = (savedGamesPath / SAVEGAME_FOLDERNAME).u8string(); + return std::string(reinterpret_cast(utf8.data()), utf8.size()); } else { - display_error("Failed to retrieve FOLDEROD_SavedGames"); + display_error("Failed to retrieve FOLDERID_SavedGames"); abort(); } } + const char *get_default_savegame_directory() { static std::string dir = getSavedGamesDirectory(); From f495364ed80af7c90f757be3ad4826e645af436d Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Thu, 1 May 2025 12:22:02 +0200 Subject: [PATCH 03/24] map descriptions was not stored into saved state during show map: #4 --- game/automap.c | 6 ++++++ game/globals.h | 3 ++- game/globmap.c | 5 +++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/game/automap.c b/game/automap.c index 754f867..b6c03f9 100644 --- a/game/automap.c +++ b/game/automap.c @@ -1109,3 +1109,9 @@ void free_map_description() { if (texty_v_mape!=NULL)release_list(texty_v_mape); texty_v_mape = NULL; } + +TSTR_LIST swap_map_description(TSTR_LIST new_list) { + TSTR_LIST old = texty_v_mape; + texty_v_mape = new_list; + return old; +} \ No newline at end of file diff --git a/game/globals.h b/game/globals.h index ec3fe1d..db843d4 100644 --- a/game/globals.h +++ b/game/globals.h @@ -1402,7 +1402,7 @@ void destroy_all_fly(); void stop_fly(LETICI_VEC *p,char zvuk); void herni_cas(char *s); - +typedef char **TSTR_LIST; //gamesaver void leave_current_map(void); @@ -1415,6 +1415,7 @@ int save_game(long game_time,char *gamename, char is_autosave); void save_map_description(TMPFILE_WR *f); void load_map_description(TMPFILE_RD *f); void free_map_description(); +TSTR_LIST swap_map_description(TSTR_LIST new_list); void wire_save_load(char save); void do_save_dialog(); char ask_save_dialog(char *name_buffer, size_t name_size, char allow_remove); diff --git a/game/globmap.c b/game/globmap.c index bb016e9..ab52d1d 100644 --- a/game/globmap.c +++ b/game/globmap.c @@ -630,6 +630,7 @@ struct _tag_map_save_state{ TSTENA *_map_sides; TSECTOR *_map_sectors; TMAP_EDIT_INFO *_map_coord; + TSTR_LIST _map_desc; int _map_size; int _viewsector; int _viewdir; @@ -647,6 +648,7 @@ static void save_current_map() { save_state._map_coord = map_coord; save_state._map_sectors = map_sectors; save_state._map_size = mapsize; + save_state._map_desc = swap_map_description(NULL); save_state._viewsector = viewsector; save_state._viewdir = viewdir; save_state._hash = current_map_hash; @@ -661,6 +663,7 @@ static void restore_saved_map() { free(map_sides); free(map_sectors); free(map_coord); + free_map_description(); mapsize =save_state._map_size; map_sides = save_state._map_sides; map_sectors = save_state._map_sectors; @@ -668,9 +671,11 @@ static void restore_saved_map() { viewsector = save_state._viewsector; viewdir = save_state._viewdir; current_map_hash = save_state._hash; + swap_map_description(save_state._map_desc); save_state._map_sides = NULL; save_state._map_coord = NULL; save_state._map_sectors = NULL; + save_state._map_desc = NULL; } } From d8ff3f4bff8d6b7226067caa2b8b6e2945add066 Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Thu, 1 May 2025 12:22:52 +0200 Subject: [PATCH 04/24] actuall strlists.c are not used, we use strlite.c instead --- libs/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 4a66d31..a551812 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -12,7 +12,7 @@ SET(files basicobj.c mgifplaya.c pcx.c wav_mem.c - strlists.c + strlite.c cztable.c music.cpp string_table.cpp ) From b22149a13a239b813fa413623aedb6903f0d8fd6 Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Thu, 1 May 2025 12:27:26 +0200 Subject: [PATCH 05/24] #1 fix handling stereo wave on multichannel stream --- platform/sdl/wave_mixer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/sdl/wave_mixer.h b/platform/sdl/wave_mixer.h index 191b6dd..5baf9fe 100644 --- a/platform/sdl/wave_mixer.h +++ b/platform/sdl/wave_mixer.h @@ -91,8 +91,8 @@ public: } else { (*iter) += value.left * vol[0]; ++iter; - (*iter) += value.right * vol[0]; - ++iter; + (*iter) += value.right * vol[1]; + std::advance(iter, channels-1); } } From 27c803f0404732ae447b73d4c29176e8062867e5 Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Thu, 1 May 2025 13:29:51 +0200 Subject: [PATCH 06/24] #3 fix issues reported by an ARM64 compiler --- game/chargen.c | 2 +- game/dialogy.c | 2 +- game/gamesave.c | 4 ++-- game/globals.h | 2 +- game/globmap.c | 2 +- game/menu.c | 10 +++++----- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/game/chargen.c b/game/chargen.c index cf19827..4f9ed6d 100644 --- a/game/chargen.c +++ b/game/chargen.c @@ -745,7 +745,7 @@ static void wait_timer(EVENT_MSG *msg, void **udata) { } } -void effect_show(va_list args) +void effect_show() { int i; char s = exit_wait; diff --git a/game/dialogy.c b/game/dialogy.c index ead61d0..4172f80 100644 --- a/game/dialogy.c +++ b/game/dialogy.c @@ -766,7 +766,7 @@ void wire_dialog_drw(void) wire_dialog(); draw_all(); ukaz_mysku(); - effect_show(NULL); + effect_show(); } void unwire_dialog(void) { diff --git a/game/gamesave.c b/game/gamesave.c index 388835d..6b00782 100644 --- a/game/gamesave.c +++ b/game/gamesave.c @@ -1770,12 +1770,12 @@ void wire_save_load(char save) { change_click_map(clk_save,CLK_SAVELOAD); redraw_save(); send_message(E_ADD, E_KEYBOARD, saveload_keyboard); - effect_show(NULL); + effect_show(); } else { curcolor = 0; redraw_load(); - effect_show(NULL); + effect_show(); if (save == 2) change_click_map(clk_load_error, CLK_LOAD_ERROR); else if (save == 4) { diff --git a/game/globals.h b/game/globals.h index db843d4..53f7de0 100644 --- a/game/globals.h +++ b/game/globals.h @@ -1764,7 +1764,7 @@ char clk_enter(int id,int xa,int ya,int xr,int yr); int enter_menu(char open); //task! void titles(va_list args); //task! void run_titles(va_list args); //task! -void effect_show(va_list args); //effektni zobrazeni // task! +void effect_show(void); //effektni zobrazeni void konec_hry(void); diff --git a/game/globmap.c b/game/globmap.c index ab52d1d..38fa16e 100644 --- a/game/globmap.c +++ b/game/globmap.c @@ -637,7 +637,7 @@ struct _tag_map_save_state{ uint32_t _hash; } MAP_SAVE_STATE; -static struct _tag_map_save_state save_state = {NULL,NULL,NULL,0,0,0,0}; +static struct _tag_map_save_state save_state = {NULL,NULL,NULL,NULL,0,0,0,0}; static void save_current_map() { if (save_state._map_coord) { diff --git a/game/menu.c b/game/menu.c index 4dc173c..8d5c9c3 100644 --- a/game/menu.c +++ b/game/menu.c @@ -350,8 +350,8 @@ int enter_menu(char open) put_picture(0,0,ablock(H_MENU_BAR)); put_picture(0,56,ablock(H_ANIM)); ukaz_mysku(); - effect_show(NULL); - //if (open) effect_show(NULL);else showview(0,0,0,0); + effect_show(); + change_click_map(clk_main_menu,CLK_MAIN_MENU); send_message(E_ADD,E_TIMER,prehraj_animaci_v_menu); send_message(E_ADD,E_KEYBOARD,klavesnice); @@ -552,7 +552,7 @@ void titles(va_list args) alock(H_PICTURE); picture=ablock(H_PICTURE); put_picture(0,0,picture); - effect_show(NULL); + effect_show(); titlefont=H_FBIG; set_font(titlefont,RGB(158,210,25));charcolors[1]=0; counter=get_timer_value();newc=counter; @@ -621,7 +621,7 @@ void konec_hry() schovej_mysku(); curcolor=0; bar32(0,0,639,479); - effect_show(NULL); + effect_show(); create_playlist(texty[205]); change_music(get_next_music_from_playlist()); timer=get_timer_value(); @@ -641,7 +641,7 @@ void konec_hry() curcolor=0; bar32(0,0,639,479); ukaz_mysku(); - effect_show(NULL); + effect_show(); timer=get_timer_value(); while (get_timer_value()-timer<150) task_sleep(); } From f9e5b3d1e95964e345470d38d1d82becbacb4e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Nov=C3=A1k?= Date: Thu, 1 May 2025 14:03:27 +0200 Subject: [PATCH 07/24] - #3 fix issues reported by an ARM64 compiler (2) --- game/chargen.c | 4 ++-- game/globals.h | 4 ++-- game/menu.c | 6 +++--- game/skeldal.c | 4 ++-- platform/linux/skeldal.sh | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/game/chargen.c b/game/chargen.c index 4f9ed6d..a729dd9 100644 --- a/game/chargen.c +++ b/game/chargen.c @@ -745,7 +745,7 @@ static void wait_timer(EVENT_MSG *msg, void **udata) { } } -void effect_show() +void effect_show(void) { int i; char s = exit_wait; @@ -861,7 +861,7 @@ char enter_generator() memset(&cur_stats,0,sizeof(cur_stats)); vypocet_vlastnosti(cur_angle,&cur_vls); b_disables=0x7; - redraw_generator(rep);if (!rep)effect_show(NULL);rep=1; + redraw_generator(rep);if (!rep)effect_show();rep=1; edit_name(); change_click_map(clk_page1,CLK_PAGE1); was_enter=0; diff --git a/game/globals.h b/game/globals.h index 53f7de0..bc5d4e3 100644 --- a/game/globals.h +++ b/game/globals.h @@ -1763,8 +1763,8 @@ char clk_enter(int id,int xa,int ya,int xr,int yr); //menu int enter_menu(char open); //task! void titles(va_list args); //task! -void run_titles(va_list args); //task! -void effect_show(void); //effektni zobrazeni +void run_titles(void ); +void effect_show(void); //effektni zobrazeni void konec_hry(void); diff --git a/game/menu.c b/game/menu.c index 8d5c9c3..d9bf6f3 100644 --- a/game/menu.c +++ b/game/menu.c @@ -604,7 +604,7 @@ void titles(va_list args) if (send_back)send_message(E_KEYBOARD,27); } -void run_titles(va_list args) +void run_titles(void) { int task_id; task_id=add_task(8196,titles,1,"titulky.TXT"); @@ -612,12 +612,12 @@ void run_titles(va_list args) term_task(task_id); } -void konec_hry() +void konec_hry(void) { int task_id; int timer; - + schovej_mysku(); curcolor=0; bar32(0,0,639,479); diff --git a/game/skeldal.c b/game/skeldal.c index ee1b6ec..28d488e 100644 --- a/game/skeldal.c +++ b/game/skeldal.c @@ -989,7 +989,7 @@ void init_skeldal(const INI_CONFIG *cfg) cti_texty(); timer_tree.next=NULL; - init_events(); + init_events(); steam_init(); @@ -1579,7 +1579,7 @@ static void start(va_list args) openning =0; break; case V_OBNOVA_HRY:load_saved_game();break; - case V_AUTORI:run_titles(NULL);break; + case V_AUTORI:run_titles();break; } } while (!exit_wait); diff --git a/platform/linux/skeldal.sh b/platform/linux/skeldal.sh index 03e6c7f..1dedef9 100755 --- a/platform/linux/skeldal.sh +++ b/platform/linux/skeldal.sh @@ -2,6 +2,7 @@ temp_file=$(mktemp /tmp/skeldal.XXXXXX.log) CURDIR=`dirname "$0"` +chmod +x "$CURDIR/skeldal_bin" LD_LIBRARY_PATH=$CURDIR:$LD_LIBRARY_PATH "$CURDIR/skeldal_bin" $* > "$temp_file" 2>&1 exit_code=$? @@ -25,4 +26,3 @@ fi rm $temp_file exit $exit_code - From f383260a98be4d348ede45914126a42b9576ee5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Nov=C3=A1k?= Date: Thu, 1 May 2025 20:22:26 +0200 Subject: [PATCH 08/24] fix path handling in linux --- platform/file_access.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/file_access.cpp b/platform/file_access.cpp index 71d13d7..6a4981f 100644 --- a/platform/file_access.cpp +++ b/platform/file_access.cpp @@ -32,6 +32,8 @@ std::filesystem::path break_and_compose_path(std::string_view pathname, char sep // Vše ostatní relativně vůči current_path return std::filesystem::current_path() / utf8_to_path(pathname); + } else if (p == 0) { + return std::filesystem::current_path().root_path() / utf8_to_path(pathname); } return break_and_compose_path(pathname.substr(0, p), sep) / utf8_to_path(pathname.substr(p + 1)); From 93ec5264820f69ea124a1ce6b6da89716c89a67e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Nov=C3=A1k?= Date: Thu, 1 May 2025 21:21:22 +0200 Subject: [PATCH 09/24] add config option sdl_renderer_driver --- platform/error.cpp | 16 ++++++++++++++++ platform/error.h | 8 +++++++- platform/linux/app_start.cpp | 3 ++- platform/linux/map_file.cpp | 2 -- platform/linux/map_file.h | 9 +++++++++ platform/sdl/BGraph2.cpp | 1 + platform/sdl/sdl_context.cpp | 13 ++++++++++++- platform/sdl/sdl_context.h | 7 ++++--- skeldal.ini | 5 +++++ 9 files changed, 56 insertions(+), 8 deletions(-) diff --git a/platform/error.cpp b/platform/error.cpp index 8002e9e..f2d2018 100644 --- a/platform/error.cpp +++ b/platform/error.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "error.h" #include "platform.h" @@ -38,3 +39,18 @@ void send_log_impl(const char *format, ...) { void throw_exception(const char *text) { throw std::runtime_error(std::string("Invoked crash:") + text); } + +std::string exception_to_string(const std::exception& e) { + std::ostringstream oss; + oss << e.what(); + + try { + std::rethrow_if_nested(e); + } catch (const std::exception& nested) { + oss << " Reason: " << exception_to_string(nested); + } catch (...) { + oss << " Reason: unknown exception of crash"; + } + + return std::move(oss).str(); +} diff --git a/platform/error.h b/platform/error.h index 5d0e975..e88b2ea 100644 --- a/platform/error.h +++ b/platform/error.h @@ -2,6 +2,11 @@ #ifdef __cplusplus + +#include +#include +std::string exception_to_string(const std::exception& e); + extern "C" { #endif @@ -10,7 +15,8 @@ void send_log_impl(const char *format, ...); void display_error(const char *format, ...); void throw_exception(const char *text); - #ifdef __cplusplus + + } #endif diff --git a/platform/linux/app_start.cpp b/platform/linux/app_start.cpp index 7ec40d4..a0f1736 100644 --- a/platform/linux/app_start.cpp +++ b/platform/linux/app_start.cpp @@ -1,6 +1,7 @@ #include "../../game/skeldal.h" #include "../getopt.h" #include "../platform.h" +#include "../error.h" #include #include @@ -63,7 +64,7 @@ int main(int argc, char **argv) { } } catch (const std::exception &e) { - std::cerr << "ERROR: " << e.what() << std::endl; + std::cerr << "ERROR: " << exception_to_string(e) << std::endl; return 1; } diff --git a/platform/linux/map_file.cpp b/platform/linux/map_file.cpp index 89adbc3..24c3810 100644 --- a/platform/linux/map_file.cpp +++ b/platform/linux/map_file.cpp @@ -1,9 +1,7 @@ -extern "C" { #include "map_file.h" #include "../error.h" -} #include #include diff --git a/platform/linux/map_file.h b/platform/linux/map_file.h index e4495ed..2c4c27a 100644 --- a/platform/linux/map_file.h +++ b/platform/linux/map_file.h @@ -1,4 +1,13 @@ #include #include + +#ifdef __cplusplus +extern "C" { +#endif + void *map_file_to_memory(const char *name, size_t *sz); void unmap_file(void *ptr, size_t sz); + +#ifdef __cplusplus +} +#endif diff --git a/platform/sdl/BGraph2.cpp b/platform/sdl/BGraph2.cpp index e841088..51f0418 100644 --- a/platform/sdl/BGraph2.cpp +++ b/platform/sdl/BGraph2.cpp @@ -41,6 +41,7 @@ char game_display_init(const INI_CONFIG_SECTION *display_section, const char *ti else cfg.crt_filter = SDLContext::CrtFilterType::autoselect; cfg.cursor_size = ini_get_int(display_section, "cursor_size", 100)*0.01f; + cfg.hint_renderer = ini_get_string(display_section, "sdl_renderer_driver", NULL); screen_pitch = 640; get_sdl_global_context().init_video(cfg, title); diff --git a/platform/sdl/sdl_context.cpp b/platform/sdl/sdl_context.cpp index e0c59c7..58ea510 100644 --- a/platform/sdl/sdl_context.cpp +++ b/platform/sdl/sdl_context.cpp @@ -219,6 +219,9 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { _enable_crt = false; } + if (config.hint_renderer) { + SDL_SetHint(SDL_HINT_RENDER_DRIVER, config.hint_renderer); + } _fullscreen_mode = config.fullscreen; _mouse_size = config.cursor_size; @@ -294,7 +297,15 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { done.wait(false); if (e) { _render_thread.join(); - std::rethrow_exception(e); + try { + std::rethrow_exception(e); + } catch (...) { + std::throw_with_nested( + std::runtime_error("Oops! The app couldn't start properly (problem during SDL initialization). " + "This may be caused by outdated or missing graphics or audio drivers." + "To fix this, please try the following: Restart your computer and try again/" + "Make sure your graphics and sound drivers are up to date.")); + } } diff --git a/platform/sdl/sdl_context.h b/platform/sdl/sdl_context.h index 0e11bda..2cfa786 100644 --- a/platform/sdl/sdl_context.h +++ b/platform/sdl/sdl_context.h @@ -33,6 +33,7 @@ public: CrtFilterType crt_filter; int composer; const char *scale_quality; + const char *hint_renderer; bool fullscreen; int aspect_x; int aspect_y; @@ -238,8 +239,8 @@ protected: std::unique_ptr _crt_effect; std::unique_ptr _mouse; unique_value _audio; - SDL_Texture *_visible_texture; - SDL_Texture *_hidden_texture; + SDL_Texture *_visible_texture = nullptr; + SDL_Texture *_hidden_texture = nullptr; bool _fullscreen_mode = false; @@ -256,7 +257,7 @@ protected: std::queue _keyboard_queue; SDL_Rect _mouse_rect; SDL_Point _mouse_finger; - float _mouse_size; + float _mouse_size = 1; SpriteList _sprites; diff --git a/skeldal.ini b/skeldal.ini index 5e7be5f..cab6ad9 100644 --- a/skeldal.ini +++ b/skeldal.ini @@ -33,6 +33,10 @@ # composer = auto - choose best supported driver # hardware,hw - use hardware for composition # software,sw - use software for composition +# sdl_renderer_driver - help SDL to choose optimal rederer +# direct3d,direct3d11,direct3d12 +# opengl,opengles2,opengles +# metal,software # scale_quality = auto - best for hardware composer, nearest for software comporser # best - best scale quality (SDL = linear) # linear - use linear filtering (Direct3D and OpenGL) @@ -47,6 +51,7 @@ #crt_filter=auto #scale_quality=auto #composer=auto +#sdl_renderer_driver=software #aspect_ratio=4:3 #cursor_size=100 From 46c85d8f308fd74be1fd4ae6ed19a7adc0e96b70 Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Thu, 1 May 2025 19:36:11 +0200 Subject: [PATCH 10/24] improve SDL error reporting --- platform/sdl/sdl_context.cpp | 2 +- platform/windows/app_start.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/sdl/sdl_context.cpp b/platform/sdl/sdl_context.cpp index 58ea510..bb95bda 100644 --- a/platform/sdl/sdl_context.cpp +++ b/platform/sdl/sdl_context.cpp @@ -74,7 +74,7 @@ SDLContext::SDLContext() { void handle_sdl_error(const char *msg) { char buff[512]; - snprintf(buff, sizeof(buff), "SDL critical error (check video driver): %s %s",msg, SDL_GetError()); + snprintf(buff, sizeof(buff), "SDL critical error: %s %s",msg, SDL_GetError()); throw std::runtime_error(buff); } diff --git a/platform/windows/app_start.cpp b/platform/windows/app_start.cpp index 8ecc5a9..0149e4e 100644 --- a/platform/windows/app_start.cpp +++ b/platform/windows/app_start.cpp @@ -1,6 +1,7 @@ #include "../../game/skeldal.h" #include "../getopt.h" #include "../platform.h" +#include "../error.h" #include #include #include @@ -82,7 +83,7 @@ int main(int argc, char **argv) { } } catch (const std::exception &e) { - cfg.show_error(e.what()); + cfg.show_error(exception_to_string(e).c_str()); return 1; } catch (...) { From 0398711b5c48e2b834a8555abdb5cd7902e207ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Nov=C3=A1k?= Date: Fri, 2 May 2025 08:10:40 +0200 Subject: [PATCH 11/24] autosave option is correctly set on options page --- game/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game/setup.c b/game/setup.c index 49487a2..28118e3 100644 --- a/game/setup.c +++ b/game/setup.c @@ -187,7 +187,7 @@ void new_setup() case 0:c_default(show_names);break; case 1:c_default(enable_sort);break; case 2:c_default(autoattack);break; - case 3:c_default(1);break; + case 3:c_default(autosave_enabled);break; case 4:c_default(level_preload);break; } } From 7ec2eb9e71891482478389b52af253a8d75f7da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Nov=C3=A1k?= Date: Fri, 2 May 2025 09:15:37 +0200 Subject: [PATCH 12/24] unload shop's invetory when exiting shop --- game/inv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/game/inv.c b/game/inv.c index e20e230..fcaa2f8 100644 --- a/game/inv.c +++ b/game/inv.c @@ -3099,6 +3099,7 @@ void unwire_shop(void) norefresh=0; wire_proc=wire_shop; inv_view_mode=old_inv_view_mode; + memset(shp_item_map, 0, sizeof(shp_item_map)); } void wire_shop(void) From 9013f1038a13d7d2c2bf707d6e860de258fb9d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Nov=C3=A1k?= Date: Fri, 2 May 2025 09:24:53 +0200 Subject: [PATCH 13/24] improve previous commit --- game/inv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game/inv.c b/game/inv.c index fcaa2f8..43b497d 100644 --- a/game/inv.c +++ b/game/inv.c @@ -3099,7 +3099,6 @@ void unwire_shop(void) norefresh=0; wire_proc=wire_shop; inv_view_mode=old_inv_view_mode; - memset(shp_item_map, 0, sizeof(shp_item_map)); } void wire_shop(void) @@ -3208,6 +3207,7 @@ char _exit_shop(int id, int xa, int ya,int xr,int yr) { xr,yr,xa,ya,id; SEND_LOG("(SHOP) Exiting shop..."); + memset(shp_item_map, 0, sizeof(shp_item_map)); if (cur_owner==-1) { free(picked_item); From ba500bec5f63acd9cad38a88760f42e9a51dc41f Mon Sep 17 00:00:00 2001 From: Petr Hodina Date: Sat, 3 May 2025 09:58:37 +0200 Subject: [PATCH 14/24] cmake: set STEAMLIB only if STEAM_ENABLED on darwin --- platform/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt index 343a8e2..c2203da 100644 --- a/platform/CMakeLists.txt +++ b/platform/CMakeLists.txt @@ -95,7 +95,9 @@ elseif(APPLE) linux/app_start.cpp ) target_compile_definitions(mylib PRIVATE PLATFORM_MACOS) - set(STEAMLIB ${STEAMWORKS_SDK_DIR}/redistributable_bin/osx/libsteam_api.dylib) + if(STEAM_ENABLED) + set(STEAMLIB ${STEAMWORKS_SDK_DIR}/redistributable_bin/osx/libsteam_api.dylib) + endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations") message(STATUS "Building for macOS") target_link_libraries(skeldal ${all_libs} ${STEAMLIB}) From 8d5c5c419a21361ad4a2196dfcadaa8a9f1f1c38 Mon Sep 17 00:00:00 2001 From: Petr Hodina Date: Sat, 3 May 2025 10:06:01 +0200 Subject: [PATCH 15/24] cmake: remove mylib target on darwin --- platform/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt index c2203da..d9daadb 100644 --- a/platform/CMakeLists.txt +++ b/platform/CMakeLists.txt @@ -94,7 +94,6 @@ elseif(APPLE) target_sources(skeldal PRIVATE linux/app_start.cpp ) - target_compile_definitions(mylib PRIVATE PLATFORM_MACOS) if(STEAM_ENABLED) set(STEAMLIB ${STEAMWORKS_SDK_DIR}/redistributable_bin/osx/libsteam_api.dylib) endif() From 990b96a29b280dcaeb20f49a4a2051f3cd2a3be8 Mon Sep 17 00:00:00 2001 From: Petr Hodina Date: Sat, 3 May 2025 10:12:34 +0200 Subject: [PATCH 16/24] mem.h: Fix malloc.h include --- platform/mem.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/mem.h b/platform/mem.h index eaac886..edaf164 100644 --- a/platform/mem.h +++ b/platform/mem.h @@ -1,2 +1,6 @@ #include -#include +#if defined(__linux__) + #include +#elif defined(__APPLE__) + #include +#endif From 3cc7c14064dfa8f0461e61cc4e3309453ded2d49 Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Sat, 3 May 2025 10:46:57 +0200 Subject: [PATCH 17/24] fix glitch in inventory and interface --- game/interfac.c | 7 ++++--- game/inv.c | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/game/interfac.c b/game/interfac.c index c241815..188df8c 100644 --- a/game/interfac.c +++ b/game/interfac.c @@ -1486,8 +1486,9 @@ int smlouvat_prodej(int cena,int ponuka,int posledni,int puvod,int pocet) if (ponuka==0) return 0; if (ponuka<=cena) return 0; - if (posledni!=0) if (ponuka>=posledni || ponuka>min) return 1; - if (p_ok>r_ok) return 0; + if (ponuka <= min && (posledni==0 || ponukar_ok) return 0; + } if (p_ok>75) return 2; if (p_ok>50) return 3; if (p_ok>25) return 4; @@ -1544,7 +1545,7 @@ THAGGLERESULT smlouvat_dlg(int cena,int puvod,int pocet,int posledni, int money, define(-1,150,15,100,13,0,label,int2ascii(cena,buffer,10)); set_font(H_FBOLD,MSG_COLOR1); define(-1,10,30,1,1,0,label,texty[238]); - define(10,150,30,100,13,0,input_line,8,0,0,"");property(def_border(5,BAR_COLOR),NULL,NULL,0);set_default(""); + define(10,150,30,100,13,0,input_line,7,0,0,"");property(def_border(5,BAR_COLOR),NULL,NULL,0);set_default(""); on_control_event(smlouvat_enter); define(20,20,20,80,20,2,button,texty[239]);property(def_border(5,BAR_COLOR),NULL,NULL,BAR_COLOR);on_control_change(terminate_gui); define(30,110,20,80,20,2,button,texty[230]);property(def_border(5,BAR_COLOR),NULL,NULL,BAR_COLOR);on_control_change(terminate_gui); diff --git a/game/inv.c b/game/inv.c index 43b497d..e33e0ae 100644 --- a/game/inv.c +++ b/game/inv.c @@ -2494,7 +2494,6 @@ static int shop_sector; T_CLK_MAP clk_shop[]= { {-1,54,378,497,479,shop_change_player,2+8,-1}, - {-1,0,0,639,479,_exit_shop,8,-1}, {-1,INV_X,INV_Y,INV_X+INV_XS*6,INV_Y+INV_YS*5,shop_bag_click,MS_EVENT_MOUSE_LPRESS,-1}, {1,2+BUYBOX_X,39+BUYBOX_Y,22+BUYBOX_X,76+BUYBOX_Y,shop_block_click,2,H_MS_DEFAULT}, {2,246+BUYBOX_X,39+BUYBOX_Y,266+BUYBOX_X,76+BUYBOX_Y,shop_block_click,2,H_MS_DEFAULT}, @@ -2503,6 +2502,7 @@ T_CLK_MAP clk_shop[]= {-1,337,0,357,14,go_map,2,H_MS_DEFAULT}, {-1,87,0,142,14,game_setup,2,H_MS_DEFAULT}, {-1,30,0,85,14,konec,2,H_MS_DEFAULT}, + {-1,0,0,639,479,_exit_shop,8,-1}, }; static void shop_mouse_event(EVENT_MSG *msg,void **unused) @@ -3207,7 +3207,6 @@ char _exit_shop(int id, int xa, int ya,int xr,int yr) { xr,yr,xa,ya,id; SEND_LOG("(SHOP) Exiting shop..."); - memset(shp_item_map, 0, sizeof(shp_item_map)); if (cur_owner==-1) { free(picked_item); From 54247b5720eaaa3696d96f70f7b56fedccb6fa83 Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Sat, 3 May 2025 14:08:24 +0200 Subject: [PATCH 18/24] options->speed up battles, game speed, #1 fix volume --- game/builder.c | 6 +++--- game/gamesave.c | 15 ++++++++++++++- game/globals.h | 8 ++++++-- game/setup.c | 10 +++++++--- game/skeldal.c | 7 +++++-- game/souboje.c | 6 +++--- lang/en/ui.csv | 4 ++-- platform/sdl/sound.cpp | 3 ++- 8 files changed, 42 insertions(+), 17 deletions(-) diff --git a/game/builder.c b/game/builder.c index e100514..e9ad729 100644 --- a/game/builder.c +++ b/game/builder.c @@ -327,14 +327,14 @@ static const void *bott_draw_normal(const void *pp, int32_t *s) { char c[]=" ";int z,lv,llv; put_picture(x,0,ablock(H_OKNO));lv=p->lives;llv=p->vlastnosti[VLS_MAXHIT]; - if (lv || p->used & 0x80 || p->kondice > 0) + if (lv || p->used & 0x80) { z=3-((lv-1)*4/llv);if (lv==llv) z=0; z*=75; if (p->xicht>=0)put_8bit_clipped(ablock(H_XICHTY+i),bott_scr+PIC_X+x+PIC_Y*scr_linelen2,z,54,75); - if (!lv && !(p->used & 0x80) && p->kondice>0) { + /* if (!lv && !(p->used & 0x80) && p->kondice>0) { greyscale_rectangle(PIC_X+x,PIC_Y, 54, 75); - } + }*/ if (p->bonus) draw_small_icone(0,PIC_X+x+1,PIC_Y+1); if (p->spell) draw_small_icone(1,PIC_X+x+1,PIC_Y+1); if (!p->voda) draw_small_icone(2,PIC_X+x+1,PIC_Y+1); diff --git a/game/gamesave.c b/game/gamesave.c index 6b00782..358f500 100644 --- a/game/gamesave.c +++ b/game/gamesave.c @@ -30,6 +30,9 @@ #define SLOTS_MAX 10 #define GM_MAPENABLE 0x1 +#define GM_FASTBATTLES 0x2 +#define GM_GAMESPEED_SHIFT 2 +#define GM_GAMESPEED_MASK 0x1F #define SAVE_SLOT_S 34 #define LOAD_SLOT_S (372+34) @@ -618,7 +621,14 @@ int save_basic_info() s.swapchans=MIN(get_snd_effect(SND_SWAP),255); s.out_filter=MIN(get_snd_effect(SND_OUTFILTER),255); s.autosave=autosave_enabled; - s.game_flags=(enable_glmap!=0); + s.game_flags=0; + + if (enable_glmap!=0) s.game_flags |= GM_MAPENABLE; + if (gamespeedbattle> GM_GAMESPEED_SHIFT) & GM_GAMESPEED_MASK; + if (tmsp) timerspeed_val = tmsp; i=s.picks; if (picked_item!=NULL) free(picked_item); if (i) diff --git a/game/globals.h b/game/globals.h index bc5d4e3..85715ae 100644 --- a/game/globals.h +++ b/game/globals.h @@ -12,6 +12,10 @@ #define POCET_POSTAV 6 #define HODINA 360 +#define GAMESPEED 5 +#define GAMESPEED_FASTBATTLE 2 + + #define MAX_FILESYSTEM_PATH 256 #define A_SIDEMAP 0x8001 @@ -581,8 +585,8 @@ extern word minimap[VIEW3D_Z+1][VIEW3D_X*2+1]; //minimalizovana mapa s informace extern char norefresh; //vypina refresh obrazovky extern char cancel_pass; //okamzite zrusi plynuly prechod extern char reverse_draw ; //kresba odpredu dozadu -extern char gamespeed; //rychlost hry -extern char gamespeedbattle; //akcelerace rychlosti pro bitvy +extern uint8_t gamespeed; //rychlost hry +extern uint8_t gamespeedbattle; //akcelerace rychlosti pro bitvy extern int num_ofsets[]; //tabulka offsetu pro steny extern int back_color; //cislo barvy pozadi extern uint8_t cur_group; //cislo aktualni skupiny diff --git a/game/setup.c b/game/setup.c index 28118e3..bff5d7b 100644 --- a/game/setup.c +++ b/game/setup.c @@ -44,7 +44,7 @@ static void checkbox_animator(THE_TIMER *t) animate_checkbox(10,130,10); } -static int effects[]={SND_GVOLUME,SND_MUSIC,SND_GFX,SND_TREBL,SND_BASS,SND_XBASS}; +static int effects[]={SND_GVOLUME,SND_MUSIC,SND_GFX,SND_TREBL,SND_BASS}; static void do_setup_change(void) { @@ -55,6 +55,7 @@ static void do_setup_change(void) { case 10:set_snd_effect(SND_SWAP,c & 1);break; case 20:set_snd_effect(SND_OUTFILTER,c & 1);break; + case 250:timerspeed_val = TIMERSPEED- c;break; default:set_snd_effect(effects[o_aktual->id/10-20],c);break; } } @@ -111,7 +112,7 @@ static void unwire_setup(void) enable_sort=f_get_value(0,100) & 1; autoattack=f_get_value(0,110) & 1; autosave_enabled=f_get_value(0,120) & 1; - level_preload=f_get_value(0,130) & 1; + gamespeedbattle=(f_get_value(0,130) & 1)?GAMESPEED_FASTBATTLE:gamespeed; delete_from_timer(TM_CHECKBOX); mix_back_sound(32768); close_current(); @@ -188,7 +189,7 @@ void new_setup() case 1:c_default(enable_sort);break; case 2:c_default(autoattack);break; case 3:c_default(autosave_enabled);break; - case 4:c_default(level_preload);break; + case 4:c_default(gamespeedbattle < gamespeed);break; } } @@ -201,6 +202,9 @@ void new_setup() define(200+i*10,50+i*60,30,30,200,0,skeldal_soupak,effects[i]==SND_MUSIC?127:255);c_default(get_snd_effect(effects[i])); on_control_change(do_setup_change); } + define(200+5*10,50+5*60,30,30,200,0,skeldal_soupak,TIMERSPEED-1);c_default(timerspeed_val >TIMERSPEED?0:TIMERSPEED - timerspeed_val); + on_control_change(do_setup_change); + define(300,559,336,81,21,0,setup_ok_button,texty[174]);on_control_change(exit_setup_action); property(NULL,ablock(H_FTINY),&color_topbar,0); redraw_window(); diff --git a/game/skeldal.c b/game/skeldal.c index 28d488e..e126c04 100644 --- a/game/skeldal.c +++ b/game/skeldal.c @@ -75,12 +75,13 @@ typedef struct inis THE_TIMER timer_tree; + int hl_ptr=H_FIRST_FREE; int debug_enabled=0; char sound_detection=1; int snd_devnum,snd_parm1,snd_parm2,snd_parm3,snd_mixing=22000; -char gamespeed=5; -char gamespeedbattle=0; +uint8_t gamespeed=GAMESPEED; +uint8_t gamespeedbattle=GAMESPEED; char level_preload=1; char *level_fname=NULL; int game_extras=0; @@ -823,6 +824,8 @@ void cti_texty(void) //patch stringtable if (!texty[98]) str_replace(&texty,98,"Ulo\x91it hru jako"); if (!texty[99]) str_replace(&texty,99,"CRT Filter (>720p)"); + str_replace(&texty, 144, "Zrychlit souboje"); + str_replace(&texty, 51, "Celkov\x88 Hudba Efekty V\x98\xA8ky Basy Rychlost"); str_replace(&texty,0,"Byl nalezen p\xA9ipojen\x98 ovlada\x87\nPro aktivaci ovlada\x87""e stiskn\x88te kter\x82koliv tla\x87\xA1tko na ovlada\x87i"); lang_patch_stringtable(&texty, "ui.csv", ""); } diff --git a/game/souboje.c b/game/souboje.c index fdf925a..6cd3890 100644 --- a/game/souboje.c +++ b/game/souboje.c @@ -879,7 +879,7 @@ char JePozdrzeno() void pozdrz_akci() { - int battlespeed=gamespeed-gamespeed*gamespeedbattle/5; + int battlespeed=gamespeedbattle; SPozdrzeno=get_game_tick_count()+battlespeed*2000/6; } @@ -1146,7 +1146,7 @@ static void pouzij_svitek(THUMAN *p,int ruka) static void play_weapon_anim(int anim_num,int hitpos) { char count_save=global_anim_counter; - int battlespeed=gamespeed-gamespeed*gamespeedbattle/5; + int battlespeed=gamespeedbattle; if (anim_num==0) return; hold_timer(TM_SCENE,1); @@ -1453,7 +1453,7 @@ void jadro_souboje(EVENT_MSG *msg,void **unused) //!!!! Jadro souboje void wire_jadro_souboje(void) { - int battlespeed=gamespeed-gamespeed*gamespeedbattle/5; + int battlespeed=gamespeedbattle; recalc_volumes(viewsector,viewdir); if (battlespeed<1) battlespeed=1; add_to_timer(TM_SCENE,battlespeed,-1,hrat_souboj); diff --git a/lang/en/ui.csv b/lang/en/ui.csv index 7703124..98046c6 100644 --- a/lang/en/ui.csv +++ b/lang/en/ui.csv @@ -45,7 +45,7 @@ To activate the controller, press any button on the controller" 48,Start 49,Throw 50,Combat in Progress -51,Overall Music Sounds Treble Bass +51,Overall Music Sounds Treble Bass Speed 52,Stereo Settings (Ultrasound) 53,Swap Sides 54,Output Filter (SBPro) @@ -117,7 +117,7 @@ To activate the controller, press any button on the controller" 141,Rearrange Portraits 142,Auto Attack 143,Auto Save -144,Load All Into Memory +144,Speed up battles 145,Adventure Length: 146,%d day and 147,%d days and diff --git a/platform/sdl/sound.cpp b/platform/sdl/sound.cpp index 6c2c562..2885308 100644 --- a/platform/sdl/sound.cpp +++ b/platform/sdl/sound.cpp @@ -299,7 +299,8 @@ static void update_music_volume(){ float v = music_volume * master_volume; for (int i = 0; i <2; i++) sound_mixer.visit_track(music_track_id_base+i,[&](WaveMixer<2> &m){ - m.set_channel_volume(v, v); + m.set_channel_volume(0, v); + m.set_channel_volume(1, v); }); } From 61044d9a606a62e607bdba113506bb0c44939544 Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Sat, 3 May 2025 14:12:14 +0200 Subject: [PATCH 19/24] #7 attempt to fix warning --- tools/ddl_ar_class.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ddl_ar_class.cpp b/tools/ddl_ar_class.cpp index 0142254..e59a8bb 100644 --- a/tools/ddl_ar_class.cpp +++ b/tools/ddl_ar_class.cpp @@ -45,7 +45,7 @@ DDLArchive::Extracted DDLArchive::extract_file(std::ifstream &s, std::vector data; data.resize(sz); s.read(data.data(), sz); - if (s.gcount() != sz) return {fname, false, {}}; + if (static_cast(s.gcount()) != sz) return {fname, false, {}}; return {fname, true, std::move(data)}; } From 14d2aef34e2b95f1fb34176e9dbfe279f028d22b Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Sat, 3 May 2025 16:47:04 +0200 Subject: [PATCH 20/24] implement list of destroyed items and a way to return them into game --- game/enemy.c | 28 ++++++++++++++++++++++------ game/gamesave.c | 24 ++++++++++++++++++++++++ game/globals.h | 7 ++++--- game/inv.c | 49 ++++++++++++++++++++++++++++--------------------- game/realgame.c | 3 ++- 5 files changed, 80 insertions(+), 31 deletions(-) diff --git a/game/enemy.c b/game/enemy.c index 7a5811c..d2a2a1f 100644 --- a/game/enemy.c +++ b/game/enemy.c @@ -1317,18 +1317,24 @@ void vymaz_zasahy(THE_TIMER *q) bott_draw(0); } +static int select_drop_inventory_place(TMOB *p) { + int x,y,pl; + if (p->locx>128) x=1;else if (p->locx<128) x=-1;else x=rnd(2)*2-1; + if (p->locy>128) y=1;else if (p->locy<128) y=-1;else y=rnd(2)*2-1; + pl=0;if (x>0) pl++; + if (y>0) pl=3-pl; + return pl; +} + static int drop_inventory(TMOB *p) { - int i,x,y,pl; + int i,pl; short c[]={0,0}; - for(i=-1;iinv[i] || (i<0 && p->money)) { - if (p->locx>128) x=1;else if (p->locx<128) x=-1;else x=rnd(2)*2-1; - if (p->locy>128) y=1;else if (p->locy<128) y=-1;else y=rnd(2)*2-1; - pl=0;if (x>0) pl++; - if (y>0) pl=3-pl; + pl = select_drop_inventory_place(p); if (i<0) { int z=(int)p->money+(int)(rnd(40)-20)*(int)p->money/(int)100; @@ -1341,6 +1347,16 @@ static int drop_inventory(TMOB *p) } push_item(p->sector,pl,c); } + } + if (destroyed_items) { + int cnt = count_items_total(destroyed_items); + if (cnt) { + int idx = cnt -1; + pl = select_drop_inventory_place(p); + push_item(p->sector,pl, destroyed_items+idx); + destroyed_items[idx] = 0; + } + } return 0; } diff --git a/game/gamesave.c b/game/gamesave.c index 358f500..f87b217 100644 --- a/game/gamesave.c +++ b/game/gamesave.c @@ -586,6 +586,14 @@ int unpack_all_status(FILE *f) return -1; } +static void save_destroyed_items(TMPFILE_WR *f) { + short c = (short)count_items_total(destroyed_items); + temp_storage_write(&c,sizeof(c), f); + if (c) { + temp_storage_write(destroyed_items,sizeof(short)*c, f); + } +} + int save_basic_info() { TMPFILE_WR *f; @@ -645,11 +653,26 @@ int save_basic_info() for(i=0,h=postavy;idemon_save!=NULL) temp_storage_write(h->demon_save,sizeof(THUMAN)*1,f); //ulozeni polozek s demony res|=save_dialog_info(f); + save_destroyed_items(f); temp_storage_close_wr(f); SEND_LOG("(SAVELOAD) Done... Result: %d",res); return res; } +static int load_destroyed_items(TMPFILE_RD *f) { + int res = 0; + short destroyed_items_count = 0; + temp_storage_read(&destroyed_items_count,sizeof(destroyed_items_count), f); + free(destroyed_items); + destroyed_items = NULL; + if (destroyed_items_count) { + destroyed_items = NewArr(short, destroyed_items_count+1); + res|=temp_storage_read(destroyed_items,destroyed_items_count*sizeof(short), f) != destroyed_items_count*sizeof(short); + destroyed_items[destroyed_items_count] = 0; + } + return res; +} + int load_basic_info() { TMPFILE_RD *f; @@ -698,6 +721,7 @@ int load_basic_info() } } res|=load_dialog_info(f); + res|=load_destroyed_items(f); temp_storage_close_rd(f); viewsector=s.viewsector; viewdir=s.viewdir; diff --git a/game/globals.h b/game/globals.h index 85715ae..b5381bd 100644 --- a/game/globals.h +++ b/game/globals.h @@ -577,6 +577,7 @@ extern int mapsize; //pocet sektoru v mape extern int hl_ptr; //ukazatel na konec staticke tabulky registraci extern int end_ptr; //ukazatel na uplny konec tabulky registraci extern short **map_items; //ukazatel na mapu predmetu +extern short *destroyed_items; //list of destroyed items to be returned to the game extern int default_ms_cursor; //cislo zakladniho mysiho kurzoru extern void (*unwire_proc)(void); //procedura zajistujici odpojeni prave ukoncovane interakce extern void (*wire_proc)(void); //procedura zajistujici pripojeni drive ukoncene interakce @@ -990,10 +991,10 @@ char pick_item_(int id,int xa,int ya,int xr,int yr); void wire_inv_mode(THUMAN *select); void init_inventory(void); void init_items(void); -void push_item(int sect,int pos,short *picked_item); +void push_item(int sect,int pos,const short *picked_item); void pop_item(int sect,int pos,int mask,short **picked_item); -int count_items_inside(short *place); -int count_items_total(short *place); +int count_items_inside(const short *place); +int count_items_total(const short *place); char put_item_to_inv(THUMAN *p,short *picked_items); //funkce vklada predmet(y) do batohu postavy void pick_set_cursor(void); //nastavuje kurzor podle vlozeneho predmetu; void calc_fly(THE_TIMER *t); diff --git a/game/inv.c b/game/inv.c index e33e0ae..afbe09e 100644 --- a/game/inv.c +++ b/game/inv.c @@ -432,7 +432,7 @@ void draw_placed_items_normal(int celx,int cely,int sect,int side) } } -int count_items_total(short *place) +int count_items_total(const short *place) { int c=0; @@ -441,7 +441,7 @@ int count_items_total(short *place) return c; } -int count_items_visible(short *place) +int count_items_visible(const short *place) { int c=0; @@ -455,7 +455,7 @@ int count_items_visible(short *place) } -int count_items_inside(short *place) +int count_items_inside(const short *place) { int c=1; @@ -492,30 +492,37 @@ static char ValidateSector(word sector, void *_) return 0; } -void push_item(int sect,int pos,short *picked_item) +void push_to_destroyed_items(const short *picked_items) { + int new_count = count_items_total(picked_items); + if (new_count == 0) return; + int cur_destroyed = count_items_total(destroyed_items); + short *nw = NewArr(short, new_count+cur_destroyed+1); + for (int i = 0; i < new_count; ++i) { + nw[i] = abs(picked_items[i]); + } + for (int i = 0; i < cur_destroyed; ++i) { + nw[new_count+i] = destroyed_items[i]; + } + nw[new_count+cur_destroyed] = 0; + free(destroyed_items); + destroyed_items = nw; +} + +void push_item(int sect,int pos,const short *picked_item) { int bc; int pc; int tc; short *p; + char s = map_sectors[sect].sector_type; + - if (map_sectors[sect].sector_type==S_DIRA || ISTELEPORTSECT(sect)) + if (s==S_DIRA || ISTELEPORTSECT(sect) || s == S_SCHODY) sect=map_sectors[sect].sector_tag; - if (sect==0 || map_sectors[sect].sector_type==S_VODA) - { - if (game_extras & EX_RECOVER_DESTROYED_ITEMS) - { - labyrinth_find_path(viewsector,65535,SD_PLAY_IMPS,ValidateSector,NULL, NULL); - push_item(lastsector,viewdir,picked_item); - return; - } - else - { - free(picked_item); - picked_item=NULL; - return; - } - } + if (sect==0 || s==S_VODA || s == S_LAVA || s == S_SSMRT) { + push_to_destroyed_items(picked_item); + return; + } sect=(sect<<2)+pos; bc=count_items_total(map_items[sect]); pc=count_items_total(picked_item); @@ -682,7 +689,7 @@ char pick_item_(int id,int xa,int ya,int xr,int yr) idd=(id+viewdir)&0x3; if (picked_item!=NULL) { - if (map_sectors[sect].sector_type==S_DIRA) + if (map_sectors[sect].sector_type==S_DIRA) { throw_fly(xa,ya,0); letici_veci->speed=0; diff --git a/game/realgame.c b/game/realgame.c index 80fd10c..e946bd5 100644 --- a/game/realgame.c +++ b/game/realgame.c @@ -62,7 +62,8 @@ TSTENA *map_sides; TSECTOR *map_sectors; TVYKLENEK *map_vyk; //mapa vyklenku word vyk_max; //pocet vyklenku v mape -short **map_items; +short **map_items = 0; +short *destroyed_items = 0;; char *flag_map; TMAP_EDIT_INFO *map_coord; TSTR_LIST level_texts; From 3f23c65b8beef9de8347863fe078eb6402d1e94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Nov=C3=A1k?= Date: Sat, 3 May 2025 17:27:43 +0200 Subject: [PATCH 21/24] fix compile errors in linux --- game/inv.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/game/inv.c b/game/inv.c index afbe09e..27d16b6 100644 --- a/game/inv.c +++ b/game/inv.c @@ -479,19 +479,6 @@ int find_item(short *place,int mask) return lastitem; } -static int lastsector; - -static char ValidateSector(word sector, void *_) - { - int pp=map_sectors[sector].sector_type; - if (pp==S_NORMAL || pp==S_SMER || pp==S_LEAVE || pp==S_FLT_SMER) - { - lastsector=sector; - return 1; - } - return 0; - } - void push_to_destroyed_items(const short *picked_items) { int new_count = count_items_total(picked_items); if (new_count == 0) return; @@ -515,11 +502,11 @@ void push_item(int sect,int pos,const short *picked_item) int tc; short *p; char s = map_sectors[sect].sector_type; - + if (s==S_DIRA || ISTELEPORTSECT(sect) || s == S_SCHODY) sect=map_sectors[sect].sector_tag; - if (sect==0 || s==S_VODA || s == S_LAVA || s == S_SSMRT) { + if (sect==0 || s==S_VODA || s == S_LAVA || s == S_SSMRT || s == S_LODKA) { push_to_destroyed_items(picked_item); return; } From 564381471055aed470edeffd99907b8f3622fe94 Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Sun, 4 May 2025 13:36:17 +0200 Subject: [PATCH 22/24] improve video initialization, use more compatible and common format --- platform/error.cpp | 4 +- platform/sdl/BGraph2.cpp | 1 - platform/sdl/sdl_context.cpp | 215 ++++++++++++++++++++++++++++++----- platform/sdl/sdl_context.h | 10 +- skeldal.ini | 4 - 5 files changed, 196 insertions(+), 38 deletions(-) diff --git a/platform/error.cpp b/platform/error.cpp index f2d2018..1f635c4 100644 --- a/platform/error.cpp +++ b/platform/error.cpp @@ -47,9 +47,9 @@ std::string exception_to_string(const std::exception& e) { try { std::rethrow_if_nested(e); } catch (const std::exception& nested) { - oss << " Reason: " << exception_to_string(nested); + oss << "\n\n Reason: " << exception_to_string(nested); } catch (...) { - oss << " Reason: unknown exception of crash"; + oss << "\n\n Reason: unknown exception of crash"; } return std::move(oss).str(); diff --git a/platform/sdl/BGraph2.cpp b/platform/sdl/BGraph2.cpp index 51f0418..e841088 100644 --- a/platform/sdl/BGraph2.cpp +++ b/platform/sdl/BGraph2.cpp @@ -41,7 +41,6 @@ char game_display_init(const INI_CONFIG_SECTION *display_section, const char *ti else cfg.crt_filter = SDLContext::CrtFilterType::autoselect; cfg.cursor_size = ini_get_int(display_section, "cursor_size", 100)*0.01f; - cfg.hint_renderer = ini_get_string(display_section, "sdl_renderer_driver", NULL); screen_pitch = 640; get_sdl_global_context().init_video(cfg, title); diff --git a/platform/sdl/sdl_context.cpp b/platform/sdl/sdl_context.cpp index bb95bda..dfdf113 100644 --- a/platform/sdl/sdl_context.cpp +++ b/platform/sdl/sdl_context.cpp @@ -4,6 +4,7 @@ #include #include #include "../platform.h" +#include "../error.h" #include #include @@ -34,6 +35,9 @@ void SDLContext::SDL_Deleter::operator ()(SDL_Surface* surface) { void SDLContext::SDL_Deleter::operator ()(SDL_Texture* texture) { SDL_DestroyTexture(texture); } +void SDLContext::SDL_Deleter::operator ()(SDL_PixelFormat* f) { + SDL_FreeFormat(f); +} void SDLContext::SDL_Audio_Deleter::operator()(SDL_AudioDeviceID x) { SDL_CloseAudioDevice(x); @@ -78,6 +82,20 @@ void handle_sdl_error(const char *msg) { throw std::runtime_error(buff); } +bool isFormatSupported(SDL_Renderer *renderer, Uint32 pixel_format) { + SDL_RendererInfo info; + if (SDL_GetRendererInfo(renderer, &info) != 0) { + handle_sdl_error("Failed to get renderer info"); + return false; + } + + for (Uint32 i = 0; i < info.num_texture_formats; ++i) { + if (info.texture_formats[i] == pixel_format) { + return true; + } + } + return false; +} void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** texture, int width, int height, CrtFilterType type) { @@ -95,6 +113,8 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur default: break; } + + if (type == CrtFilterType::scanlines || type == CrtFilterType::scanlines_2) { width = 32; } else { @@ -105,8 +125,11 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur unsigned int mult_of_base = std::max((height+240)/480,interfer); height = height * interfer / mult_of_base; } + + + // Vytvoř novou texturu ve správné velikosti - *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height); + *texture = SDL_CreateTexture(renderer, _texture_render_format, SDL_TEXTUREACCESS_STREAMING, width, height); if (!*texture) { type = CrtFilterType::none; return; //crt filter failed to create, do not use filter @@ -125,11 +148,13 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur } Uint32* pixelArray = (Uint32*)pixels; + if (type == CrtFilterType::scanlines) { - Uint32 darkPixel = 0xA0A0A0FF; - Uint32 transparentPixel = 0xFFFFFFC0; + + Uint32 darkPixel = SDL_MapRGBA(_main_pixel_format.get(), 0xA0, 0xA0, 0xA0, 0xFF); + Uint32 transparentPixel = SDL_MapRGBA(_main_pixel_format.get(), 0xFF, 0xFF, 0xFF, 0xC0); for (int y = 0; y < height; y++) { Uint32 color = ((y & 1)== 0) ? darkPixel : transparentPixel; @@ -141,8 +166,8 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur else if (type == CrtFilterType::scanlines_2) { - Uint32 darkPixel = 0x808080FF; - Uint32 transparentPixel = 0xFFFFFFE0; + Uint32 darkPixel = SDL_MapRGBA(_main_pixel_format.get(), 0x80, 0x80, 0x80, 0xFF); + Uint32 transparentPixel = SDL_MapRGBA(_main_pixel_format.get(), 0xFF, 0xFF, 0xFF, 0xE0); for (int y = 0; y < height; y++) { Uint32 color = (y % 3== 2) ? darkPixel : transparentPixel; @@ -152,10 +177,10 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur } } else { - static Uint32 red_pixel = 0xFF8080A0; - static Uint32 green_pixel = 0x80FF80A0; - static Uint32 blue_pixel = 0x8080FFA0; - static Uint32 dark_pixel = 0x000000C0; + static Uint32 red_pixel = SDL_MapRGBA(_main_pixel_format.get(), 0xFF, 0x80, 0x80, 0xA0); + static Uint32 green_pixel = SDL_MapRGBA(_main_pixel_format.get(), 0x80, 0xFF, 0x80, 0xA0); + static Uint32 blue_pixel = SDL_MapRGBA(_main_pixel_format.get(), 0x80, 0x80, 0xFF, 0xA0); + static Uint32 dark_pixel = SDL_MapRGBA(_main_pixel_format.get(), 0x0, 0x0, 0x00, 0xA0); for (int y = 2; y < height; y++) { if (type == CrtFilterType::rgb_matrix_2) { for (int x = 2; x < width; x+=3) { @@ -199,6 +224,30 @@ static void crash_sdl_exception() { abort(); } +static int select_best_rendered_driver(int max_texture_width, int max_texture_height, Uint32 texture_format, bool force_software) { + int best_index = -1; + int num_drivers = SDL_GetNumRenderDrivers(); + for (int i = 0; i < num_drivers; ++i) { + SDL_RendererInfo info; + if (SDL_GetRenderDriverInfo(i, &info) == 0) { + bool found_format = std::find(info.texture_formats, info.texture_formats + info.num_texture_formats, texture_format) != info.texture_formats + info.num_texture_formats; + if (found_format) { + if (force_software && (info.flags & SDL_RENDERER_SOFTWARE)) { + best_index = i; + break; + } + if (!force_software && (info.flags & SDL_RENDERER_ACCELERATED)) { + if (info.max_texture_width >= max_texture_width && + info.max_texture_height >= max_texture_height) { + best_index = i; + break; + } + } + } + } + } + return best_index; +} void SDLContext::init_video(const VideoConfig &config, const char *title) { static Uint32 update_request_event = SDL_RegisterEvents(1); @@ -219,18 +268,16 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { _enable_crt = false; } - if (config.hint_renderer) { - SDL_SetHint(SDL_HINT_RENDER_DRIVER, config.hint_renderer); - } - _fullscreen_mode = config.fullscreen; _mouse_size = config.cursor_size; std::atomic done = false; std::exception_ptr e; + std::string_view stage; _render_thread = std::jthread([&](std::stop_token stp){ bool err = false; try { + stage = "window"; SDL_Window *window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE|(_fullscreen_mode?SDL_WINDOW_FULLSCREEN_DESKTOP:0)); @@ -239,12 +286,42 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { handle_sdl_error("SDL Error create window"); } + stage = "renderer"; + int rindex = -1; + if (rindex == -1) { + _texture_render_format = SDL_PIXELFORMAT_RGBA8888; + rindex = select_best_rendered_driver(640,480, _texture_render_format, config.composer & SDL_RENDERER_SOFTWARE); + } + if (rindex == -1) { + _texture_render_format = SDL_PIXELFORMAT_ARGB8888; + rindex = select_best_rendered_driver(640,480, _texture_render_format, config.composer & SDL_RENDERER_SOFTWARE); + } + if (rindex == -1){ + _texture_render_format = SDL_PIXELFORMAT_ARGB8888; + rindex = select_best_rendered_driver(640,480, _texture_render_format, true); + } + if (rindex == -1){ + _texture_render_format = SDL_PIXELFORMAT_RGBA8888; + rindex = select_best_rendered_driver(640,480, _texture_render_format, true); + } + if (rindex == -1) { + throw std::runtime_error("Unsupported graphic driver, (software fallback also failed)"); + } + + _window.reset(window); - SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), -1, config.composer); + SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), rindex, config.composer); if (!renderer) { handle_sdl_error("Failed to create composer"); } + stage = "pixel format"; + + _main_pixel_format.reset(SDL_AllocFormat(_texture_render_format)); + if (!_main_pixel_format) { + handle_sdl_error("Failed to create texture format"); + } + SDL_RendererInfo rinfo; SDL_GetRendererInfo(renderer, &rinfo); @@ -256,20 +333,31 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, config.scale_quality); } + _renderer.reset(renderer); - SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB1555, SDL_TEXTUREACCESS_STREAMING, 640, 480); + + stage = "main render target"; + + + SDL_Texture *texture = SDL_CreateTexture(renderer, _texture_render_format, SDL_TEXTUREACCESS_STREAMING, 640, 480); if (!texture) { handle_sdl_error("Failed to create render target"); } SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); _texture.reset(texture); - texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB1555, SDL_TEXTUREACCESS_STREAMING, 640, 480); + + stage = "secondary render target"; + + texture = SDL_CreateTexture(renderer, _texture_render_format, SDL_TEXTUREACCESS_STREAMING, 640, 480); if (!texture) { handle_sdl_error("Failed to create second render target"); } SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); _texture2.reset(texture); + + stage = "all done"; + _visible_texture = _texture.get(); _hidden_texture = _texture2.get(); } catch (...) { @@ -301,10 +389,11 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { std::rethrow_exception(e); } catch (...) { std::throw_with_nested( - std::runtime_error("Oops! The app couldn't start properly (problem during SDL initialization). " + std::runtime_error(std::string("Oops! The application couldn't start properly (problem during SDL initialization). Stage: [") + .append(stage).append("]\n\n" "This may be caused by outdated or missing graphics or audio drivers." - "To fix this, please try the following: Restart your computer and try again/" - "Make sure your graphics and sound drivers are up to date.")); + "To fix this, please try the following:\n- Restart your computer and try again\n- " + "Make sure your graphics and sound drivers are up to date."))); } } @@ -346,6 +435,75 @@ int SDLContext::adjust_deadzone(int v, short deadzone) { return 0; } +void SDLContext::update_texture_with_conversion(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch) +{ + SDL_Rect r; + if (rect) { + r = *rect; + } else { + SDL_QueryTexture(texture, nullptr, nullptr, &r.w, &r.h); + r.x = 0; + r.y = 0; + } + + converted_pixels.clear(); + converted_pixels.resize(r.w * r.h); + + switch (_texture_render_format) { + case SDL_PIXELFORMAT_RGBA8888: { + const Uint16* src = static_cast(pixels); + auto trg = converted_pixels.data(); + for (int y = 0; y < r.h; ++y) { + for (int x = 0; x < r.w; ++x) { + Uint16 pixel = src[x]; + Uint32 a = (pixel & 0x8000) ? 0 : 0xFF; + Uint32 r = ((pixel >> 10) & 0x1F); + Uint32 g = ((pixel >> 5) & 0x1F); + Uint32 b = (pixel & 0x1F); + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + if constexpr (std::endian::native == std::endian::little) { + trg[x] = (r << 24) | (g << 16) | (b << 8) | a; + } else { + trg[x] = (r) | (g << 8) | (b << 16) | (a << 24); + } + } + trg += r.w; + src = src + pitch/2; + } + } + break; + case SDL_PIXELFORMAT_ARGB8888: { + const Uint16* src = static_cast(pixels); + auto trg = converted_pixels.data(); + for (int y = 0; y < r.h; ++y) { + for (int x = 0; x < r.w; ++x) { + Uint16 pixel = src[x]; + Uint32 a = (pixel & 0x8000) ? 0 : 0xFF; + Uint32 r = ((pixel >> 10) & 0x1F); + Uint32 g = ((pixel >> 5) & 0x1F); + Uint32 b = (pixel & 0x1F); + r = (r << 3) | (r >> 2); + g = (g << 3) | (g >> 2); + b = (b << 3) | (b >> 2); + if constexpr (std::endian::native == std::endian::little) { + trg[x] = (a << 24) | (r << 16) | (g << 8) | b; + } else { + trg[x] = (a) | (r << 8) | (g << 16) | (b << 24); + } + } + trg += r.w; + src = src + pitch/2; + } + } + break; + } + if (SDL_UpdateTexture(texture, &r, converted_pixels.data(), r.w * 4) < 0) { + handle_sdl_error("Failed to update texture"); + } +} + static int axis_dynamic(int c) { double f = std::floor(std::pow(std::abs(c)*0.001,2)*0.025); @@ -709,19 +867,19 @@ void SDLContext::update_screen(bool force_refresh) { SDL_Rect r; pop_item(iter, r); std::string_view data = pop_data(iter, r.w*r.h*2); - if (SDL_UpdateTexture(_texture.get(), &r, data.data(), r.w*2)<0) handle_sdl_error("Update of render target failed"); + update_texture_with_conversion(_texture.get(), &r, data.data(), r.w*2); } break; case DisplayRequest::show_mouse_cursor: { SDL_Rect r; pop_item(iter, r); std::string_view data = pop_data(iter, r.w*r.h*2); - _mouse.reset(SDL_CreateTexture(_renderer.get(), SDL_PIXELFORMAT_ARGB1555,SDL_TEXTUREACCESS_STATIC, r.w, r.h)); + _mouse.reset(SDL_CreateTexture(_renderer.get(), _texture_render_format,SDL_TEXTUREACCESS_STATIC, r.w, r.h)); if (!_mouse) handle_sdl_error("Failed to create surface for mouse cursor"); SDL_SetTextureBlendMode(_mouse.get(), SDL_BLENDMODE_BLEND); _mouse_rect.w = r.w; _mouse_rect.h = r.h; - if (SDL_UpdateTexture(_mouse.get(), NULL, data.data(), r.w*2)<0) handle_sdl_error("Update of mouse cursor failed"); + update_texture_with_conversion(_mouse.get(), NULL, data.data(), r.w*2); } break; case DisplayRequest::hide_mouse_cursor: { @@ -758,10 +916,10 @@ void SDLContext::update_screen(bool force_refresh) { if (iter == _sprites.end()) { iter = _sprites.insert(iter,{id}); } - iter->_txtr.reset(SDL_CreateTexture(_renderer.get(), SDL_PIXELFORMAT_ARGB1555, SDL_TEXTUREACCESS_STATIC,r.w, r.h)); + iter->_txtr.reset(SDL_CreateTexture(_renderer.get(), _texture_render_format, SDL_TEXTUREACCESS_STATIC,r.w, r.h)); if (!iter->_txtr) handle_sdl_error("Failed to create compositor sprite"); SDL_SetTextureBlendMode(iter->_txtr.get(), SDL_BLENDMODE_BLEND); - if (SDL_UpdateTexture(iter->_txtr.get(), NULL, data.data(), r.w*2)<0) handle_sdl_error("Update of sprite failed"); + update_texture_with_conversion(iter->_txtr.get(), NULL, data.data(), r.w*2); iter->_rect = r; update_zindex(); } break; @@ -862,10 +1020,8 @@ void SDLContext::push_update_msg(const SDL_Rect &rc, const uint16_t *data, int p _display_update_queue.resize(sz+rc.w*rc.h*2); short *trg = reinterpret_cast(_display_update_queue.data()+sz); for (int yp = 0; yp < rc.h; ++yp) { - for (int xp = 0; xp < rc.w; ++xp) { - *trg = data[xp] ^ 0x8000; - ++trg; - } + std::copy(data, data+rc.w, trg); + trg += rc.w; data += pitch; } } @@ -1020,7 +1176,7 @@ void put_picture_ex(unsigned short x,unsigned short y,const void *p, unsigned sh } void SDLContext::push_hi_image(const unsigned short *image) { - SDL_Rect rc; + SDL_Rect rc = {}; rc.w= image[0]; rc.h =image[1]; push_item(rc); @@ -1030,7 +1186,6 @@ void SDLContext::push_hi_image(const unsigned short *image) { unsigned short *trg = reinterpret_cast(_display_update_queue.data()+sz); std::fill(trg, trg+imgsz, 0x8000); put_picture_ex(0, 0, image, trg, rc.w); - std::transform(trg, trg+imgsz, trg, [](unsigned short &x)->unsigned short {return x ^ 0x8000;}); } void SDLContext::show_mouse_cursor(const unsigned short *ms_hi_format, SDL_Point finger) { diff --git a/platform/sdl/sdl_context.h b/platform/sdl/sdl_context.h index 2cfa786..a13c84c 100644 --- a/platform/sdl/sdl_context.h +++ b/platform/sdl/sdl_context.h @@ -33,7 +33,6 @@ public: CrtFilterType crt_filter; int composer; const char *scale_quality; - const char *hint_renderer; bool fullscreen; int aspect_x; int aspect_y; @@ -171,6 +170,7 @@ protected: void operator()(SDL_Renderer *); void operator()(SDL_Surface *); void operator()(SDL_Texture *); + void operator()(SDL_PixelFormat* f); }; struct BlendTransitionReq { @@ -238,13 +238,16 @@ protected: std::unique_ptr _texture2; std::unique_ptr _crt_effect; std::unique_ptr _mouse; + std::unique_ptr _main_pixel_format; unique_value _audio; SDL_Texture *_visible_texture = nullptr; SDL_Texture *_hidden_texture = nullptr; + uint32_t _texture_render_format = SDL_PIXELFORMAT_ARGB1555; bool _fullscreen_mode = false; bool _present = false; + bool _convert_format = false; std::atomic _key_control = false; std::atomic _key_shift = false; std::atomic _key_capslock = false; @@ -253,6 +256,7 @@ protected: std::vector _display_update_queue; + std::vector converted_pixels; using QueueIter = const char *; std::queue _keyboard_queue; SDL_Rect _mouse_rect; @@ -308,4 +312,8 @@ protected: void generate_j_event(int button, char up); static int adjust_deadzone(int v, short deadzone); + void update_texture_with_conversion(SDL_Texture * texture, + const SDL_Rect * rect, + const void *pixels, int pitch); + }; diff --git a/skeldal.ini b/skeldal.ini index cab6ad9..c49ddbe 100644 --- a/skeldal.ini +++ b/skeldal.ini @@ -33,10 +33,6 @@ # composer = auto - choose best supported driver # hardware,hw - use hardware for composition # software,sw - use software for composition -# sdl_renderer_driver - help SDL to choose optimal rederer -# direct3d,direct3d11,direct3d12 -# opengl,opengles2,opengles -# metal,software # scale_quality = auto - best for hardware composer, nearest for software comporser # best - best scale quality (SDL = linear) # linear - use linear filtering (Direct3D and OpenGL) From 8e5a26011d56e5cb5afe5ef86f241f0d128cfe44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Nov=C3=A1k?= Date: Sun, 4 May 2025 18:47:04 +0200 Subject: [PATCH 23/24] version, more pixel formats, detect native format --- CMakeLists.txt | 24 +++ game/menu.c | 8 + platform/sdl/format_mapping.h | 182 +++++++++++++++++++++++ platform/sdl/sdl_context.cpp | 265 ++++++++++++++++++++-------------- platform/sdl/sdl_context.h | 3 + version.in.h | 5 + 6 files changed, 381 insertions(+), 106 deletions(-) create mode 100644 platform/sdl/format_mapping.h create mode 100644 version.in.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ca0216e..736b519 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,30 @@ else() endif() +set(VERSION_IN "${CMAKE_SOURCE_DIR}/version.in.h") +set(VERSION_OUT "${CMAKE_BINARY_DIR}/version.h") + +find_package(Git QUIET) + +if(GIT_FOUND) + execute_process( + COMMAND ${GIT_EXECUTABLE} describe --tags --always + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE GIT_RESULT + ) + if(NOT GIT_RESULT EQUAL 0) + set(GIT_VERSION "unknown") + endif() +else() + set(GIT_VERSION "unknown") +endif() + +set(APP_VERSION "${GIT_VERSION}") +configure_file(${VERSION_IN} ${VERSION_OUT} @ONLY) + +include_directories(${CMAKE_BINARY_DIR}) include_directories(.) diff --git a/game/menu.c b/game/menu.c index d9bf6f3..0721add 100644 --- a/game/menu.c +++ b/game/menu.c @@ -20,6 +20,7 @@ #include "ach_events.h" #include "lang.h" +#include #define MUSIC "TRACK06.MUS" @@ -334,6 +335,12 @@ static void klavesnice(EVENT_MSG *msg,void **unused) } } +static void show_version() { + const char *verstr = "Version: " SKELDAL_VERSION; + set_font(H_FLITT5, RGB888(255,255,255)); + set_aligned_position(639, 479, 2, 2, verstr); + outtext(verstr); +} int enter_menu(char open) { @@ -350,6 +357,7 @@ int enter_menu(char open) put_picture(0,0,ablock(H_MENU_BAR)); put_picture(0,56,ablock(H_ANIM)); ukaz_mysku(); + show_version(); effect_show(); change_click_map(clk_main_menu,CLK_MAIN_MENU); diff --git a/platform/sdl/format_mapping.h b/platform/sdl/format_mapping.h new file mode 100644 index 0000000..1c2ccc8 --- /dev/null +++ b/platform/sdl/format_mapping.h @@ -0,0 +1,182 @@ +#pragma once +#include + + +template +struct FormatMapping; + +template<> +struct FormatMapping { + static constexpr int RShift = 20; + static constexpr int GShift = 10; + static constexpr int BShift = 0; + static constexpr int AShift = 30; + + static constexpr int RBits = 10; + static constexpr int GBits = 10; + static constexpr int BBits = 10; + static constexpr int ABits = 2; +}; + + +template<> +struct FormatMapping { + static constexpr int RShift = 0; + static constexpr int GShift = 8; + static constexpr int BShift = 16; + static constexpr int AShift = 24; + + static constexpr int RBits = 8; + static constexpr int GBits = 8; + static constexpr int BBits = 8; + static constexpr int ABits = 8; +}; + +template<> +struct FormatMapping { + static constexpr int RShift = 16; + static constexpr int GShift = 8; + static constexpr int BShift = 0; + static constexpr int AShift = 24; + + static constexpr int RBits = 8; + static constexpr int GBits = 8; + static constexpr int BBits = 8; + static constexpr int ABits = 8; +}; + +template<> +struct FormatMapping { + static constexpr int RShift = 24; + static constexpr int GShift = 16; + static constexpr int BShift = 8; + static constexpr int AShift = 0; + + static constexpr int RBits = 8; + static constexpr int GBits = 8; + static constexpr int BBits = 8; + static constexpr int ABits = 8; +}; + +template<> +struct FormatMapping { + static constexpr int RShift = 8; + static constexpr int GShift = 16; + static constexpr int BShift = 24; + static constexpr int AShift = 0; + + static constexpr int RBits = 8; + static constexpr int GBits = 8; + static constexpr int BBits = 8; + static constexpr int ABits = 8; +}; + + +template<> +struct FormatMapping { + static constexpr int RShift = 0; + static constexpr int GShift = 4; + static constexpr int BShift = 8; + static constexpr int AShift = 12; + + static constexpr int RBits = 4; + static constexpr int GBits = 4; + static constexpr int BBits = 4; + static constexpr int ABits = 4; +}; + +template<> +struct FormatMapping { + static constexpr int RShift = 8; + static constexpr int GShift = 4; + static constexpr int BShift = 0; + static constexpr int AShift = 12; + + static constexpr int RBits = 4; + static constexpr int GBits = 4; + static constexpr int BBits = 4; + static constexpr int ABits = 4; +}; + +template<> +struct FormatMapping { + static constexpr int RShift = 12; + static constexpr int GShift = 8; + static constexpr int BShift = 4; + static constexpr int AShift = 0; + + static constexpr int RBits = 4; + static constexpr int GBits = 4; + static constexpr int BBits = 4; + static constexpr int ABits = 4; +}; + +template<> +struct FormatMapping { + static constexpr int RShift = 4; + static constexpr int GShift = 8; + static constexpr int BShift = 12; + static constexpr int AShift = 0; + + static constexpr int RBits = 4; + static constexpr int GBits = 4; + static constexpr int BBits = 4; + static constexpr int ABits = 4; +}; + + +template<> +struct FormatMapping { + static constexpr int RShift = 0; + static constexpr int GShift = 5; + static constexpr int BShift = 10; + static constexpr int AShift = 15; + + static constexpr int RBits = 5; + static constexpr int GBits = 5; + static constexpr int BBits = 5; + static constexpr int ABits = 1; +}; + +template<> +struct FormatMapping { + static constexpr int RShift = 10; + static constexpr int GShift = 5; + static constexpr int BShift = 0; + static constexpr int AShift = 15; + + static constexpr int RBits = 8; + static constexpr int GBits = 8; + static constexpr int BBits = 8; + static constexpr int ABits = 1; +}; + +template<> +struct FormatMapping { + static constexpr int RShift = 11; + static constexpr int GShift = 6; + static constexpr int BShift = 1; + static constexpr int AShift = 0; + + static constexpr int RBits = 5; + static constexpr int GBits = 5; + static constexpr int BBits = 5; + static constexpr int ABits = 1; +}; + +template<> +struct FormatMapping { + static constexpr int RShift = 1; + static constexpr int GShift = 6; + static constexpr int BShift = 11; + static constexpr int AShift = 0; + + static constexpr int RBits = 5; + static constexpr int GBits = 5; + static constexpr int BBits = 5; + static constexpr int ABits = 1; +}; + + + + diff --git a/platform/sdl/sdl_context.cpp b/platform/sdl/sdl_context.cpp index dfdf113..01a1d2a 100644 --- a/platform/sdl/sdl_context.cpp +++ b/platform/sdl/sdl_context.cpp @@ -1,5 +1,6 @@ #include "sdl_context.h" #include "keyboard_map.h" +#include "format_mapping.h" #include #include @@ -113,7 +114,7 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur default: break; } - + if (type == CrtFilterType::scanlines || type == CrtFilterType::scanlines_2) { width = 32; @@ -126,7 +127,7 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur height = height * interfer / mult_of_base; } - + // Vytvoř novou texturu ve správné velikosti *texture = SDL_CreateTexture(renderer, _texture_render_format, SDL_TEXTUREACCESS_STREAMING, width, height); @@ -148,7 +149,7 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur } Uint32* pixelArray = (Uint32*)pixels; - + if (type == CrtFilterType::scanlines) { @@ -224,29 +225,47 @@ static void crash_sdl_exception() { abort(); } -static int select_best_rendered_driver(int max_texture_width, int max_texture_height, Uint32 texture_format, bool force_software) { - int best_index = -1; - int num_drivers = SDL_GetNumRenderDrivers(); - for (int i = 0; i < num_drivers; ++i) { - SDL_RendererInfo info; - if (SDL_GetRenderDriverInfo(i, &info) == 0) { - bool found_format = std::find(info.texture_formats, info.texture_formats + info.num_texture_formats, texture_format) != info.texture_formats + info.num_texture_formats; - if (found_format) { - if (force_software && (info.flags & SDL_RENDERER_SOFTWARE)) { - best_index = i; - break; - } - if (!force_software && (info.flags & SDL_RENDERER_ACCELERATED)) { - if (info.max_texture_width >= max_texture_width && - info.max_texture_height >= max_texture_height) { - best_index = i; - break; - } - } - } +// Seznam akceptovatelných formátů odpovídajících RGBA8888 (v různém pořadí) +constexpr Uint32 acceptable_formats[] = { + SDL_PIXELFORMAT_RGBA8888, + SDL_PIXELFORMAT_ARGB8888, + SDL_PIXELFORMAT_BGRA8888, + SDL_PIXELFORMAT_ABGR8888, + + SDL_PIXELFORMAT_RGBA4444, + SDL_PIXELFORMAT_ARGB4444, + SDL_PIXELFORMAT_BGRA4444, + SDL_PIXELFORMAT_ABGR4444, + + SDL_PIXELFORMAT_ARGB2101010, +}; + +constexpr bool is_acceptable_format(Uint32 format) { + for (size_t i = 0; i < sizeof(acceptable_formats)/sizeof(acceptable_formats[0]); ++i) { + if (format == acceptable_formats[i]) { + return true; } } - return best_index; + return false; +} + +static Uint32 find_best_rgba_like_format(SDL_Renderer* renderer) { + SDL_RendererInfo info; + if (SDL_GetRendererInfo(renderer, &info) != 0) { + return 0; + } + + if ((info.max_texture_width != 0 && info.max_texture_width < 640) || + (info.max_texture_height!= 0 && info.max_texture_height < 480)) return 0; + + for (Uint32 i = 0; i < info.num_texture_formats; ++i) { + Uint32 fmt = info.texture_formats[i]; + if (is_acceptable_format(fmt)) { + return fmt; + } + } + + return 0; } void SDLContext::init_video(const VideoConfig &config, const char *title) { @@ -274,6 +293,7 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { std::atomic done = false; std::exception_ptr e; std::string_view stage; + std::string rname; _render_thread = std::jthread([&](std::stop_token stp){ bool err = false; try { @@ -286,35 +306,44 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { handle_sdl_error("SDL Error create window"); } - stage = "renderer"; - int rindex = -1; - if (rindex == -1) { - _texture_render_format = SDL_PIXELFORMAT_RGBA8888; - rindex = select_best_rendered_driver(640,480, _texture_render_format, config.composer & SDL_RENDERER_SOFTWARE); - } - if (rindex == -1) { - _texture_render_format = SDL_PIXELFORMAT_ARGB8888; - rindex = select_best_rendered_driver(640,480, _texture_render_format, config.composer & SDL_RENDERER_SOFTWARE); - } - if (rindex == -1){ - _texture_render_format = SDL_PIXELFORMAT_ARGB8888; - rindex = select_best_rendered_driver(640,480, _texture_render_format, true); - } - if (rindex == -1){ - _texture_render_format = SDL_PIXELFORMAT_RGBA8888; - rindex = select_best_rendered_driver(640,480, _texture_render_format, true); - } - if (rindex == -1) { - throw std::runtime_error("Unsupported graphic driver, (software fallback also failed)"); - } - - _window.reset(window); - SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), rindex, config.composer); - if (!renderer) { - handle_sdl_error("Failed to create composer"); + + auto composer = config.composer; + + stage = "renderer"; + + while (true) { + + SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), -1, composer); + if (!renderer) { + if (config.composer & SDL_RENDERER_SOFTWARE) { + handle_sdl_error("Failed to create composer"); + } else { + composer |= SDL_RENDERER_SOFTWARE; + continue; + } + } + + _texture_render_format = find_best_rgba_like_format(renderer); + if (_texture_render_format == 0) { + if (composer & SDL_RENDERER_SOFTWARE) { + throw std::runtime_error("Failed to create composer, failed software fallback"); + } else { + SDL_DestroyRenderer(renderer); + composer |= SDL_RENDERER_SOFTWARE; + continue; + } + } + _renderer.reset(renderer); + break; } + + SDL_RendererInfo rinfo; + SDL_GetRendererInfo(_renderer.get(), &rinfo); + + rname = rinfo.name; + stage = "pixel format"; _main_pixel_format.reset(SDL_AllocFormat(_texture_render_format)); @@ -322,9 +351,6 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { handle_sdl_error("Failed to create texture format"); } - SDL_RendererInfo rinfo; - SDL_GetRendererInfo(renderer, &rinfo); - if (istrcmp(config.scale_quality, "auto") == 0) { if (rinfo.flags & SDL_RENDERER_ACCELERATED) { SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); @@ -334,12 +360,11 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { } - _renderer.reset(renderer); stage = "main render target"; - SDL_Texture *texture = SDL_CreateTexture(renderer, _texture_render_format, SDL_TEXTUREACCESS_STREAMING, 640, 480); + SDL_Texture *texture = SDL_CreateTexture(_renderer.get(), _texture_render_format, SDL_TEXTUREACCESS_STREAMING, 640, 480); if (!texture) { handle_sdl_error("Failed to create render target"); } @@ -349,13 +374,13 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { stage = "secondary render target"; - texture = SDL_CreateTexture(renderer, _texture_render_format, SDL_TEXTUREACCESS_STREAMING, 640, 480); + texture = SDL_CreateTexture(_renderer.get(), _texture_render_format, SDL_TEXTUREACCESS_STREAMING, 640, 480); if (!texture) { handle_sdl_error("Failed to create second render target"); } SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); _texture2.reset(texture); - + stage = "all done"; _visible_texture = _texture.get(); @@ -391,6 +416,7 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { std::throw_with_nested( std::runtime_error(std::string("Oops! The application couldn't start properly (problem during SDL initialization). Stage: [") .append(stage).append("]\n\n" + "Renderer: ").append(rname).append("\n\n" "This may be caused by outdated or missing graphics or audio drivers." "To fix this, please try the following:\n- Restart your computer and try again\n- " "Make sure your graphics and sound drivers are up to date."))); @@ -435,6 +461,52 @@ int SDLContext::adjust_deadzone(int v, short deadzone) { return 0; } +template +constexpr Uint32 shift_bits_5(Uint32 val) { + if constexpr(shift > 0) { + return val << shift | shift_bits_5(val); + } else if constexpr(shift < 0) { + return val >> (-shift); + } else { + return val; + } +} + + +template +void SDLContext::convert_bitmap(const void *pixels, SDL_Rect rect, int pitch) { + + constexpr auto RShift = FormatMapping::RShift; + constexpr auto GShift = FormatMapping::GShift; + constexpr auto BShift = FormatMapping::BShift; + constexpr auto AShift = FormatMapping::AShift; + constexpr auto RBits = FormatMapping::RBits; + constexpr auto GBits = FormatMapping::GBits; + constexpr auto BBits = FormatMapping::BBits; + constexpr auto ABits = FormatMapping::ABits; + + const Uint16 *src = static_cast(pixels); + auto trg = converted_pixels.data(); + for (int y = 0; y < rect.h; ++y) { + for (int x = 0; x < rect.w; ++x) { + Uint16 pixel = src[x]; + Uint32 a = (pixel & 0x8000) ? 0 : 0x1F; + Uint32 r = ((pixel >> 10) & 0x1F); + Uint32 g = ((pixel >> 5) & 0x1F); + Uint32 b = (pixel & 0x1F); + + r = shift_bits_5(r); + g = shift_bits_5(g); + b = shift_bits_5(b); + a = shift_bits_5(a); + + trg[x] = (r << RShift) | (g << GShift) | (b << BShift) | (a << AShift); + } + trg += rect.w; + src = src + pitch / 2; + } +} + void SDLContext::update_texture_with_conversion(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch) { SDL_Rect r; @@ -450,55 +522,36 @@ void SDLContext::update_texture_with_conversion(SDL_Texture *texture, const SDL_ converted_pixels.resize(r.w * r.h); switch (_texture_render_format) { - case SDL_PIXELFORMAT_RGBA8888: { - const Uint16* src = static_cast(pixels); - auto trg = converted_pixels.data(); - for (int y = 0; y < r.h; ++y) { - for (int x = 0; x < r.w; ++x) { - Uint16 pixel = src[x]; - Uint32 a = (pixel & 0x8000) ? 0 : 0xFF; - Uint32 r = ((pixel >> 10) & 0x1F); - Uint32 g = ((pixel >> 5) & 0x1F); - Uint32 b = (pixel & 0x1F); - r = (r << 3) | (r >> 2); - g = (g << 3) | (g >> 2); - b = (b << 3) | (b >> 2); - if constexpr (std::endian::native == std::endian::little) { - trg[x] = (r << 24) | (g << 16) | (b << 8) | a; - } else { - trg[x] = (r) | (g << 8) | (b << 16) | (a << 24); - } - } - trg += r.w; - src = src + pitch/2; - } - } - break; - case SDL_PIXELFORMAT_ARGB8888: { - const Uint16* src = static_cast(pixels); - auto trg = converted_pixels.data(); - for (int y = 0; y < r.h; ++y) { - for (int x = 0; x < r.w; ++x) { - Uint16 pixel = src[x]; - Uint32 a = (pixel & 0x8000) ? 0 : 0xFF; - Uint32 r = ((pixel >> 10) & 0x1F); - Uint32 g = ((pixel >> 5) & 0x1F); - Uint32 b = (pixel & 0x1F); - r = (r << 3) | (r >> 2); - g = (g << 3) | (g >> 2); - b = (b << 3) | (b >> 2); - if constexpr (std::endian::native == std::endian::little) { - trg[x] = (a << 24) | (r << 16) | (g << 8) | b; - } else { - trg[x] = (a) | (r << 8) | (g << 16) | (b << 24); - } - } - trg += r.w; - src = src + pitch/2; - } - } - break; + case SDL_PIXELFORMAT_ABGR8888: + convert_bitmap(pixels, r, pitch);break; + case SDL_PIXELFORMAT_ARGB8888: + convert_bitmap(pixels, r, pitch);break; + case SDL_PIXELFORMAT_ARGB2101010: + convert_bitmap(pixels, r, pitch);break; + case SDL_PIXELFORMAT_RGBA8888: + convert_bitmap(pixels, r, pitch);break; + case SDL_PIXELFORMAT_BGRA8888: + convert_bitmap(pixels, r, pitch);break; + case SDL_PIXELFORMAT_ABGR4444: + convert_bitmap(pixels, r, pitch);break; + case SDL_PIXELFORMAT_ARGB4444: + convert_bitmap(pixels, r, pitch);break; + case SDL_PIXELFORMAT_BGRA4444: + convert_bitmap(pixels, r, pitch);break; + case SDL_PIXELFORMAT_RGBA4444: + convert_bitmap(pixels, r, pitch);break; + case SDL_PIXELFORMAT_ABGR1555: + convert_bitmap(pixels, r, pitch);break; + case SDL_PIXELFORMAT_ARGB1555: + convert_bitmap(pixels, r, pitch);break; + case SDL_PIXELFORMAT_RGBA5551: + convert_bitmap(pixels, r, pitch);break; + case SDL_PIXELFORMAT_BGRA5551: + convert_bitmap(pixels, r, pitch);break; + default: + return; } + if (SDL_UpdateTexture(texture, &r, converted_pixels.data(), r.w * 4) < 0) { handle_sdl_error("Failed to update texture"); } @@ -879,7 +932,7 @@ void SDLContext::update_screen(bool force_refresh) { SDL_SetTextureBlendMode(_mouse.get(), SDL_BLENDMODE_BLEND); _mouse_rect.w = r.w; _mouse_rect.h = r.h; - update_texture_with_conversion(_mouse.get(), NULL, data.data(), r.w*2); + update_texture_with_conversion(_mouse.get(), NULL, data.data(), r.w*2); } break; case DisplayRequest::hide_mouse_cursor: { diff --git a/platform/sdl/sdl_context.h b/platform/sdl/sdl_context.h index a13c84c..d3cd613 100644 --- a/platform/sdl/sdl_context.h +++ b/platform/sdl/sdl_context.h @@ -316,4 +316,7 @@ protected: const SDL_Rect * rect, const void *pixels, int pitch); + template + void convert_bitmap(const void *pixels, SDL_Rect r, int pitch); + }; diff --git a/version.in.h b/version.in.h new file mode 100644 index 0000000..0f14310 --- /dev/null +++ b/version.in.h @@ -0,0 +1,5 @@ +#pragma once + +#define SKELDAL_VERSION "@APP_VERSION@" + + From 4ab5f37d82cb532f55f7e2106045f7690cd027f6 Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Sun, 4 May 2025 19:13:58 +0200 Subject: [PATCH 24/24] fix mapping for 1555 --- platform/sdl/format_mapping.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/platform/sdl/format_mapping.h b/platform/sdl/format_mapping.h index 1c2ccc8..9ac5170 100644 --- a/platform/sdl/format_mapping.h +++ b/platform/sdl/format_mapping.h @@ -1,9 +1,11 @@ #pragma once -#include +#include template -struct FormatMapping; +struct FormatMapping { + static_assert(false, "Unsupported pixel format"); +}; template<> struct FormatMapping { @@ -145,9 +147,9 @@ struct FormatMapping { static constexpr int BShift = 0; static constexpr int AShift = 15; - static constexpr int RBits = 8; - static constexpr int GBits = 8; - static constexpr int BBits = 8; + static constexpr int RBits = 5; + static constexpr int GBits = 5; + static constexpr int BBits = 5; static constexpr int ABits = 1; };