Merge branch 'main' into mapedit_support

This commit is contained in:
Ondrej Novak 2025-08-28 20:07:46 +02:00
commit 2f4caf3173
15 changed files with 250 additions and 273 deletions

View file

@ -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);

View file

@ -204,7 +204,6 @@ static const void *load_SEQ_file(const void *src, int *sc, int handle) {
}
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);
@ -407,7 +406,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);
@ -561,7 +560,7 @@ void load_enemies(const short *data,int size,int *grptr,const TMOB *template,int
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);
@ -1824,7 +1823,7 @@ void mobs_live(int num)
if (p->sector>=mapsize)
{
char buff[256];
closemode();
sprintf(buff,"Potvora v neexistujicim sektoru (%d, %d) ",num,p->sector);
display_error(buff);
exit(1);

View file

@ -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);

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);
SEND_LOG("(ERROR) %s : %s",popis,text);
closemode();
display_error(popis);
exit(1);
}

View file

@ -169,7 +169,7 @@ void load_items()
f=open_ddl_file(ITEM_FILE,SR_MAP);
if (f==NULL)
{
closemode();
display_error("Selhalo otevreni souboru ITEMS.DAT. Zkotroluj zda vubec existuje.");
exit(1);
}
@ -964,7 +964,7 @@ void definuj_postavy()
}
if (r!=1)
{
closemode();
display_error("Error in file POSTAVY.DAT. May be missing a parameter in some definition.");
exit(1);
}

View file

@ -527,7 +527,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);

View file

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

View file

@ -811,7 +811,7 @@ void cti_texty(void)
if ((err=load_string_list_ex(&texty,TEXTY, SR_DATA))!=0)
{
char buff[256];
closemode();
switch (err)
{
case -1:sprintf(buff,"Can't load string table. File %s has not been found\n",TEXTY);break;
@ -874,7 +874,7 @@ void error_exception(EVENT_MSG *msg,void **unused)
SEND_LOG("(ERROR) Log: Sector %d Direction %d",viewsector,viewdir);
SEND_LOG("(ERROR) Log: Battle: %d Select_player %d",battle,select_player);
closemode();
display_error("error_exception called");
}
@ -971,7 +971,6 @@ void sse_listener_watch(EVENT_MSG *msg, void **userdata) {
const char *s = sse_receiver_receive(sse_receiver);
if (s) {
if (strcmp(s,"STOP") == 0) {
closemode();
exit(0);
} else {
send_message(E_EXTERNAL_MSG, s);
@ -999,11 +998,83 @@ void sse_listener_init(const char *hostport) {
send_message(E_ADD, E_WATCH, sse_listener_watch);
}
typedef int (*GAME_THREAD_CB)(va_list);
void init_skeldal(const INI_CONFIG *cfg)
int init_skeldal_thread(va_list args) {
const INI_CONFIG *cfg = va_arg(args, const INI_CONFIG *);
GAME_THREAD_CB game_thread = va_arg(args,GAME_THREAD_CB);
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");
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));
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();
cti_texty();
@ -1011,74 +1082,20 @@ void init_skeldal(const INI_CONFIG *cfg)
init_events();
steam_init();
va_list args;
va_start(args,game_thread);
char verr = game_display_init(ini_section_open(cfg, "video"), "Skeldal");
if (!verr)
int verr = game_display_init(ini_section_open(cfg, "video"), "Skeldal",
init_skeldal_thread, cfg, game_thread, &args);
if (verr < 0)
{
display_error("Error game_display_init %d", verr);
exit(1);
return 1;
}
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");
install_gui();
if (is_joystick_enabled()) {
show_joystick_info();
return verr;
}
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));
}
void wire_main_functs();
void unwire_main_functs(void)
{
@ -1304,7 +1321,7 @@ static void game_big_circle(char enforced)
if (err)
{
char buff[256];
closemode();
switch (err)
{
case -1: sprintf(buff,"Error while loading map (%s) ....file not found\n",s);break;
@ -1639,6 +1656,26 @@ int skeldal_gen_string_table_entry_point(const SKELDAL_CONFIG *start_cfg, const
}
const char *run_launcher();
void skeldal_entry_point_thread(va_list args) {
const SKELDAL_CONFIG *start_cfg = va_arg(args, const SKELDAL_CONFIG *);
if (start_cfg->launcher) {
const char *ddl = run_launcher();
if (ddl==NULL) return;
if (ddl[0]) {
add_patch_file(ddl);
reload_ddls();
}
}
int start_task = add_task(65536,start);
escape();
term_task_wait(start_task);
return;
}
int skeldal_entry_point(const SKELDAL_CONFIG *start_cfg)
{
def_mman_group_table(gpathtable);
@ -1692,27 +1729,11 @@ int skeldal_entry_point(const SKELDAL_CONFIG *start_cfg)
purge_temps(1);
clrscr();
init_skeldal(cfg);
if (start_cfg->launcher) {
const char *ddl = run_launcher();
if (ddl==NULL) goto cleanup;
if (ddl[0]) {
add_patch_file(ddl);
reload_ddls();
}
}
int start_task = add_task(65536,start);
escape();
term_task_wait(start_task);
cleanup:;
closemode();
int r = init_skeldal(cfg, skeldal_entry_point_thread, start_cfg);
ini_close(cfg);
return 0;
return r;
}

View file

@ -18,7 +18,6 @@ int cur_event_number;
static void event_error(char *text,int number)
{
char buff[256];
closemode();
sprintf(buff,"%s\n Specproc num: %d\n",text,number);
display_error(buff);
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_ex(const char *text, int space);
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 position(word x,word 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)
@ -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)

View file

@ -10,7 +10,12 @@ static std::unique_ptr<uint16_t[]> 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<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() {
return render_target;

View file

@ -1,4 +1,5 @@
#include <stdint.h>
#include <stdarg.h>
#include "../config.h"
#include <stddef.h>
@ -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();

View file

@ -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<int()> 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,127 @@ 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::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;

View file

@ -98,13 +98,12 @@ public:
int freq;
};
void init_video(const VideoConfig &config, const char *title);
int init_window(const VideoConfig &config, const char *title, std::function<int()> game_thread);
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);
@ -274,7 +273,6 @@ protected:
Uint32 _update_request_event;
Uint32 _refresh_request;
std::jthread _render_thread;
void event_loop(std::stop_token stp);