SLD context now running in main thread (for better compatibility)

This commit is contained in:
Ondřej Novák 2025-08-28 12:17:24 +02:00
parent 96eaeb4851
commit e0aa5096ba
16 changed files with 259 additions and 275 deletions

View file

@ -339,7 +339,7 @@ static char *transfer_text(const char *source,char *target)
if (source==NULL) if (source==NULL)
{ {
char buff[256]; char buff[256];
closemode();
sprintf(buff,"%s\r\nChybny rod nebo maly pocet tvaru od jednoho slova",orgn); sprintf(buff,"%s\r\nChybny rod nebo maly pocet tvaru od jednoho slova",orgn);
error(buff); error(buff);
exit(-1); exit(-1);
@ -353,7 +353,7 @@ static char *transfer_text(const char *source,char *target)
if (source==NULL) if (source==NULL)
{ {
char buff[256]; char buff[256];
closemode();
sprintf(buff,"%s\r\nOcekava se ]",orgn); sprintf(buff,"%s\r\nOcekava se ]",orgn);
error(buff); error(buff);
exit(-1); exit(-1);

View file

@ -243,7 +243,7 @@ static void register_mob_graphics(int num,char *name_part,const char *anims,cons
if (*seq=='\r') if (*seq=='\r')
{ {
char buff[256]; char buff[256];
closemode();
sprintf(buff,"Soubor sekvence %s obsahuje chybne udaje nebo je sekvence je moc kratka\n", fulname); sprintf(buff,"Soubor sekvence %s obsahuje chybne udaje nebo je sekvence je moc kratka\n", fulname);
display_error(buff); display_error(buff);
exit(0); 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) if (mobs[i].speed<1)
{ {
char buff[256]; char buff[256];
closemode();
sprintf(buff,"Nestvura cislo #%d (%s) je spatne definovana (rychlost)",i,mobs[i].name); sprintf(buff,"Nestvura cislo #%d (%s) je spatne definovana (rychlost)",i,mobs[i].name);
display_error(buff); display_error(buff);
exit(1); exit(1);
@ -1464,7 +1464,7 @@ void mob_strelba(TMOB *p)
for(i=0;i<item_count;i++) if (glob_items[i].umisteni==PL_SIP && glob_items[i].druh==TYP_VRHACI) break; for(i=0;i<item_count;i++) if (glob_items[i].umisteni==PL_SIP && glob_items[i].druh==TYP_VRHACI) break;
if (i==item_count) if (i==item_count)
{ {
closemode();
display_error("Nestvura nemuze strilet. Neni nadefinovan obekt sipu"); display_error("Nestvura nemuze strilet. Neni nadefinovan obekt sipu");
exit(1); exit(1);
} }
@ -1640,7 +1640,7 @@ void mobs_live(int num)
if (p->sector>=mapsize) if (p->sector>=mapsize)
{ {
char buff[256]; char buff[256];
closemode();
sprintf(buff,"Potvora v neexistujicim sektoru (%d, %d) ",num,p->sector); sprintf(buff,"Potvora v neexistujicim sektoru (%d, %d) ",num,p->sector);
display_error(buff); display_error(buff);
exit(1); exit(1);

View file

@ -93,7 +93,6 @@ static int unable_open_temp(char *c)
char d[]="Unable to open the file : ",*e; char d[]="Unable to open the file : ",*e;
concat(e,d,c); concat(e,d,c);
closemode();
display_error(e); display_error(e);
SEND_LOG("(SAVELOAD) Open temp error detected (%s)",c); SEND_LOG("(SAVELOAD) Open temp error detected (%s)",c);
exit(1); exit(1);
@ -104,7 +103,6 @@ static void unable_write_temp(char *c)
char d[]="Unable to write to the temp file : ",*e; char d[]="Unable to write to the temp file : ",*e;
concat(e,d,c); concat(e,d,c);
closemode();
display_error(e); display_error(e);
SEND_LOG("(SAVELOAD) Open temp error detected (%s)",c); SEND_LOG("(SAVELOAD) Open temp error detected (%s)",c);
exit(1); exit(1);

View file

@ -172,7 +172,7 @@ static void error(const char *text)
sprintf(popis,"Chyba v souboru "GLOBMAP" na radce %d.\r\n%s",linecounter,text); sprintf(popis,"Chyba v souboru "GLOBMAP" na radce %d.\r\n%s",linecounter,text);
SEND_LOG("(ERROR) %s : %s",popis,text); SEND_LOG("(ERROR) %s : %s",popis,text);
closemode();
display_error(popis); display_error(popis);
exit(0); exit(0);
} }

View file

@ -130,7 +130,7 @@ void init_item_sounds(int *ptr)
c=(char *)ablock(H_SOUND_DAT)+sound_table[glob_items[i].sound-1]; c=(char *)ablock(H_SOUND_DAT)+sound_table[glob_items[i].sound-1];
if (c==NULL || c[0]==0) if (c==NULL || c[0]==0)
{ {
closemode();
puts("Invalid Sound Table integrity - rebuild SOUND.DAT using MapEdit"); puts("Invalid Sound Table integrity - rebuild SOUND.DAT using MapEdit");
exit(1); exit(1);
} }
@ -171,7 +171,7 @@ void load_items()
f=fopen_icase(name,"rb"); f=fopen_icase(name,"rb");
if (f==NULL) if (f==NULL)
{ {
closemode();
display_error("Selhalo otevreni souboru ITEMS.DAT. Zkotroluj zda vubec existuje."); display_error("Selhalo otevreni souboru ITEMS.DAT. Zkotroluj zda vubec existuje.");
exit(0); exit(0);
} }
@ -955,7 +955,7 @@ void definuj_postavy()
} }
if (r!=1) if (r!=1)
{ {
closemode();
display_error("Error in file POSTAVY.DAT. May be missing a parameter in some definition."); display_error("Error in file POSTAVY.DAT. May be missing a parameter in some definition.");
exit(0); exit(0);
} }

View file

@ -526,7 +526,6 @@ static void seek_section(TMPFILE_RD *txt,int sect_number)
c=0; c=0;
} }
while (i!=EOF); while (i!=EOF);
closemode();
{ {
char buff[256]; char buff[256];
sprintf(buff,"Nemohu najit odstavec s cislem %d.",sect_number); sprintf(buff,"Nemohu najit odstavec s cislem %d.",sect_number);

View file

@ -407,7 +407,7 @@ char *get_next_title(signed char control,const char *filename)
if (titles==NULL) if (titles==NULL)
{ {
char popis[300]; char popis[300];
closemode();
sprintf(popis,"Soubor nenalezen: %s nebo %s\n",path,path2); sprintf(popis,"Soubor nenalezen: %s nebo %s\n",path,path2);
display_error(popis); display_error(popis);
exit(1); exit(1);

View file

@ -417,7 +417,6 @@ int load_map(const char *filename)
for(r=0;r<mapsize*4;r++) flag_map[r]=(char)map_sides[r].flags; for(r=0;r<mapsize*4;r++) flag_map[r]=(char)map_sides[r].flags;
if (!doNotLoadMapState && load_map_state()==-2) if (!doNotLoadMapState && load_map_state()==-2)
{ {
closemode();
display_error("Bug in temp file. Please purge some status blocks in last load savegame file."); display_error("Bug in temp file. Please purge some status blocks in last load savegame file.");
exit(0); exit(0);
} }

View file

@ -809,7 +809,7 @@ void cti_texty(void)
if ((err=load_string_list_ex(&texty,path))!=0) if ((err=load_string_list_ex(&texty,path))!=0)
{ {
char buff[256]; char buff[256];
closemode();
switch (err) switch (err)
{ {
case -1:sprintf(buff,"Can't load string table. File %s has not been found\n",path);break; case -1:sprintf(buff,"Can't load string table. File %s has not been found\n",path);break;
@ -870,7 +870,7 @@ void error_exception(EVENT_MSG *msg,void **unused)
SEND_LOG("(ERROR) Log: Sector %d Direction %d",viewsector,viewdir); SEND_LOG("(ERROR) Log: Sector %d Direction %d",viewsector,viewdir);
SEND_LOG("(ERROR) Log: Battle: %d Select_player %d",battle,select_player); SEND_LOG("(ERROR) Log: Battle: %d Select_player %d",battle,select_player);
closemode();
display_error("error_exception called"); display_error("error_exception called");
} }
@ -983,11 +983,96 @@ void show_loading_picture(char *filename)
ablock_free(p); ablock_free(p);
} }
typedef struct {
va_list _args;
} Args ;
void init_skeldal(const INI_CONFIG *cfg) int init_skeldal_thread(va_list args) {
const INI_CONFIG *cfg = va_arg(args, const INI_CONFIG *);
int (*game_thread)(va_list) = va_arg(args, int (*)(va_list));
va_list *game_args = va_arg(args, va_list *);
showview = game_display_update_rect;
game_display_set_icon(getWindowIcon(), getWindowIconSize());
init_joystick(ini_section_open(cfg, "controller"));
general_engine_init();
atexit(done_skeldal);
init_DDL_manager();
show_loading_picture("LOADING.HI");
if (lang_get_folder()) {
texty_knihy = build_pathname(2, lang_get_folder(), "book.txt");
if (!check_file_exists(texty_knihy)) {
texty_knihy=strdup(build_pathname(2,gpathtable[SR_MAP],"kniha.txt"));
} else {
texty_knihy=strdup(texty_knihy);
}
} else {
texty_knihy=strdup(build_pathname(2,gpathtable[SR_MAP],"kniha.txt"));
}
install_gui();
if (is_joystick_enabled()) {
show_joystick_info();
}
send_message(E_DONE,E_WATCH,timer);
send_message(E_DONE,E_IDLE,redraw_desktop_call);
send_message(E_ADD,E_TIMER,timming);
send_message(E_ADD,E_WATCH,user_timer);
send_message(E_ADD,E_MOUSE,ms_clicker);
send_message(E_ADD,E_KEYBOARD,global_kbd);
send_message(E_ADD,E_PRGERROR,error_exception);
add_to_timer(TM_BACK_MUSIC,5,-1,back_music);
add_game_window();
game_sound_init_device(ini_section_open(cfg, "audio"));
start_mixing();
int verr;
if ((verr=init_mysky())!=0)
{
puts(texty[174-verr]);
SEND_LOG("(ERROR) %s (%d)",texty[174-verr],verr);
exit(0);
}
// hranice_mysky(0,0,639,479);
mouse_set_default(H_MS_DEFAULT);
ukaz_mysku();
set_end_of_song_callback(end_of_song_callback, NULL);
kouzla_init();
load_items();
load_shops();
memset(&loadlevel,0,sizeof(loadlevel));
loadlevel.eflags = 0xFF;
int r = game_thread(*game_args);
va_end(args);
return r;
}
int init_skeldal(const INI_CONFIG *cfg, void (*game_thread)(va_list), ...)
{ {
boldcz=LoadDefaultFont(); boldcz=LoadDefaultFont();
cti_texty(); cti_texty();
@ -995,84 +1080,19 @@ void init_skeldal(const INI_CONFIG *cfg)
init_events(); init_events();
steam_init(); steam_init();
va_list args;
va_start(args,game_thread);
char verr = game_display_init(ini_section_open(cfg, "video"), "Skeldal"); int verr = game_display_init(ini_section_open(cfg, "video"), "Skeldal",
if (!verr) init_skeldal_thread, cfg, game_thread, &args);
if (verr < 0)
{ {
display_error("Error game_display_init %d", verr); display_error("Error game_display_init %d", verr);
exit(1); return 1;
} }
showview = game_display_update_rect; return verr;
game_display_set_icon(getWindowIcon(), getWindowIconSize());
init_joystick(ini_section_open(cfg, "controller"));
general_engine_init();
atexit(done_skeldal);
init_DDL_manager();
show_loading_picture("LOADING.HI");
if (lang_get_folder()) {
texty_knihy = build_pathname(2, lang_get_folder(), "book.txt");
if (!check_file_exists(texty_knihy)) {
texty_knihy=strdup(build_pathname(2,gpathtable[SR_MAP],"kniha.txt"));
} else {
texty_knihy=strdup(texty_knihy);
}
} else {
texty_knihy=strdup(build_pathname(2,gpathtable[SR_MAP],"kniha.txt"));
} }
install_gui();
if (is_joystick_enabled()) {
show_joystick_info();
}
send_message(E_DONE,E_WATCH,timer);
send_message(E_DONE,E_IDLE,redraw_desktop_call);
send_message(E_ADD,E_TIMER,timming);
send_message(E_ADD,E_WATCH,user_timer);
send_message(E_ADD,E_MOUSE,ms_clicker);
send_message(E_ADD,E_KEYBOARD,global_kbd);
send_message(E_ADD,E_PRGERROR,error_exception);
add_to_timer(TM_BACK_MUSIC,5,-1,back_music);
add_game_window();
game_sound_init_device(ini_section_open(cfg, "audio"));
start_mixing();
if ((verr=init_mysky())!=0)
{
closemode();
puts(texty[174-verr]);
SEND_LOG("(ERROR) %s (%d)",texty[174-verr],verr);
exit(0);
}
// hranice_mysky(0,0,639,479);
mouse_set_default(H_MS_DEFAULT);
ukaz_mysku();
set_end_of_song_callback(end_of_song_callback, NULL);
kouzla_init();
load_items();
load_shops();
memset(&loadlevel,0,sizeof(loadlevel));
loadlevel.eflags = 0xFF;
}
void wire_main_functs(); void wire_main_functs();
void unwire_main_functs(void) void unwire_main_functs(void)
@ -1376,7 +1396,7 @@ static void game_big_circle(char enforced)
if (err) if (err)
{ {
char buff[256]; char buff[256];
closemode();
switch (err) switch (err)
{ {
case -1: sprintf(buff,"Error while loading map (%s) ....file not found\n",s);break; case -1: sprintf(buff,"Error while loading map (%s) ....file not found\n",s);break;
@ -1713,6 +1733,15 @@ int skeldal_gen_string_table_entry_point(const SKELDAL_CONFIG *start_cfg, const
return 0; return 0;
} }
void skeldal_entry_point_thread() {
int start_task = add_task(65536,start);
escape();
term_task_wait(start_task);
return;
}
int skeldal_entry_point(const SKELDAL_CONFIG *start_cfg) int skeldal_entry_point(const SKELDAL_CONFIG *start_cfg)
{ {
def_mman_group_table(gpathtable); def_mman_group_table(gpathtable);
@ -1758,20 +1787,11 @@ int skeldal_entry_point(const SKELDAL_CONFIG *start_cfg)
purge_temps(1); purge_temps(1);
clrscr(); clrscr();
init_skeldal(cfg); int r = init_skeldal(cfg, skeldal_entry_point_thread);
int start_task = add_task(65536,start);
escape();
term_task_wait(start_task);
closemode();
ini_close(cfg); ini_close(cfg);
return r;
return 0;
} }

View file

@ -18,7 +18,6 @@ int cur_event_number;
static void event_error(char *text,int number) static void event_error(char *text,int number)
{ {
char buff[256]; char buff[256];
closemode();
sprintf(buff,"%s\n Specproc num: %d\n",text,number); sprintf(buff,"%s\n Specproc num: %d\n",text,number);
display_error(buff); display_error(buff);
exit(1); exit(1);

View file

@ -100,17 +100,6 @@ void showview_lo(word x,word y,word xs,word ys);
void outtext(const char *text); void outtext(const char *text);
void outtext_ex(const char *text, int space); void outtext_ex(const char *text, int space);
void outtext_w_nl(const char *text); void outtext_w_nl(const char *text);
int initmode(const INI_CONFIG_SECTION *, const char *app_name);
int initmode32(void);
int initmode32b(void);
int initmode256(void *paletefile);
int initmode256b(void *paletefile);
int initmode_lo(void *paletefile);
int initmode16(void *paletefile);
int initmode64(void *paletefile);
int initmode64b(void *paletefile);
void *create_hixlat(void);
void closemode(void);
void line32(word x1,word y1, word x2, word y2); void line32(word x1,word y1, word x2, word y2);
void position(word x,word y); void position(word x,word y);
void show_ms_cursor(integer x,integer y); void show_ms_cursor(integer x,integer y);

View file

@ -328,14 +328,6 @@ void switchvesabank(word bank)
} }
*/ */
int initmode(const INI_CONFIG_SECTION *display_config, const char *app_name)
{
if (!game_display_init(display_config, app_name)) return -1;
showview=game_display_update_rect;
screenstate=1;
return 0;
}
/* /*
int initmode256(void *paletefile) int initmode256(void *paletefile)
@ -435,15 +427,6 @@ int initmode_lo(void *paletefile)
} }
*/ */
void closemode()
{
if (screenstate)
{
game_display_close();
}
screenstate=0;
}
/* /*
static void showview64b(word x,word y,word xs,word ys) static void showview64b(word x,word y,word xs,word ys)

View file

@ -10,7 +10,12 @@ static std::unique_ptr<uint16_t[]> buffer2nd;
static uint16_t *render_target; static uint16_t *render_target;
static uint16_t screen_pitch = 640; 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 = {}; SDLContext::VideoConfig cfg = {};
const char *aspect_str; 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; cfg.cursor_size = ini_get_int(display_section, "cursor_size", 100)*0.01f;
screen_pitch = 640; screen_pitch = 640;
get_sdl_global_context().init_video(cfg, title);
screen_buffer = std::make_unique<uint16_t[]>(screen_pitch*480);
buffer2nd = std::make_unique<uint16_t[]>(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<uint16_t[]>(screen_pitch*480);
buffer2nd = std::make_unique<uint16_t[]>(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() { uint16_t *GetScreenAdr() {
return render_target; return render_target;

View file

@ -1,4 +1,5 @@
#include <stdint.h> #include <stdint.h>
#include <stdarg.h>
#include "../config.h" #include "../config.h"
#include <stddef.h> #include <stddef.h>
@ -19,8 +20,11 @@ void RedirectScreen(uint16_t *newaddr);
void RestoreScreen(void); void RestoreScreen(void);
void RedirectScreenBufferSecond(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); void game_display_update_rect(unsigned short x,unsigned short y,unsigned short xs,unsigned short ys);
char game_display_is_quit_requested(); char game_display_is_quit_requested();
void game_display_cancel_quit_request(); void game_display_cancel_quit_request();

View file

@ -268,14 +268,12 @@ static Uint32 find_best_rgba_like_format(SDL_Renderer* renderer) {
return 0; return 0;
} }
void SDLContext::init_video(const VideoConfig &config, const char *title) { int SDLContext::init_window(const VideoConfig &config, const char *title, std::function<int()> game_thread) {
static Uint32 update_request_event = SDL_RegisterEvents(1); static Uint32 update_request_event = SDL_RegisterEvents(1);
static Uint32 refresh_request_event = SDL_RegisterEvents(1); static Uint32 refresh_request_event = SDL_RegisterEvents(1);
_update_request_event = update_request_event; _update_request_event = update_request_event;
_refresh_request = refresh_request_event; _refresh_request = refresh_request_event;
assert(!_render_thread.joinable());
int width = config.window_width; int width = config.window_width;
int height = config.window_height; int height = config.window_height;
@ -294,142 +292,132 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) {
std::exception_ptr e; std::exception_ptr e;
std::string_view stage; std::string_view stage;
std::string rname; std::string rname;
_render_thread = std::jthread([&](std::stop_token stp){ int exit_code = 0;
bool err = false; try {
try { stage = "window";
stage = "window"; SDL_Window *window = SDL_CreateWindow(title,
SDL_Window *window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE|(_fullscreen_mode?SDL_WINDOW_FULLSCREEN_DESKTOP:0));
width, height, SDL_WINDOW_RESIZABLE|(_fullscreen_mode?SDL_WINDOW_FULLSCREEN_DESKTOP:0));
if (!window) { if (!window) {
handle_sdl_error("SDL Error create 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;
} }
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 { try {
SDL_ShowCursor(SDL_DISABLE); exit_code = game_thread();
event_loop(stp);
} catch (...) { } catch (...) {
SDL_ShowCursor(SDL_ENABLE); e = std::current_exception();
crash_sdl_exception();
} }
} stop_src.request_stop();
_texture.reset(); });
_texture2.reset(); main_thrd.detach();
_renderer.reset(); SDL_ShowCursor(SDL_DISABLE);
_window.reset(); event_loop(stop_src.get_token());
}); SDL_ShowCursor(SDL_ENABLE);
done.wait(false); } catch (...) {
if (e) { crash_sdl_exception();
_render_thread.join(); return -1;
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.")));
}
} }
_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 SDLContext::check_axis_dir(int &cooldown, int value) {
int range = 0x8000-_jcontrol_map.walk_deadzone; int range = 0x8000-_jcontrol_map.walk_deadzone;

View file

@ -98,13 +98,14 @@ public:
int freq; int freq;
}; };
int init_window(const VideoConfig &config, const char *title, std::function<int()> game_thread);
void init_video(const VideoConfig &config, const char *title); void init_video(const VideoConfig &config, const char *title);
void set_window_icon(const void *icon_data, size_t icon_size); void set_window_icon(const void *icon_data, size_t icon_size);
void configure_controller(const JoystickConfig &cfg); void configure_controller(const JoystickConfig &cfg);
void close_video();
AudioInfo init_audio(const AudioConfig &config, SDL_AudioCallback cb, void *cb_ctx); AudioInfo init_audio(const AudioConfig &config, SDL_AudioCallback cb, void *cb_ctx);
void pause_audio(bool pause); void pause_audio(bool pause);
@ -272,7 +273,6 @@ protected:
Uint32 _update_request_event; Uint32 _update_request_event;
Uint32 _refresh_request; Uint32 _refresh_request;
std::jthread _render_thread;
void event_loop(std::stop_token stp); void event_loop(std::stop_token stp);