mirror of
https://github.com/ondra-novak/gates_of_skeldal.git
synced 2025-08-18 12:17:13 -04:00
Merge branch 'mapedit_support' of https://github.com/ondra-novak/gates_of_skeldal.git into mapedit_support
This commit is contained in:
commit
bd6ca836ba
24 changed files with 442 additions and 153 deletions
|
@ -725,7 +725,7 @@ void crt_minimap_itr(int sector,int smer,int itrx,int itry, int automap)
|
|||
if (itrx<0 || itrx>VIEW3D_X*2 || itry>VIEW3D_Z) return;
|
||||
if (minimap[itry][itrx]) return;
|
||||
minimap[itry][itrx]=sector;
|
||||
if (!set_halucination) map_coord[sector].flags|=automap & (itrx<=VIEW3D_X+1 && itrx>=VIEW3D_X-1) ;
|
||||
if (automap && !set_halucination && (itrx<=VIEW3D_X+1 && itrx>=VIEW3D_X-1)) map_coord[sector].flags|=MC_AUTOMAP;
|
||||
if (itrx<=VIEW3D_X)
|
||||
{
|
||||
sector_temp=map_sectors[sector].step_next[dirs[0]];
|
||||
|
@ -734,7 +734,7 @@ void crt_minimap_itr(int sector,int smer,int itrx,int itry, int automap)
|
|||
{
|
||||
savee=enter;
|
||||
enter=-enter_tab[itry][itrx];
|
||||
crt_minimap_itr(sector_temp,smer,itrx-1,itry,automap &(sideflags & 1));
|
||||
crt_minimap_itr(sector_temp,smer,itrx-1,itry,automap &(sideflags & SD_AUTOMAP));
|
||||
enter=savee;
|
||||
}
|
||||
}
|
||||
|
@ -746,7 +746,7 @@ void crt_minimap_itr(int sector,int smer,int itrx,int itry, int automap)
|
|||
{
|
||||
savee=enter;
|
||||
enter=enter_tab[itry][itrx];
|
||||
crt_minimap_itr(sector_temp,smer,itrx+1,itry,automap &(sideflags & 1));
|
||||
crt_minimap_itr(sector_temp,smer,itrx+1,itry,automap &(sideflags & SD_AUTOMAP));
|
||||
enter=savee;
|
||||
}
|
||||
}
|
||||
|
@ -756,7 +756,7 @@ void crt_minimap_itr(int sector,int smer,int itrx,int itry, int automap)
|
|||
{
|
||||
savee=enter;
|
||||
enter-=(enter>0)-(enter<0);
|
||||
crt_minimap_itr(sector_temp,smer,itrx,itry+1,automap &(sideflags & 1));
|
||||
crt_minimap_itr(sector_temp,smer,itrx,itry+1,automap &(sideflags & SD_AUTOMAP));
|
||||
enter=savee;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -755,7 +755,7 @@ void a_touch(int sector,int dir);
|
|||
int do_action(int action_numb,int sector,int direct,int flags,int nosend);
|
||||
void delay_action(int action_numb,int sector,int direct,int flags,int nosend,int delay);
|
||||
//int32_t load_section(FILE *f,void **section, int *sct_type,int32_t *sect_size);
|
||||
uint32_t load_section_mem(TMPFILE_RD *f,const void **section, int *sct_type,uint32_t *sect_size);
|
||||
int32_t load_section_mem(TMPFILE_RD *f,const void **section, int *sct_type,uint32_t *sect_size);
|
||||
TMPFILE_RD *open_ddl_file(const char *name, int group);
|
||||
int prepare_graphics(int *ofs,const char *names,int32_t size,ABLOCK_DECODEPROC decomp,int cls);
|
||||
void show_automap(char full);
|
||||
|
@ -1228,7 +1228,7 @@ typedef struct tma_fireball
|
|||
|
||||
typedef struct tma_loadlev
|
||||
{
|
||||
uint8_t action,flags,eflags; //3+padding
|
||||
uint8_t action,flags,lflags; //3+padding
|
||||
short start_pos; //6
|
||||
char dir; //7
|
||||
char name[13];
|
||||
|
|
152
game/interfac.c
152
game/interfac.c
|
@ -18,10 +18,11 @@
|
|||
#include <ctype.h>
|
||||
#include <libs/gui.h>
|
||||
#include <libs/basicobj.h>
|
||||
#include <libs/strlists.h>
|
||||
#include <time.h>
|
||||
#include <libs/mgfplay.h>
|
||||
#include <libs/wav.h>
|
||||
#include <fcntl.h>
|
||||
#include <platform/ugc.h>
|
||||
#include "globals.h"
|
||||
#include "engine1.h"
|
||||
#include <stdarg.h>
|
||||
|
@ -1627,81 +1628,90 @@ char ask_save_dialog(char *name_buffer, size_t name_size, char allow_remove) {
|
|||
|
||||
}
|
||||
|
||||
#if 0
|
||||
//----------------- JRC LOGO ----------------------------------
|
||||
static char *launcher_ddl_file = NULL;
|
||||
static void free_ddl_file_name(void) {
|
||||
free(launcher_ddl_file);
|
||||
}
|
||||
|
||||
#define SHOWDELAY 125
|
||||
#define SHOWDEND (SHOWDELAY-32)
|
||||
const char *run_launcher() {
|
||||
const char *str_label = texty[198];
|
||||
TSTR_LIST lst = create_list(100);
|
||||
TSTR_LIST ddl_lst = create_list(100);
|
||||
CTL3D ctl = {0,0,4,0};
|
||||
int selected = 0;
|
||||
size_t item_count = 1;
|
||||
|
||||
typedef struct _hicolpal
|
||||
{
|
||||
unsigned blue:5;
|
||||
unsigned green:5;
|
||||
unsigned red:5;
|
||||
}HICOLPAL;
|
||||
|
||||
void show_jrc_logo(char *filename)
|
||||
{
|
||||
char *pcx;word *pcxw;
|
||||
char bnk=1;
|
||||
int xp,yp,i;
|
||||
word palette[256],*palw;
|
||||
int cntr,cdiff,cpalf,ccc;
|
||||
|
||||
change_music(NULL);
|
||||
curcolor=0;bar32(0,0,639,479);
|
||||
showview(0,0,0,0);sleep_ms(1000);
|
||||
const char *s = build_pathname(2, gpathtable[SR_VIDEO],filename);
|
||||
if (open_pcx(s,A_8BIT,&pcx)) return;
|
||||
pcxw=(word *)pcx;
|
||||
xp=pcxw[0];
|
||||
yp=pcxw[1];
|
||||
palw=pcxw+3;
|
||||
memcpy(palette,palw,256*sizeof(word));
|
||||
memset(palw,0,256*sizeof(word));
|
||||
xp/=2;yp/=2;xp=320-xp;yp=240-yp;
|
||||
cntr=get_timer_value();ccc=0;
|
||||
do
|
||||
{
|
||||
cdiff=(get_timer_value()-cntr)/2;
|
||||
if (cdiff<SHOWDEND && ccc!=cdiff)
|
||||
{
|
||||
cpalf=cdiff;
|
||||
if (cpalf<32)
|
||||
for (i=0;i<256;i++)
|
||||
{
|
||||
int r=(cpalf<<11),g=(cpalf<<6),b=cpalf,k;
|
||||
k=palette[i] & 0xF800;if (k>r) palw[i]=r;else palw[i]=k;
|
||||
k=palette[i] & 0x7e0;if (k>g) palw[i]|=g;else palw[i]|=k;
|
||||
k=palette[i] & 0x1f;if (k>b) palw[i]|=b;else palw[i]|=k;
|
||||
UGCManager *ugc = UGC_create();
|
||||
size_t ugccount = UGC_Fetch(ugc);;
|
||||
for (size_t i = 0; i < ugccount; ++i) {
|
||||
UGCItem item = UGC_GetItem(ugc, i);
|
||||
char buff[60];
|
||||
const char *title = item.name;
|
||||
size_t tlen = strlen(title);
|
||||
const char *author = item.author;
|
||||
size_t alen = strlen(author);
|
||||
size_t reserve = sizeof(buff)-4;
|
||||
char d1 = 0;
|
||||
char d2 = 0;
|
||||
if (tlen + alen > reserve) {
|
||||
if (alen < reserve/2) {tlen = reserve - alen - 3;d1 = 1;}
|
||||
else if (tlen < reserve/2) {alen = reserve - tlen - 3;d2=1;}
|
||||
else {
|
||||
tlen = reserve/2-3; d1 = 1;
|
||||
alen = reserve/2-3; d2 = 1;
|
||||
}
|
||||
}
|
||||
char *iter = buff;
|
||||
for (size_t i = 0; i < tlen; ++i) *iter++ = title[i];
|
||||
if (d1) for (size_t i = 0; i < 3; ++i) *iter++='.';
|
||||
memcpy(iter, " - ",3); iter+=3;
|
||||
for (size_t i = 0; i < alen; ++i) *iter++ = author[i];
|
||||
if (d2) for (size_t i = 0; i < 3; ++i) *iter++='.';
|
||||
*iter = 0;
|
||||
str_add(&lst, buff);
|
||||
str_add(&ddl_lst, item.ddl_path);
|
||||
++item_count;
|
||||
}
|
||||
else if (ccc!=cdiff)
|
||||
{
|
||||
cpalf=SHOWDELAY-cdiff;
|
||||
if (cpalf<32)
|
||||
for (i=0;i<256;i++)
|
||||
{
|
||||
int r,g,b,k=32-cpalf;
|
||||
|
||||
b=palette[i];g=b>>5;b&=0x1f;r=g>>6;g&=0x1f;
|
||||
b-=k;r-=k;g-=k;
|
||||
if (b<0) b=0;
|
||||
if (r<0) r=0;
|
||||
if (g<0) g=0;
|
||||
palw[i]=b | (r<<11) | (g<<6);
|
||||
}
|
||||
str_add(&lst, texty[199]);
|
||||
str_add(&ddl_lst, "");
|
||||
|
||||
|
||||
curcolor = RGB555(0,0,0);
|
||||
set_font(H_FBIG,RGB555_ALPHA(31,31,31));
|
||||
add_window(120,60,400,300,H_WINTXTR,3,20,20);
|
||||
define(-1,20,10,1,1,0,label,str_label);
|
||||
set_font(H_FKNIHA,RGB555_ALPHA(31,31,31));
|
||||
define(9,15,38,335,212,0,&listbox,lst,RGB555(16,16,16),0);
|
||||
property(&ctl,NULL,NULL,RGB555(0,0,0));c_default(0);
|
||||
if (item_count>19) {
|
||||
define(10,355,38,20,212,0,scroll_bar_v,0,item_count-19,19,RGB555(8,8,8));
|
||||
property(&ctl,NULL,NULL,RGB555(10,10,10));
|
||||
}
|
||||
put_picture(xp, yp, pcx);
|
||||
if (bnk) {
|
||||
showview(xp, yp, pcxw[0], pcxw[1]);
|
||||
}
|
||||
ccc=cdiff;
|
||||
mix_back_sound(0);
|
||||
}
|
||||
while (cdiff<SHOWDELAY && !_bios_keybrd(_KEYBRD_READY));
|
||||
curcolor=0;bar32(0,0,639,479);
|
||||
showview(0,0,0,0);
|
||||
free(pcx);
|
||||
}
|
||||
#endif
|
||||
define(20,20,20,60,20,2,button,texty[43]);property(def_border(5,BAR_COLOR),NULL,NULL,BAR_COLOR);on_control_change(terminate_gui);
|
||||
define(30,90,20,60,20,2,button,texty[80]);property(def_border(5,BAR_COLOR),NULL,NULL,BAR_COLOR);on_control_change(terminate_gui);
|
||||
redraw_window();
|
||||
send_message(E_ADD,E_KEYBOARD,save_dialog_keyboards);
|
||||
send_message(E_ADD,E_MOUSE,save_dialog_keyboards);
|
||||
escape();
|
||||
send_message(E_DONE,E_KEYBOARD,save_dialog_keyboards);
|
||||
send_message(E_DONE,E_MOUSE,save_dialog_keyboards);
|
||||
int butt = o_aktual->id;
|
||||
get_value(0,9,&selected);
|
||||
char *selddl = strdup(ddl_lst[selected]);
|
||||
release_list(lst);
|
||||
release_list(ddl_lst);
|
||||
close_current();
|
||||
if (butt != 30 || selddl == NULL || selddl[0] == 0) {
|
||||
free(selddl);
|
||||
UGC_Destroy(ugc);
|
||||
return butt != 30?NULL:"";
|
||||
}
|
||||
launcher_ddl_file = selddl;
|
||||
UGC_StartPlay(ugc, selected);
|
||||
UGC_Destroy(ugc);
|
||||
atexit(&free_ddl_file_name);
|
||||
return launcher_ddl_file;
|
||||
}
|
|
@ -117,7 +117,7 @@ int32_t load_section(FILE *f,void **section, int *sct_type,int32_t *sect_size)
|
|||
}
|
||||
*/
|
||||
|
||||
uint32_t load_section_mem(TMPFILE_RD *f,const void **section, int *sct_type,uint32_t *sect_size) {
|
||||
int32_t load_section_mem(TMPFILE_RD *f,const void **section, int *sct_type,uint32_t *sect_size) {
|
||||
uint32_t s;
|
||||
char c[20];
|
||||
|
||||
|
@ -284,8 +284,8 @@ int load_map(const char *filename)
|
|||
mapsize = 0;
|
||||
do
|
||||
{
|
||||
uint32_t r=load_section_mem(f,&temp,§,&size);
|
||||
if (r==size)
|
||||
int32_t r=load_section_mem(f,&temp,§,&size);
|
||||
if (r==(int32_t)size)
|
||||
switch (sect)
|
||||
{
|
||||
case A_SIDEMAP:
|
||||
|
|
101
game/skeldal.c
101
game/skeldal.c
|
@ -16,6 +16,7 @@
|
|||
#include <libs/mgfplay.h>
|
||||
#include <libs/inicfg.h>
|
||||
#include <platform/save_folder.h>
|
||||
#include <platform/ugc.h>
|
||||
#include "globals.h"
|
||||
#include "resources.h"
|
||||
//
|
||||
|
@ -825,6 +826,8 @@ void cti_texty(void)
|
|||
//patch stringtable
|
||||
if (!texty[98]) str_replace(&texty,98,"Ulo\x91it hru jako");
|
||||
if (!texty[99]) str_replace(&texty,99,"CRT Filter (>720p)");
|
||||
if (!texty[198]) str_replace(&texty,198,"Zvol dobrodru\x91stv\xA1");
|
||||
if (!texty[199]) str_replace(&texty,199,"Br\xA0ny Skeldalu (p\x96vodn\xA1 dobrodru\x91stv\xA1)");
|
||||
str_replace(&texty, 144, "Zrychlit souboje");
|
||||
str_replace(&texty, 51, "Celkov\x88 Hudba Efekty V\x98\xA8ky Basy Rychlost");
|
||||
str_replace(&texty,0,"Byl nalezen p\xA9ipojen\x98 ovlada\x87\nPro aktivaci ovlada\x87""e stiskn\x88te kter\x82koliv tla\x87\xA1tko na ovlada\x87i");
|
||||
|
@ -888,14 +891,17 @@ const void *boldcz;
|
|||
void init_DDL_manager() {
|
||||
|
||||
const char *ddlfile = build_pathname(2, gpathtable[SR_DATA],"SKELDAL.DDL");
|
||||
ddlfile = local_strdup(ddlfile);
|
||||
ddlfile = local_strdup(ddlfile);
|
||||
|
||||
init_manager();
|
||||
for (size_t sz = countof(patch_files); sz > 0;) {
|
||||
--sz;
|
||||
if (patch_files[sz]) {
|
||||
if (!add_patch_file(patch_files[sz])) {
|
||||
display_error("Can't open resource file (adv_patch): %s", patch_files[sz]);
|
||||
if (!add_patch_file(ddlfile)) {
|
||||
display_error("Can't open resource file (main): %s", ddlfile);
|
||||
abort();
|
||||
}
|
||||
for (size_t i = 0; i < countof(patch_files); ++i) {
|
||||
if (patch_files[i]) {
|
||||
if (!add_patch_file(patch_files[i])) {
|
||||
display_error("Can't open resource file (adv_patch): %s", patch_files[i]);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
@ -906,10 +912,6 @@ void init_DDL_manager() {
|
|||
gfx = local_strdup(gfx);
|
||||
add_patch_file(gfx);
|
||||
}
|
||||
if (!add_patch_file(ddlfile)) {
|
||||
display_error("Can't open resource file (main): %s", ddlfile);
|
||||
abort();
|
||||
}
|
||||
|
||||
SEND_LOG("(GAME) Memory manager initialized. Using DDL: '%s'",ddlfile);
|
||||
|
||||
|
@ -968,7 +970,12 @@ void sse_listener_watch(EVENT_MSG *msg, void **userdata) {
|
|||
if (msg->msg == E_WATCH) {
|
||||
const char *s = sse_receiver_receive(sse_receiver);
|
||||
if (s) {
|
||||
send_message(E_EXTERNAL_MSG, s);
|
||||
if (strcmp(s,"STOP") == 0) {
|
||||
closemode();
|
||||
exit(0);
|
||||
} else {
|
||||
send_message(E_EXTERNAL_MSG, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1070,8 +1077,6 @@ void init_skeldal(const INI_CONFIG *cfg)
|
|||
|
||||
load_shops();
|
||||
memset(&loadlevel,0,sizeof(loadlevel));
|
||||
loadlevel.eflags = 0xFF;
|
||||
|
||||
}
|
||||
|
||||
void wire_main_functs();
|
||||
|
@ -1128,29 +1133,35 @@ extern char running_battle;
|
|||
const char *m = va_arg(msg->data, const char *);
|
||||
char fname[13];
|
||||
int sector;
|
||||
int side;
|
||||
int i;
|
||||
|
||||
if (sscanf(m, "RELOAD %12s %d", fname, §or) == 2) {
|
||||
if (sscanf(m, "RELOAD %12s %d %d", fname, §or, &side) == 3) {
|
||||
|
||||
reload_ddls();
|
||||
strcopy_n(loadlevel.name,fname,sizeof(loadlevel.name));
|
||||
loadlevel.start_pos=sector;
|
||||
loadlevel.start_pos=sector;
|
||||
loadlevel.dir = side;
|
||||
for(i=0;i<POCET_POSTAV;i++) if (postavy[i].used) {
|
||||
postavy[i].sektor=loadlevel.start_pos;
|
||||
postavy[i].direction=loadlevel.dir;
|
||||
postavy[i].groupnum = 1;
|
||||
}
|
||||
SEND_LOG("(WIZARD) Load map '%s' %d",loadlevel.name,loadlevel.start_pos);
|
||||
SEND_LOG("(WIZARD) Load map '%s' %d %d",loadlevel.name,loadlevel.start_pos, loadlevel.dir);
|
||||
unwire_proc();
|
||||
if (battle) konec_kola();
|
||||
battle=0;
|
||||
running_battle=0;
|
||||
doNotLoadMapState=1;
|
||||
hl_ptr=ikon_libs;
|
||||
destroy_fly_map();
|
||||
load_items();
|
||||
zneplatnit_block(H_ENEMY);
|
||||
zneplatnit_block(H_SHOP_PIC);
|
||||
zneplatnit_block(H_DIALOGY_DAT);
|
||||
battle=0;
|
||||
running_battle=0;
|
||||
doNotLoadMapState=1;
|
||||
hl_ptr=ikon_libs;
|
||||
destroy_fly_map();
|
||||
load_items();
|
||||
zneplatnit_block(H_ENEMY);
|
||||
zneplatnit_block(H_SHOP_PIC);
|
||||
zneplatnit_block(H_DIALOGY_DAT);
|
||||
load_shops();
|
||||
autosave_on_enter = 0;
|
||||
game_display_focus();
|
||||
send_message(E_CLOSE_MAP);
|
||||
} else if (strncmp(m, "MESSAGE ", 8) == 0) {
|
||||
bott_disp_text(m+8);
|
||||
|
@ -1180,8 +1191,8 @@ void enter_game(void)
|
|||
|
||||
send_message(E_ADD,E_RELOADMAP,reload_map_handler);
|
||||
{
|
||||
EVENT_MSG *msg = task_wait_event(E_CLOSE_MAP);
|
||||
end = va_arg(msg->data, int);
|
||||
EVENT_MSG *msg = task_wait_event(E_CLOSE_MAP);
|
||||
end = msg != NULL?va_arg(msg->data, int):0;
|
||||
}
|
||||
send_message(E_DONE,E_RELOADMAP,reload_map_handler);
|
||||
|
||||
|
@ -1196,22 +1207,8 @@ void enter_game(void)
|
|||
}
|
||||
|
||||
|
||||
static int update_config(void)
|
||||
{
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void help(void)
|
||||
{
|
||||
printf("Pouziti:\n\n S <filename.MAP> <start_sector>\n\n"
|
||||
"<filename.MAP> jmeno mapy\n"
|
||||
"<start_sector> Cislo startovaciho sektoru\n"
|
||||
);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
extern char nofloors;
|
||||
|
||||
/*
|
||||
|
@ -1496,11 +1493,6 @@ static void start_from_mapedit(va_list args)
|
|||
}
|
||||
#endif
|
||||
|
||||
void disable_intro(void)
|
||||
{
|
||||
add_field_num(&cur_config,sinit[12].heslo,1);
|
||||
update_config();
|
||||
}
|
||||
|
||||
/*
|
||||
* -char def_path[]="";
|
||||
|
@ -1560,6 +1552,8 @@ const char *configure_pathtable(const INI_CONFIG *cfg) {
|
|||
if (ini_get_boolean(paths, "patch_mode", 0)) {
|
||||
mman_patch = 1;
|
||||
}
|
||||
const char *ugc_path = ini_get_string(paths, "local_ugc", "adv");
|
||||
UGCSetLocalFoler(ugc_path);
|
||||
|
||||
return groot;
|
||||
}
|
||||
|
@ -1610,6 +1604,7 @@ int skeldal_gen_string_table_entry_point(const SKELDAL_CONFIG *start_cfg, const
|
|||
return 0;
|
||||
}
|
||||
|
||||
const char *run_launcher();
|
||||
int skeldal_entry_point(const SKELDAL_CONFIG *start_cfg)
|
||||
{
|
||||
def_mman_group_table(gpathtable);
|
||||
|
@ -1665,21 +1660,29 @@ int skeldal_entry_point(const SKELDAL_CONFIG *start_cfg)
|
|||
|
||||
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();
|
||||
|
||||
|
||||
ini_close(cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "version.h"
|
||||
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ typedef struct {
|
|||
const char *patch_file;
|
||||
|
||||
const char *sse_hostport;
|
||||
char launcher; //<run launcher
|
||||
|
||||
} SKELDAL_CONFIG;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ SET(files basicobj.c
|
|||
mgifplaya.c
|
||||
pcx.c
|
||||
wav_mem.c
|
||||
strlite.c
|
||||
strlists.c
|
||||
cztable.c
|
||||
minimp3.c
|
||||
music.cpp
|
||||
|
|
|
@ -131,7 +131,7 @@ typedef struct ddlmap_info {
|
|||
char *path;
|
||||
} TDDLMAP_INFO;
|
||||
|
||||
#define MAX_PATCHES 4
|
||||
#define MAX_PATCHES 8
|
||||
|
||||
static TDDLMAP_INFO ddlmap[MAX_PATCHES];
|
||||
|
||||
|
@ -178,8 +178,12 @@ static TNAMETABLE_REF load_file_table(const void *bmf_m)
|
|||
const uint32_t *src_table = (const uint32_t *)bmf_m;
|
||||
uint32_t grptabsiz = src_table[1];
|
||||
TNAMETABLE_REF out;
|
||||
out.data = (const TNAMETABLE *)((const char *)bmf_m + grptabsiz);
|
||||
out.count = (out.data[0].seek - grptabsiz)/sizeof(TNAMETABLE);
|
||||
const TNAMETABLE *ptr = (const TNAMETABLE *)((const char *)bmf_m + grptabsiz);
|
||||
size_t count = (ptr[0].seek - grptabsiz)/sizeof(TNAMETABLE);
|
||||
TNAMETABLE *tbl = NewArr(TNAMETABLE, count);
|
||||
memcpy(tbl,ptr, count * sizeof(TNAMETABLE) );
|
||||
out.data = tbl;
|
||||
out.count = count;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -201,7 +205,8 @@ char get_file_entry(int group,const char *name, THANDLE_DATA *h) {
|
|||
|
||||
ex=mman_patch && test_file_exist_DOS(group,name);
|
||||
if (!ex) {
|
||||
for (int i = 0; i < MAX_PATCHES; ++i) {
|
||||
for (int i = MAX_PATCHES; i >0 ; ) {
|
||||
--i;
|
||||
const TDDLMAP_INFO *nfo = &ddlmap[i];
|
||||
if (nfo->ptr) {
|
||||
int sk = get_file_entry_in_table(&nfo->nametable, name);
|
||||
|
@ -329,6 +334,7 @@ void reload_ddls(void) {
|
|||
}
|
||||
h->status = BK_NOT_LOADED;
|
||||
h->blockdata = NULL;
|
||||
get_file_entry(h->path,h->src_file,h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -343,9 +349,19 @@ void reload_ddls(void) {
|
|||
}
|
||||
dinfo->ptr = bmf;
|
||||
dinfo->size = bmf_s;
|
||||
ablock_free(dinfo->nametable.data);
|
||||
dinfo->nametable = load_file_table(bmf);
|
||||
}
|
||||
}
|
||||
for(i=0;i<BK_MAJOR_HANDLES;i++) if (_handles[i]!=NULL) {
|
||||
p=(THANDLE_DATA *)(_handles[i]);
|
||||
for(j=0;j<BK_MINOR_HANDLES;j++) {
|
||||
THANDLE_DATA *h = p+j;
|
||||
if (h->src_file[0]) {
|
||||
get_file_entry(h->path,h->src_file,h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -630,8 +646,9 @@ void close_manager()
|
|||
for(j=0;j<BK_MINOR_HANDLES;j ++) undef_handle(i*BK_MINOR_HANDLES+j);
|
||||
free(_handles[i]);
|
||||
}
|
||||
for (int i = 0; i < MAX_PATCHES; ++i) {
|
||||
for (int i = 0; i < MAX_PATCHES; ++i) if (ddlmap[i].ptr) {
|
||||
unmap_file((void *)ddlmap[i].ptr, ddlmap[i].size);
|
||||
ablock_free(ddlmap[i].nametable.data);
|
||||
free(ddlmap[i].path);
|
||||
}
|
||||
|
||||
|
|
|
@ -275,16 +275,4 @@ void listbox(OBJREC *o)
|
|||
//o->done=string_list_done;
|
||||
}
|
||||
|
||||
/*void main()
|
||||
{
|
||||
TSTR_LIST test;
|
||||
int i,j;
|
||||
|
||||
test=read_directory("c:\\windows\\system\\*.*",DIR_BREIF,_A_NORMAL);
|
||||
j=str_count(test);
|
||||
for(i=0;i<j;i++)
|
||||
if (test[i]!=NULL) printf("%s\n",test[i]);
|
||||
printf("%d souboru.\n",j);
|
||||
release_list(test);
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -13,6 +13,7 @@ target_sources(skeldal_platform PRIVATE
|
|||
getopt.c
|
||||
achievements.cpp
|
||||
sse_receiver.c
|
||||
ugc.cpp
|
||||
)
|
||||
|
||||
set(all_libs
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <filesystem>
|
||||
|
||||
typedef struct ini_config_section_tag {
|
||||
using Section = std::map<std::string, std::string, std::less<>>;
|
||||
|
@ -59,7 +60,8 @@ void parseIniStream(std::istream& input, Callback &&callback) {
|
|||
|
||||
INI_CONFIG* ini_open(const char *filename) {
|
||||
|
||||
std::fstream input(filename);
|
||||
std::filesystem::path fname(reinterpret_cast<const char8_t *>(filename));
|
||||
std::fstream input(fname);
|
||||
if (!input) return NULL;
|
||||
INI_CONFIG *c = new INI_CONFIG;
|
||||
parseIniStream(input, [&](std::string_view section, std::string_view key, std::string_view value) {
|
||||
|
|
|
@ -17,6 +17,7 @@ struct TaskInfo {
|
|||
bool exited = false;
|
||||
|
||||
TaskInfo(int id):id(id) {}
|
||||
~TaskInfo();
|
||||
};
|
||||
|
||||
using TaskList = std::unordered_map<int, std::unique_ptr<TaskInfo> >;
|
||||
|
@ -212,3 +213,11 @@ void task_sleep_for(unsigned int time_ms) {
|
|||
}
|
||||
}
|
||||
|
||||
TaskInfo::~TaskInfo() {
|
||||
|
||||
//destructor is called only when task is already in cleanup state
|
||||
if (!exited) {
|
||||
thr.detach();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ void show_help(const char *arg0) {
|
|||
"-l <lang> set language (cz|en)\n"
|
||||
"-s <directory> generate string-tables (for localization) and exit\n"
|
||||
"-c <host:port> connect to host:port for remote control (mapedit)\n"
|
||||
"-L run launcher - select workshop adventure\n"
|
||||
"-h this help\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -38,13 +39,15 @@ int main(int argc, char **argv) {
|
|||
std::string patch;
|
||||
std::string lang;
|
||||
std::string sse_hostport;
|
||||
for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:s:l:p:c:")) != -1; ) {
|
||||
bool launcher = false;
|
||||
for (int optchr = -1; (optchr = getopt(argc, argv, "hLf:a:s:l:p:c:")) != -1; ) {
|
||||
switch (optchr) {
|
||||
case 'f': config_name = optarg;break;
|
||||
case 'a': adv_config_file = optarg;break;
|
||||
case 'h': show_help(argv[0]);break;
|
||||
case 'p': patch = optarg; break;
|
||||
case 'l': lang = optarg;break;
|
||||
case 'L': launcher = true;break;
|
||||
case 's': gen_stringtable_path = optarg;break;
|
||||
case 'c': sse_hostport = optarg;break;
|
||||
default: show_help_short();
|
||||
|
@ -62,6 +65,7 @@ int main(int argc, char **argv) {
|
|||
cfg.lang_path = lang.empty()?NULL:lang.c_str();
|
||||
cfg.patch_file = patch.empty()?NULL:patch.c_str();
|
||||
cfg.sse_hostport = sse_hostport.empty()?NULL:sse_hostport.c_str();
|
||||
cfg.launcher = launcher?1:0;
|
||||
try {
|
||||
|
||||
if (!gen_stringtable_path.empty()) {
|
||||
|
|
|
@ -281,3 +281,9 @@ void game_display_disable_crt_effect_temporary(char disable) {
|
|||
auto &sdl = get_sdl_global_context();
|
||||
sdl.disable_crt_effect_temprary(disable?true:false);
|
||||
}
|
||||
|
||||
void game_display_focus()
|
||||
{
|
||||
auto &sdl = get_sdl_global_context();
|
||||
sdl.raise_window();
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ void game_display_hide_sprite(int sprite_id);
|
|||
///unload sprite and free index
|
||||
void game_display_unload_sprite(int sprite);
|
||||
void game_display_disable_crt_effect_temporary(char disable);
|
||||
void game_display_focus();
|
||||
|
||||
void *DxPrepareWalk(int ypos);
|
||||
void DxZoomWalk(void *handle, int ypos, int *points,float phase, void *lodka);
|
||||
|
|
|
@ -1354,3 +1354,12 @@ SDLContext::JoystickButton SDLContext::button_from_string(std::string_view s) {
|
|||
void SDLContext::disable_crt_effect_temprary(bool disable) {
|
||||
_disable_crt_tmp = disable;
|
||||
}
|
||||
|
||||
void SDLContext::raise_window() const
|
||||
{
|
||||
SDL_RaiseWindow(_window.get());
|
||||
SDL_SetWindowAlwaysOnTop(_window.get(),SDL_TRUE);
|
||||
SDL_Delay(100); // malá pauza (volitelné)
|
||||
SDL_SetWindowAlwaysOnTop(_window.get(),SDL_FALSE);
|
||||
|
||||
}
|
||||
|
|
|
@ -163,6 +163,8 @@ public:
|
|||
bool is_joystick_used() const;
|
||||
bool is_joystick_enabled() const;
|
||||
void disable_crt_effect_temprary(bool disable);
|
||||
|
||||
void raise_window() const;
|
||||
protected:
|
||||
|
||||
struct SDL_Deleter {
|
||||
|
|
|
@ -252,6 +252,7 @@ void stop_play_music() {
|
|||
if (music_source) {
|
||||
fade_music();
|
||||
stop_music();
|
||||
current_music.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ static void set_nonblocking(sock_t sock) {
|
|||
static int connect_and_handshake(SSE_RECEIVER *sse) {
|
||||
struct addrinfo hints = {0}, *res = NULL;
|
||||
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (getaddrinfo(sse->host, sse->port, &hints, &res) != 0) {
|
||||
|
@ -128,6 +128,12 @@ const char *sse_receiver_receive(SSE_RECEIVER *sse) {
|
|||
if (strncmp(r,"data:",5) == 0) {
|
||||
r+=5;
|
||||
while (*r && isspace(*r)) ++r;
|
||||
char *s = strchr(r, 0)-1;
|
||||
while (s > r && isspace(*s)) {
|
||||
*s = 0;
|
||||
--s;
|
||||
}
|
||||
|
||||
if (*r) {
|
||||
return r;
|
||||
}
|
||||
|
|
190
platform/ugc.cpp
Normal file
190
platform/ugc.cpp
Normal file
|
@ -0,0 +1,190 @@
|
|||
#include "ugc.h"
|
||||
#include "config.h"
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
#include <string_view>
|
||||
|
||||
|
||||
#include <memory>
|
||||
|
||||
std::wstring toWideChar(std::string_view text) {
|
||||
unsigned int codepoint = 0;
|
||||
unsigned int bytes = 0;
|
||||
std::wstring out;
|
||||
for (char c : text) {
|
||||
if ((c & 0x80) == 0) out.push_back(c);
|
||||
else {
|
||||
if ((c & 0xC0) == 0x80) {
|
||||
codepoint = (codepoint << 6) | (c & 0x3F);
|
||||
} else if ((c & 0xE0) == 0xC0) {
|
||||
bytes=2; codepoint = c & 0x1F;
|
||||
} else if ((c & 0xF0) == 0xE0) {
|
||||
bytes=3; codepoint = c & 0x0F;
|
||||
} else if ((c & 0xF8) == 0xF0) {
|
||||
bytes=4; codepoint = c & 0x07;
|
||||
}
|
||||
--bytes;
|
||||
if (!bytes) out.push_back(static_cast<wchar_t>(codepoint));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
constexpr std::pair<int,int> cztable[]={
|
||||
{0x010C,'\x80'},
|
||||
{0x00FC,'u'},
|
||||
{0x00E9,'\x82'},
|
||||
{0x010F,'\x83'},
|
||||
{0x00E4,'a'},
|
||||
{0x010E,'\x85'},
|
||||
{0x0164,'\x86'},
|
||||
{0x010D,'\x87'},
|
||||
{0x011B,'\x88'},
|
||||
{0x011A,'\x89'},
|
||||
{0x0139,'L'},
|
||||
{0x00CD,'\x8B'},
|
||||
{0x013E,'l'},
|
||||
{0x013A,'l'},
|
||||
{0x00C4,'A'},
|
||||
{0x00C1,'\x8F'},
|
||||
{0x00C9,'\x90'},
|
||||
{0x017E,'\x91'},
|
||||
{0x017D,'\x92'},
|
||||
{0x00F4,'o'},
|
||||
{0x00F6,'o'},
|
||||
{0x00D3,'\x95'},
|
||||
{0x016F,'\x96'},
|
||||
{0x00DA,'\x97'},
|
||||
{0x00FD,'\x98'},
|
||||
{0x00D6,'O'},
|
||||
{0x00DC,'U'},
|
||||
{0x0160,'\x9b'},
|
||||
{0x013D,'L'},
|
||||
{0x00DD,'\x9d'},
|
||||
{0x0158,'\x9e'},
|
||||
{0x0165,'\x9f'},
|
||||
{0x00E1,'\xA0'},
|
||||
{0x00ED,'\xA1'},
|
||||
{0x00F3,'\xA2'},
|
||||
{0x00FA,'\xA3'},
|
||||
{0x0148,'\xA4'},
|
||||
{0x0147,'\xA5'},
|
||||
{0x016E,'\xA6'},
|
||||
{0x00D4,'O'},
|
||||
{0x0161,'\xA8'},
|
||||
{0x0159,'\xA9'},
|
||||
{0x0155,'r'},
|
||||
{0x0154,'R'},
|
||||
{0x00BC,'\xAC'},
|
||||
{0x00A7,'\xAD'},
|
||||
{0x00AB,'<'},
|
||||
{0x00BB,'>'},
|
||||
};
|
||||
|
||||
|
||||
std::string toKEYBCS2(const char *text) {
|
||||
auto wstr = toWideChar(text);
|
||||
std::string out;
|
||||
out.resize(wstr.size());
|
||||
std::transform(wstr.begin(), wstr.end(), out.begin(), [](wchar_t c){
|
||||
if (c <= 0x80) return static_cast<char>(c);
|
||||
auto iter = std::find_if(std::begin(cztable), std::end(cztable), [c](const auto &x){return x.first == c;});
|
||||
if (iter == std::end(cztable)) return '_';
|
||||
return static_cast<char>(iter->second);
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
struct UGCItemEx : UGCItem {
|
||||
std::unique_ptr<char[]> text_data;
|
||||
std::filesystem::path _stamp_file;
|
||||
};
|
||||
|
||||
struct tag_UGCManager {
|
||||
std::vector<UGCItemEx> _list;
|
||||
};
|
||||
|
||||
UGCManager *UGC_create() {
|
||||
return new UGCManager;
|
||||
}
|
||||
void UGC_Destroy(UGCManager *inst) {
|
||||
delete inst;
|
||||
}
|
||||
|
||||
static std::filesystem::path ugc_local_path;
|
||||
|
||||
void UGCSetLocalFoler(const char *path) {
|
||||
ugc_local_path = reinterpret_cast<const char8_t *>(path);
|
||||
}
|
||||
|
||||
size_t UGC_Fetch(UGCManager *manager) {
|
||||
|
||||
manager->_list.clear();
|
||||
std::error_code ec;
|
||||
auto iter = std::filesystem::directory_iterator(ugc_local_path,ec);
|
||||
if (ec == std::error_code()) {
|
||||
auto fend = std::filesystem::directory_iterator();
|
||||
while (iter != fend) {
|
||||
const auto &entry = *iter;
|
||||
if (entry.is_directory()) {
|
||||
auto entry_path =std::filesystem::weakly_canonical(entry.path()) ;
|
||||
auto info_path = entry_path / "content.ini";
|
||||
if (std::filesystem::is_regular_file(info_path)) {
|
||||
INI_CONFIG *cfg = ini_open(reinterpret_cast<const char *>(info_path.u8string().c_str()));
|
||||
if (cfg) {
|
||||
const INI_CONFIG_SECTION *section = ini_section_open(cfg, "description");
|
||||
std::string title = toKEYBCS2(ini_get_string(section, "title", NULL));
|
||||
std::string author = toKEYBCS2(ini_get_string(section, "author", "unknown author"));
|
||||
const INI_CONFIG_SECTION *files = ini_section_open(cfg, "files");
|
||||
const char *ddl = ini_get_string(files, "ddlfile", NULL);
|
||||
if (ddl && !title.empty()) {
|
||||
UGCItemEx r;
|
||||
std::filesystem::path ddlpath = entry_path / ddl;
|
||||
auto pstr = ddlpath.u8string();
|
||||
ddl = reinterpret_cast<const char *>(pstr.c_str());
|
||||
|
||||
auto tlen = title.size()+1;
|
||||
auto alen = author.size()+1;
|
||||
auto dlen = strlen(ddl)+1;
|
||||
|
||||
r.text_data = std::make_unique<char[]>(tlen+alen+dlen);
|
||||
char *c = r.text_data.get();
|
||||
memcpy(c, title.c_str(), tlen);r.name = c;c+=tlen;
|
||||
memcpy(c, author.c_str(), alen);r.author = c;c+=alen;
|
||||
memcpy(c, ddl, dlen);r.ddl_path= c;c+=alen;
|
||||
|
||||
auto stampfile = entry_path / "stamp";
|
||||
std::filesystem::file_time_type tp = std::filesystem::last_write_time(stampfile, ec);
|
||||
auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp - std::filesystem::file_time_type::clock::now()
|
||||
+ std::chrono::system_clock::now());
|
||||
r.last_played = std::chrono::system_clock::to_time_t(sctp);
|
||||
r._stamp_file = std::move(stampfile);
|
||||
manager->_list.push_back(std::move(r));
|
||||
}
|
||||
ini_close(cfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
|
||||
}
|
||||
std::sort(manager->_list.begin(), manager->_list.end(), [](const UGCItem &a, const UGCItem &b){
|
||||
return a.last_played > b.last_played;
|
||||
});
|
||||
|
||||
return manager->_list.size();
|
||||
|
||||
}
|
||||
UGCItem UGC_GetItem(UGCManager *manager, size_t pos) {
|
||||
return manager->_list[pos];
|
||||
}
|
||||
|
||||
void UGC_StartPlay(UGCManager *manager, size_t pos) {
|
||||
std::ofstream out(manager->_list[pos]._stamp_file, std::ios::out|std::ios::trunc);
|
||||
}
|
||||
|
||||
|
||||
|
29
platform/ugc.h
Normal file
29
platform/ugc.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include <time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *ddl_path;
|
||||
const char *author;
|
||||
time_t last_played;
|
||||
} UGCItem;
|
||||
|
||||
typedef struct tag_UGCManager UGCManager;
|
||||
|
||||
|
||||
void UGCSetLocalFoler(const char *path);
|
||||
UGCManager *UGC_create();
|
||||
size_t UGC_Fetch(UGCManager *manager);
|
||||
UGCItem UGC_GetItem(UGCManager *manager, size_t pos);
|
||||
void UGC_StartPlay(UGCManager *manager, size_t pos);
|
||||
void UGC_Destroy(UGCManager *inst);
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -25,6 +25,7 @@ void show_help(std::ostream &out, const char *arg0) {
|
|||
"-l <lang> set language (cz|en)\n"
|
||||
"-s <directory> generate string-tables (for localization) and exit\n"
|
||||
"-c <host:port> connect to host:port for remote control (mapedit)\n"
|
||||
"-L run launcher - select workshop adventure\n"
|
||||
"-h this help\n";
|
||||
}
|
||||
|
||||
|
@ -40,14 +41,17 @@ int main(int argc, char **argv) {
|
|||
std::string lang;
|
||||
std::string patch;
|
||||
std::string sse_hostport;
|
||||
bool launcher = false;
|
||||
std::ostringstream console;
|
||||
for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:s:l:c:p:")) != -1; ) {
|
||||
for (int optchr = -1; (optchr = getopt(argc, argv, "hLf:a:s:l:c:p:")) != -1; ) {
|
||||
switch (optchr) {
|
||||
case 'f': config_name = optarg;break;
|
||||
case 'a': adv_config_file = optarg;break;
|
||||
case 'h': show_help(console, argv[0]);break;
|
||||
case 'p': patch = optarg; break;
|
||||
case 'l': lang = optarg;break;
|
||||
case 'L': launcher = true;break;
|
||||
|
||||
case 's': gen_stringtable_path = optarg;break;
|
||||
case 'c': sse_hostport = optarg;break;
|
||||
default: show_help_short(console);break;
|
||||
|
@ -72,6 +76,7 @@ int main(int argc, char **argv) {
|
|||
cfg.lang_path = lang.empty()?NULL:lang.c_str();
|
||||
cfg.patch_file = patch.empty()?NULL:patch.c_str();
|
||||
cfg.sse_hostport = sse_hostport.empty()?NULL:sse_hostport.c_str();
|
||||
cfg.launcher = launcher?1:0;
|
||||
|
||||
{
|
||||
std::string msg = console.str();
|
||||
|
|
|
@ -10,6 +10,7 @@ extern "C" {
|
|||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdexcept>
|
||||
#include <filesystem>
|
||||
|
||||
// Funkce pro mapování souboru do paměti
|
||||
const void* map_file_to_memory_cpp(const char *name, size_t *sz) {
|
||||
|
@ -17,8 +18,10 @@ const void* map_file_to_memory_cpp(const char *name, size_t *sz) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
HANDLE h = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
if (h == INVALID_HANDLE_VALUE) throw std::runtime_error(std::string("Failed to open file for mapping: ").append(name));
|
||||
std::filesystem::path p(reinterpret_cast<const char8_t *>(name));
|
||||
|
||||
HANDLE h = CreateFileW(p.c_str(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
if (h == INVALID_HANDLE_VALUE) throw std::runtime_error(std::string("Failed to open file for mapping: ")+p.string());
|
||||
|
||||
LARGE_INTEGER fsize;
|
||||
if (!GetFileSizeEx(h, &fsize)) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
# data = relative path to skeldal.ddl
|
||||
# language = path language folders
|
||||
# savegame = path to savegame, if not defined, retrieved from platform settings
|
||||
# local_ugc = path to local repository for user generated content (if team is enabled it also uses steam workshop path)
|
||||
|
||||
|
||||
[paths]
|
||||
|
@ -15,6 +16,7 @@
|
|||
# data=./
|
||||
# language=./lang
|
||||
# savegame = determine default
|
||||
# local_ugc=./adv
|
||||
|
||||
#### video settings
|
||||
#
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue