#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "globals.h" #include "temp_storage.h" #include #include #include #define STATE_CUR_VER 2 #define _GAME_ST "_GAME.TMP" #define _GLOBAL_ST "_GLOBEV.TMP" #define _SLOT_SAV "slot%02d.SAV" #define SLOTS_MAX 10 #define GM_MAPENABLE 0x1 #define SAVE_SLOT_S 32 #define LOAD_SLOT_S (372+34) #define SAVE_SLOT_E (34+203) #define LOAD_SLOT_E (372+34+203) #define SSAVE_VERSION 0 static TMPFILE_WR *story=NULL; static char load_another; static unsigned long current_campaign = 0; static long prev_game_time_save = -999; char reset_mobiles=0; typedef struct s_save { int viewsector; char viewdir; short version; char not_used; int gold; short cur_group; char autosave; char enable_sort; char shownames; char showlives; char zoom_speed; char turn_speed; char autoattack; char music_vol; char sample_vol; char xbass; char bass; char treble; char stereing; char swapchans; char out_filter; int32_t glob_flags; int32_t game_time; char runes[5]; char level_name[13]; short picks; //pocet_sebranych predmetu v mysi short items_added; //pocet_pridanych predmetu int sleep_long; int game_flags; }S_SAVE; static int get_list_count(); static int unable_open_temp(char *c) { char d[]="Unable to open the file : ",*e; concat(e,d,c); closemode(); display_error(e); SEND_LOG("(SAVELOAD) Open temp error detected (%s)",c); exit(1); } static void unable_write_temp(char *c) { char d[]="Unable to write to the temp file : ",*e; concat(e,d,c); closemode(); display_error(e); SEND_LOG("(SAVELOAD) Open temp error detected (%s)",c); exit(1); } int load_org_map(char *filename,TSTENA **sides,TSECTOR **sectors,TMAP_EDIT_INFO **coords,int *mapsize) { FILE *f; void *temp; int sect; int32_t size,r; char nmapend=1; const char *c=build_pathname(2, gpathtable[SR_MAP],filename); f=fopen_icase(c,"rb"); if (f==NULL) return -1; do { r=load_section(f,&temp,§,&size); if (r==size) switch (sect) { case A_SIDEMAP: *sides=temp; break; case A_SECTMAP: *sectors=temp; if (mapsize!=NULL) *mapsize=size/sizeof(TSECTOR); break; case A_MAPINFO: if (coords!=NULL) *coords=temp;else free(temp); break; case A_MAPGLOB: //memcpy(&mglob,temp,min(sizeof(mglob),size)); free(temp); break; case A_MAPEND : nmapend=0; free(temp); break; default: free(temp); } else { if (temp!=NULL)free(temp); fclose(f); return -1; } } while (nmapend); fclose(f); return 0; } void save_daction(TMPFILE_WR *f,int count,D_ACTION *ptr) { if (ptr!=NULL) { save_daction(f,count+1,ptr->next); temp_storage_write(ptr,sizeof(D_ACTION),f); } else temp_storage_write(&count,2,f); } void load_daction(TMPFILE_RD *fsta) { uint16_t i,j; i=0; while (d_action!=NULL) //vymaz pripadne delaited actions { D_ACTION *p; p=d_action; d_action=p->next;free(p); } temp_storage_read(&i,2,fsta);d_action=NULL; for(j=0;jnext=d_action; d_action=p; } } void save_items(TMPFILE_WR *f) { int32_t i,j; short *c; for(i=0;i= item_count) { free(new_item_map[i]); new_item_map[i] = map_items[i]; map_items[i] = NULL; break; } ++v; } } for(i=0;ivyk_max) return -2; temp_storage_read(map_vyk,vyk_max*sizeof(TVYKLENEK),fsta); } return 0; } void save_all_fly(TMPFILE_WR *fsta) { LETICI_VEC *f; int32_t sz = 1; f=letici_veci; while (f!=NULL) { short *c; sz = sizeof(*f); temp_storage_write(&sz,sizeof(sz),fsta); temp_storage_write(f,sz,fsta); c=f->items; if (c!=NULL) do temp_storage_write(c,1*2,fsta); while (*c++); f=f->next; } sz = 0; temp_storage_write(&sz,sizeof(sz),fsta); } int load_all_fly(TMPFILE_RD *fsta) { LETICI_VEC *n; int32_t sz; destroy_all_fly(); temp_storage_read(&sz,sizeof(sz),fsta); while (sz == sizeof(LETICI_VEC)) { short items[100],*c; n=New(LETICI_VEC); c=items;memset(items,0,sizeof(items)); if (temp_storage_read(n,1*sizeof(*n),fsta)!=sizeof(*n)) { free(n); return -2; } if (n->items!=NULL) { do temp_storage_read(c,2,fsta); while (*c++); n->items=NewArr(short,c-items); memcpy(n->items,items,(c-items)*sizeof(short)); } add_fly(n); temp_storage_read(&sz,sizeof(sz),fsta); } return sz != 0; } int save_map_state() //uklada stav mapy pro savegame (neuklada aktualni pozici); { char sta[200]; char *bf = NULL; TMPFILE_WR *fsta; int32_t i; int32_t siz; TSTENA *org_sides; TSECTOR *org_sectors; short res=-1; unsigned char ver=0; strcpy(sta,level_fname); fsta=temp_storage_create(sta);if (fsta==NULL) unable_open_temp(sta); SEND_LOG("(SAVELOAD) Saving map state for current map"); if (load_org_map(level_fname,&org_sides,&org_sectors,NULL,NULL)) goto err; siz=(mapsize+7)/8; bf=(char *)getmem(siz); ver=STATE_CUR_VER; temp_storage_write(&ver,sizeof(ver)*1,fsta); //<------------------------- temp_storage_write(&mapsize,sizeof(mapsize)*1,fsta); //<------------------------- memset(bf,0,siz); temp_storage_write(&siz,1*sizeof(siz),fsta); //<------------------------- for(i=0;i>3]|=1<<(i & 7); temp_storage_write(bf,siz*1,fsta); for(i=0;i>3]|=1<<(i & 7); temp_storage_write(bf,siz*1,fsta); save_map_description(fsta); for(i=0;iSTATE_CUR_VER) goto err; if (!temp_storage_read(&i,sizeof(mapsize)*1,fsta)) goto err; if (mapsize!=i) goto err; SEND_LOG("(SAVELOAD) Loading map state for current map"); temp_storage_read(&siz,1*sizeof(siz),fsta); bf=(char *)getmem(siz); if (!temp_storage_read(bf,siz*1,fsta)) goto err; for (i=0;i>3]>>(i & 7)) & 1) map_coord[i].flags|=MC_AUTOMAP; if (!temp_storage_read(bf,siz*1,fsta)) goto err; for (i=0;i>3]>>(i & 7)) & 1) map_coord[i].flags|=MC_DISCLOSED; load_map_description(fsta); while (temp_storage_read(&i,sizeof(i),fsta) && i >= 0 && i<=mapsize*4) if (temp_storage_read(map_sides+i,1*sizeof(TSTENA),fsta)!=sizeof(TSTENA)) goto err; while (temp_storage_read(&i,sizeof(i),fsta) && i >= 0 && i<=mapsize) if (temp_storage_read(map_sectors+i,1*sizeof(TSECTOR),fsta)!=sizeof(TSECTOR)) goto err; if (reset_mobiles) //reloads mobiles if flag present { char mm[MAX_MOBS]; for(i=0;i=0 && i<=MAX_MOBS) if (temp_storage_read(mobs+i,1*sizeof(TMOB),fsta)!=sizeof(TMOB)) goto err; } for(i=0;i 255) name_size_b = 255; else name_size_b = (uint8_t)name_size; fwrite(&name_size_b,1,1,f); fwrite(name, 1, name_size_b, f); uint32_t data_size = sz; fwrite(&data_size,1,sizeof(data_size),f); fwrite(data, 1,data_size, f); } static void pack_status_file_cb(const char *name, void *ctx) { FILE *f = ctx; int32_t sz = temp_storage_find(name); assert(sz > 0); void *data = getmem(sz); temp_storage_retrieve(name, data, sz); add_status_file(f, name, sz, data); free(data); } int pack_all_status(FILE *f) { char c = 0; temp_storage_list(pack_status_file_cb, f); fwrite(&c,1,1,f); return 0; } typedef enum enum_all_status_callback_result_t { enum_status_cont_skip, //continue, skip this block enum_status_cont_read, //continue, i read this block enum_status_skip_stop, //stop, skip this block enum_status_read_stop, //stop, don't skip i read this block enum_status_error //error } ENUM_ALL_STATUS_CALLBACK_RESULT; //return 1 success, 0 stopped, -1 error static int enum_all_status(FILE *f, ENUM_ALL_STATUS_CALLBACK_RESULT (*cb)(FILE *, const char *, size_t , void *), void *ctx) { while(1) { uint8_t name_size_b; if (fread(&name_size_b, 1,1,f)==0) return 1; char *name = (char *)alloca(name_size_b+1); if (fread(name, 1, name_size_b, f) != name_size_b) return -1; name[name_size_b] = 0; uint32_t data_size; if (fread(&data_size,1,sizeof(uint32_t),f) != sizeof(uint32_t)) return -1; ENUM_ALL_STATUS_CALLBACK_RESULT st = cb(f, name, data_size, ctx); switch (st) { case enum_status_error: return 0; case enum_status_cont_skip: fseek(f, data_size, SEEK_CUR);break; case enum_status_cont_read: break; case enum_status_skip_stop: fseek(f, data_size, SEEK_CUR);return 0; case enum_status_read_stop: return 0; } } } static ENUM_ALL_STATUS_CALLBACK_RESULT unpack_status_callback(FILE *f, const char *name, size_t datasize, void *_) { void *buff = getmem(datasize); if (fread(buff, 1, datasize, f) != datasize) { free(buff); return enum_status_error;; } temp_storage_store(name, buff, datasize); free(buff); return enum_status_cont_read; } int unpack_all_status(FILE *f) { int r = enum_all_status(f, &unpack_status_callback, NULL); if (r) return 0; return -1; } int save_basic_info() { TMPFILE_WR *f; S_SAVE s; short *p; int i; char res=0; THUMAN *h; SEND_LOG("(SAVELOAD) Saving basic info for game (file:%s)",_GAME_ST ); f=temp_storage_create(_GAME_ST); if (f==NULL) return 1; s.viewsector=viewsector; s.viewdir=viewdir; s.version=SSAVE_VERSION; s.not_used=0; s.gold=money; s.cur_group=cur_group; s.shownames=show_names; s.showlives=show_lives; s.autoattack=autoattack; s.turn_speed=turn_speed(-1); s.zoom_speed=zoom_speed(-1); s.game_time=game_time; s.enable_sort=enable_sort; s.sleep_long=sleep_ticks; s.sample_vol=MIN(get_snd_effect(SND_GFX),255); s.music_vol=MIN(get_snd_effect(SND_MUSIC),255); s.xbass=MIN(get_snd_effect(SND_XBASS),255); s.bass=MIN(get_snd_effect(SND_BASS),255); s.treble=MIN(get_snd_effect(SND_TREBL),255); s.stereing=MIN(get_snd_effect(SND_LSWAP),255); 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); 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) for(i=1,p=picked_item;*p;i++,p++);else i=0; s.picks=i; s.items_added=item_count-it_count_orgn; temp_storage_write(&s,1*sizeof(s),f); if (i) temp_storage_write(picked_item,2*i,f); if (s.items_added) temp_storage_write(glob_items+it_count_orgn,sizeof(TITEM)*s.items_added,f); save_spells(f); temp_storage_write(postavy,1*sizeof(postavy),f); for(i=0,h=postavy;idemon_save!=NULL) temp_storage_write(h->demon_save,sizeof(THUMAN)*1,f); //ulozeni polozek s demony res|=save_dialog_info(f); temp_storage_close_wr(f); SEND_LOG("(SAVELOAD) Done... Result: %d",res); return res; } int load_basic_info() { TMPFILE_RD *f; S_SAVE s; int i; char res=0; TITEM *itg; THUMAN *h; SEND_LOG("(SAVELOAD) Loading basic info for game (file:%s)",_GAME_ST); f=temp_storage_open(_GAME_ST); 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; i=s.picks; if (picked_item!=NULL) free(picked_item); if (i) { picked_item=NewArr(short,i); res|=(temp_storage_read(picked_item,2*i,f)!=(unsigned)i); } else picked_item=NULL; itg=NewArr(TITEM,it_count_orgn+s.items_added); memcpy(itg,glob_items,it_count_orgn*sizeof(TITEM)); free(glob_items);glob_items=itg; if (s.items_added) res|=(temp_storage_read(glob_items+it_count_orgn,sizeof(TITEM)*s.items_added,f)!=(unsigned)s.items_added); item_count=it_count_orgn+s.items_added; res|=load_spells(f); for(i=0,h=postavy;idemon_save!=NULL) free(h->demon_save); if (!res) res|=(temp_storage_read(postavy,1*sizeof(postavy),f)!=sizeof(postavy)); for(i=0,h=postavy;iprogramovano=0; h->provadena_akce=h->zvolene_akce=NULL; h->dostal=0; if (h->demon_save!=NULL) { h->demon_save=New(THUMAN); temp_storage_read(h->demon_save,sizeof(THUMAN)*1,f);//obnova polozek s demony } } res|=load_dialog_info(f); temp_storage_close_rd(f); viewsector=s.viewsector; viewdir=s.viewdir; cur_group=s.cur_group; show_names=s.shownames; show_lives=s.showlives; autoattack=s.autoattack; turn_speed(s.turn_speed); zoom_speed(s.zoom_speed); game_time=s.game_time; sleep_ticks=s.sleep_long; enable_sort=s.enable_sort; autosave_enabled=s.autosave; money=s.gold; for(i=0;i<5;i++) runes[i]=s.runes[i]; set_snd_effect(SND_GFX,s.sample_vol); set_snd_effect(SND_MUSIC,s.music_vol); set_snd_effect(SND_XBASS,s.xbass); set_snd_effect(SND_BASS,s.bass); set_snd_effect(SND_TREBL,s.treble); set_snd_effect(SND_LSWAP,s.stereing); set_snd_effect(SND_SWAP,s.swapchans); set_snd_effect(SND_OUTFILTER,s.out_filter); if (level_fname==NULL || strcmp(s.level_name,level_fname)) { strcopy_n(loadlevel.name,s.level_name,sizeof(loadlevel.name)); loadlevel.start_pos=viewsector; loadlevel.dir=viewdir; send_message(E_CLOSE_MAP,NULL); load_another=1; } else load_another=0; for(i=0;i0) { SEND_LOG("(ERROR) Error detected during unpacking game... Loading stopped (result:%d)",r); return r; } load_book(); load_global_events(); if ((t=load_saved_shops())!=0) return t; if ((t=load_basic_info())!=0) return t; running_battle=0; norefresh=0; if (!load_another) restore_current_map(); else { save_map=0; norefresh=1; } for(t=0;tname) == 0) { void *d = getmem(datasize); if (fread(d, 1, datasize, f) != datasize) { free(d); return enum_status_error; } me->size = datasize; me->data = d; return enum_status_read_stop; } else { return enum_status_cont_skip; } } //------------------------ SAVE LOAD DIALOG ---------------------------- static char force_save; //static TSTR_LIST slot_list=NULL; static int last_select=-1; static TSTR_LIST story_text=NULL; static void *back_texture=NULL; static int cur_story_pos=0; //static char load_mode; #define SLOT_SPACE 33 #define SLOT_FONT H_FBOLD #define SELECT_COLOR RGB555(31,31,31) #define NORMAL_COLOR RGB555(12,31,12) #define STORY_X 57 #define STORY_Y 50 #define STORY_XS (298-57) #define STORY_YS (302-50) #if 0 void read_slot_list() { int i; char *name; char slotname[SAVE_NAME_SIZE]; if (slot_list==NULL) slot_list=create_list(SLOTS_MAX); const char *mask = build_pathname(2, gpathtable[SR_SAVES],_SLOT_SAV); name=alloca(strlen(mask)+1); for(i=0;iprefix_len == 0 || strncmp(name, st->prefix, st->prefix_len) == 0) { size_t nlen = strlen(name); if (st->count == (size_t)str_count(st->files)) { TSTR_LIST nw = create_list(st->count * 3/2); str_move_list(nw, st->files);; release_list(st->files); st->files = nw; } char *buff = NewArr(char, nlen + 1 + sizeof(tm)); strncpy(buff, name, nlen+1); memcpy(buff+nlen+1, &tm, sizeof(tm)); st->files[st->count] = buff; ++st->count; } return 0; } static int compare_strings (const void *a, const void *b) { return strcmp(*(const char **)a, *(const char **)b); } static int compare_by_time (const void *a, const void *b) { const char *s1 = *(const char **)a; const char *s2 = *(const char **)b; size_t tm1; size_t tm2; memcpy(&tm1, s1 + strlen(s1)+1, sizeof(tm1)); memcpy(&tm2, s2 + strlen(s2)+1, sizeof(tm2)); return tm1tm2?-1:0; } static int dedup_strings_prefix(TSTR_LIST lst, int count) { int j = -1; for (int i = 0; i < count; ++i) { if (j < 0 || !is_same_prefix(lst[j], lst[i])) { ++j; } if (j != i) lst[j] = lst[i]; } ++j; int r = j; while (j != count) { lst[j] = NULL; ++j; } return r; } /* static void load_specific_file(int slot_num,char *filename,void **out,int32_t *size) //call it in task! { FILE *slot; if (current_game_slot_list.count <= (size_t)slot_num) { *out = NULL; return; } slot=fopen_icase(build_pathname(2, gpathtable[SR_SAVES], current_game_slot_list.files[slot_num]),"rb"); if (slot==NULL) { *out=NULL; return; } fseek(slot,SAVE_NAME_SIZE,SEEK_CUR); LOAD_SPECIFIC_FILE_CALLBACK_DATA ctx; ctx.name = filename; *out = NULL; *size = 0; if (enum_all_status(slot, &load_specific_file_callback, &ctx) == 0){ *out = ctx.data; *size = ctx.size; } fclose(slot); } */ static void load_specific_file(const char *filename,const char *name, void **out,int32_t *size) //call it in task! { FILE *slot; slot=fopen_icase(build_pathname(2, gpathtable[SR_SAVES], filename),"rb"); if (slot==NULL) { *out=NULL; return; } fseek(slot,SAVE_NAME_SIZE,SEEK_CUR); LOAD_SPECIFIC_FILE_CALLBACK_DATA ctx; ctx.name = name; *out = NULL; *size = 0; if (enum_all_status(slot, &load_specific_file_callback, &ctx) == 0){ *out = ctx.data; *size = ctx.size; } fclose(slot); } static TSAVEGAME_LIST get_all_savegames(unsigned long kampan) { //sav.creation_time.game_save_time char prefix[50]; snprintf(prefix,50,"sav.%08lx.",kampan); TSAVEGAME_CB_STATE st; st.files = create_list(32); st.prefix = kampan?prefix:NULL; st.prefix_len = kampan?strlen(prefix):0; st.count = 0; list_files(gpathtable[SR_SAVES], file_type_just_name|file_type_need_timestamp|file_type_normal, get_all_savegames_callback, &st); qsort(st.files, st.count, sizeof(char *), compare_strings); if (kampan == 0) { st.count =dedup_strings_prefix(st.files, (int)st.count); } qsort(st.files, st.count, sizeof(char *), compare_by_time); TSTR_LIST names = create_list(st.count); for (size_t i = 0; i < st.count; ++i) { FILE *f=fopen_icase(build_pathname(2, gpathtable[SR_SAVES], st.files[i]), "rb"); if (f!=NULL) { char slotname[SAVE_NAME_SIZE+1]; fread(slotname,1,SAVE_NAME_SIZE,f); slotname[SAVE_NAME_SIZE] = 0; fclose(f); str_replace(&names, i, slotname); } else { str_replace(&names, i, texty[75]); } } TSAVEGAME_LIST out; out.files = st.files; out.names = names; out.count = st.count; return out; } static void free_savegame_list(TSAVEGAME_LIST *lst) { release_list(lst->files); release_list(lst->names); lst->files = 0; lst->names = 0; } static void place_name(int c,int i,char show, char sel) { int z,x; int p = i + current_slot_list_top_line; if ((size_t)p >= current_game_slot_list.count) return; if (c) x=SAVE_SLOT_S;else x=LOAD_SLOT_S; if (show) schovej_mysku(); const char *name = current_game_slot_list.names[p]; set_font(SLOT_FONT,sel?SELECT_COLOR:NORMAL_COLOR); int w = text_width(name); int spc = 0; if (w > 210) { int len = strlen(name); int extra = (w-210)/len; spc = -extra-1; } position(x,z=i*SLOT_SPACE+21+SCREEN_OFFLINE); outtext_ex(name,spc); if (show) { ukaz_mysku(); showview(x,z,204,18); } } static void redraw_save() { int i; schovej_mysku(); put_picture(0,SCREEN_OFFLINE,ablock(H_SAVELOAD)); put_picture(274,SCREEN_OFFLINE,ablock(H_SVITEK)); for(i=0;i0) { int xs,ys; d=c; while (size>0 && *d!='\r' && *d!='\n') {d++;size--;}; if (!size) break; *d=0; { char *e,*or; or=e=getmem(strlen(c)+2); zalamovani(c,e,STORY_XS,&xs,&ys); while (*e) { str_add(&ls,e); if (text_width(e)>STORY_XS) abort(); e=strchr(e,0)+1; } c=d+1;size--; if (size > 0 &&(*c=='\n' || *c=='\r')) {c++;size--;}; free(or); } } free(text_data); } else ls=NULL; if (story_text!=NULL) release_list(story_text); story_text=ls; cur_story_pos=get_list_count();if (cur_story_pos<0) cur_story_pos=0; redraw_story_bar(cur_story_pos); } static void read_story(int slot) { static int task_num=-1; if (task_num!=-1) term_task(task_num); if (slot!=-1) task_num=add_task(8196,read_story_task,slot); } */ static void read_story(const char *filename) { void *text_data; int32_t size; TSTR_LIST ls; char *c,*d; load_specific_file(filename,STORY_BOOK,&text_data,&size); if (text_data!=NULL) { ls=create_list(2); c=text_data; set_font(H_FONT6,0); while (size>0) { int xs,ys; d=c; while (size>0 && *d!='\r' && *d!='\n') {d++;size--;}; if (!size) break; *d=0; { char *e,*or; or=e=getmem(strlen(c)+2); zalamovani(c,e,STORY_XS,&xs,&ys); while (*e) { str_add(&ls,e); if (text_width(e)>STORY_XS) abort(); e=strchr(e,0)+1; } c=d+1;size--; if (size > 0 &&(*c=='\n' || *c=='\r')) {c++;size--;}; free(or); } } free(text_data); } else ls=NULL; if (story_text!=NULL) release_list(story_text); story_text=ls; cur_story_pos=get_list_count();if (cur_story_pos<0) cur_story_pos=0; redraw_story_bar(cur_story_pos); } static int get_list_count() { int count,i,max=0; if (story_text==NULL) return 0; count=str_count(story_text); for(i=0;imsg == E_MOUSE) { MS_EVENT *ms; ms=get_mouse(msg); if (ms->event_type==0x4 || !ms->tl1 || ms->tl2 || ms->tl3) { send_message(E_DONE,E_MOUSE,updown_scroll_hold); send_message(E_DONE,E_TIMER,updown_scroll_hold); updown_noinst=0; } } if (msg->msg == E_TIMER) { MS_EVENT *ms; updown_noinst=1; ms=&ms_last_event; ms->event_type=0x2; send_message(E_MOUSE,ms); if (updown_noinst) { send_message(E_DONE,E_MOUSE,updown_scroll_hold); send_message(E_DONE,E_TIMER,updown_scroll_hold); updown_noinst=0; } else updown_noinst=1; } } char updown_scroll(int id,int xa,int ya,int xr,int yr) { int count; xr,yr,xa,ya; if (story_text==NULL) return 0; cur_story_pos+=id; count=get_list_count(); if (cur_story_pos>count) cur_story_pos=count; if (cur_story_pos<0) cur_story_pos=0; redraw_story_bar(cur_story_pos); if (updown_noinst) { updown_noinst=0; return 1; } send_message(E_ADD,E_MOUSE,updown_scroll_hold); send_message(E_ADD,E_TIMER,updown_scroll_hold); return 1; } static char close_saveload(int id,int xa,int ya,int xr,int yr) { xa;ya;xr;yr;id; if (ms_last_event.event_type & 0x8) { unwire_proc(); wire_proc(); } return 1; } char clk_load_konec(int id,int xa,int ya,int xr,int yr) { id;xa;ya;xr;yr; send_message(E_CLOSE_MAP,NULL); return 1; } static char clk_load_proc(int id,int xa,int ya,int xr,int yr); #define CLK_LOAD_ERROR 5 T_CLK_MAP clk_load_error[]= { {-1,59,14+SCREEN_OFFLINE,306,46+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, {1,59,310+SCREEN_OFFLINE,306,332+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, {-1,LOAD_SLOT_S,SCREEN_OFFLINE,LOAD_SLOT_E,350,clk_load_proc,3,H_MS_DEFAULT}, {-1,30,0,85,14,clk_load_konec,2,H_MS_DEFAULT}, {-1,0,0,639,479,empty_clk,0xff,H_MS_DEFAULT}, }; static char clk_load_proc_menu(int id,int xa,int ya,int xr,int yr) { id=bright_slot(yr-18); xa;ya;xr;yr; if (ms_last_event.event_type & 0x2 && id>=0 && (size_t)id < current_game_slot_list.count) { send_message(E_CLOSE_MAP,current_game_slot_list.files[id]); } return 1; } #define CLK_LOAD_MENU 5 T_CLK_MAP clk_load_menu[]= { {-1,59,14+SCREEN_OFFLINE,306,46+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, {1,59,310+SCREEN_OFFLINE,306,332+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, {-1,LOAD_SLOT_S,SCREEN_OFFLINE,LOAD_SLOT_E,350,clk_load_proc_menu,3,H_MS_DEFAULT}, {-1,0,0,639,479,clk_load_konec,8,H_MS_DEFAULT}, {-1,0,0,639,479,empty_clk,0xff,H_MS_DEFAULT}, }; static void load_save_pos_ingame(int id) { if (load_game(current_game_slot_list.files[id])) { message(1,0,0,"",texty[79],texty[80]); redraw_load(); showview(0,0,0,0); change_click_map(clk_load_error,CLK_LOAD_ERROR); } else { unwire_proc(); wire_proc(); if (battle) konec_kola(); unwire_proc(); if (!load_another) { wire_main_functs(); cur_mode=MD_GAME; bott_draw(1); pick_set_cursor(); for(id=0;id=0 && (size_t)id < current_game_slot_list.count) { load_save_pos_ingame(id); } return 1; } static char global_gamename[SAVE_NAME_SIZE]; static int slot_pos; void save_step_next(EVENT_MSG *msg,void **unused) { int c; unused; if (msg->msg==E_KEYBOARD) { c=va_arg(msg->data, int); if (c==13) { send_message(E_KEYBOARD,c); save_game(slot_pos,global_gamename); wire_proc(); // read_slot_list(); msg->msg=-2; } else if(c==27) { send_message(E_KEYBOARD,c); msg->msg=-2; wire_save_load(1); } } } static char clk_askname_stop(int id,int xa,int ya,int xr,int yr) { id,xa,ya,xr,yr; if (ms_last_event.event_type & 0x2) { send_message(E_KEYBOARD,13); return 1; } else { send_message(E_KEYBOARD,27); return 1; } } static void save_it(char ok) { if (ok) { save_game(slot_pos,global_gamename); // read_slot_list(); wire_proc(); GlobEvent(MAGLOB_AFTERSAVE,viewsector,viewdir); } else { wire_save_load(force_save); } } #define CLK_ASK_NAME 2 T_CLK_MAP clk_ask_name[]= { {-1,0,0,639,479,clk_askname_stop,8+2,H_MS_DEFAULT}, {-1,0,0,639,479,empty_clk,0xff,H_MS_DEFAULT}, }; void wire_ask_gamename(int id) { int x,y; x=SAVE_SLOT_S; y=id*SLOT_SPACE+21+SCREEN_OFFLINE; slot_pos=id; schovej_mysku(); put_picture(x,y,ablock(H_LOADTXTR)); //strcpy(global_gamename,slot_list[id]); clk_ask_name[0].id=add_task(16384,type_text_v2,global_gamename,x,y,SAVE_SLOT_E-SAVE_SLOT_S,SAVE_NAME_SIZE,H_FBOLD,RGB555(31,31,0),save_it); change_click_map(clk_ask_name,CLK_ASK_NAME); ukaz_mysku(); } #define CLK_SAVELOAD 11 T_CLK_MAP clk_load[]= { {-1,LOAD_SLOT_S,SCREEN_OFFLINE,LOAD_SLOT_E,350,clk_load_proc,3,H_MS_DEFAULT}, {-1,59,14+SCREEN_OFFLINE,306,46+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, {1,59,310+SCREEN_OFFLINE,306,332+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, {-1,54,378,497,479,start_invetory,2+8,-1}, {-1,337,0,357,14,go_map,2,H_MS_DEFAULT}, {-1,291,0,313,14,go_book,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,147,0,205,14,clk_saveload,2,H_MS_DEFAULT}, {-1,267,0,289,15,clk_sleep,2,H_MS_DEFAULT}, {-1,0,0,639,479,close_saveload,9,H_MS_DEFAULT}, }; static char clk_save_proc(int id,int xa,int ya,int xr,int yr) { id=bright_slot(yr-18)+current_slot_list_top_line; xa;ya;xr;yr; if (ms_last_event.event_type & 0x2 && id>=0) { unwire_proc(); wire_ask_gamename(id); } return 1; } T_CLK_MAP clk_save[]= { {-1,SAVE_SLOT_S,SCREEN_OFFLINE,SAVE_SLOT_E,350,clk_save_proc,3,H_MS_DEFAULT}, {-1,59+274,14+SCREEN_OFFLINE,306+274,46+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, {1,59+274,310+SCREEN_OFFLINE,306+274,332+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, {-1,54,378,497,479,start_invetory,2+8,-1}, {-1,337,0,357,14,go_map,2,H_MS_DEFAULT}, {-1,291,0,313,14,go_book,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}, {0,207,0,265,14,clk_saveload,2,H_MS_DEFAULT}, {-1,267,0,289,15,clk_sleep,2,H_MS_DEFAULT}, {-1,0,0,639,479,close_saveload,9,H_MS_DEFAULT}, }; static void select_slot(int i) { int rel = i-current_slot_list_top_line; while (rel < 0) { --current_slot_list_top_line; schovej_mysku(); redraw_load(); showview(0,0,0,0); ukaz_mysku(); rel++; } while (rel > SLOTS_MAX-1) { ++current_slot_list_top_line; schovej_mysku(); redraw_load(); showview(0,0,0,0); ukaz_mysku(); rel--; } if (last_select != i) { if (last_select != -1) place_name(0,last_select-current_slot_list_top_line,1,0); place_name(0,i-current_slot_list_top_line,1,1); last_select = i; if (last_select != -1 && last_select < (int)current_game_slot_list.count) { read_story(current_game_slot_list.files[last_select]); } } } static void saveload_keyboard(EVENT_MSG *msg,void **_) { if (msg->msg == E_KEYBOARD) { int v = quit_request_as_escape(va_arg(msg->data, int)); switch (v>>8) { case 1:unwire_proc();wire_proc();break; case 'H':if (last_select>0) select_slot(last_select-1);break; case 'P':if (last_select<(int)current_game_slot_list.count-1) select_slot(last_select+1);break; case 28:if (last_select>=0) load_save_pos_ingame(last_select);break; } } } static void saveload_keyboard_menu(EVENT_MSG *msg,void **_) { if (msg->msg == E_KEYBOARD) { int v = quit_request_as_escape(va_arg(msg->data, int)); switch (v>>8) { case 1:send_message(E_CLOSE_MAP,NULL);break; case 'H':if (last_select>0) select_slot(last_select-1);break; case 'P':if (last_select<(int)current_game_slot_list.count-1) select_slot(last_select+1);break; case 28:if (last_select>= 0 && last_select < (int)current_game_slot_list.count) { send_message(E_CLOSE_MAP, current_game_slot_list.files[last_select]); break; } } } } void unwire_save_load(void) { term_task_wait(clk_ask_name[0].id); if (back_texture!=NULL) free(back_texture); back_texture=NULL; if (story_text!=NULL)release_list(story_text); story_text=NULL; cancel_pass=0; send_message(E_DONE,E_KEYBOARD,saveload_keyboard); send_message(E_DONE,E_KEYBOARD,saveload_keyboard_menu); free_savegame_list(¤t_game_slot_list); } void wire_save_load(char save) { if (save == 1) { //TODO save } else { schovej_mysku(); mute_all_tracks(0); current_game_slot_list = get_all_savegames(current_campaign); curcolor = 0; bar32(0, 17, 639, 17 + 360); if (force_save) redraw_save(); else redraw_load(); if (save == 4) effect_show(NULL); else showview(0, 0, 0, 0); redraw_story_bar(cur_story_pos); unwire_proc = unwire_save_load; if (save == 1) change_click_map(clk_save, CLK_SAVELOAD); else if (save == 2) change_click_map(clk_load_error, CLK_LOAD_ERROR); else if (save == 4) { change_click_map(clk_load_menu, CLK_LOAD_MENU); send_message(E_ADD, E_KEYBOARD, saveload_keyboard_menu); } else { send_message(E_ADD, E_KEYBOARD, saveload_keyboard); change_click_map(clk_load, CLK_SAVELOAD); } cancel_pass = 1; if (last_select != -1) { int x = last_select * SLOT_SPACE + 1; last_select = -1; bright_slot(x); } ukaz_mysku(); update_mysky(); } } void open_story_file() { story=temp_storage_append(STORY_BOOK); SEND_LOG("(STORY) Story temp file is opened...."); } void write_story_text(char *text) { int l = strlen(text); temp_storage_write( text, l, story); temp_storage_write("\n", 1, story); } void close_story_file() { if (story!=NULL) temp_storage_close_wr(story); story=NULL; SEND_LOG("(STORY) Story temp file is closed..."); } static int load_map_state_partial(char *level_fname,int mapsize) //obnovuje stav mapy; castecne { char *bf = NULL; TMPFILE_RD *fsta; int i; int32_t siz; short res=-2; unsigned char ver; fsta=temp_storage_open(level_fname); if (fsta==NULL) return -1; if (!temp_storage_read(&ver,sizeof(ver)*1,fsta)) goto err; if (ver>STATE_CUR_VER) goto err; if (!temp_storage_read(&i,sizeof(mapsize)*1,fsta)) goto err; if (mapsize!=i) goto err; SEND_LOG("(SAVELOAD) Partial restore for map: %s (%s)",level_fname,"START"); temp_storage_read(&siz,1*sizeof(siz),fsta); bf=(char *)getmem(siz); if (!temp_storage_read(bf,siz*1,fsta)) goto err; for (i=0;i>3]>>(i & 7)) & 1; load_map_description(fsta); while (temp_storage_read(&i,1*2,fsta) && i<=mapsize*4) if (temp_storage_read(map_sides+i,1*sizeof(TSTENA),fsta)!=sizeof(TSTENA)) goto err; while (temp_storage_read(&i,1*2,fsta) && i<=mapsize) if (temp_storage_read(map_sectors+i,1*sizeof(TSECTOR),fsta)!=sizeof(TSECTOR)) goto err; res=0; err: free(bf); temp_storage_close_rd(fsta); SEND_LOG("(SAVELOAD) Partial restore for map: %s (%s)",level_fname,"DONE"); return res; } int load_map_automap(char *mapfile) { int i; SEND_LOG("(SAVEGAME) CRITICAL SECTION - Swapping maps: %s <-> %s",level_fname,mapfile); kill_all_sounds(); for(i=0;i= 96*60) { int32_t inhours = inmin/60; sprintf(c,"%dd %dh", inhours/24, inhours%24); } else { sprintf(c,"%02d:%02d", inmin/60, inmin%60); } } #define DEFAULT_GAME_NAME(extra) \ char game_name[100];\ char hernicas[50];\ herni_cas_for_savegame(hernicas);\ snprintf(game_name, sizeof(game_name), "%s %s" extra, mglob.mapname, hernicas); void do_autosave() { DEFAULT_GAME_NAME(" (A)"); if (game_time - prev_game_time_save<360) return; prev_game_time_save = game_time; save_game(game_time, game_name); } void do_save_dialog() { DEFAULT_GAME_NAME(""); if (ask_save_dialog(game_name, sizeof(game_name))) { prev_game_time_save = game_time; save_game(game_time, game_name); } }