rewrite config, options, work with path

This commit is contained in:
Ondřej Novák 2025-01-31 12:46:48 +01:00
parent 4a0c7d4fd0
commit 77f1700902
30 changed files with 466 additions and 532 deletions

1
.gitignore vendored
View file

@ -9,3 +9,4 @@ _UpgradeReport_Files
/.cproject /.cproject
/.project /.project
/.settings /.settings
/skeldal.local.ini

View file

@ -583,7 +583,6 @@ void draw_automap(int xr,int yr)
outtext(s); outtext(s);
} }
ukaz_mysku(); ukaz_mysku();
wait_retrace();
showview(0,16,640,360); showview(0,16,640,360);
} }
void *map_keyboard(EVENT_MSG *msg,void **usr); void *map_keyboard(EVENT_MSG *msg,void **usr);

View file

@ -232,7 +232,6 @@ void chveni(int i)
if (i) count=i; if (i) count=i;
count--; count--;
if (!count) pos=0; if (!count) pos=0;
wait_retrace();
setvesa_displaystart(8*pos,0); setvesa_displaystart(8*pos,0);
pos=!pos; pos=!pos;
} }

View file

@ -1,4 +1,4 @@
#include <base64.h> #include <libs/base64.h>
constexpr binary_data font_data ="@CONTENT@"; constexpr binary_data font_data ="@CONTENT@";

View file

@ -947,9 +947,6 @@ void general_engine_init()
create_zooming(); create_zooming();
clear_screen(GetScreenAdr(),0); clear_screen(GetScreenAdr(),0);
clear_screen(GetBuffer2nd(),0); clear_screen(GetBuffer2nd(),0);
int32_t scr_linelen2 = GetScreenPitch();
screen_buffer_size=scr_linelen2*480*2;
} }
void map_pos(int celx,int cely,int posx,int posy,int posz,int *x,int *y) void map_pos(int celx,int cely,int posx,int posy,int posz,int *x,int *y)

View file

@ -268,7 +268,7 @@ static __inline int rangrnd(int a, int b) {return rnd(b-a+1)+a;}
#define concat(c,s1,s2) c=strcat(strcpy((char *)alloca(strlen(s1)+strlen(s2)+1),s1),s2) #define concat(c,s1,s2) c=strcat(strcpy((char *)alloca(strlen(s1)+strlen(s2)+1),s1),s2)
#define local_strdup(c) strcpy((char *)strlen(c)+1, c) #define local_strdup(c) strcpy((char *)alloca(strlen(c)+1), c)
#define concat2(s1,s2) strcat(strcpy((char *)alloca(strlen(s1)+strlen(s2)+1),s1),s2) #define concat2(s1,s2) strcat(strcpy((char *)alloca(strlen(s1)+strlen(s2)+1),s1),s2)
#define concat3(s1,s2,s3) strcat(strcat(strcpy((char *)alloca(strlen(s1)+strlen(s2)+strlen(s3)+1),s1),s2),s3) #define concat3(s1,s2,s3) strcat(strcat(strcpy((char *)alloca(strlen(s1)+strlen(s2)+strlen(s3)+1),s1),s2),s3)
#define concat4(s1,s2,s3,s4) strcat(strcat(strcat(strcpy((char *)alloca(strlen(s1)+strlen(s2)+strlen(s3)+strlen(s4)+1),s1),s2),s3),s4) #define concat4(s1,s2,s3,s4) strcat(strcat(strcat(strcpy((char *)alloca(strlen(s1)+strlen(s2)+strlen(s3)+strlen(s4)+1),s1),s2),s3),s4)
@ -332,14 +332,14 @@ typedef enum skeldal_folders_tag {
SR_FONT, SR_FONT,
SR_MAP, SR_MAP,
SR_MUSIC, SR_MUSIC,
SR_BGRAFIKA, SR_TEMP, /* = unused group */
SR_BGRAFIKA ,
SR_ITEMS, SR_ITEMS,
SR_ENEMIES, SR_ENEMIES,
SR_VIDEO, SR_VIDEO,
SR_DIALOGS, SR_DIALOGS,
SR_SAVES, SR_SAVES,
SR_WORK, SR_WORK,
SR_CD,
SR_COUNT} SKELDAL_FOLDERS_TAG; SR_COUNT} SKELDAL_FOLDERS_TAG;
@ -555,7 +555,7 @@ extern int viewsector; //aktualni sektor vyhledu
extern int viewdir; //aktualni smer vyhledu extern int viewdir; //aktualni smer vyhledu
extern THE_TIMER timer_tree; //strom casovych udalosti extern THE_TIMER timer_tree; //strom casovych udalosti
extern D_ACTION *d_action; //spojovy seznam zpozdenych akci extern D_ACTION *d_action; //spojovy seznam zpozdenych akci
extern char *gpathtable[SR_COUNT]; //tabulka adresaru extern const char *gpathtable[SR_COUNT]; //tabulka adresaru
extern char level_preload; //informace o preloadingu extern char level_preload; //informace o preloadingu
extern char **texty; //globalni tabulka textu extern char **texty; //globalni tabulka textu
extern char **level_texts; //lokalni tabulka textu extern char **level_texts; //lokalni tabulka textu
@ -565,7 +565,6 @@ extern int hl_ptr; //ukazatel na konec staticke tabulky registra
extern int end_ptr; //ukazatel na uplny konec tabulky registraci extern int end_ptr; //ukazatel na uplny konec tabulky registraci
extern short **map_items; //ukazatel na mapu predmetu extern short **map_items; //ukazatel na mapu predmetu
extern int default_ms_cursor; //cislo zakladniho mysiho kurzoru extern int default_ms_cursor; //cislo zakladniho mysiho kurzoru
extern void *cur_xlat; //aktualni tabulka pro 256 barev
extern void (*unwire_proc)(void); //procedura zajistujici odpojeni prave ukoncovane interakce extern void (*unwire_proc)(void); //procedura zajistujici odpojeni prave ukoncovane interakce
extern void (*wire_proc)(void); //procedura zajistujici pripojeni drive ukoncene interakce extern void (*wire_proc)(void); //procedura zajistujici pripojeni drive ukoncene interakce
extern char cur_mode; //cislo aktualni interakce extern char cur_mode; //cislo aktualni interakce
@ -642,7 +641,6 @@ extern char marker; //tato promenna je 0, jen v pripade ze je 1 probehne assert
//builder - skeldal //builder - skeldal
int set_video(int mode);
void *game_keyboard(EVENT_MSG *msg,void **usr); void *game_keyboard(EVENT_MSG *msg,void **usr);
void calc_animations(void); void calc_animations(void);
int load_map(char *filename); int load_map(char *filename);

View file

@ -1599,11 +1599,8 @@ void show_jrc_logo(char *filename)
palw[i]=b | (r<<11) | (g<<6); palw[i]=b | (r<<11) | (g<<6);
} }
} }
if (!bnk)
wait_retrace();
put_picture(xp, yp, pcx); put_picture(xp, yp, pcx);
if (bnk) { if (bnk) {
wait_retrace();
showview(xp, yp, pcxw[0], pcxw[1]); showview(xp, yp, pcxw[0], pcxw[1]);
} }
ccc=cdiff; ccc=cdiff;

View file

@ -374,11 +374,13 @@ char *get_next_title(signed char control,char *filename)
switch(control) switch(control)
{ {
case 1: case 1:
path = local_strdup(build_pathname(2, gpathtable[SR_MAP],filename)); path = build_pathname(2, gpathtable[SR_MAP],filename);
path = local_strdup(path);
titles=enc_open(path); titles=enc_open(path);
if (titles==NULL) if (titles==NULL)
{ {
const char *path2 = local_strdup(build_pathname(2, gpathtable[SR_DATA],filename)); const char *path2 = build_pathname(2, gpathtable[SR_DATA],filename);
path2 = local_strdup(path2);
titles=enc_open(path2); titles=enc_open(path2);
if (titles==NULL) if (titles==NULL)
{ {

View file

@ -222,10 +222,11 @@ int load_map(char *filename)
char snd_load=0; char snd_load=0;
void *mob_template; void *mob_template;
int32_t mob_size; int32_t mob_size;
int suc; int suc = 0;
map_with_password=0; map_with_password=0;
const char *mpath = build_pathname(2, gpathtable[SR_MAP], filename); const char *mpath = build_pathname(2, gpathtable[SR_MAP], filename);
mpath = local_strdup(mpath);
schovej_mysku(); schovej_mysku();
if (level_preload) show_loading_picture("LOADING.HI"); if (level_preload) show_loading_picture("LOADING.HI");
change_music("?"); change_music("?");

View file

@ -1,42 +1,33 @@
#include <platform/platform.h> #include <platform/platform.h>
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h> #include <stdio.h>
#include <malloc.h>
#include <libs/pcx.h> #include <libs/pcx.h>
#include <libs/types.h>
#include <libs/bgraph.h> #include <libs/bgraph.h>
#include <libs/event.h> #include <libs/event.h>
#include <libs/devices.h>
#include <libs/bmouse.h> #include <libs/bmouse.h>
#include <libs/memman.h> #include <libs/memman.h>
#include <libs/zvuk.h> #include <libs/zvuk.h>
#include <libs/strlite.h> #include <libs/strlite.h>
#include <libs/gui.h> #include <libs/gui.h>
#include <libs/basicobj.h> #include <libs/basicobj.h>
#include <time.h>
#include <libs/mgfplay.h> #include <libs/mgfplay.h>
#include <libs/inicfg.h> #include <libs/inicfg.h>
#include <platform/getopt.h>
#include <platform/save_folder.h>
#include "globals.h" #include "globals.h"
#include "engine1.h"
#include "wizard.h"
#include "version.h"
#include "default_font.h" #include "default_font.h"
//
#include "advconfig.h" #include "advconfig.h"
#include <unistd.h>
#define CONFIG_NAME SKELDALINI #define CONFIG_NAME SKELDALINI
#define INI_TEXT 1 #define INI_TEXT 1
#define INI_INT 2 #define INI_INT 2
#define ERR_GENERAL 1 #define ERR_GENERAL 1
char *gpathtable[SR_COUNT]; const char *gpathtable[SR_COUNT];
/* /*
char *pathtable[]= char *pathtable[]=
@ -66,7 +57,6 @@ int charmax=3;
int autoopenaction=0; int autoopenaction=0;
int autoopendata=0; int autoopendata=0;
void *cur_xlat;
void redraw_desktop_call(void); void redraw_desktop_call(void);
@ -99,12 +89,7 @@ void (*wire_proc)(void);
char cur_mode,battle_mode; char cur_mode,battle_mode;
static int init_music_vol=127; static int init_music_vol=127;
static int init_gfx_vol=255; static int init_gfx_vol=255;
static char full_video=0;
static char titles_on=0; static char titles_on=0;
static char windowed=0;
static char windowedzoom=1;
static char monitor=0;
static int refresh=0;
void pcx_fade_decomp(void **p,int32_t *s); void pcx_fade_decomp(void **p,int32_t *s);
void pcx_15bit_decomp(void **p,int32_t *s); void pcx_15bit_decomp(void **p,int32_t *s);
@ -290,49 +275,6 @@ INIS sinit[]=
int last_ms_cursor=-1; int last_ms_cursor=-1;
int vmode=2; int vmode=2;
int set_video(int mode)
{
int er=0;
int32_t scr_linelen2 = GetScreenPitch();
report_mode(1);
er=initmode_dx(windowed,windowedzoom,monitor,refresh);
/*
switch(mode)
{
case 1:er=initmode256(cur_xlat);
if (banking) report_mode(5); else report_mode(2);
break;
case 2:er=initmode32();
if (banking) report_mode(4); else report_mode(1);
break;
case 0:er=initmode_lo(cur_xlat);
report_mode(3);
break;
case 3: free(cur_xlat);cur_xlat=create_blw_palette16();
er=initmode16(cur_xlat);
report_mode(3);
break;
case 4:er=init_empty_mode();
report_mode(3);
break;
case 5:free(cur_xlat);cur_xlat=create_hixlat();
er=initmode64(cur_xlat);
if (banking) report_mode(7); else report_mode(6);
break;
default:er=-1;
}*/
screen_buffer_size=scr_linelen2*2*480;
return er;
}
void purge_temps(char _) { void purge_temps(char _) {
temp_storage_clear(); temp_storage_clear();
@ -989,31 +931,27 @@ static void patch_error(int err)
void init_skeldal(const INI_CONFIG *cfg) void init_skeldal(const INI_CONFIG *cfg)
{ {
int verr;
boldcz=LoadDefaultFont(); boldcz=LoadDefaultFont();
cti_texty(); cti_texty();
timer_tree.next=NULL; timer_tree.next=NULL;
srand(clock());
cur_xlat=create_special_palette();
init_events(); init_events();
verr=set_video(vmode); char verr = game_display_init(ini_section_open(cfg, "video"), "Skeldal");
if (verr) if (!verr)
{ {
exit(ERR_GENERAL); exit(1);
} }
showview = game_display_update_rect;
general_engine_init(); general_engine_init();
atexit(done_skeldal); atexit(done_skeldal);
/* /*
install_dos_error(device_error,(char *)getmem(4096)+4096);*/ install_dos_error(device_error,(char *)getmem(4096)+4096);*/
swap_error=swap_error_exception; const char *ddlfile = build_pathname(2, gpathtable[SR_DATA],"SKELDAL.DDL");
const char *ddlfile = local_strdup(build_pathname(2, gpathtable[SR_DATA],"SKELDAL.DDL")); ddlfile = local_strdup(ddlfile);
init_manager(ddlfile, NULL); init_manager(ddlfile, NULL);
SEND_LOG("(GAME) Memory manager initialized. Using DDL: '%s'",ddlfile); SEND_LOG("(GAME) Memory manager initialized. Using DDL: '%s'",ddlfile);
@ -1037,8 +975,6 @@ void init_skeldal(const INI_CONFIG *cfg)
send_message(E_ADD,E_PRGERROR,error_exception); send_message(E_ADD,E_PRGERROR,error_exception);
if (debug_enabled) install_wizard();
add_to_timer(TM_BACK_MUSIC,5,-1,back_music); add_to_timer(TM_BACK_MUSIC,5,-1,back_music);
add_game_window(); add_game_window();
@ -1323,24 +1259,7 @@ void set_verify(char state);
*/ */
void play_movie_seq(const char *s,int y) void play_movie_seq(const char *s,int y)
{ {
int hic=full_video?SMD_HICOLOR+128:SMD_HICOLOR,cc=full_video?SMD_256+128:SMD_256; play_animation(s,0,y,0);
word *lbuffer=GetScreenAdr();
set_play_attribs(lbuffer,0,banking,vmode==5);
switch (vmode)
{
case 1:if (!banking)
play_animation(s,cc,y,snd_devnum!=DEV_NOSOUND);
else
{
set_play_attribs(GetScreenAdr(),1,0,vmode==5);
play_animation(s,hic,y,snd_devnum!=DEV_NOSOUND);
}
break;
case 5:
case 2:play_animation(s,hic,y,snd_devnum!=DEV_NOSOUND);break;
default: set_play_attribs(GetScreenAdr(),1,0,vmode==5);
play_animation(s,hic,y,snd_devnum!=DEV_NOSOUND);break;
}
} }
@ -1369,68 +1288,6 @@ void play_anim(int anim_num)
} }
/*main(int argc,char *argv[])
{
int err;int sect;int dir=0;
//if (argc<2) help();
dir;
set_verify(0);
mman_pathlist=&pathtable;
//nofloors=1;
zoom_speed(1);
turn_speed(1);
configure("skeldal.ini",config_skeldal);
purge_temps(1);
textmode_effekt();
clrscr();
init_skeldal();
enter_menu();
if (argc<2)
{
invex_anim();
// send_message(E_ADD,E_MOUSE,waiter);
// send_message(E_ADD,E_KEYBOARD,waiter);
// add_to_timer(TM_WAITER,1,-1,timer_waiter);
strncpy(loadlevel.name,default_map,12);
}
else strncpy(loadlevel.name,argv[1],12);
err=load_map(loadlevel.name);
if (argc>=3) sscanf(argv[2],"%d",&sect);
else
{
sect=mglob.start_sector;
dir=mglob.direction;
}
loadlevel.start_pos=sect;
loadlevel.dir=dir;
init_game();
while (loadlevel.name[0])
{
if (err)
{
closemode();
switch (err)
{
case -1: printf("Error while loading map....file not found\n");break;
case -2: printf("Missing -1 at the end of map string table");break;
case -3: printf("Map file is corrupted!\n");break;
default: printf("Error in string table at line %d",err);break;
}
exit(1);
}
viewsector=loadlevel.start_pos;
viewdir=loadlevel.dir;
loadlevel.name[0]=0;
enter_game();
leave_current_map();
if (loadlevel.name[0]!=0)err=load_map(loadlevel.name);
}
closemode();
}
*/
#define V_NOVA_HRA 0 #define V_NOVA_HRA 0
#define V_OBNOVA_HRY 1 #define V_OBNOVA_HRY 1
@ -1661,9 +1518,80 @@ void disable_intro(void)
update_config(); update_config();
} }
/*
* -char def_path[]="";
-char graph_path[]="graphics" PATH_SEPARATOR;
-char basc_graph[]="graphics" PATH_SEPARATOR "basic" PATH_SEPARATOR;
-char item_graph[]="graphics" PATH_SEPARATOR "items" PATH_SEPARATOR;
-char sample_path[]="samples" PATH_SEPARATOR;
-char font_path[]="font" PATH_SEPARATOR;
-char map_path[]="maps" PATH_SEPARATOR;
-char music_path[]="music" PATH_SEPARATOR;
-char org_music_path[]="music" PATH_SEPARATOR;
-char temp_path[]="?";
-char enemies_path[]="graphics" PATH_SEPARATOR "enemies" PATH_SEPARATOR;
-char video_path[]="video" PATH_SEPARATOR;
-char dialogs_path[]="graphics" PATH_SEPARATOR "dialogs" PATH_SEPARATOR;
-char saves_path[]="";
-char work_path[]="";
-char cd_path[]="";
-char map2_path[]="";
-char plugins_path[]="";
*/
void new_configure(const INI_CONFIG *) { //returns game root
const char *configure_pathtable(const INI_CONFIG *cfg) {
#define DEFAULT_SUBPATHS 4
#define DEFAULT_SUBPATHS_LEN 20
const char *sub_paths[DEFAULT_SUBPATHS] = {
"basic", "dialogs", "enemies","items"
};
static char default_subpaths[DEFAULT_SUBPATHS][DEFAULT_SUBPATHS_LEN];
for (int i = 0; i < DEFAULT_SUBPATHS; ++i) {
strncpy(default_subpaths[i], build_pathname(2, "graphics", sub_paths[i]), DEFAULT_SUBPATHS_LEN);
}
const INI_CONFIG_SECTION *paths = ini_section_open(cfg, "paths");
const char *groot = ini_get_string(paths, "root", "./");
gpathtable[SR_BGRAFIKA] = ini_get_string(paths, "gui", default_subpaths[0]);
gpathtable[SR_DIALOGS] = ini_get_string(paths, "dialogs", default_subpaths[1]);
gpathtable[SR_ENEMIES] = ini_get_string(paths, "enemies", default_subpaths[2]);
gpathtable[SR_FONT] = ini_get_string(paths, "fonts", "font");
gpathtable[SR_GRAFIKA] = ini_get_string(paths, "graphics", "graphics");
gpathtable[SR_ITEMS] = ini_get_string(paths, "items", default_subpaths[3]);
gpathtable[SR_MAP] = ini_get_string(paths, "maps", "maps");
gpathtable[SR_MUSIC] = ini_get_string(paths, "music", "music");
gpathtable[SR_ZVUKY] = ini_get_string(paths, "sounds", "sounds");
gpathtable[SR_VIDEO] = ini_get_string(paths, "video", "video");
gpathtable[SR_SAVES] = ini_get_string(paths, "savegame", get_default_savegame_directory());
gpathtable[SR_DATA]= ini_get_string(paths, "data", "./");
return groot;
}
void show_help(const char *arg0) {
printf(
"Brany Skeldalu (Gates of Skeldal) portable game player\n"
"Copyright (c) 2025 Ondrej Novak. All rights reserved.\n\n"
"This work is licensed under the terms of the MIT license.\n"
"For a copy, see <https://opensource.org/licenses/MIT>.\n"
"\n"
"Usage:"
);
printf("%s [-f <file>] [-a <file>] [-h]\n\n", arg0);
printf("-f <file> path to configuration file\n"
"-a <adv> path for adventure file (.adv)\n"
"-h this help\n");
exit(0);
}
void show_help_short() {
printf("add -h to print help\n");
} }
int main(int argc,char *argv[]) int main(int argc,char *argv[])
@ -1671,39 +1599,47 @@ int main(int argc,char *argv[])
def_mman_group_table(gpathtable); def_mman_group_table(gpathtable);
zoom_speed(1); zoom_speed(1);
turn_speed(1); turn_speed(1);
const char *config_name = CONFIG_NAME;
const char *adv_config_file = NULL;
for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:")) != -1; ) {
switch (optchr) {
case 'f': config_name = local_strdup(optarg);break;
case 'a': adv_config_file = local_strdup(optarg);break;
case 'h': show_help(argv[0]);break;
default: show_help_short();
return 1;
}
}
INI_CONFIG *cfg = ini_open(CONFIG_NAME); INI_CONFIG *cfg = ini_open(config_name);
if (cfg == NULL) { if (cfg == NULL) {
fprintf(stderr, "Failed to open configuration file: %s\n", CONFIG_NAME); fprintf(stderr, "Failed to open configuration file: %s\n", CONFIG_NAME);
show_help_short();
return 1; return 1;
} }
if (argc >= 2) { if (adv_config_file) {
TSTR_LIST adv_config=read_config(argv[1]);; TSTR_LIST adv_config=read_config(adv_config_file);
adv_patch_config(cfg, adv_config); adv_patch_config(cfg, adv_config);
release_list(adv_config); release_list(adv_config);
} }
new_configure(cfg); const char *groot = configure_pathtable(cfg);
if (!change_current_directory(groot)) {
fprintf(stderr, "Can't change directory to %s", groot);
return 1;
}
start_check(); start_check();
purge_temps(1); purge_temps(1);
// textmode_effekt();
clrscr(); clrscr();
init_skeldal(cfg); init_skeldal(cfg);
add_task(65536,start);
//add_task(32768,check_number_1phase,argv[0]);
add_task(65536,start);
/* position(200,200);
set_font(H_FBIG,RGB(200,200,200));
outtext("Ahoj lidi");
showview(0,0,0,0);*/
escape(); escape();
closemode(); closemode();

View file

@ -17,11 +17,7 @@ void RedirectScreenBufferSecond(void);
extern word curcolor,charcolors[7]; extern word curcolor,charcolors[7];
extern word *curfont,*writepos,writeposx; extern word *curfont,*writepos,writeposx;
extern byte fontdsize; extern byte fontdsize;
extern byte *palmem,*xlatmem;
extern void (*showview)(word,word,word,word); extern void (*showview)(word,word,word,word);
extern char line480;
extern int32_t screen_buffer_size;
extern char banking;
extern char __skip_change_line_test; extern char __skip_change_line_test;
extern char no_restore_mode; extern char no_restore_mode;
@ -98,7 +94,7 @@ void showview32(word x,word y,word xs,word ys);
void showview256(word x,word y,word xs,word ys); void showview256(word x,word y,word xs,word ys);
void showview_lo(word x,word y,word xs,word ys); void showview_lo(word x,word y,word xs,word ys);
void outtext(const char *text); void outtext(const char *text);
int initmode_dx(char inwindow, char zoom, char monitor, int refresh); int initmode(const INI_CONFIG_SECTION *, const char *app_name);
int initmode32(void); int initmode32(void);
int initmode32b(void); int initmode32b(void);
int initmode256(void *paletefile); int initmode256(void *paletefile);
@ -119,15 +115,9 @@ void redraw_ms_cursor_on_screen(void);
int text_height(char *text); int text_height(char *text);
int text_width(char *text); int text_width(char *text);
void set_aligned_position(int x,int y,char alignx, char aligny,char *text); void set_aligned_position(int x,int y,char alignx, char aligny,char *text);
void wait_retrace(void);
void pal_optimize(void);
void rectangle(int x1,int y1,int x2,int y2,int color); void rectangle(int x1,int y1,int x2,int y2,int color);
word *mapvesaadr1(word *a); word *mapvesaadr1(word *a);
void *create_special_palette(void);
void *create_special_palette2(void);
void *create_blw_palette16(void);
void rel_position_x(word x); void rel_position_x(word x);
int init_empty_mode(void);
void put_8bit_clipped(void *src,void *trg,int startline,int velx,int vely); void put_8bit_clipped(void *src,void *trg,int startline,int velx,int vely);
//#pragma aux put_8bit_clipped parm [ESI][EDI][EAX][EBX][EDX] modify [ECX]; //#pragma aux put_8bit_clipped parm [ESI][EDI][EAX][EBX][EDX] modify [ECX];

View file

@ -10,11 +10,9 @@ word *screen;
word curcolor,charcolors[7] = {0x0000,RGB555(0,31,0),RGB555(0,28,0),RGB555(0,24,0),RGB555(0,20,0),0x0000,0x0000}; word curcolor,charcolors[7] = {0x0000,RGB555(0,31,0),RGB555(0,28,0),RGB555(0,24,0),RGB555(0,20,0),0x0000,0x0000};
word *curfont,*writepos,writeposx; word *curfont,*writepos,writeposx;
byte fontdsize=0; byte fontdsize=0;
byte *palmem=NULL,*xlatmem=NULL;
void (*showview)(word,word,word,word); void (*showview)(word,word,word,word);
char line480=0; char line480=0;
int32_t screen_buffer_size=0; int32_t screen_buffer_size=0;
char banking=0;
char screenstate=0; char screenstate=0;
char __skip_change_line_test=0; char __skip_change_line_test=0;
char no_restore_mode=0; char no_restore_mode=0;
@ -289,10 +287,10 @@ void switchvesabank(word bank)
} }
*/ */
int initmode_dx(char inwindow, char zoom, char monitor, int refresh) int initmode(const INI_CONFIG_SECTION *display_config, const char *app_name)
{ {
if (!DXInit64(inwindow,zoom,monitor,refresh)) return -1; if (!game_display_init(display_config, app_name)) return -1;
showview=showview_dx; showview=game_display_update_rect;
screenstate=1; screenstate=1;
return 0; return 0;
} }
@ -400,25 +398,12 @@ void closemode()
{ {
if (screenstate) if (screenstate)
{ {
palmem=NULL; game_display_close();
DXCloseMode();
} }
screenstate=0; screenstate=0;
} }
void showview_dx(word x,word y,word xs,word ys)
{
// register longint a;
if (x>DxGetResX() || y>DxGetResY()) return;
if (xs==0) xs=DxGetResX();
if (ys==0) ys=DxGetResY();
xs+=2;ys+=2;
if (x+xs>DxGetResX()) xs=DxGetResX()-x;
if (y+ys>DxGetResY()) ys=DxGetResY()-y;
DXCopyRects64(x,y,xs,ys);
}
/* /*
static void showview64b(word x,word y,word xs,word ys) static void showview64b(word x,word y,word xs,word ys)
{ {
@ -593,70 +578,6 @@ void set_aligned_position(int x,int y,char alignx,char aligny,char *text)
position(x,y); position(x,y);
} }
/*void pal_optimize()
{
int32_t *stattable;
word *c;
char *d;
int i;
int32_t maxr,maxg,maxb,max;
int j;
if (palmem==NULL) return;
stattable=(int32_t *)getmem(32768*sizeof(int32_t));
memset(stattable,0,32768*sizeof(int32_t));
c=screen;
for(i=0;i<screen_buffer_size;i++,c++)
stattable[*c & 0x7fff]++;
for(j=0;j<256;j++)
{
max=0;
for (i=0;i<32768;i++)
if (stattable[i]>max)
{
*((word *)xlatmem+j)=i;
max=stattable[i];
}
stattable[*((word *)xlatmem+j)]=-1;
}
d=palmem;
c=(word *)xlatmem;
for(i=0;i<256;i++)
{
j=*c++;
*d++=((j>>9)& 0x3e);
*d++=((j>>4)& 0x3e);
*d++=(j & 0x1f)<<1;
}
setpal((void *)palmem);
memset(xlatmem,0,65536);
for(j=0;j<32768;j++)
{
int r1,g1,b1;
int r2,g2,b2,dif;
char *c;
maxr=maxg=maxb=999999999;
r1=(j>>9)& 0x3e;g1=(j>>4)& 0x3e;b1=(j & 0x1f)<<1;
c=palmem;
for(i=0;i<256;i++)
{
r2=abs(r1-*c++);
g2=abs(g1-*c++);
b2=abs(b1-*c++);
dif=r2+b2+g2;
if (dif<=maxb)
{
if (dif<maxb) xlatmem[j*2]=i;
else xlatmem[j*2]=xlatmem[j*2+1];
xlatmem[j*2+1]=i;
maxb=dif;
}
}
}
showview(0,0,0,0);
free(stattable);
}
*/
void rectangle(int x1,int y1,int x2,int y2,int color) void rectangle(int x1,int y1,int x2,int y2,int color)
{ {
curcolor=color; curcolor=color;
@ -666,135 +587,3 @@ void rectangle(int x1,int y1,int x2,int y2,int color)
ver_line32(x2,y1,y2); ver_line32(x2,y1,y2);
} }
void *create_special_palette()
{
char *c;
int i,j,k;
void *z;
z=c=getmem(3*256+2*32768);
for(i=0;i<6;i++)
for(j=0;j<7;j++)
for(k=0;k<6;k++)
{*c++=12*i;*c++=10*j;*c++=12*k;}
c=z;
c+=768;
for(i=0;i<32;i++)
for(j=0;j<32;j++)
for(k=0;k<32;k++)
{
*c++=((i+3)/6)*42+((j+3)/5)*6+((k+3)/6);
*c++=(i*2/12)*42+(j/5)*6+(k*2/12);
}
return z;
}
void *create_special_palette2()
{
char *c;
int i,j,k;
void *z;
z=c=getmem(3*256+2*32768);
for(i=0;i<64;i++)
{
*c++=0;*c++=i;*c++=0;
}
for(j=0;j<24;j++)
for(k=0;k<8;k++)
{*c++=j*64/24;*c++=0;*c++=k*8;}
c=z;
c+=768;
for(i=0;i<32;i++)
for(j=0;j<32;j++)
for(k=0;k<32;k++)
{
*c++=64+(i*24/32)*8+k/4;
*c++=j*2;
}
return z;
}
void *create_blw_palette16()
{
char *c;
int i,j,k;
void *z;
uint8_t pal_colors[]={0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63};
uint8_t carnat[]={0,1,3,2,4,5,7,6,12,13,15,14,8,9,11,10};
z=c=getmem(3*256+2*32768);
for(i=0;i<16;i++)
{
j=pal_colors[carnat[i]]*3;k=i*4+3;
c[j]=k;c[j+1]=k;c[j+2]=k;
}
c+=768;
for(i=0;i<32;i++)
for(j=0;j<32;j++)
for(k=0;k<32;k++)
{
int u=(i*3+j*5+k*2)/10;
c[0]=carnat[u/2];
c[1]=carnat[(u+1)/2];
c+=2;
}
return z;
}
/*
void showview16(word x,word y,word xs,word ys)
{
int x1,x2;
if (x>640 || y>480) return;
if (xs==0) xs=640;
if (ys==0) ys=480;
if (x+xs>640) xs=640-x;
if (y+ys>480) ys=480-y;
if (xs>550 && ys>400)
{
redraw16(screen,lbuffer,xlatmem);
return;
}
x1=x & ~0x7;
x2=(x+xs+7) & ~0x7;
redrawbox16((x2-x1)/8,ys,screen+x1+640*y,(char *)lbuffer+x1/8+80*y,xlatmem);
}
void init16colors();
#pragma aux init16colors modify [eax]=\
"mov eax,12h"\
"int 10h"\
int initmode16(void *palette)
{
palette;
init16colors();
lbuffer=(word *)0xa0000;
screen=lbuffer;
linelen=640*2;
showview=showview16;
screen=(void *)malloc(screen_buffer_size);
palmem=(char *)palette;
xlatmem=palmem+768;
setpal((void *)palmem);
banking=0;
screenstate=1;
return 0;
}
void empty_show_view(int x,int y,int xs,int ys)
{
x,y,xs,ys;
}
int init_empty_mode()
{
screen=(void *)malloc(screen_buffer_size);
showview=empty_show_view;
banking=1;
lbuffer=NULL;
screenstate=1;
return 0;
}
*/

20
libs/logfile.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef _SKELDAL_LOGFILE_HEADER
#define _SKELDAL_LOGFILE_HEADER
#ifdef __cplusplus
extern "C" {
#endif
#ifdef LOGFILE
void send_log_impl(const char *format, ...) __attribute__((format(printf, 1, 2)));
#define SEND_LOG(...) send_log_impl( __VA_ARGS__)
#else
#define SEND_LOG(...)
#endif
#ifdef __cplusplus
}
#endif
#endif

View file

@ -20,7 +20,7 @@
void bonz_table(); void bonz_table();
#define NON_GETMEM_RESERVED (4*1024) #define NON_GETMEM_RESERVED (4*1024)
char *const* mman_pathlist=NULL; static const char ** mman_pathlist=NULL;
static char swap_status=0; static char swap_status=0;
static FILE *swap = NULL; static FILE *swap = NULL;
@ -34,7 +34,7 @@ void (*mman_action)(int action)=NULL;
int32_t last_load_size; int32_t last_load_size;
void def_mman_group_table(char *const * p) { void def_mman_group_table(const char ** p) {
mman_pathlist = p; mman_pathlist = p;
} }
@ -42,7 +42,6 @@ void standard_mem_error(size_t size)
{ {
char buff[256]; char buff[256];
SEND_LOG("(ERROR) Memory allocation error detected, %lu bytes missing",size); SEND_LOG("(ERROR) Memory allocation error detected, %lu bytes missing",size);
DXCloseMode();
sprintf(buff,"Memory allocation error\n Application can't allocate %lu bytes of memory (%xh)\n",size,memman_handle); sprintf(buff,"Memory allocation error\n Application can't allocate %lu bytes of memory (%xh)\n",size,memman_handle);
display_error(buff); display_error(buff);
exit(1); exit(1);
@ -52,10 +51,6 @@ void load_error(const char *filename)
{ {
char buff[256]; char buff[256];
SEND_LOG("(ERROR) Load error detected, system can't load file: %s",filename); SEND_LOG("(ERROR) Load error detected, system can't load file: %s",filename);
#ifdef LOGFILE
// bonz_table();
#endif
DXCloseMode();
sprintf(buff,"Load error while loading file: %s", filename); sprintf(buff,"Load error while loading file: %s", filename);
display_error(buff); display_error(buff);
exit(1); exit(1);
@ -64,7 +59,6 @@ void load_error(const char *filename)
void standard_swap_error() void standard_swap_error()
{ {
char buff[256]; char buff[256];
DXCloseMode();
sprintf(buff,"Swap error. Maybe disk is full"); sprintf(buff,"Swap error. Maybe disk is full");
display_error(buff); display_error(buff);
exit(1); exit(1);
@ -531,7 +525,6 @@ void *ablock(int handle)
if (h->status==BK_NOT_LOADED) if (h->status==BK_NOT_LOADED)
{ {
void *p;int32_t s; void *p;int32_t s;
char c[200];
SEND_LOG("(LOAD) Loading file as block '%-.12s' %04X",h->src_file,handle); SEND_LOG("(LOAD) Loading file as block '%-.12s' %04X",h->src_file,handle);
if (h->seekpos==0) if (h->seekpos==0)
@ -539,10 +532,8 @@ void *ablock(int handle)
if (h->src_file[0]!=0) if (h->src_file[0]!=0)
{ {
if (mman_action!=NULL) mman_action(MMA_READ); if (mman_action!=NULL) mman_action(MMA_READ);
strcpy(c,mman_pathlist[h->path]); const char *name = build_pathname(2,mman_pathlist[h->path], h->src_file);
strcat(c,h->src_file); p=load_file(name);
c[strlen(mman_pathlist[h->path])+12]='\0';
p=load_file(c);
s=last_load_size; s=last_load_size;
} }
else else

View file

@ -2,6 +2,7 @@
#include <stdio.h> #include <stdio.h>
#include "logfile.h"
#ifndef _MEMMAN_H_ #ifndef _MEMMAN_H_
@ -66,16 +67,14 @@ typedef handle_list *handle_groups[BK_MAJOR_HANDLES];
#define BK_PRELOAD 8 #define BK_PRELOAD 8
#define BK_HSWAP 16 #define BK_HSWAP 16
extern char *const * mman_pathlist; //tento pointer musi byt naplnen ukazatelem na tabulku cest //extern char *const * mman_pathlist; //tento pointer musi byt naplnen ukazatelem na tabulku cest
extern void (*mem_error)(size_t); //pokud neni NULL je tato funkce volana vzdy kdyz dojde pamet a system si s tim nevi rady
extern void (*swap_error)(void);
extern int memman_handle; //cislo handle naposled zpracovavaneho prikazem ablock extern int memman_handle; //cislo handle naposled zpracovavaneho prikazem ablock
extern char mman_patch; //jednicka zapina moznost pouziti patchu extern char mman_patch; //jednicka zapina moznost pouziti patchu
void *getmem(int32_t size); //alokace pameti pres memman. alokovat pomoci malloc lze ale hrozi nebezpeci ze vrati NULL void *getmem(int32_t size); //alokace pameti pres memman. alokovat pomoci malloc lze ale hrozi nebezpeci ze vrati NULL
void *grealloc(void *m,int32_t size); //realokace pameti pres memman void *grealloc(void *m,int32_t size); //realokace pameti pres memman
void *load_file(const char *filename); //obycejne natahne soubor do pameti a vrati ukazatel. void *load_file(const char *filename); //obycejne natahne soubor do pameti a vrati ukazatel.
void init_manager(const char *filename,const char *swp); //inicializuje manager. Jmeno filename i swapname nejsou povinne (musi byt NULL kdyz nejsou pouzity) void init_manager(const char *filename,const char *swp); //inicializuje manager. Jmeno filename i swapname nejsou povinne (musi byt NULL kdyz nejsou pouzity)
void def_mman_group_table( char *const * ); //define pointer to table of paths, for each group there is path void def_mman_group_table(const char ** ); //define pointer to table of paths, for each group there is path
THANDLE_DATA *def_handle(int handle,const char *filename,void *decompress,char path); //deklaruje rukojet. promenna decompress je ukazatel na funkci ktera upravi data pred vracenim ukazatele THANDLE_DATA *def_handle(int handle,const char *filename,void *decompress,char path); //deklaruje rukojet. promenna decompress je ukazatel na funkci ktera upravi data pred vracenim ukazatele
void *ablock(int handle); //vraci ukazatel bloku spojeneho s handlem void *ablock(int handle); //vraci ukazatel bloku spojeneho s handlem
void alock(int handle); //zamyka blok void alock(int handle); //zamyka blok
@ -115,22 +114,11 @@ extern void (*mman_action)(int action); //udalost volajici se pri akci mmanager
void display_status(void); //zobrazi na display status memmanageru void display_status(void); //zobrazi na display status memmanageru
#ifdef LOGFILE
char *get_time_str(void);
int q_current_task(void);
void send_log_impl(int task, const char *format, ...) __attribute__((format(printf, 2, 3)));
#define OPEN_LOG(log) memcpy(stderr,fopen_icase(log,"w"),sizeof(FILE));
#define SEND_LOG(...) send_log_impl(q_current_task(), __VA_ARGS__)
#define CLOSE_LOG(void) fclose(logfile);
#else
#define OPEN_LOG(log)
#define SEND_LOG(...)
#define CLOSE_LOG(void)
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View file

@ -14,6 +14,7 @@ target_sources(skeldal_platform PRIVATE
config.cpp config.cpp
error.cpp error.cpp
timer.cpp timer.cpp
getopt.c
) )
# Podmínky pro platformu Windows # Podmínky pro platformu Windows

View file

@ -5,10 +5,16 @@
#include <map> #include <map>
#include <string> #include <string>
#include <string_view> #include <string_view>
typedef struct ini_config_section_tag {
using Section = std::map<std::string, std::string, std::less<>>;
Section data;
} INI_CONFIG_SECTION;
typedef struct ini_config_tag { typedef struct ini_config_tag {
using Section = std::map<std::string, std::string, std::less<>>;
using Config = std::map<std::string, Section , std::less<>>; using Config = std::map<std::string, INI_CONFIG_SECTION , std::less<>>;
Config data; Config data;
} INI_CONFIG; } INI_CONFIG;
@ -44,7 +50,7 @@ void parseIniStream(std::istream& input, Callback &&callback) {
if (eqPos != std::string_view::npos) { if (eqPos != std::string_view::npos) {
std::string_view key_view = trim(line_view.substr(0, eqPos)); std::string_view key_view = trim(line_view.substr(0, eqPos));
std::string_view value_view = trim(line_view.substr(eqPos + 1)); std::string_view value_view = trim(line_view.substr(eqPos + 1));
callback(currentSection, std::string(key_view), std::string(value_view)); callback(currentSection, key_view, value_view);
} }
} }
} }
@ -59,9 +65,9 @@ INI_CONFIG* ini_open(const char *filename) {
parseIniStream(input, [&](std::string_view section, std::string_view key, std::string_view value) { parseIniStream(input, [&](std::string_view section, std::string_view key, std::string_view value) {
INI_CONFIG::Config::iterator iter = c->data.find(section); INI_CONFIG::Config::iterator iter = c->data.find(section);
if (iter == c->data.end()) { if (iter == c->data.end()) {
iter = c->data.emplace(std::string(section), INI_CONFIG::Section()).first; iter = c->data.emplace(std::string(section), INI_CONFIG_SECTION()).first;
} }
iter->second.emplace(std::string(key), std::string(value)); iter->second.data.emplace(std::string(key), std::string(value));
}); });
return c; return c;
} }
@ -73,15 +79,14 @@ void ini_close(INI_CONFIG *config) {
const INI_CONFIG_SECTION* ini_section_open(const INI_CONFIG *cfg, const char *section) { const INI_CONFIG_SECTION* ini_section_open(const INI_CONFIG *cfg, const char *section) {
auto iter = cfg->data.find(std::string_view(section)); auto iter = cfg->data.find(std::string_view(section));
if (iter == cfg->data.end()) return NULL; if (iter == cfg->data.end()) return NULL;
else return reinterpret_cast<const INI_CONFIG_SECTION *>(&iter->second); else return &iter->second;
} }
const char* ini_find_key(const INI_CONFIG_SECTION *section, const char* ini_find_key(const INI_CONFIG_SECTION *section,
const char *key) { const char *key) {
if (section == NULL) return NULL; if (section == NULL) return NULL;
const INI_CONFIG::Section *s = reinterpret_cast<const INI_CONFIG::Section *>(section); auto iter = section->data.find(std::string_view(key));
auto iter = s->find(std::string_view(key)); if (iter == section->data.end()) return NULL;
if (iter == s->end()) return NULL;
return iter->second.c_str(); return iter->second.c_str();
} }
@ -171,8 +176,7 @@ int ini_get_boolean(const INI_CONFIG_SECTION *section, const char *key,
} }
void ini_replace_key( INI_CONFIG_SECTION *section, const char *key, const char *value) { void ini_replace_key( INI_CONFIG_SECTION *section, const char *key, const char *value) {
auto s = reinterpret_cast<INI_CONFIG::Section *>(section); section->data[std::string(key)] = std::string(value);
(*s)[std::string(key)] = std::string(value);
} }
INI_CONFIG_SECTION* ini_create_section(INI_CONFIG *cfg, const char *section_name) { INI_CONFIG_SECTION* ini_create_section(INI_CONFIG *cfg, const char *section_name) {
@ -189,7 +193,7 @@ void ini_store_to_file(const INI_CONFIG *config, const char *filename) {
std::ofstream out(filename,std::ios::out|std::ios::trunc); std::ofstream out(filename,std::ios::out|std::ios::trunc);
for (const auto &[sname, s]: config->data) { for (const auto &[sname, s]: config->data) {
out << '[' << sname << ']' << std::endl; out << '[' << sname << ']' << std::endl;
for (const auto &[k,v]: s) { for (const auto &[k,v]: s.data) {
out << k << '=' << v << std::endl; out << k << '=' << v << std::endl;
} }
} }

View file

@ -1,10 +1,10 @@
#include "legacy_coroutines.h"
#include <cassert> #include <cassert>
#include <cstdarg> #include <cstdarg>
#include <cstdint> #include <cstdint>
#include <iostream> #include <iostream>
extern "C" {
#include "error.h" #include "error.h"
}
#include "platform.h" #include "platform.h"
@ -15,8 +15,9 @@ void display_error(const char *text) {
static std::uint32_t gtick = get_game_tick_count(); static std::uint32_t gtick = get_game_tick_count();
void send_log_impl(int task, const char *format, ...) { void send_log_impl(const char *format, ...) {
va_list args; va_list args;
int task = q_current_task();
char buff2[1000]; char buff2[1000];
va_start(args, format); va_start(args, format);
auto reltik = get_game_tick_count() - gtick; auto reltik = get_game_tick_count() - gtick;

View file

@ -1,4 +1,14 @@
#pragma once #pragma once
#ifdef __cplusplus
extern "C" {
#endif
void display_error(const char *text); void display_error(const char *text);
void send_log_impl(int task, const char *format, ...); void send_log_impl(const char *format, ...);
#ifdef __cplusplus
}
#endif

View file

@ -2,6 +2,7 @@
#include <cstdarg> #include <cstdarg>
#include <filesystem> #include <filesystem>
#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(const std::string_view &pathname, char sep) {
@ -67,6 +68,8 @@ FILE *fopen_icase(const char *pathname, const char *mode) {
static thread_local std::string build_pathname_buffer; static thread_local std::string build_pathname_buffer;
const char * build_pathname(size_t nparts, const char *part1, ...) { const char * build_pathname(size_t nparts, const char *part1, ...) {
va_list lst; va_list lst;
va_start(lst, part1); va_start(lst, part1);
@ -76,6 +79,7 @@ const char * build_pathname(size_t nparts, const char *part1, ...) {
p = p / va_arg(lst, const char *); p = p / va_arg(lst, const char *);
} }
build_pathname_buffer = p; build_pathname_buffer = p;
SEND_LOG("(BUILD_PATHNAME) %s", build_pathname_buffer.c_str());
return build_pathname_buffer.c_str(); return build_pathname_buffer.c_str();
} }
@ -84,3 +88,10 @@ char create_directories(const char *path) {
std::error_code ec; std::error_code ec;
return std::filesystem::create_directories(p, ec)?1:0; return std::filesystem::create_directories(p, ec)?1:0;
} }
char change_current_directory(const char *path) {
std::error_code ec;
std::filesystem::current_path(std::filesystem::path(path), ec);
return ec == std::error_code{}?1:0;
}

117
platform/getopt.c Normal file
View file

@ -0,0 +1,117 @@
// Put this in a separate .h file (called "getopt.h").
// The prototype for the header file is:
/*
#ifndef GETOPT_H
#define GETOPT_H
int getopt(int nargc, char * const nargv[], const char *ostr) ;
#endif
*/
#include "getopt.h" // make sure you construct the header file as dictated above
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <string.h>
#include <stdio.h>
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*/
int getopt(int nargc, char * const nargv[], const char *ostr)
{
static char *place = EMSG; /* option letter processing */
const char *oli; /* option letter list index */
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = EMSG;
return (-1);
}
if (place[1] && *++place == '-') { /* found "--" */
++optind;
place = EMSG;
return (-1);
}
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (optopt == (int)'-')
return (-1);
if (!*place)
++optind;
if (opterr && *ostr != ':')
(void)printf("illegal option -- %c\n", optopt);
return (BADCH);
}
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
}
else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (nargc <= ++optind) { /* no arg */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
(void)printf("option requires an argument -- %c\n", optopt);
return (BADCH);
}
else /* white space */
optarg = nargv[optind];
place = EMSG;
++optind;
}
return (optopt); /* dump back option letter */
}

13
platform/getopt.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef GETOPT_H
#define GETOPT_H
extern int opterr; /* if error message should be printed */
extern int optind; /* index into parent argv vector */
extern int optopt; /* character checked for validity */
extern int optreset; /* reset getopt */
extern char *optarg; /* argument associated with option */
int getopt(int nargc, char * const nargv[], const char *ostr);
#endif

View file

@ -17,9 +17,10 @@ static std::string get_default_savegame_dir() {
const char *get_default_savegame_directory() { const char *get_default_savegame_directory(void) {
static std::string dir = get_default_savegame_dir(); static std::string dir = get_default_savegame_dir();
return dir.c_str(); return dir.c_str();
} }

View file

@ -41,6 +41,13 @@ const char * build_pathname(size_t nparts, const char *part1, ...);
* @retval 0 failure * @retval 0 failure
*/ */
char create_directories(const char *path); char create_directories(const char *path);
///change current directory
/**
* @param path path
* @retval 1 success
* @retval 0 failure
*/
char change_current_directory(const char *path);
@ -71,7 +78,7 @@ void sleep_ms(uint32_t);
} }
#endif #endif
//------------- BGRAPH DX wrapper -------------------
#include "sdl/BGraph2.h" #include "sdl/BGraph2.h"
#define WM_RELOADMAP (WM_APP+215) #define WM_RELOADMAP (WM_APP+215)

View file

@ -1,11 +1,15 @@
#ifdef __cplusplus__ #ifndef _SKELDAL_PLATFORM_SAVE_FOLDER
#define _SKELDAL_PLATFORM_SAVE_FOLDER
#ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define SAVEGAME_FOLDERNAME "Skeldal"; #define SAVEGAME_FOLDERNAME "Skeldal";
const char *get_default_savegame_directory(); const char *get_default_savegame_directory(void);
#ifdef __cplusplus__ #ifdef __cplusplus
} }
#endif #endif
#endif

View file

@ -1,4 +1,5 @@
#include "BGraph2.h" #include "BGraph2.h"
#include "../platform.h"
#include "sdl_context.h" #include "sdl_context.h"
#include "global_context.h" #include "global_context.h"
@ -9,34 +10,50 @@ 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 DXInit64(char inwindow,int zoom,int monitor, int refresh) { char game_display_init(const INI_CONFIG_SECTION *display_section, const char *title) {
SDLContext::DisplayMode mode; SDLContext::Config cfg = {};
if (inwindow) { const char *aspect_str;
if (zoom) {
mode = SDLContext::double_window; aspect_str = ini_get_string(display_section, "aspect_ratio", "4:3");
} else { if (sscanf(aspect_str, "%d:%d",&cfg.aspect_x, &cfg.aspect_y) != 2) {
mode = SDLContext::native_window; cfg.aspect_x = cfg.aspect_y = 0;
}
} else {
mode = SDLContext::fullscreen;
} }
cfg.fullscreen = ini_get_boolean(display_section, "fullscreen", 1) == 1;
const char *comp = ini_get_string(display_section, "composer", "auto");
if (stricmp(comp, "hardware") == 0 || stricmp(comp, "hw") == 0) {
cfg.composer = SDL_RENDERER_ACCELERATED;
} else if (stricmp(comp, "software") == 0 || stricmp(comp, "sw") == 0) {
cfg.composer = SDL_RENDERER_SOFTWARE;
} else {
cfg.composer = 0;
}
cfg.scale_quality = ini_get_string(display_section, "scale_quality", "auto");
cfg.window_height = ini_get_int(display_section, "window_height", 480);
cfg.window_width = ini_get_int(display_section, "window_width", 640);
cfg.crt_filter = ini_get_boolean(display_section, "crt_filter", 1) == 1;
screen_pitch = 640; screen_pitch = 640;
get_sdl_global_context().init_screen(mode, "Skeldal"); //todo allow change get_sdl_global_context().init_video(cfg, title);
screen_buffer = std::make_unique<uint16_t[]>(screen_pitch*480); screen_buffer = std::make_unique<uint16_t[]>(screen_pitch*480);
buffer2nd = 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); std::fill(screen_buffer.get(), screen_buffer.get()+screen_pitch*480,0);
render_target = screen_buffer.get(); render_target = screen_buffer.get();
return 1; return 1;
} }
void DXCloseMode() { void game_display_close(void) {
get_sdl_global_context().close_screen(); get_sdl_global_context().close_video();
} }
uint16_t *GetScreenAdr() { uint16_t *GetScreenAdr() {
return render_target; return render_target;
} }
@ -84,11 +101,26 @@ void StripBlt(void *data, unsigned int startline, uint32_t width) {
} }
void DXCopyRects64(unsigned short x,unsigned short y,unsigned short xs,unsigned short ys) { static void DXCopyRects64(unsigned short x,unsigned short y,unsigned short xs,unsigned short ys) {
get_sdl_global_context().present_rect(screen_buffer.get(), screen_pitch, x,y,xs,ys); get_sdl_global_context().present_rect(screen_buffer.get(), screen_pitch, x,y,xs,ys);
} }
void game_display_update_rect(unsigned short x,unsigned short y,unsigned short xs,unsigned short ys)
{
if (x>DxGetResX() || y>DxGetResY()) return;
if (xs==0) xs=DxGetResX();
if (ys==0) ys=DxGetResY();
if (x+xs>DxGetResX()) xs=DxGetResX()-x;
if (y+ys>DxGetResY()) ys=DxGetResY()-y;
DXCopyRects64(x,y,xs,ys);
}
void *DxPrepareWalk(int ypos) { void *DxPrepareWalk(int ypos) {
auto &sdl = get_sdl_global_context(); auto &sdl = get_sdl_global_context();
sdl.swap_render_buffers(); sdl.swap_render_buffers();

View file

@ -1,4 +1,5 @@
#include <stdint.h> #include <stdint.h>
#include "../config.h"
#ifndef __BGRAPH_DX_WRAPPER_ #ifndef __BGRAPH_DX_WRAPPER_
#define __BGRAPH_DX_WRAPPER_ #define __BGRAPH_DX_WRAPPER_
@ -17,16 +18,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);
void game_display_update_rect(unsigned short x,unsigned short y,unsigned short xs,unsigned short ys);
//inicializuje a otevira rezim 640x480x16b v DX - otevre okno, pripravi vse pro beh hry
//Vraci 1 pri uspechu
char DXInit64(char inwindow,int zoom,int monitor, int refresh);
//uzavre rezim grafiky
void DXCloseMode(void);
//void DXCopyRects32(unsigned short x,unsigned short y,unsigned short xs,unsigned short ys);
void DXCopyRects64(unsigned short x,unsigned short y,unsigned short xs,unsigned short ys);
void *DxPrepareWalk(int ypos); void *DxPrepareWalk(int ypos);
void DxZoomWalk(void *handle, int ypos, int *points,float phase, void *lodka); void DxZoomWalk(void *handle, int ypos, int *points,float phase, void *lodka);

View file

@ -60,11 +60,10 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
int pitch; int pitch;
SDL_LockTexture(*texture, nullptr, &pixels, &pitch); SDL_LockTexture(*texture, nullptr, &pixels, &pitch);
bool wider_lines = height > 1024; bool wider_lines = height > 1350;
// Vyplň texturu patternem (liché řádky tmavší)
Uint32* pixelArray = (Uint32*)pixels; Uint32* pixelArray = (Uint32*)pixels;
Uint32 darkPixel = wider_lines?0x808080FF:0xC0C0C0FF; // Černá s částečnou průhledností Uint32 darkPixel = wider_lines?0x808080FF:0xA0A0A0FF;
Uint32 transparentPixel = wider_lines ?0xFFFFFFE0:0xFFFFFFC0; Uint32 transparentPixel = wider_lines ?0xFFFFFFE0:0xFFFFFFC0;
int step = wider_lines ?3:2; int step = wider_lines ?3:2;
@ -81,7 +80,7 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
void SDLContext::init_screen(DisplayMode mode, const char *title) { void SDLContext::init_video(const Config &config, const char *title) {
char buff[256]; char buff[256];
static Uint32 update_request_event = SDL_RegisterEvents(1); static Uint32 update_request_event = SDL_RegisterEvents(1);
_update_request_event = update_request_event; _update_request_event = update_request_event;
@ -89,14 +88,14 @@ void SDLContext::init_screen(DisplayMode mode, const char *title) {
assert(!_render_thread.joinable()); assert(!_render_thread.joinable());
int width = 640; int width = config.window_width;
int height = 480; int height = config.window_height;
if (mode == double_window) { aspect_x = config.aspect_x;
width*=2; aspect_y = config.aspect_y;
height*=2; crt_filter_enabled = config.crt_filter;
}
_fullscreen_mode = mode == fullscreen;
_fullscreen_mode = config.fullscreen;
std::atomic<bool> done = false; std::atomic<bool> done = false;
std::exception_ptr e; std::exception_ptr e;
@ -105,20 +104,31 @@ void SDLContext::init_screen(DisplayMode mode, const char *title) {
try { try {
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|(mode==fullscreen?SDL_WINDOW_FULLSCREEN_DESKTOP:0)); width, height, SDL_WINDOW_RESIZABLE|(_fullscreen_mode?SDL_WINDOW_FULLSCREEN_DESKTOP:0));
if (!window) { if (!window) {
snprintf(buff, sizeof(buff), "SDL Error create window: %s\n", SDL_GetError()); snprintf(buff, sizeof(buff), "SDL Error create window: %s\n", SDL_GetError());
throw std::runtime_error(buff); throw std::runtime_error(buff);
} }
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
_window.reset(window); _window.reset(window);
SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), -1, 0); SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), -1, config.composer);
if (!renderer) { if (!renderer) {
snprintf(buff,sizeof(buff), "Chyba při vytváření rendereru: %s\n", SDL_GetError()); snprintf(buff,sizeof(buff), "Failed to create composer: %s\n", SDL_GetError());
throw std::runtime_error(buff); throw std::runtime_error(buff);
} }
SDL_RendererInfo rinfo;
SDL_GetRendererInfo(renderer, &rinfo);
if (stricmp(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);
}
_renderer.reset(renderer); _renderer.reset(renderer);
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, 640, 480); SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, 640, 480);
if (!texture) { if (!texture) {
@ -159,7 +169,7 @@ void SDLContext::init_screen(DisplayMode mode, const char *title) {
} }
void SDLContext::close_screen() { void SDLContext::close_video() {
_render_thread.request_stop(); _render_thread.request_stop();
_render_thread.join(); _render_thread.join();
} }
@ -358,7 +368,7 @@ void SDLContext::update_screen() {
SDL_SetTextureAlphaMod(_visible_texture, 255); SDL_SetTextureAlphaMod(_visible_texture, 255);
SDL_RenderCopy(_renderer.get(), _visible_texture, NULL, &winrc); SDL_RenderCopy(_renderer.get(), _visible_texture, NULL, &winrc);
} }
if (winrc.h > 900) { if (winrc.h > 900 && crt_filter_enabled) {
if (!_crt_effect) { if (!_crt_effect) {
SDL_Texture *txt; SDL_Texture *txt;
generateCRTTexture(_renderer.get(), &txt, 128, std::min<int>(1440, winrc.h)); generateCRTTexture(_renderer.get(), &txt, 128, std::min<int>(1440, winrc.h));
@ -431,21 +441,28 @@ SDL_Rect SDLContext::get_window_aspect_rect() const {
int ww; int ww;
int wh; int wh;
SDL_GetWindowSizeInPixels(_window.get(), &ww, &wh); SDL_GetWindowSizeInPixels(_window.get(), &ww, &wh);
int apw = wh * 4 / 3; if (aspect_x && aspect_y) {
int aph = ww * 3 / 4; int apw = wh * aspect_x / aspect_y;
int fw; int aph = ww * aspect_y / aspect_x;
int fh; int fw;
if (apw > ww) { int fh;
fw = ww; if (apw > ww) {
fh = aph; fw = ww;
fh = aph;
} else {
fw = apw;
fh = wh;
}
w.h = fh;
w.w = fw;
w.x = (ww - fw)/2;
w.y = (wh - fh)/2;
} else { } else {
fw = apw; w.x = 0;
fh = wh; w.y = 0;
w.w = ww;
w.h = wh;
} }
w.h = fh;
w.w = fw;
w.x = (ww - fw)/2;
w.y = (wh - fh)/2;
return w; return w;
} }

View file

@ -14,16 +14,21 @@ public:
SDLContext(); SDLContext();
enum DisplayMode { struct Config {
native_window, int window_width;
double_window, int window_height;
fullscreen bool crt_filter;
int composer;
const char *scale_quality;
bool fullscreen;
int aspect_x;
int aspect_y;
}; };
void init_screen(DisplayMode mode, const char *title); void init_video(const Config &config, const char *title);
void close_screen(); void close_video();
void present_rect(uint16_t *pixels, unsigned int pitch, unsigned int x, unsigned int y, unsigned int xs,unsigned ys); void present_rect(uint16_t *pixels, unsigned int pitch, unsigned int x, unsigned int y, unsigned int xs,unsigned ys);
@ -89,6 +94,9 @@ protected:
MS_EVENT ms_event; MS_EVENT ms_event;
mutable std::mutex _mx; mutable std::mutex _mx;
int aspect_x = 4;
int aspect_y = 3;
bool crt_filter_enabled = false;
std::unique_ptr<SDL_Window, SDL_Deleter> _window; std::unique_ptr<SDL_Window, SDL_Deleter> _window;
std::unique_ptr<SDL_Renderer, SDL_Deleter> _renderer; std::unique_ptr<SDL_Renderer, SDL_Deleter> _renderer;

View file

@ -1,19 +1,21 @@
##### path ##### path
# #
# game_path = path to root of the game # root = path to root of the game. All other paths are relative to this path
# maps = relative path to maps # maps = relative path to maps
# video = relative path to videp # video = relative path to video
# data = relative path to skeldal.ddl # data = relative path to skeldal.ddl
# savegame = path to savegame, if not defined, retrieved from platform settings # savegame = path to savegame, if not defined, retrieved from platform settings
[paths] [paths]
game_path=/home/ondra/skeldal_game/ # root=./
# maps=./maps/ # maps=./maps/
# video=./video/ # video=./video/
# data=./ # data=./
# savegame = determine default # savegame = determine default
#### video settings #### video settings
# #
@ -28,15 +30,17 @@ game_path=/home/ondra/skeldal_game/
# best - best scale quality (SDL = linear) # best - best scale quality (SDL = linear)
# linear - use linear filtering (Direct3D and OpenGL) # linear - use linear filtering (Direct3D and OpenGL)
# nearest - use nearest filtering # nearest - use nearest filtering
# aspect_ratio = x:y, none = don't keep fixed ratio'
# #
[video] [video]
fullscreen=on #fullscreen=on
#window_width=640 #window_width=640
#window_height=480 #window_height=480
#crt_filter=on #crt_filter=on
#smooth_scale=auto #scale_quality=auto
#composer=auto #composer=auto
#scale_quality #aspect_ratio=4:3
[audio]
[audio]