diff --git a/game/dialogy.c b/game/dialogy.c index 4172f80..d9b8f7d 100644 --- a/game/dialogy.c +++ b/game/dialogy.c @@ -339,7 +339,7 @@ static char *transfer_text(const char *source,char *target) if (source==NULL) { char buff[256]; - closemode(); + sprintf(buff,"%s\r\nChybny rod nebo maly pocet tvaru od jednoho slova",orgn); error(buff); exit(-1); @@ -353,7 +353,7 @@ static char *transfer_text(const char *source,char *target) if (source==NULL) { char buff[256]; - closemode(); + sprintf(buff,"%s\r\nOcekava se ]",orgn); error(buff); exit(-1); diff --git a/game/enemy.c b/game/enemy.c index d2a2a1f..6707bce 100644 --- a/game/enemy.c +++ b/game/enemy.c @@ -243,7 +243,7 @@ static void register_mob_graphics(int num,char *name_part,const char *anims,cons if (*seq=='\r') { char buff[256]; - closemode(); + sprintf(buff,"Soubor sekvence %s obsahuje chybne udaje nebo je sekvence je moc kratka\n", fulname); display_error(buff); exit(0); @@ -387,7 +387,7 @@ void load_enemies(short *data,int size,int *grptr,const TMOB *template,int32_t t if (mobs[i].speed<1) { char buff[256]; - closemode(); + sprintf(buff,"Nestvura cislo #%d (%s) je spatne definovana (rychlost)",i,mobs[i].name); display_error(buff); exit(1); @@ -1464,7 +1464,7 @@ void mob_strelba(TMOB *p) for(i=0;isector>=mapsize) { char buff[256]; - closemode(); + sprintf(buff,"Potvora v neexistujicim sektoru (%d, %d) ",num,p->sector); display_error(buff); exit(1); diff --git a/game/gamesave.c b/game/gamesave.c index f87b217..c9a4c67 100644 --- a/game/gamesave.c +++ b/game/gamesave.c @@ -93,7 +93,6 @@ static int unable_open_temp(char *c) char d[]="Unable to open the file : ",*e; concat(e,d,c); - closemode(); display_error(e); SEND_LOG("(SAVELOAD) Open temp error detected (%s)",c); exit(1); @@ -104,7 +103,6 @@ static void unable_write_temp(char *c) char d[]="Unable to write to the temp file : ",*e; concat(e,d,c); - closemode(); display_error(e); SEND_LOG("(SAVELOAD) Open temp error detected (%s)",c); exit(1); diff --git a/game/globmap.c b/game/globmap.c index 38fa16e..a2051bb 100644 --- a/game/globmap.c +++ b/game/globmap.c @@ -172,7 +172,7 @@ static void error(const char *text) sprintf(popis,"Chyba v souboru "GLOBMAP" na radce %d.\r\n%s",linecounter,text); SEND_LOG("(ERROR) %s : %s",popis,text); - closemode(); + display_error(popis); exit(0); } diff --git a/game/inv.c b/game/inv.c index 27d16b6..f0e096f 100644 --- a/game/inv.c +++ b/game/inv.c @@ -130,7 +130,7 @@ void init_item_sounds(int *ptr) c=(char *)ablock(H_SOUND_DAT)+sound_table[glob_items[i].sound-1]; if (c==NULL || c[0]==0) { - closemode(); + puts("Invalid Sound Table integrity - rebuild SOUND.DAT using MapEdit"); exit(1); } @@ -171,7 +171,7 @@ void load_items() f=fopen_icase(name,"rb"); if (f==NULL) { - closemode(); + display_error("Selhalo otevreni souboru ITEMS.DAT. Zkotroluj zda vubec existuje."); exit(0); } @@ -955,7 +955,7 @@ void definuj_postavy() } if (r!=1) { - closemode(); + display_error("Error in file POSTAVY.DAT. May be missing a parameter in some definition."); exit(0); } diff --git a/game/kniha.c b/game/kniha.c index 8dbbaa4..7562c02 100644 --- a/game/kniha.c +++ b/game/kniha.c @@ -526,7 +526,6 @@ static void seek_section(TMPFILE_RD *txt,int sect_number) c=0; } while (i!=EOF); - closemode(); { char buff[256]; sprintf(buff,"Nemohu najit odstavec s cislem %d.",sect_number); diff --git a/game/menu.c b/game/menu.c index 0721add..f819f68 100644 --- a/game/menu.c +++ b/game/menu.c @@ -407,7 +407,7 @@ char *get_next_title(signed char control,const char *filename) if (titles==NULL) { char popis[300]; - closemode(); + sprintf(popis,"Soubor nenalezen: %s nebo %s\n",path,path2); display_error(popis); exit(1); diff --git a/game/realgame.c b/game/realgame.c index e946bd5..7a68d17 100644 --- a/game/realgame.c +++ b/game/realgame.c @@ -417,7 +417,6 @@ int load_map(const char *filename) for(r=0;r buffer2nd; static uint16_t *render_target; static uint16_t screen_pitch = 640; -char game_display_init(const INI_CONFIG_SECTION *display_section, const char *title) { +int game_display_init(const INI_CONFIG_SECTION *display_section, + const char *title, + int (*game_thread)(va_list), ...) { + + va_list args; + va_start(args,game_thread); SDLContext::VideoConfig cfg = {}; const char *aspect_str; @@ -43,19 +48,19 @@ char game_display_init(const INI_CONFIG_SECTION *display_section, const char *ti cfg.cursor_size = ini_get_int(display_section, "cursor_size", 100)*0.01f; screen_pitch = 640; - get_sdl_global_context().init_video(cfg, title); - screen_buffer = std::make_unique(screen_pitch*480); - buffer2nd = std::make_unique(screen_pitch*480); - std::fill(screen_buffer.get(), screen_buffer.get()+screen_pitch*480,0); - render_target = screen_buffer.get(); - return 1; + + + return get_sdl_global_context().init_window(cfg, title, [&]{ + screen_buffer = std::make_unique(screen_pitch*480); + buffer2nd = std::make_unique(screen_pitch*480); + std::fill(screen_buffer.get(), screen_buffer.get()+screen_pitch*480,0); + render_target = screen_buffer.get(); + return game_thread(args); + }); } -void game_display_close(void) { - get_sdl_global_context().close_video(); -} uint16_t *GetScreenAdr() { return render_target; diff --git a/platform/sdl/BGraph2.h b/platform/sdl/BGraph2.h index aabdbb3..c143fab 100644 --- a/platform/sdl/BGraph2.h +++ b/platform/sdl/BGraph2.h @@ -1,4 +1,5 @@ #include +#include #include "../config.h" #include @@ -19,8 +20,11 @@ void RedirectScreen(uint16_t *newaddr); void RestoreScreen(void); void RedirectScreenBufferSecond(void); -char game_display_init(const INI_CONFIG_SECTION *display_section, const char *title); -void game_display_close(void); + +///Initializes display - in current thread (main thread), starts game thread. Display is closed when thread finishes +int game_display_init(const INI_CONFIG_SECTION *display_section, + const char *title, + int (*game_thread)(va_list), ...); void game_display_update_rect(unsigned short x,unsigned short y,unsigned short xs,unsigned short ys); char game_display_is_quit_requested(); void game_display_cancel_quit_request(); diff --git a/platform/sdl/sdl_context.cpp b/platform/sdl/sdl_context.cpp index 01a1d2a..5cbc5a3 100644 --- a/platform/sdl/sdl_context.cpp +++ b/platform/sdl/sdl_context.cpp @@ -268,14 +268,12 @@ static Uint32 find_best_rgba_like_format(SDL_Renderer* renderer) { return 0; } -void SDLContext::init_video(const VideoConfig &config, const char *title) { +int SDLContext::init_window(const VideoConfig &config, const char *title, std::function game_thread) { static Uint32 update_request_event = SDL_RegisterEvents(1); static Uint32 refresh_request_event = SDL_RegisterEvents(1); _update_request_event = update_request_event; _refresh_request = refresh_request_event; - assert(!_render_thread.joinable()); - int width = config.window_width; int height = config.window_height; @@ -294,142 +292,132 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) { std::exception_ptr e; std::string_view stage; std::string rname; - _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)); + int exit_code = 0; + 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)); - if (!window) { - handle_sdl_error("SDL Error create window"); - } - - _window.reset(window); - - 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)); - if (!_main_pixel_format) { - handle_sdl_error("Failed to create texture format"); - } - - if (istrcmp(config.scale_quality, "auto") == 0) { - if (rinfo.flags & SDL_RENDERER_ACCELERATED) { - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); - } - } else { - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, config.scale_quality); - } - - - - stage = "main render target"; - - - 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"); - } - - SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); - _texture.reset(texture); - - stage = "secondary render target"; - - 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(); - _hidden_texture = _texture2.get(); - } catch (...) { - e = std::current_exception(); - err = true; + if (!window) { + handle_sdl_error("SDL Error create window"); } - done = true; - done.notify_all(); - if (!err) { + _window.reset(window); + + 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)); + if (!_main_pixel_format) { + handle_sdl_error("Failed to create texture format"); + } + + if (istrcmp(config.scale_quality, "auto") == 0) { + if (rinfo.flags & SDL_RENDERER_ACCELERATED) { + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); + } + } else { + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, config.scale_quality); + } + + + + stage = "main render target"; + + + 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"); + } + + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + _texture.reset(texture); + + stage = "secondary render target"; + + 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(); + _hidden_texture = _texture2.get(); + + std::stop_source stop_src; + + std::thread main_thrd([&]{ try { - SDL_ShowCursor(SDL_DISABLE); - event_loop(stp); + exit_code = game_thread(); } catch (...) { - SDL_ShowCursor(SDL_ENABLE); - crash_sdl_exception(); + e = std::current_exception(); } - } - _texture.reset(); - _texture2.reset(); - _renderer.reset(); - _window.reset(); - }); + stop_src.request_stop(); + }); + main_thrd.detach(); + SDL_ShowCursor(SDL_DISABLE); + event_loop(stop_src.get_token()); + SDL_ShowCursor(SDL_ENABLE); - done.wait(false); - if (e) { - _render_thread.join(); - try { - std::rethrow_exception(e); - } catch (...) { - 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."))); - } + } catch (...) { + crash_sdl_exception(); + return -1; } + _texture.reset(); + _texture2.reset(); + _renderer.reset(); + _window.reset(); + + if (e) { + std::rethrow_exception(e); + } + return exit_code; +} + +void SDLContext::init_video(const VideoConfig &config, const char *title) { } -void SDLContext::close_video() { - _render_thread.request_stop(); - _render_thread.join(); -} int SDLContext::check_axis_dir(int &cooldown, int value) { int range = 0x8000-_jcontrol_map.walk_deadzone; diff --git a/platform/sdl/sdl_context.h b/platform/sdl/sdl_context.h index d3cd613..50bd164 100644 --- a/platform/sdl/sdl_context.h +++ b/platform/sdl/sdl_context.h @@ -98,13 +98,14 @@ public: int freq; }; + int init_window(const VideoConfig &config, const char *title, std::function game_thread); + void init_video(const VideoConfig &config, const char *title); void set_window_icon(const void *icon_data, size_t icon_size); void configure_controller(const JoystickConfig &cfg); - void close_video(); AudioInfo init_audio(const AudioConfig &config, SDL_AudioCallback cb, void *cb_ctx); void pause_audio(bool pause); @@ -272,7 +273,6 @@ protected: Uint32 _update_request_event; Uint32 _refresh_request; - std::jthread _render_thread; void event_loop(std::stop_token stp);