mirror of
https://github.com/ondra-novak/gates_of_skeldal.git
synced 2025-07-20 13:15:16 -04:00
Merge branch 'main' into sse
This commit is contained in:
commit
5931c6eab4
37 changed files with 739 additions and 147 deletions
|
@ -40,6 +40,30 @@ else()
|
|||
|
||||
endif()
|
||||
|
||||
set(VERSION_IN "${CMAKE_SOURCE_DIR}/version.in.h")
|
||||
set(VERSION_OUT "${CMAKE_BINARY_DIR}/version.h")
|
||||
|
||||
find_package(Git QUIET)
|
||||
|
||||
if(GIT_FOUND)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} describe --tags --always
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE GIT_RESULT
|
||||
)
|
||||
if(NOT GIT_RESULT EQUAL 0)
|
||||
set(GIT_VERSION "unknown")
|
||||
endif()
|
||||
else()
|
||||
set(GIT_VERSION "unknown")
|
||||
endif()
|
||||
|
||||
set(APP_VERSION "${GIT_VERSION}")
|
||||
configure_file(${VERSION_IN} ${VERSION_OUT} @ONLY)
|
||||
|
||||
include_directories(${CMAKE_BINARY_DIR})
|
||||
|
||||
include_directories(.)
|
||||
|
||||
|
|
|
@ -1109,3 +1109,9 @@ void free_map_description() {
|
|||
if (texty_v_mape!=NULL)release_list(texty_v_mape);
|
||||
texty_v_mape = NULL;
|
||||
}
|
||||
|
||||
TSTR_LIST swap_map_description(TSTR_LIST new_list) {
|
||||
TSTR_LIST old = texty_v_mape;
|
||||
texty_v_mape = new_list;
|
||||
return old;
|
||||
}
|
|
@ -327,14 +327,14 @@ static const void *bott_draw_normal(const void *pp, int32_t *s)
|
|||
{
|
||||
char c[]=" ";int z,lv,llv;
|
||||
put_picture(x,0,ablock(H_OKNO));lv=p->lives;llv=p->vlastnosti[VLS_MAXHIT];
|
||||
if (lv || p->used & 0x80 || p->kondice > 0)
|
||||
if (lv || p->used & 0x80)
|
||||
{
|
||||
z=3-((lv-1)*4/llv);if (lv==llv) z=0;
|
||||
z*=75;
|
||||
if (p->xicht>=0)put_8bit_clipped(ablock(H_XICHTY+i),bott_scr+PIC_X+x+PIC_Y*scr_linelen2,z,54,75);
|
||||
if (!lv && !(p->used & 0x80) && p->kondice>0) {
|
||||
/* if (!lv && !(p->used & 0x80) && p->kondice>0) {
|
||||
greyscale_rectangle(PIC_X+x,PIC_Y, 54, 75);
|
||||
}
|
||||
}*/
|
||||
if (p->bonus) draw_small_icone(0,PIC_X+x+1,PIC_Y+1);
|
||||
if (p->spell) draw_small_icone(1,PIC_X+x+1,PIC_Y+1);
|
||||
if (!p->voda) draw_small_icone(2,PIC_X+x+1,PIC_Y+1);
|
||||
|
|
|
@ -745,7 +745,7 @@ static void wait_timer(EVENT_MSG *msg, void **udata) {
|
|||
}
|
||||
}
|
||||
|
||||
void effect_show(va_list args)
|
||||
void effect_show(void)
|
||||
{
|
||||
int i;
|
||||
char s = exit_wait;
|
||||
|
@ -861,7 +861,7 @@ char enter_generator()
|
|||
memset(&cur_stats,0,sizeof(cur_stats));
|
||||
vypocet_vlastnosti(cur_angle,&cur_vls);
|
||||
b_disables=0x7;
|
||||
redraw_generator(rep);if (!rep)effect_show(NULL);rep=1;
|
||||
redraw_generator(rep);if (!rep)effect_show();rep=1;
|
||||
edit_name();
|
||||
change_click_map(clk_page1,CLK_PAGE1);
|
||||
was_enter=0;
|
||||
|
|
|
@ -766,7 +766,7 @@ void wire_dialog_drw(void)
|
|||
wire_dialog();
|
||||
draw_all();
|
||||
ukaz_mysku();
|
||||
effect_show(NULL);
|
||||
effect_show();
|
||||
}
|
||||
void unwire_dialog(void)
|
||||
{
|
||||
|
|
28
game/enemy.c
28
game/enemy.c
|
@ -1317,18 +1317,24 @@ void vymaz_zasahy(THE_TIMER *q)
|
|||
bott_draw(0);
|
||||
}
|
||||
|
||||
static int select_drop_inventory_place(TMOB *p) {
|
||||
int x,y,pl;
|
||||
if (p->locx>128) x=1;else if (p->locx<128) x=-1;else x=rnd(2)*2-1;
|
||||
if (p->locy>128) y=1;else if (p->locy<128) y=-1;else y=rnd(2)*2-1;
|
||||
pl=0;if (x>0) pl++;
|
||||
if (y>0) pl=3-pl;
|
||||
return pl;
|
||||
}
|
||||
|
||||
static int drop_inventory(TMOB *p)
|
||||
{
|
||||
int i,x,y,pl;
|
||||
int i,pl;
|
||||
short c[]={0,0};
|
||||
|
||||
for(i=-1;i<MOBS_INV;i++)
|
||||
for(i=-1;i<MOBS_INV;i++) {
|
||||
if (p->inv[i] || (i<0 && p->money))
|
||||
{
|
||||
if (p->locx>128) x=1;else if (p->locx<128) x=-1;else x=rnd(2)*2-1;
|
||||
if (p->locy>128) y=1;else if (p->locy<128) y=-1;else y=rnd(2)*2-1;
|
||||
pl=0;if (x>0) pl++;
|
||||
if (y>0) pl=3-pl;
|
||||
pl = select_drop_inventory_place(p);
|
||||
if (i<0)
|
||||
{
|
||||
int z=(int)p->money+(int)(rnd(40)-20)*(int)p->money/(int)100;
|
||||
|
@ -1341,6 +1347,16 @@ static int drop_inventory(TMOB *p)
|
|||
}
|
||||
push_item(p->sector,pl,c);
|
||||
}
|
||||
}
|
||||
if (destroyed_items) {
|
||||
int cnt = count_items_total(destroyed_items);
|
||||
if (cnt) {
|
||||
int idx = cnt -1;
|
||||
pl = select_drop_inventory_place(p);
|
||||
push_item(p->sector,pl, destroyed_items+idx);
|
||||
destroyed_items[idx] = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
#define SLOTS_MAX 10
|
||||
|
||||
#define GM_MAPENABLE 0x1
|
||||
#define GM_FASTBATTLES 0x2
|
||||
#define GM_GAMESPEED_SHIFT 2
|
||||
#define GM_GAMESPEED_MASK 0x1F
|
||||
|
||||
#define SAVE_SLOT_S 34
|
||||
#define LOAD_SLOT_S (372+34)
|
||||
|
@ -583,6 +586,14 @@ int unpack_all_status(FILE *f)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void save_destroyed_items(TMPFILE_WR *f) {
|
||||
short c = (short)count_items_total(destroyed_items);
|
||||
temp_storage_write(&c,sizeof(c), f);
|
||||
if (c) {
|
||||
temp_storage_write(destroyed_items,sizeof(short)*c, f);
|
||||
}
|
||||
}
|
||||
|
||||
int save_basic_info()
|
||||
{
|
||||
TMPFILE_WR *f;
|
||||
|
@ -618,7 +629,14 @@ int save_basic_info()
|
|||
s.swapchans=MIN(get_snd_effect(SND_SWAP),255);
|
||||
s.out_filter=MIN(get_snd_effect(SND_OUTFILTER),255);
|
||||
s.autosave=autosave_enabled;
|
||||
s.game_flags=(enable_glmap!=0);
|
||||
s.game_flags=0;
|
||||
|
||||
if (enable_glmap!=0) s.game_flags |= GM_MAPENABLE;
|
||||
if (gamespeedbattle<gamespeed) s.game_flags |= GM_FASTBATTLES;
|
||||
if (timerspeed_val <= GM_GAMESPEED_MASK) {
|
||||
s.game_flags |= (timerspeed_val & GM_GAMESPEED_MASK) << GM_GAMESPEED_SHIFT;
|
||||
}
|
||||
|
||||
strcopy_n(s.level_name,level_fname,sizeof(s.level_name));
|
||||
for(i=0;i<5;i++) s.runes[i]=runes[i];
|
||||
if (picked_item!=NULL)
|
||||
|
@ -635,11 +653,26 @@ int save_basic_info()
|
|||
for(i=0,h=postavy;i<POCET_POSTAV;h++,i++) if (h->demon_save!=NULL)
|
||||
temp_storage_write(h->demon_save,sizeof(THUMAN)*1,f); //ulozeni polozek s demony
|
||||
res|=save_dialog_info(f);
|
||||
save_destroyed_items(f);
|
||||
temp_storage_close_wr(f);
|
||||
SEND_LOG("(SAVELOAD) Done... Result: %d",res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_destroyed_items(TMPFILE_RD *f) {
|
||||
int res = 0;
|
||||
short destroyed_items_count = 0;
|
||||
temp_storage_read(&destroyed_items_count,sizeof(destroyed_items_count), f);
|
||||
free(destroyed_items);
|
||||
destroyed_items = NULL;
|
||||
if (destroyed_items_count) {
|
||||
destroyed_items = NewArr(short, destroyed_items_count+1);
|
||||
res|=temp_storage_read(destroyed_items,destroyed_items_count*sizeof(short), f) != destroyed_items_count*sizeof(short);
|
||||
destroyed_items[destroyed_items_count] = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_basic_info()
|
||||
{
|
||||
TMPFILE_RD *f;
|
||||
|
@ -654,6 +687,9 @@ int load_basic_info()
|
|||
if (f==NULL) return 1;
|
||||
res|=(temp_storage_read(&s,1*sizeof(s),f)!=sizeof(s));
|
||||
if (s.game_flags & GM_MAPENABLE) enable_glmap=1;else enable_glmap=0;
|
||||
gamespeedbattle =s.game_flags & GM_FASTBATTLES? GAMESPEED_FASTBATTLE:gamespeed;
|
||||
int tmsp = (s.game_flags >> GM_GAMESPEED_SHIFT) & GM_GAMESPEED_MASK;
|
||||
if (tmsp) timerspeed_val = tmsp;
|
||||
i=s.picks;
|
||||
if (picked_item!=NULL) free(picked_item);
|
||||
if (i)
|
||||
|
@ -685,6 +721,7 @@ int load_basic_info()
|
|||
}
|
||||
}
|
||||
res|=load_dialog_info(f);
|
||||
res|=load_destroyed_items(f);
|
||||
temp_storage_close_rd(f);
|
||||
viewsector=s.viewsector;
|
||||
viewdir=s.viewdir;
|
||||
|
@ -776,11 +813,12 @@ int save_game(long game_time,char *gamename, char is_autosave)
|
|||
temp_storage_store("playtime",&new_play_time, sizeof(new_play_time));
|
||||
|
||||
svf=fopen_icase(sn,"wb");
|
||||
if (svf==NULL)
|
||||
{
|
||||
char buff[256];
|
||||
sprintf(buff,"Nelze ulozit pozici na cestu: %s", sn);
|
||||
display_error(buff);
|
||||
if (svf==NULL){
|
||||
if (!is_autosave) {
|
||||
char buff[256];
|
||||
sprintf(buff,"Failed to create savegame at path %s", sn);
|
||||
message(1,0,0,"",buff,texty[80]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1769,12 +1807,12 @@ void wire_save_load(char save) {
|
|||
change_click_map(clk_save,CLK_SAVELOAD);
|
||||
redraw_save();
|
||||
send_message(E_ADD, E_KEYBOARD, saveload_keyboard);
|
||||
effect_show(NULL);
|
||||
effect_show();
|
||||
|
||||
} else {
|
||||
curcolor = 0;
|
||||
redraw_load();
|
||||
effect_show(NULL);
|
||||
effect_show();
|
||||
if (save == 2)
|
||||
change_click_map(clk_load_error, CLK_LOAD_ERROR);
|
||||
else if (save == 4) {
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
#define POCET_POSTAV 6
|
||||
#define HODINA 360
|
||||
|
||||
#define GAMESPEED 5
|
||||
#define GAMESPEED_FASTBATTLE 2
|
||||
|
||||
|
||||
#define MAX_FILESYSTEM_PATH 256
|
||||
|
||||
#define A_SIDEMAP 0x8001
|
||||
|
@ -573,6 +577,7 @@ extern int mapsize; //pocet sektoru v mape
|
|||
extern int hl_ptr; //ukazatel na konec staticke tabulky registraci
|
||||
extern int end_ptr; //ukazatel na uplny konec tabulky registraci
|
||||
extern short **map_items; //ukazatel na mapu predmetu
|
||||
extern short *destroyed_items; //list of destroyed items to be returned to the game
|
||||
extern int default_ms_cursor; //cislo zakladniho mysiho kurzoru
|
||||
extern void (*unwire_proc)(void); //procedura zajistujici odpojeni prave ukoncovane interakce
|
||||
extern void (*wire_proc)(void); //procedura zajistujici pripojeni drive ukoncene interakce
|
||||
|
@ -581,8 +586,8 @@ extern word minimap[VIEW3D_Z+1][VIEW3D_X*2+1]; //minimalizovana mapa s informace
|
|||
extern char norefresh; //vypina refresh obrazovky
|
||||
extern char cancel_pass; //okamzite zrusi plynuly prechod
|
||||
extern char reverse_draw ; //kresba odpredu dozadu
|
||||
extern char gamespeed; //rychlost hry
|
||||
extern char gamespeedbattle; //akcelerace rychlosti pro bitvy
|
||||
extern uint8_t gamespeed; //rychlost hry
|
||||
extern uint8_t gamespeedbattle; //akcelerace rychlosti pro bitvy
|
||||
extern int num_ofsets[]; //tabulka offsetu pro steny
|
||||
extern int back_color; //cislo barvy pozadi
|
||||
extern uint8_t cur_group; //cislo aktualni skupiny
|
||||
|
@ -986,10 +991,10 @@ char pick_item_(int id,int xa,int ya,int xr,int yr);
|
|||
void wire_inv_mode(THUMAN *select);
|
||||
void init_inventory(void);
|
||||
void init_items(void);
|
||||
void push_item(int sect,int pos,short *picked_item);
|
||||
void push_item(int sect,int pos,const short *picked_item);
|
||||
void pop_item(int sect,int pos,int mask,short **picked_item);
|
||||
int count_items_inside(short *place);
|
||||
int count_items_total(short *place);
|
||||
int count_items_inside(const short *place);
|
||||
int count_items_total(const short *place);
|
||||
char put_item_to_inv(THUMAN *p,short *picked_items); //funkce vklada predmet(y) do batohu postavy
|
||||
void pick_set_cursor(void); //nastavuje kurzor podle vlozeneho predmetu;
|
||||
void calc_fly(THE_TIMER *t);
|
||||
|
@ -1402,7 +1407,7 @@ void destroy_all_fly();
|
|||
void stop_fly(LETICI_VEC *p,char zvuk);
|
||||
void herni_cas(char *s);
|
||||
|
||||
|
||||
typedef char **TSTR_LIST;
|
||||
|
||||
//gamesaver
|
||||
void leave_current_map(void);
|
||||
|
@ -1415,6 +1420,7 @@ int save_game(long game_time,char *gamename, char is_autosave);
|
|||
void save_map_description(TMPFILE_WR *f);
|
||||
void load_map_description(TMPFILE_RD *f);
|
||||
void free_map_description();
|
||||
TSTR_LIST swap_map_description(TSTR_LIST new_list);
|
||||
void wire_save_load(char save);
|
||||
void do_save_dialog();
|
||||
char ask_save_dialog(char *name_buffer, size_t name_size, char allow_remove);
|
||||
|
@ -1762,8 +1768,8 @@ char clk_enter(int id,int xa,int ya,int xr,int yr);
|
|||
//menu
|
||||
int enter_menu(char open); //task!
|
||||
void titles(va_list args); //task!
|
||||
void run_titles(va_list args); //task!
|
||||
void effect_show(va_list args); //effektni zobrazeni // task!
|
||||
void run_titles(void );
|
||||
void effect_show(void); //effektni zobrazeni
|
||||
void konec_hry(void);
|
||||
|
||||
|
||||
|
|
|
@ -630,13 +630,14 @@ struct _tag_map_save_state{
|
|||
TSTENA *_map_sides;
|
||||
TSECTOR *_map_sectors;
|
||||
TMAP_EDIT_INFO *_map_coord;
|
||||
TSTR_LIST _map_desc;
|
||||
int _map_size;
|
||||
int _viewsector;
|
||||
int _viewdir;
|
||||
uint32_t _hash;
|
||||
} MAP_SAVE_STATE;
|
||||
|
||||
static struct _tag_map_save_state save_state = {NULL,NULL,NULL,0,0,0,0};
|
||||
static struct _tag_map_save_state save_state = {NULL,NULL,NULL,NULL,0,0,0,0};
|
||||
|
||||
static void save_current_map() {
|
||||
if (save_state._map_coord) {
|
||||
|
@ -647,6 +648,7 @@ static void save_current_map() {
|
|||
save_state._map_coord = map_coord;
|
||||
save_state._map_sectors = map_sectors;
|
||||
save_state._map_size = mapsize;
|
||||
save_state._map_desc = swap_map_description(NULL);
|
||||
save_state._viewsector = viewsector;
|
||||
save_state._viewdir = viewdir;
|
||||
save_state._hash = current_map_hash;
|
||||
|
@ -661,6 +663,7 @@ static void restore_saved_map() {
|
|||
free(map_sides);
|
||||
free(map_sectors);
|
||||
free(map_coord);
|
||||
free_map_description();
|
||||
mapsize =save_state._map_size;
|
||||
map_sides = save_state._map_sides;
|
||||
map_sectors = save_state._map_sectors;
|
||||
|
@ -668,9 +671,11 @@ static void restore_saved_map() {
|
|||
viewsector = save_state._viewsector;
|
||||
viewdir = save_state._viewdir;
|
||||
current_map_hash = save_state._hash;
|
||||
swap_map_description(save_state._map_desc);
|
||||
save_state._map_sides = NULL;
|
||||
save_state._map_coord = NULL;
|
||||
save_state._map_sectors = NULL;
|
||||
save_state._map_desc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1486,8 +1486,9 @@ int smlouvat_prodej(int cena,int ponuka,int posledni,int puvod,int pocet)
|
|||
|
||||
if (ponuka==0) return 0;
|
||||
if (ponuka<=cena) return 0;
|
||||
if (posledni!=0) if (ponuka>=posledni || ponuka>min) return 1;
|
||||
if (p_ok>r_ok) return 0;
|
||||
if (ponuka <= min && (posledni==0 || ponuka<posledni)) {
|
||||
if (p_ok>r_ok) return 0;
|
||||
}
|
||||
if (p_ok>75) return 2;
|
||||
if (p_ok>50) return 3;
|
||||
if (p_ok>25) return 4;
|
||||
|
@ -1544,7 +1545,7 @@ THAGGLERESULT smlouvat_dlg(int cena,int puvod,int pocet,int posledni, int money,
|
|||
define(-1,150,15,100,13,0,label,int2ascii(cena,buffer,10));
|
||||
set_font(H_FBOLD,MSG_COLOR1);
|
||||
define(-1,10,30,1,1,0,label,texty[238]);
|
||||
define(10,150,30,100,13,0,input_line,8,0,0,"");property(def_border(5,BAR_COLOR),NULL,NULL,0);set_default("");
|
||||
define(10,150,30,100,13,0,input_line,7,0,0,"");property(def_border(5,BAR_COLOR),NULL,NULL,0);set_default("");
|
||||
on_control_event(smlouvat_enter);
|
||||
define(20,20,20,80,20,2,button,texty[239]);property(def_border(5,BAR_COLOR),NULL,NULL,BAR_COLOR);on_control_change(terminate_gui);
|
||||
define(30,110,20,80,20,2,button,texty[230]);property(def_border(5,BAR_COLOR),NULL,NULL,BAR_COLOR);on_control_change(terminate_gui);
|
||||
|
|
60
game/inv.c
60
game/inv.c
|
@ -432,7 +432,7 @@ void draw_placed_items_normal(int celx,int cely,int sect,int side)
|
|||
}
|
||||
}
|
||||
|
||||
int count_items_total(short *place)
|
||||
int count_items_total(const short *place)
|
||||
{
|
||||
int c=0;
|
||||
|
||||
|
@ -441,7 +441,7 @@ int count_items_total(short *place)
|
|||
return c;
|
||||
}
|
||||
|
||||
int count_items_visible(short *place)
|
||||
int count_items_visible(const short *place)
|
||||
{
|
||||
int c=0;
|
||||
|
||||
|
@ -455,7 +455,7 @@ int count_items_visible(short *place)
|
|||
}
|
||||
|
||||
|
||||
int count_items_inside(short *place)
|
||||
int count_items_inside(const short *place)
|
||||
{
|
||||
int c=1;
|
||||
|
||||
|
@ -479,43 +479,37 @@ int find_item(short *place,int mask)
|
|||
return lastitem;
|
||||
}
|
||||
|
||||
static int lastsector;
|
||||
|
||||
static char ValidateSector(word sector, void *_)
|
||||
{
|
||||
int pp=map_sectors[sector].sector_type;
|
||||
if (pp==S_NORMAL || pp==S_SMER || pp==S_LEAVE || pp==S_FLT_SMER)
|
||||
{
|
||||
lastsector=sector;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
void push_to_destroyed_items(const short *picked_items) {
|
||||
int new_count = count_items_total(picked_items);
|
||||
if (new_count == 0) return;
|
||||
int cur_destroyed = count_items_total(destroyed_items);
|
||||
short *nw = NewArr(short, new_count+cur_destroyed+1);
|
||||
for (int i = 0; i < new_count; ++i) {
|
||||
nw[i] = abs(picked_items[i]);
|
||||
}
|
||||
for (int i = 0; i < cur_destroyed; ++i) {
|
||||
nw[new_count+i] = destroyed_items[i];
|
||||
}
|
||||
nw[new_count+cur_destroyed] = 0;
|
||||
free(destroyed_items);
|
||||
destroyed_items = nw;
|
||||
}
|
||||
|
||||
void push_item(int sect,int pos,short *picked_item)
|
||||
void push_item(int sect,int pos,const short *picked_item)
|
||||
{
|
||||
int bc;
|
||||
int pc;
|
||||
int tc;
|
||||
short *p;
|
||||
char s = map_sectors[sect].sector_type;
|
||||
|
||||
if (map_sectors[sect].sector_type==S_DIRA || ISTELEPORTSECT(sect))
|
||||
|
||||
if (s==S_DIRA || ISTELEPORTSECT(sect) || s == S_SCHODY)
|
||||
sect=map_sectors[sect].sector_tag;
|
||||
if (sect==0 || map_sectors[sect].sector_type==S_VODA)
|
||||
{
|
||||
if (game_extras & EX_RECOVER_DESTROYED_ITEMS)
|
||||
{
|
||||
labyrinth_find_path(viewsector,65535,SD_PLAY_IMPS,ValidateSector,NULL, NULL);
|
||||
push_item(lastsector,viewdir,picked_item);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(picked_item);
|
||||
picked_item=NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (sect==0 || s==S_VODA || s == S_LAVA || s == S_SSMRT || s == S_LODKA) {
|
||||
push_to_destroyed_items(picked_item);
|
||||
return;
|
||||
}
|
||||
sect=(sect<<2)+pos;
|
||||
bc=count_items_total(map_items[sect]);
|
||||
pc=count_items_total(picked_item);
|
||||
|
@ -682,7 +676,7 @@ char pick_item_(int id,int xa,int ya,int xr,int yr)
|
|||
idd=(id+viewdir)&0x3;
|
||||
if (picked_item!=NULL)
|
||||
{
|
||||
if (map_sectors[sect].sector_type==S_DIRA)
|
||||
if (map_sectors[sect].sector_type==S_DIRA)
|
||||
{
|
||||
throw_fly(xa,ya,0);
|
||||
letici_veci->speed=0;
|
||||
|
@ -2494,7 +2488,6 @@ static int shop_sector;
|
|||
T_CLK_MAP clk_shop[]=
|
||||
{
|
||||
{-1,54,378,497,479,shop_change_player,2+8,-1},
|
||||
{-1,0,0,639,479,_exit_shop,8,-1},
|
||||
{-1,INV_X,INV_Y,INV_X+INV_XS*6,INV_Y+INV_YS*5,shop_bag_click,MS_EVENT_MOUSE_LPRESS,-1},
|
||||
{1,2+BUYBOX_X,39+BUYBOX_Y,22+BUYBOX_X,76+BUYBOX_Y,shop_block_click,2,H_MS_DEFAULT},
|
||||
{2,246+BUYBOX_X,39+BUYBOX_Y,266+BUYBOX_X,76+BUYBOX_Y,shop_block_click,2,H_MS_DEFAULT},
|
||||
|
@ -2503,6 +2496,7 @@ T_CLK_MAP clk_shop[]=
|
|||
{-1,337,0,357,14,go_map,2,H_MS_DEFAULT},
|
||||
{-1,87,0,142,14,game_setup,2,H_MS_DEFAULT},
|
||||
{-1,30,0,85,14,konec,2,H_MS_DEFAULT},
|
||||
{-1,0,0,639,479,_exit_shop,8,-1},
|
||||
};
|
||||
|
||||
static void shop_mouse_event(EVENT_MSG *msg,void **unused)
|
||||
|
|
24
game/menu.c
24
game/menu.c
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "ach_events.h"
|
||||
#include "lang.h"
|
||||
#include <version.h>
|
||||
|
||||
#define MUSIC "TRACK06.MUS"
|
||||
|
||||
|
@ -334,6 +335,12 @@ static void klavesnice(EVENT_MSG *msg,void **unused)
|
|||
}
|
||||
}
|
||||
|
||||
static void show_version() {
|
||||
const char *verstr = "Version: " SKELDAL_VERSION;
|
||||
set_font(H_FLITT5, RGB888(255,255,255));
|
||||
set_aligned_position(639, 479, 2, 2, verstr);
|
||||
outtext(verstr);
|
||||
}
|
||||
|
||||
int enter_menu(char open)
|
||||
{
|
||||
|
@ -350,8 +357,9 @@ int enter_menu(char open)
|
|||
put_picture(0,0,ablock(H_MENU_BAR));
|
||||
put_picture(0,56,ablock(H_ANIM));
|
||||
ukaz_mysku();
|
||||
effect_show(NULL);
|
||||
//if (open) effect_show(NULL);else showview(0,0,0,0);
|
||||
show_version();
|
||||
effect_show();
|
||||
|
||||
change_click_map(clk_main_menu,CLK_MAIN_MENU);
|
||||
send_message(E_ADD,E_TIMER,prehraj_animaci_v_menu);
|
||||
send_message(E_ADD,E_KEYBOARD,klavesnice);
|
||||
|
@ -552,7 +560,7 @@ void titles(va_list args)
|
|||
alock(H_PICTURE);
|
||||
picture=ablock(H_PICTURE);
|
||||
put_picture(0,0,picture);
|
||||
effect_show(NULL);
|
||||
effect_show();
|
||||
titlefont=H_FBIG;
|
||||
set_font(titlefont,RGB(158,210,25));charcolors[1]=0;
|
||||
counter=get_timer_value();newc=counter;
|
||||
|
@ -604,7 +612,7 @@ void titles(va_list args)
|
|||
if (send_back)send_message(E_KEYBOARD,27);
|
||||
}
|
||||
|
||||
void run_titles(va_list args)
|
||||
void run_titles(void)
|
||||
{
|
||||
int task_id;
|
||||
task_id=add_task(8196,titles,1,"titulky.TXT");
|
||||
|
@ -612,16 +620,16 @@ void run_titles(va_list args)
|
|||
term_task(task_id);
|
||||
}
|
||||
|
||||
void konec_hry()
|
||||
void konec_hry(void)
|
||||
{
|
||||
int task_id;
|
||||
int timer;
|
||||
|
||||
|
||||
|
||||
schovej_mysku();
|
||||
curcolor=0;
|
||||
bar32(0,0,639,479);
|
||||
effect_show(NULL);
|
||||
effect_show();
|
||||
create_playlist(texty[205]);
|
||||
change_music(get_next_music_from_playlist());
|
||||
timer=get_timer_value();
|
||||
|
@ -641,7 +649,7 @@ void konec_hry()
|
|||
curcolor=0;
|
||||
bar32(0,0,639,479);
|
||||
ukaz_mysku();
|
||||
effect_show(NULL);
|
||||
effect_show();
|
||||
timer=get_timer_value();
|
||||
while (get_timer_value()-timer<150) task_sleep();
|
||||
}
|
||||
|
|
|
@ -62,7 +62,8 @@ TSTENA *map_sides;
|
|||
TSECTOR *map_sectors;
|
||||
TVYKLENEK *map_vyk; //mapa vyklenku
|
||||
word vyk_max; //pocet vyklenku v mape
|
||||
short **map_items;
|
||||
short **map_items = 0;
|
||||
short *destroyed_items = 0;;
|
||||
char *flag_map;
|
||||
TMAP_EDIT_INFO *map_coord;
|
||||
TSTR_LIST level_texts;
|
||||
|
|
12
game/setup.c
12
game/setup.c
|
@ -44,7 +44,7 @@ static void checkbox_animator(THE_TIMER *t)
|
|||
animate_checkbox(10,130,10);
|
||||
}
|
||||
|
||||
static int effects[]={SND_GVOLUME,SND_MUSIC,SND_GFX,SND_TREBL,SND_BASS,SND_XBASS};
|
||||
static int effects[]={SND_GVOLUME,SND_MUSIC,SND_GFX,SND_TREBL,SND_BASS};
|
||||
|
||||
static void do_setup_change(void)
|
||||
{
|
||||
|
@ -55,6 +55,7 @@ static void do_setup_change(void)
|
|||
{
|
||||
case 10:set_snd_effect(SND_SWAP,c & 1);break;
|
||||
case 20:set_snd_effect(SND_OUTFILTER,c & 1);break;
|
||||
case 250:timerspeed_val = TIMERSPEED- c;break;
|
||||
default:set_snd_effect(effects[o_aktual->id/10-20],c);break;
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +112,7 @@ static void unwire_setup(void)
|
|||
enable_sort=f_get_value(0,100) & 1;
|
||||
autoattack=f_get_value(0,110) & 1;
|
||||
autosave_enabled=f_get_value(0,120) & 1;
|
||||
level_preload=f_get_value(0,130) & 1;
|
||||
gamespeedbattle=(f_get_value(0,130) & 1)?GAMESPEED_FASTBATTLE:gamespeed;
|
||||
delete_from_timer(TM_CHECKBOX);
|
||||
mix_back_sound(32768);
|
||||
close_current();
|
||||
|
@ -187,8 +188,8 @@ void new_setup()
|
|||
case 0:c_default(show_names);break;
|
||||
case 1:c_default(enable_sort);break;
|
||||
case 2:c_default(autoattack);break;
|
||||
case 3:c_default(1);break;
|
||||
case 4:c_default(level_preload);break;
|
||||
case 3:c_default(autosave_enabled);break;
|
||||
case 4:c_default(gamespeedbattle < gamespeed);break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,6 +202,9 @@ void new_setup()
|
|||
define(200+i*10,50+i*60,30,30,200,0,skeldal_soupak,effects[i]==SND_MUSIC?127:255);c_default(get_snd_effect(effects[i]));
|
||||
on_control_change(do_setup_change);
|
||||
}
|
||||
define(200+5*10,50+5*60,30,30,200,0,skeldal_soupak,TIMERSPEED-1);c_default(timerspeed_val >TIMERSPEED?0:TIMERSPEED - timerspeed_val);
|
||||
on_control_change(do_setup_change);
|
||||
|
||||
define(300,559,336,81,21,0,setup_ok_button,texty[174]);on_control_change(exit_setup_action);
|
||||
property(NULL,ablock(H_FTINY),&color_topbar,0);
|
||||
redraw_window();
|
||||
|
|
|
@ -75,12 +75,13 @@ typedef struct inis
|
|||
THE_TIMER timer_tree;
|
||||
|
||||
|
||||
|
||||
int hl_ptr=H_FIRST_FREE;
|
||||
int debug_enabled=0;
|
||||
char sound_detection=1;
|
||||
int snd_devnum,snd_parm1,snd_parm2,snd_parm3,snd_mixing=22000;
|
||||
char gamespeed=5;
|
||||
char gamespeedbattle=0;
|
||||
uint8_t gamespeed=GAMESPEED;
|
||||
uint8_t gamespeedbattle=GAMESPEED;
|
||||
char level_preload=1;
|
||||
char *level_fname=NULL;
|
||||
int game_extras=0;
|
||||
|
@ -827,6 +828,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)");
|
||||
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");
|
||||
lang_patch_stringtable(&texty, "ui.csv", "");
|
||||
}
|
||||
|
@ -1622,7 +1625,7 @@ static void start(va_list args)
|
|||
openning =0;
|
||||
break;
|
||||
case V_OBNOVA_HRY:load_saved_game();break;
|
||||
case V_AUTORI:run_titles(NULL);break;
|
||||
case V_AUTORI:run_titles();break;
|
||||
}
|
||||
}
|
||||
while (!exit_wait);
|
||||
|
|
|
@ -678,6 +678,7 @@ void zacatek_kola()
|
|||
viewsector=postavy[select_player].sektor;
|
||||
viewdir=postavy[select_player].direction;
|
||||
redraw_scene();
|
||||
recalc_volumes(viewsector,viewdir);
|
||||
}
|
||||
|
||||
char check_end_game()
|
||||
|
@ -878,7 +879,7 @@ char JePozdrzeno()
|
|||
|
||||
void pozdrz_akci()
|
||||
{
|
||||
int battlespeed=gamespeed-gamespeed*gamespeedbattle/5;
|
||||
int battlespeed=gamespeedbattle;
|
||||
SPozdrzeno=get_game_tick_count()+battlespeed*2000/6;
|
||||
}
|
||||
|
||||
|
@ -905,6 +906,7 @@ void prejdi_na_pohled(THUMAN *p)
|
|||
{
|
||||
viewsector=p->sektor;
|
||||
viewdir=p->direction;
|
||||
recalc_volumes(viewsector,viewdir);
|
||||
pozdrz_akci();
|
||||
hold_timer(TM_SCENE,1);
|
||||
redraw_scene();
|
||||
|
@ -1144,7 +1146,7 @@ static void pouzij_svitek(THUMAN *p,int ruka)
|
|||
static void play_weapon_anim(int anim_num,int hitpos)
|
||||
{
|
||||
char count_save=global_anim_counter;
|
||||
int battlespeed=gamespeed-gamespeed*gamespeedbattle/5;
|
||||
int battlespeed=gamespeedbattle;
|
||||
|
||||
if (anim_num==0) return;
|
||||
hold_timer(TM_SCENE,1);
|
||||
|
@ -1440,6 +1442,7 @@ void jadro_souboje(EVENT_MSG *msg,void **unused) //!!!! Jadro souboje
|
|||
viewsector=postavy[i].sektor;
|
||||
viewdir=postavy[i].direction;
|
||||
build_player_map();
|
||||
recalc_volumes(viewsector,viewdir);
|
||||
GlobEvent(MAGLOB_AFTERBATTLE,viewsector,viewdir);
|
||||
autosave();
|
||||
}
|
||||
|
@ -1450,7 +1453,7 @@ void jadro_souboje(EVENT_MSG *msg,void **unused) //!!!! Jadro souboje
|
|||
|
||||
void wire_jadro_souboje(void)
|
||||
{
|
||||
int battlespeed=gamespeed-gamespeed*gamespeedbattle/5;
|
||||
int battlespeed=gamespeedbattle;
|
||||
recalc_volumes(viewsector,viewdir);
|
||||
if (battlespeed<1) battlespeed=1;
|
||||
add_to_timer(TM_SCENE,battlespeed,-1,hrat_souboj);
|
||||
|
@ -1924,6 +1927,7 @@ static void souboje_dalsi()
|
|||
while ((!postavy[select_player].used || postavy[select_player].inmaphash != current_map_hash || !postavy[select_player].actions || (postavy[select_player].groupnum!=cd && j>6)) && j);
|
||||
viewsector=postavy[select_player].sektor;
|
||||
viewdir=postavy[select_player].direction;
|
||||
recalc_volumes(viewsector,viewdir);
|
||||
cur_group=postavy[select_player].groupnum;
|
||||
}
|
||||
|
||||
|
@ -1944,6 +1948,7 @@ static void souboje_dalsi_user() {
|
|||
viewsector=postavy[select_player].sektor;
|
||||
viewdir=postavy[select_player].direction;
|
||||
cur_group=postavy[select_player].groupnum;
|
||||
recalc_volumes(viewsector,viewdir);
|
||||
}
|
||||
|
||||
void souboje_vybrano(int d)
|
||||
|
|
|
@ -45,7 +45,7 @@ To activate the controller, press any button on the controller"
|
|||
48,Start
|
||||
49,Throw
|
||||
50,Combat in Progress
|
||||
51,Overall Music Sounds Treble Bass
|
||||
51,Overall Music Sounds Treble Bass Speed
|
||||
52,Stereo Settings (Ultrasound)
|
||||
53,Swap Sides
|
||||
54,Output Filter (SBPro)
|
||||
|
@ -117,7 +117,7 @@ To activate the controller, press any button on the controller"
|
|||
141,Rearrange Portraits
|
||||
142,Auto Attack
|
||||
143,Auto Save
|
||||
144,Load All Into Memory
|
||||
144,Speed up battles
|
||||
145,Adventure Length:
|
||||
146,%d day and
|
||||
147,%d days and
|
||||
|
|
|
|
@ -12,7 +12,7 @@ SET(files basicobj.c
|
|||
mgifplaya.c
|
||||
pcx.c
|
||||
wav_mem.c
|
||||
strlists.c
|
||||
strlite.c
|
||||
cztable.c
|
||||
music.cpp
|
||||
string_table.cpp )
|
||||
|
|
|
@ -95,9 +95,10 @@ elseif(APPLE)
|
|||
target_sources(skeldal PRIVATE
|
||||
linux/app_start.cpp
|
||||
)
|
||||
target_compile_definitions(mylib PRIVATE PLATFORM_MACOS)
|
||||
set(STEAMLIB ${STEAMWORKS_SDK_DIR}/redistributable_bin/osx/libsteam_api.dylib)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
|
||||
if(STEAM_ENABLED)
|
||||
set(STEAMLIB ${STEAMWORKS_SDK_DIR}/redistributable_bin/osx/libsteam_api.dylib)
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
|
||||
message(STATUS "Building for macOS")
|
||||
target_link_libraries(skeldal ${all_libs} ${STEAMLIB})
|
||||
else()
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "error.h"
|
||||
#include "platform.h"
|
||||
|
||||
|
@ -38,3 +39,18 @@ void send_log_impl(const char *format, ...) {
|
|||
void throw_exception(const char *text) {
|
||||
throw std::runtime_error(std::string("Invoked crash:") + text);
|
||||
}
|
||||
|
||||
std::string exception_to_string(const std::exception& e) {
|
||||
std::ostringstream oss;
|
||||
oss << e.what();
|
||||
|
||||
try {
|
||||
std::rethrow_if_nested(e);
|
||||
} catch (const std::exception& nested) {
|
||||
oss << "\n\n Reason: " << exception_to_string(nested);
|
||||
} catch (...) {
|
||||
oss << "\n\n Reason: unknown exception of crash";
|
||||
}
|
||||
|
||||
return std::move(oss).str();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string>
|
||||
#include <exception>
|
||||
std::string exception_to_string(const std::exception& e);
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
@ -10,7 +15,8 @@ void send_log_impl(const char *format, ...);
|
|||
void display_error(const char *format, ...);
|
||||
void throw_exception(const char *text);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -7,23 +7,37 @@
|
|||
#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(std::string_view pathname, char sep) {
|
||||
auto utf8_to_path = [](std::string_view sv) -> std::filesystem::path {
|
||||
return std::filesystem::path(std::u8string(reinterpret_cast<const char8_t*>(sv.data()), sv.size()));
|
||||
};
|
||||
|
||||
auto p = pathname.rfind(sep);
|
||||
|
||||
if (p == pathname.npos) {
|
||||
if (pathname == "." || pathname == "..") {
|
||||
return std::filesystem::canonical(".");
|
||||
} else if (pathname.empty()) {
|
||||
return std::filesystem::current_path().root_path();
|
||||
} else if (pathname == std::filesystem::current_path().root_name()) {
|
||||
return std::filesystem::current_path().root_path();
|
||||
} else {
|
||||
return std::filesystem::current_path()/pathname;
|
||||
}
|
||||
|
||||
}
|
||||
return break_and_compose_path(pathname.substr(0,p), sep) / pathname.substr(p+1);
|
||||
}
|
||||
// Detekce Windows drive letter jako "C:"
|
||||
if (pathname.size() == 2 && std::isalpha(static_cast<unsigned char>(pathname[0])) && pathname[1] == ':') {
|
||||
return utf8_to_path(std::string(pathname) + "\\"); // vždy konstruujeme s \ pro root disku
|
||||
}
|
||||
|
||||
// Kontrola na root (např. "/") – musíme převést pro porovnání
|
||||
if (utf8_to_path(pathname) == std::filesystem::current_path().root_path()) {
|
||||
return std::filesystem::current_path().root_path();
|
||||
}
|
||||
|
||||
// Vše ostatní relativně vůči current_path
|
||||
return std::filesystem::current_path() / utf8_to_path(pathname);
|
||||
} else if (p == 0) {
|
||||
return std::filesystem::current_path().root_path() / utf8_to_path(pathname);
|
||||
}
|
||||
|
||||
return break_and_compose_path(pathname.substr(0, p), sep) / utf8_to_path(pathname.substr(p + 1));
|
||||
}
|
||||
|
||||
std::filesystem::path convert_pathname_to_path(const std::string_view &pathname) {
|
||||
auto p = pathname.find('\\');
|
||||
|
@ -81,7 +95,12 @@ const char *file_icase_find(const char *pathname) {
|
|||
|
||||
FILE *fopen_icase(const char *pathname, const char *mode) {
|
||||
std::filesystem::path path = try_to_find_file(convert_pathname_to_path(pathname));
|
||||
#ifdef _WIN32
|
||||
std::wstring wmode(mode, mode + std::strlen(mode)); // bezpečnější převod
|
||||
return _wfopen(path.wstring().c_str(), wmode.c_str());
|
||||
#else
|
||||
return fopen(path.string().c_str(), mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
static thread_local std::string build_pathname_buffer;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "../../game/skeldal.h"
|
||||
#include "../getopt.h"
|
||||
#include "../platform.h"
|
||||
#include "../error.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
|
@ -67,7 +68,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||
std::cerr << "ERROR: " << exception_to_string(e) << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
|
||||
|
||||
extern "C" {
|
||||
#include "map_file.h"
|
||||
#include "../error.h"
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *map_file_to_memory(const char *name, size_t *sz);
|
||||
void unmap_file(void *ptr, size_t sz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
temp_file=$(mktemp /tmp/skeldal.XXXXXX.log)
|
||||
CURDIR=`dirname "$0"`
|
||||
|
||||
chmod +x "$CURDIR/skeldal_bin"
|
||||
LD_LIBRARY_PATH=$CURDIR:$LD_LIBRARY_PATH "$CURDIR/skeldal_bin" $* > "$temp_file" 2>&1
|
||||
|
||||
exit_code=$?
|
||||
|
@ -25,4 +26,3 @@ fi
|
|||
rm $temp_file
|
||||
exit $exit_code
|
||||
|
||||
|
||||
|
|
|
@ -1,2 +1,6 @@
|
|||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#if defined(__linux__)
|
||||
#include <malloc.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
|
184
platform/sdl/format_mapping.h
Normal file
184
platform/sdl/format_mapping.h
Normal file
|
@ -0,0 +1,184 @@
|
|||
#pragma once
|
||||
#include <SDL_surface.h>
|
||||
|
||||
|
||||
template<Uint32 format>
|
||||
struct FormatMapping {
|
||||
static_assert(false, "Unsupported pixel format");
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_ARGB2101010> {
|
||||
static constexpr int RShift = 20;
|
||||
static constexpr int GShift = 10;
|
||||
static constexpr int BShift = 0;
|
||||
static constexpr int AShift = 30;
|
||||
|
||||
static constexpr int RBits = 10;
|
||||
static constexpr int GBits = 10;
|
||||
static constexpr int BBits = 10;
|
||||
static constexpr int ABits = 2;
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_ABGR8888> {
|
||||
static constexpr int RShift = 0;
|
||||
static constexpr int GShift = 8;
|
||||
static constexpr int BShift = 16;
|
||||
static constexpr int AShift = 24;
|
||||
|
||||
static constexpr int RBits = 8;
|
||||
static constexpr int GBits = 8;
|
||||
static constexpr int BBits = 8;
|
||||
static constexpr int ABits = 8;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_ARGB8888> {
|
||||
static constexpr int RShift = 16;
|
||||
static constexpr int GShift = 8;
|
||||
static constexpr int BShift = 0;
|
||||
static constexpr int AShift = 24;
|
||||
|
||||
static constexpr int RBits = 8;
|
||||
static constexpr int GBits = 8;
|
||||
static constexpr int BBits = 8;
|
||||
static constexpr int ABits = 8;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_RGBA8888> {
|
||||
static constexpr int RShift = 24;
|
||||
static constexpr int GShift = 16;
|
||||
static constexpr int BShift = 8;
|
||||
static constexpr int AShift = 0;
|
||||
|
||||
static constexpr int RBits = 8;
|
||||
static constexpr int GBits = 8;
|
||||
static constexpr int BBits = 8;
|
||||
static constexpr int ABits = 8;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_BGRA8888> {
|
||||
static constexpr int RShift = 8;
|
||||
static constexpr int GShift = 16;
|
||||
static constexpr int BShift = 24;
|
||||
static constexpr int AShift = 0;
|
||||
|
||||
static constexpr int RBits = 8;
|
||||
static constexpr int GBits = 8;
|
||||
static constexpr int BBits = 8;
|
||||
static constexpr int ABits = 8;
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_ABGR4444> {
|
||||
static constexpr int RShift = 0;
|
||||
static constexpr int GShift = 4;
|
||||
static constexpr int BShift = 8;
|
||||
static constexpr int AShift = 12;
|
||||
|
||||
static constexpr int RBits = 4;
|
||||
static constexpr int GBits = 4;
|
||||
static constexpr int BBits = 4;
|
||||
static constexpr int ABits = 4;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_ARGB4444> {
|
||||
static constexpr int RShift = 8;
|
||||
static constexpr int GShift = 4;
|
||||
static constexpr int BShift = 0;
|
||||
static constexpr int AShift = 12;
|
||||
|
||||
static constexpr int RBits = 4;
|
||||
static constexpr int GBits = 4;
|
||||
static constexpr int BBits = 4;
|
||||
static constexpr int ABits = 4;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_RGBA4444> {
|
||||
static constexpr int RShift = 12;
|
||||
static constexpr int GShift = 8;
|
||||
static constexpr int BShift = 4;
|
||||
static constexpr int AShift = 0;
|
||||
|
||||
static constexpr int RBits = 4;
|
||||
static constexpr int GBits = 4;
|
||||
static constexpr int BBits = 4;
|
||||
static constexpr int ABits = 4;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_BGRA4444> {
|
||||
static constexpr int RShift = 4;
|
||||
static constexpr int GShift = 8;
|
||||
static constexpr int BShift = 12;
|
||||
static constexpr int AShift = 0;
|
||||
|
||||
static constexpr int RBits = 4;
|
||||
static constexpr int GBits = 4;
|
||||
static constexpr int BBits = 4;
|
||||
static constexpr int ABits = 4;
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_ABGR1555> {
|
||||
static constexpr int RShift = 0;
|
||||
static constexpr int GShift = 5;
|
||||
static constexpr int BShift = 10;
|
||||
static constexpr int AShift = 15;
|
||||
|
||||
static constexpr int RBits = 5;
|
||||
static constexpr int GBits = 5;
|
||||
static constexpr int BBits = 5;
|
||||
static constexpr int ABits = 1;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_ARGB1555> {
|
||||
static constexpr int RShift = 10;
|
||||
static constexpr int GShift = 5;
|
||||
static constexpr int BShift = 0;
|
||||
static constexpr int AShift = 15;
|
||||
|
||||
static constexpr int RBits = 5;
|
||||
static constexpr int GBits = 5;
|
||||
static constexpr int BBits = 5;
|
||||
static constexpr int ABits = 1;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_RGBA5551> {
|
||||
static constexpr int RShift = 11;
|
||||
static constexpr int GShift = 6;
|
||||
static constexpr int BShift = 1;
|
||||
static constexpr int AShift = 0;
|
||||
|
||||
static constexpr int RBits = 5;
|
||||
static constexpr int GBits = 5;
|
||||
static constexpr int BBits = 5;
|
||||
static constexpr int ABits = 1;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct FormatMapping<SDL_PIXELFORMAT_BGRA5551> {
|
||||
static constexpr int RShift = 1;
|
||||
static constexpr int GShift = 6;
|
||||
static constexpr int BShift = 11;
|
||||
static constexpr int AShift = 0;
|
||||
|
||||
static constexpr int RBits = 5;
|
||||
static constexpr int GBits = 5;
|
||||
static constexpr int BBits = 5;
|
||||
static constexpr int ABits = 1;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
#include "sdl_context.h"
|
||||
#include "keyboard_map.h"
|
||||
#include "format_mapping.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include "../platform.h"
|
||||
#include "../error.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
@ -34,6 +36,9 @@ void SDLContext::SDL_Deleter::operator ()(SDL_Surface* surface) {
|
|||
void SDLContext::SDL_Deleter::operator ()(SDL_Texture* texture) {
|
||||
SDL_DestroyTexture(texture);
|
||||
}
|
||||
void SDLContext::SDL_Deleter::operator ()(SDL_PixelFormat* f) {
|
||||
SDL_FreeFormat(f);
|
||||
}
|
||||
|
||||
void SDLContext::SDL_Audio_Deleter::operator()(SDL_AudioDeviceID x) {
|
||||
SDL_CloseAudioDevice(x);
|
||||
|
@ -74,10 +79,24 @@ SDLContext::SDLContext() {
|
|||
void handle_sdl_error(const char *msg) {
|
||||
char buff[512];
|
||||
|
||||
snprintf(buff, sizeof(buff), "SDL critical error (check video driver): %s %s",msg, SDL_GetError());
|
||||
snprintf(buff, sizeof(buff), "SDL critical error: %s %s",msg, SDL_GetError());
|
||||
throw std::runtime_error(buff);
|
||||
}
|
||||
|
||||
bool isFormatSupported(SDL_Renderer *renderer, Uint32 pixel_format) {
|
||||
SDL_RendererInfo info;
|
||||
if (SDL_GetRendererInfo(renderer, &info) != 0) {
|
||||
handle_sdl_error("Failed to get renderer info");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Uint32 i = 0; i < info.num_texture_formats; ++i) {
|
||||
if (info.texture_formats[i] == pixel_format) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** texture, int width, int height, CrtFilterType type) {
|
||||
|
||||
|
@ -95,6 +114,8 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
|
|||
default: break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (type == CrtFilterType::scanlines || type == CrtFilterType::scanlines_2) {
|
||||
width = 32;
|
||||
} else {
|
||||
|
@ -105,8 +126,11 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
|
|||
unsigned int mult_of_base = std::max<unsigned int>((height+240)/480,interfer);
|
||||
height = height * interfer / mult_of_base;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Vytvoř novou texturu ve správné velikosti
|
||||
*texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||
*texture = SDL_CreateTexture(renderer, _texture_render_format, SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||
if (!*texture) {
|
||||
type = CrtFilterType::none;
|
||||
return; //crt filter failed to create, do not use filter
|
||||
|
@ -126,10 +150,12 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
|
|||
|
||||
Uint32* pixelArray = (Uint32*)pixels;
|
||||
|
||||
|
||||
if (type == CrtFilterType::scanlines) {
|
||||
|
||||
Uint32 darkPixel = 0xA0A0A0FF;
|
||||
Uint32 transparentPixel = 0xFFFFFFC0;
|
||||
|
||||
Uint32 darkPixel = SDL_MapRGBA(_main_pixel_format.get(), 0xA0, 0xA0, 0xA0, 0xFF);
|
||||
Uint32 transparentPixel = SDL_MapRGBA(_main_pixel_format.get(), 0xFF, 0xFF, 0xFF, 0xC0);
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
Uint32 color = ((y & 1)== 0) ? darkPixel : transparentPixel;
|
||||
|
@ -141,8 +167,8 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
|
|||
else if (type == CrtFilterType::scanlines_2) {
|
||||
|
||||
|
||||
Uint32 darkPixel = 0x808080FF;
|
||||
Uint32 transparentPixel = 0xFFFFFFE0;
|
||||
Uint32 darkPixel = SDL_MapRGBA(_main_pixel_format.get(), 0x80, 0x80, 0x80, 0xFF);
|
||||
Uint32 transparentPixel = SDL_MapRGBA(_main_pixel_format.get(), 0xFF, 0xFF, 0xFF, 0xE0);
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
Uint32 color = (y % 3== 2) ? darkPixel : transparentPixel;
|
||||
|
@ -152,10 +178,10 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
|
|||
}
|
||||
} else {
|
||||
|
||||
static Uint32 red_pixel = 0xFF8080A0;
|
||||
static Uint32 green_pixel = 0x80FF80A0;
|
||||
static Uint32 blue_pixel = 0x8080FFA0;
|
||||
static Uint32 dark_pixel = 0x000000C0;
|
||||
static Uint32 red_pixel = SDL_MapRGBA(_main_pixel_format.get(), 0xFF, 0x80, 0x80, 0xA0);
|
||||
static Uint32 green_pixel = SDL_MapRGBA(_main_pixel_format.get(), 0x80, 0xFF, 0x80, 0xA0);
|
||||
static Uint32 blue_pixel = SDL_MapRGBA(_main_pixel_format.get(), 0x80, 0x80, 0xFF, 0xA0);
|
||||
static Uint32 dark_pixel = SDL_MapRGBA(_main_pixel_format.get(), 0x0, 0x0, 0x00, 0xA0);
|
||||
for (int y = 2; y < height; y++) {
|
||||
if (type == CrtFilterType::rgb_matrix_2) {
|
||||
for (int x = 2; x < width; x+=3) {
|
||||
|
@ -199,6 +225,48 @@ static void crash_sdl_exception() {
|
|||
abort();
|
||||
}
|
||||
|
||||
// Seznam akceptovatelných formátů odpovídajících RGBA8888 (v různém pořadí)
|
||||
constexpr Uint32 acceptable_formats[] = {
|
||||
SDL_PIXELFORMAT_RGBA8888,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_PIXELFORMAT_BGRA8888,
|
||||
SDL_PIXELFORMAT_ABGR8888,
|
||||
|
||||
SDL_PIXELFORMAT_RGBA4444,
|
||||
SDL_PIXELFORMAT_ARGB4444,
|
||||
SDL_PIXELFORMAT_BGRA4444,
|
||||
SDL_PIXELFORMAT_ABGR4444,
|
||||
|
||||
SDL_PIXELFORMAT_ARGB2101010,
|
||||
};
|
||||
|
||||
constexpr bool is_acceptable_format(Uint32 format) {
|
||||
for (size_t i = 0; i < sizeof(acceptable_formats)/sizeof(acceptable_formats[0]); ++i) {
|
||||
if (format == acceptable_formats[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static Uint32 find_best_rgba_like_format(SDL_Renderer* renderer) {
|
||||
SDL_RendererInfo info;
|
||||
if (SDL_GetRendererInfo(renderer, &info) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((info.max_texture_width != 0 && info.max_texture_width < 640) ||
|
||||
(info.max_texture_height!= 0 && info.max_texture_height < 480)) return 0;
|
||||
|
||||
for (Uint32 i = 0; i < info.num_texture_formats; ++i) {
|
||||
Uint32 fmt = info.texture_formats[i];
|
||||
if (is_acceptable_format(fmt)) {
|
||||
return fmt;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDLContext::init_video(const VideoConfig &config, const char *title) {
|
||||
static Uint32 update_request_event = SDL_RegisterEvents(1);
|
||||
|
@ -219,15 +287,17 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) {
|
|||
_enable_crt = false;
|
||||
}
|
||||
|
||||
|
||||
_fullscreen_mode = config.fullscreen;
|
||||
_mouse_size = config.cursor_size;
|
||||
|
||||
std::atomic<bool> done = false;
|
||||
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));
|
||||
|
@ -237,13 +307,49 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) {
|
|||
}
|
||||
|
||||
_window.reset(window);
|
||||
SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), -1, config.composer);
|
||||
if (!renderer) {
|
||||
handle_sdl_error("Failed to create composer");
|
||||
|
||||
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, &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) {
|
||||
|
@ -253,20 +359,30 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) {
|
|||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, config.scale_quality);
|
||||
}
|
||||
|
||||
_renderer.reset(renderer);
|
||||
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB1555, SDL_TEXTUREACCESS_STREAMING, 640, 480);
|
||||
|
||||
|
||||
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);
|
||||
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB1555, SDL_TEXTUREACCESS_STREAMING, 640, 480);
|
||||
|
||||
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 (...) {
|
||||
|
@ -294,7 +410,17 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) {
|
|||
done.wait(false);
|
||||
if (e) {
|
||||
_render_thread.join();
|
||||
std::rethrow_exception(e);
|
||||
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.")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -335,6 +461,102 @@ int SDLContext::adjust_deadzone(int v, short deadzone) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
template<int shift>
|
||||
constexpr Uint32 shift_bits_5(Uint32 val) {
|
||||
if constexpr(shift > 0) {
|
||||
return val << shift | shift_bits_5<shift-5>(val);
|
||||
} else if constexpr(shift < 0) {
|
||||
return val >> (-shift);
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<Uint32 pixel_format>
|
||||
void SDLContext::convert_bitmap(const void *pixels, SDL_Rect rect, int pitch) {
|
||||
|
||||
constexpr auto RShift = FormatMapping<pixel_format>::RShift;
|
||||
constexpr auto GShift = FormatMapping<pixel_format>::GShift;
|
||||
constexpr auto BShift = FormatMapping<pixel_format>::BShift;
|
||||
constexpr auto AShift = FormatMapping<pixel_format>::AShift;
|
||||
constexpr auto RBits = FormatMapping<pixel_format>::RBits;
|
||||
constexpr auto GBits = FormatMapping<pixel_format>::GBits;
|
||||
constexpr auto BBits = FormatMapping<pixel_format>::BBits;
|
||||
constexpr auto ABits = FormatMapping<pixel_format>::ABits;
|
||||
|
||||
const Uint16 *src = static_cast<const Uint16*>(pixels);
|
||||
auto trg = converted_pixels.data();
|
||||
for (int y = 0; y < rect.h; ++y) {
|
||||
for (int x = 0; x < rect.w; ++x) {
|
||||
Uint16 pixel = src[x];
|
||||
Uint32 a = (pixel & 0x8000) ? 0 : 0x1F;
|
||||
Uint32 r = ((pixel >> 10) & 0x1F);
|
||||
Uint32 g = ((pixel >> 5) & 0x1F);
|
||||
Uint32 b = (pixel & 0x1F);
|
||||
|
||||
r = shift_bits_5<RBits-5>(r);
|
||||
g = shift_bits_5<GBits-5>(g);
|
||||
b = shift_bits_5<BBits-5>(b);
|
||||
a = shift_bits_5<ABits-5>(a);
|
||||
|
||||
trg[x] = (r << RShift) | (g << GShift) | (b << BShift) | (a << AShift);
|
||||
}
|
||||
trg += rect.w;
|
||||
src = src + pitch / 2;
|
||||
}
|
||||
}
|
||||
|
||||
void SDLContext::update_texture_with_conversion(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
|
||||
{
|
||||
SDL_Rect r;
|
||||
if (rect) {
|
||||
r = *rect;
|
||||
} else {
|
||||
SDL_QueryTexture(texture, nullptr, nullptr, &r.w, &r.h);
|
||||
r.x = 0;
|
||||
r.y = 0;
|
||||
}
|
||||
|
||||
converted_pixels.clear();
|
||||
converted_pixels.resize(r.w * r.h);
|
||||
|
||||
switch (_texture_render_format) {
|
||||
case SDL_PIXELFORMAT_ABGR8888:
|
||||
convert_bitmap<SDL_PIXELFORMAT_ABGR8888>(pixels, r, pitch);break;
|
||||
case SDL_PIXELFORMAT_ARGB8888:
|
||||
convert_bitmap<SDL_PIXELFORMAT_ARGB8888>(pixels, r, pitch);break;
|
||||
case SDL_PIXELFORMAT_ARGB2101010:
|
||||
convert_bitmap<SDL_PIXELFORMAT_ARGB2101010>(pixels, r, pitch);break;
|
||||
case SDL_PIXELFORMAT_RGBA8888:
|
||||
convert_bitmap<SDL_PIXELFORMAT_RGBA8888>(pixels, r, pitch);break;
|
||||
case SDL_PIXELFORMAT_BGRA8888:
|
||||
convert_bitmap<SDL_PIXELFORMAT_BGRA8888>(pixels, r, pitch);break;
|
||||
case SDL_PIXELFORMAT_ABGR4444:
|
||||
convert_bitmap<SDL_PIXELFORMAT_ABGR4444>(pixels, r, pitch);break;
|
||||
case SDL_PIXELFORMAT_ARGB4444:
|
||||
convert_bitmap<SDL_PIXELFORMAT_ARGB4444>(pixels, r, pitch);break;
|
||||
case SDL_PIXELFORMAT_BGRA4444:
|
||||
convert_bitmap<SDL_PIXELFORMAT_BGRA4444>(pixels, r, pitch);break;
|
||||
case SDL_PIXELFORMAT_RGBA4444:
|
||||
convert_bitmap<SDL_PIXELFORMAT_RGBA4444>(pixels, r, pitch);break;
|
||||
case SDL_PIXELFORMAT_ABGR1555:
|
||||
convert_bitmap<SDL_PIXELFORMAT_ABGR1555>(pixels, r, pitch);break;
|
||||
case SDL_PIXELFORMAT_ARGB1555:
|
||||
convert_bitmap<SDL_PIXELFORMAT_ARGB1555>(pixels, r, pitch);break;
|
||||
case SDL_PIXELFORMAT_RGBA5551:
|
||||
convert_bitmap<SDL_PIXELFORMAT_RGBA5551>(pixels, r, pitch);break;
|
||||
case SDL_PIXELFORMAT_BGRA5551:
|
||||
convert_bitmap<SDL_PIXELFORMAT_BGRA5551>(pixels, r, pitch);break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (SDL_UpdateTexture(texture, &r, converted_pixels.data(), r.w * 4) < 0) {
|
||||
handle_sdl_error("Failed to update texture");
|
||||
}
|
||||
}
|
||||
|
||||
static int axis_dynamic(int c) {
|
||||
double f = std::floor(std::pow(std::abs(c)*0.001,2)*0.025);
|
||||
|
||||
|
@ -698,19 +920,19 @@ void SDLContext::update_screen(bool force_refresh) {
|
|||
SDL_Rect r;
|
||||
pop_item(iter, r);
|
||||
std::string_view data = pop_data(iter, r.w*r.h*2);
|
||||
if (SDL_UpdateTexture(_texture.get(), &r, data.data(), r.w*2)<0) handle_sdl_error("Update of render target failed");
|
||||
update_texture_with_conversion(_texture.get(), &r, data.data(), r.w*2);
|
||||
}
|
||||
break;
|
||||
case DisplayRequest::show_mouse_cursor: {
|
||||
SDL_Rect r;
|
||||
pop_item(iter, r);
|
||||
std::string_view data = pop_data(iter, r.w*r.h*2);
|
||||
_mouse.reset(SDL_CreateTexture(_renderer.get(), SDL_PIXELFORMAT_ARGB1555,SDL_TEXTUREACCESS_STATIC, r.w, r.h));
|
||||
_mouse.reset(SDL_CreateTexture(_renderer.get(), _texture_render_format,SDL_TEXTUREACCESS_STATIC, r.w, r.h));
|
||||
if (!_mouse) handle_sdl_error("Failed to create surface for mouse cursor");
|
||||
SDL_SetTextureBlendMode(_mouse.get(), SDL_BLENDMODE_BLEND);
|
||||
_mouse_rect.w = r.w;
|
||||
_mouse_rect.h = r.h;
|
||||
if (SDL_UpdateTexture(_mouse.get(), NULL, data.data(), r.w*2)<0) handle_sdl_error("Update of mouse cursor failed");
|
||||
update_texture_with_conversion(_mouse.get(), NULL, data.data(), r.w*2);
|
||||
}
|
||||
break;
|
||||
case DisplayRequest::hide_mouse_cursor: {
|
||||
|
@ -747,10 +969,10 @@ void SDLContext::update_screen(bool force_refresh) {
|
|||
if (iter == _sprites.end()) {
|
||||
iter = _sprites.insert(iter,{id});
|
||||
}
|
||||
iter->_txtr.reset(SDL_CreateTexture(_renderer.get(), SDL_PIXELFORMAT_ARGB1555, SDL_TEXTUREACCESS_STATIC,r.w, r.h));
|
||||
iter->_txtr.reset(SDL_CreateTexture(_renderer.get(), _texture_render_format, SDL_TEXTUREACCESS_STATIC,r.w, r.h));
|
||||
if (!iter->_txtr) handle_sdl_error("Failed to create compositor sprite");
|
||||
SDL_SetTextureBlendMode(iter->_txtr.get(), SDL_BLENDMODE_BLEND);
|
||||
if (SDL_UpdateTexture(iter->_txtr.get(), NULL, data.data(), r.w*2)<0) handle_sdl_error("Update of sprite failed");
|
||||
update_texture_with_conversion(iter->_txtr.get(), NULL, data.data(), r.w*2);
|
||||
iter->_rect = r;
|
||||
update_zindex();
|
||||
} break;
|
||||
|
@ -851,10 +1073,8 @@ void SDLContext::push_update_msg(const SDL_Rect &rc, const uint16_t *data, int p
|
|||
_display_update_queue.resize(sz+rc.w*rc.h*2);
|
||||
short *trg = reinterpret_cast<short *>(_display_update_queue.data()+sz);
|
||||
for (int yp = 0; yp < rc.h; ++yp) {
|
||||
for (int xp = 0; xp < rc.w; ++xp) {
|
||||
*trg = data[xp] ^ 0x8000;
|
||||
++trg;
|
||||
}
|
||||
std::copy(data, data+rc.w, trg);
|
||||
trg += rc.w;
|
||||
data += pitch;
|
||||
}
|
||||
}
|
||||
|
@ -1009,7 +1229,7 @@ void put_picture_ex(unsigned short x,unsigned short y,const void *p, unsigned sh
|
|||
}
|
||||
|
||||
void SDLContext::push_hi_image(const unsigned short *image) {
|
||||
SDL_Rect rc;
|
||||
SDL_Rect rc = {};
|
||||
rc.w= image[0];
|
||||
rc.h =image[1];
|
||||
push_item(rc);
|
||||
|
@ -1019,7 +1239,6 @@ void SDLContext::push_hi_image(const unsigned short *image) {
|
|||
unsigned short *trg = reinterpret_cast<unsigned short *>(_display_update_queue.data()+sz);
|
||||
std::fill(trg, trg+imgsz, 0x8000);
|
||||
put_picture_ex(0, 0, image, trg, rc.w);
|
||||
std::transform(trg, trg+imgsz, trg, [](unsigned short &x)->unsigned short {return x ^ 0x8000;});
|
||||
}
|
||||
|
||||
void SDLContext::show_mouse_cursor(const unsigned short *ms_hi_format, SDL_Point finger) {
|
||||
|
|
|
@ -170,6 +170,7 @@ protected:
|
|||
void operator()(SDL_Renderer *);
|
||||
void operator()(SDL_Surface *);
|
||||
void operator()(SDL_Texture *);
|
||||
void operator()(SDL_PixelFormat* f);
|
||||
};
|
||||
|
||||
struct BlendTransitionReq {
|
||||
|
@ -237,13 +238,16 @@ protected:
|
|||
std::unique_ptr<SDL_Texture, SDL_Deleter> _texture2;
|
||||
std::unique_ptr<SDL_Texture, SDL_Deleter> _crt_effect;
|
||||
std::unique_ptr<SDL_Texture, SDL_Deleter> _mouse;
|
||||
std::unique_ptr<SDL_PixelFormat, SDL_Deleter> _main_pixel_format;
|
||||
unique_value<SDL_AudioDeviceID, SDL_Audio_Deleter> _audio;
|
||||
SDL_Texture *_visible_texture;
|
||||
SDL_Texture *_hidden_texture;
|
||||
SDL_Texture *_visible_texture = nullptr;
|
||||
SDL_Texture *_hidden_texture = nullptr;
|
||||
uint32_t _texture_render_format = SDL_PIXELFORMAT_ARGB1555;
|
||||
|
||||
|
||||
bool _fullscreen_mode = false;
|
||||
bool _present = false;
|
||||
bool _convert_format = false;
|
||||
std::atomic<bool> _key_control = false;
|
||||
std::atomic<bool> _key_shift = false;
|
||||
std::atomic<bool> _key_capslock = false;
|
||||
|
@ -252,11 +256,12 @@ protected:
|
|||
|
||||
|
||||
std::vector<char> _display_update_queue;
|
||||
std::vector<uint32_t> converted_pixels;
|
||||
using QueueIter = const char *;
|
||||
std::queue<uint16_t> _keyboard_queue;
|
||||
SDL_Rect _mouse_rect;
|
||||
SDL_Point _mouse_finger;
|
||||
float _mouse_size;
|
||||
float _mouse_size = 1;
|
||||
SpriteList _sprites;
|
||||
|
||||
|
||||
|
@ -307,4 +312,11 @@ protected:
|
|||
void generate_j_event(int button, char up);
|
||||
static int adjust_deadzone(int v, short deadzone);
|
||||
|
||||
void update_texture_with_conversion(SDL_Texture * texture,
|
||||
const SDL_Rect * rect,
|
||||
const void *pixels, int pitch);
|
||||
|
||||
template<Uint32 pixel_format>
|
||||
void convert_bitmap(const void *pixels, SDL_Rect r, int pitch);
|
||||
|
||||
};
|
||||
|
|
|
@ -299,7 +299,8 @@ static void update_music_volume(){
|
|||
float v = music_volume * master_volume;
|
||||
for (int i = 0; i <2; i++)
|
||||
sound_mixer.visit_track(music_track_id_base+i,[&](WaveMixer<2> &m){
|
||||
m.set_channel_volume(v, v);
|
||||
m.set_channel_volume(0, v);
|
||||
m.set_channel_volume(1, v);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -91,8 +91,8 @@ public:
|
|||
} else {
|
||||
(*iter) += value.left * vol[0];
|
||||
++iter;
|
||||
(*iter) += value.right * vol[0];
|
||||
++iter;
|
||||
(*iter) += value.right * vol[1];
|
||||
std::advance(iter, channels-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "../../game/skeldal.h"
|
||||
#include "../getopt.h"
|
||||
#include "../platform.h"
|
||||
#include "../error.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
@ -86,7 +87,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
} catch (const std::exception &e) {
|
||||
cfg.show_error(e.what());
|
||||
cfg.show_error(exception_to_string(e).c_str());
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
|
|
|
@ -15,13 +15,17 @@ std::string getSavedGamesDirectory() {
|
|||
PWSTR path = nullptr;
|
||||
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_SavedGames, 0, NULL, &path))) {
|
||||
fs::path savedGamesPath(path);
|
||||
CoTaskMemFree(path);
|
||||
return (savedGamesPath / SAVEGAME_FOLDERNAME).string();
|
||||
CoTaskMemFree(path);
|
||||
|
||||
// Převod na UTF-8 std::string
|
||||
std::u8string utf8 = (savedGamesPath / SAVEGAME_FOLDERNAME).u8string();
|
||||
return std::string(reinterpret_cast<const char*>(utf8.data()), utf8.size());
|
||||
} else {
|
||||
display_error("Failed to retrieve FOLDEROD_SavedGames");
|
||||
display_error("Failed to retrieve FOLDERID_SavedGames");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
const char *get_default_savegame_directory() {
|
||||
|
||||
static std::string dir = getSavedGamesDirectory();
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#crt_filter=auto
|
||||
#scale_quality=auto
|
||||
#composer=auto
|
||||
#sdl_renderer_driver=software
|
||||
#aspect_ratio=4:3
|
||||
#cursor_size=100
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ DDLArchive::Extracted DDLArchive::extract_file(std::ifstream &s,
|
|||
std::vector<char> data;
|
||||
data.resize(sz);
|
||||
s.read(data.data(), sz);
|
||||
if (s.gcount() != sz) return {fname, false, {}};
|
||||
if (static_cast<uint32_t>(s.gcount()) != sz) return {fname, false, {}};
|
||||
return {fname, true, std::move(data)};
|
||||
|
||||
}
|
||||
|
|
5
version.in.h
Normal file
5
version.in.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#define SKELDAL_VERSION "@APP_VERSION@"
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue