#include #include #include #include #include #include #define EVENT_MSG int32_t #include "globals.h" #include #include #include TSTR_LIST skini; #define PLAYERS 3 void *datablast; int32_t datablastsize; char *lasterror=NULL; char relarr[6]; char szBuff[65536]; char sekceid[]=""; typedef struct s_save { int viewsector; int viewdir; 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[12]; short picks; //pocet_sebranych predmetu v mysi short items_added; //pocet_pridanych predmetu int sleep_long; int game_flags; }S_SAVE; typedef struct tkouzlo { word num,um,mge; word pc; short owner,accnum; //accnum = akumulacni cislo, owner = kdo kouzlo seslal int start; short cil; //kladna cisla jsou postavy zaporna potvory (0 je bez urceni postavy) char povaha; word backfire; //backfire / 1 = demon , 0 = bez demona word wait; //wait - cekani pocet animaci word delay; //delay - cekani pocet kol char traceon; //jinak noanim - neprehravaji se animace a zvuky char spellname[30]; }TKOUZLO; typedef struct _tkzlall { TKOUZLO kouzlo; short vlstab[24]; int32_t flagmap; }TKZLALL; THUMAN postavy[6],postavy2[6]; S_SAVE s; char mapname[13]; int startsect; int startsid; char cz_table_1[]=" 1!3457�908+,-./�+��������\"�?=:_2ABCDEFGHIJKLMNOPQRSTUVWXYZ�\\)6=;abcdefghijklmnopqrstuvwxyz/|(; "; char cz_table_2[]=" !\"#$%&'()*+,-./0123456789:;<=>?@�BCD�FGH�JK�MN�PQ�ST�VWX�Z[\\]^_`�bcd�fgh�jk�mn�pq�st�vwx�z{|}~ "; char cz_table_3[]=" !\"#$%&'()*+,-./0123456789:;<=>?@AB���FGHIJK�M��PQ����VWXY�[\\]^_`ab���fghijk�m��pq����vwxy�{|}~ "; char *cz_key_tabs[]={cz_table_1,cz_table_2,cz_table_3}; word keyconv(word key) { int i; static char cz_mode=0; char c,d; i=key; d=i>>8; c=i & 0xff; if (c=='+' && d<55 && !cz_mode) cz_mode=2; else if (c=='=' && d<55 && !cz_mode) cz_mode=1; else if (c>32 && c<127 && d<=53) { c=cz_key_tabs[cz_mode][c-32]; i=d; i=(i<<8)+c; cz_mode=0; return i; } else return i; return 0; } #define ZAKLAD_CRC 0xC005 static word vypocet_crc(char *data,int32_t delka) { uint32_t l=0; do { l=(l<<8)|(delka>0?*data++:0);delka--; l=(l<<8)|(delka>0?*data++:0);delka--; l%=ZAKLAD_CRC; } while(delka>-1); return l & 0xffff; } static simple_cz_input(char *buff,int maxchars) { int cnt=strlen(buff); int w; char *a; a=alloca(cnt+1); strcpy(a,buff); maxchars--; cputs(buff); do { w=_bios_keybrd(_KEYBRD_READ); w=keyconv(w); if (w==0) continue; switch (w & 0xff) { case 13: return; case 0x8: if (cnt>0) { cnt--;buff[cnt]=0;cputs("\x8 \x8"); } break; case 0:break; case 27:strcpy(buff,a); return; default: if (cntkouzlo.cil-1; if (kzl->kouzlo.cil>0) { for (j=0;j<22;j++) h->stare_vls[j]+=kzl->vlstab[j]; h->stare_vls[VLS_KOUZLA]&=~(kzl->flagmap & 0xffff); } } } void zero_inv(THUMAN *h) { h->inv_size=6; memset(h->inv,0,sizeof(h->inv)); memset(h->wearing,0,sizeof(h->wearing)); memset(h->prsteny,0,sizeof(h->prsteny)); memcpy(h->vlastnosti,h->stare_vls,sizeof(h->vlastnosti)); h->demon_save=NULL; h->sektor=startsect; h->direction=startsid; h->groupnum=1; } void zero_all_inv() { THUMAN *h=postavy;int i; for (i=0;i<6;i++,h++) if (h->used) zero_inv(h); } void unpack_save(void *in) { int kouzel; TKZLALL *kzl; int i; in=loadmem(&s,in,sizeof(s)); //load basic info in=(void *)((char *)in+s.picks*2+s.items_added*sizeof(TITEM)); //skip items; in=loadmem(&kouzel,in,sizeof(kouzel)); //load spell table kzl=in; //signup spell table for future use in=(void *)((char *)in+sizeof(TKZLALL)*kouzel); in=loadmem(postavy,in,sizeof(postavy)); //load character table for (i=0;i<6;i++) if (postavy[i].demon_save!=NULL) //correct demons; in=loadmem(postavy+i,in,sizeof(THUMAN)); //skip dialog info. //load done; return_spells(kouzel,kzl); zero_all_inv(); s.viewsector=startsect; s.viewdir=startsid; s.picks=0; s.items_added=0; s.glob_flags=0; s.game_time=0; strncpy(s.level_name,mapname,12); memset(s.runes,0,sizeof(s.runes)); } void del_character(char c) { int i; for(i=c;i<5;i++) relarr[i]=relarr[i+1]; relarr[i]=0; } void add_character(char c) { THUMAN *h=postavy+c; int i; if (!h->used) { lasterror="Musis vybrat postavu!";return; } for (i=0;i<6;i++) if (relarr[i]==c+1) { del_character(i);return; } for (i=0;i<6;i++) if (!relarr[i]) break; if (i==6) { lasterror="Nevim sice jak se ti to povedlo, ale neni uz misto!";return; } relarr[i]=c+1; } char nvlast[][16]= {"Sila","Schopnost magie","Pohyblivost","Obratnost","Max zraneni", "Kondice","Max mana","Obrana(dolni)","Obrana(Horni)","Utok(Dolni)", "Utok(Horni)","Ohen","Voda","Zeme","Vzduch","Mysl","Zivoty Regen", "Mana Regen","Kondice Regen","Magicka sila(D)", "Magicka sila(H)","","Ucinnek zasahu","*"}; char *zbrane[]={"Mec","Sekera","Kladivo","Hul","Dyka","Strelne","Specialni"}; char build_players() { int i; char z=0; memset(postavy2,0,sizeof(postavy2)); for (i=0;i<6;i++) if (relarr[i])postavy2[i]=postavy[relarr[i]-1],z=1; return z; } void c_info(int b) { THUMAN *h=postavy+b; int i; do { _clearscreen(_GCLEARSCREEN); for(i=0;i<22;i++) { cprintf("%-17s %3d ",nvlast[i],h->stare_vls[i]); if (i<7) cprintf("%-12s %3d ",zbrane[i],h->bonus_zbrani[i]); if (i<7) switch (i) { case 0: cprintf("Jmeno: %s",h->jmeno);break; case 1: cprintf("Uroven: %d",h->level);break; case 2: cprintf("Zkusenost: %d",h->exp);break; case 3: cprintf("Pohlavi: %s",h->female?"Zena":"Muz");break; case 4: cprintf("Portret: XICHT%02X.PCX",h->xicht);break; case 5: cprintf("Jidlo: %d",h->jidlo/360);break; case 6: cprintf("Voda: %d",h->voda/360);break; } cprintf("\n\r"); } cprintf("ENTER - zmena jmena, P - pohlavi, X - vzhledu, ESC - navrat:"); do {i=toupper(getche());putch(8);} while (i!=13 && i!='X' && i!=27 && i!='P'); if (i==13) { cprintf("\r\n\n Zmen jmeno:");simple_cz_input(h->jmeno,sizeof(h->jmeno)); } else if (i=='X') { cprintf("\r\n\n Jelikoz jednoduchost tohoto programu neumoznuje prohizet si obrazky je nutne\n\r" "tuto volbu odzkouset metodou pokus omyl. Nikdo totiz nezaruci, zda v novem \n\r" "dobrodruzstvi se nektere z postav nezmeni pohlavi (na obrazku).\r\n" "V puvodnim SKELDALU:\n\r" "--------------------\n\r" "Muzi: 0, 2, 3, 4, 8(Roland), 12(Gralt), 13(Erik)\n\r" "Zeny: 1, 5, 6, 7\n\r" "\nZmenit vzhled <%d>, 'x' storno:",h->xicht); if (scanf("%hd",&h->xicht)==0) while (getchar()!='\n'); } else if (i=='P') h->female=!h->female; } while (i!=27) ; } char assign_players() { int i; char c; char backrel[6]; do { _clearscreen(_GCLEARSCREEN); if (lasterror!=NULL) cprintf("%s\x7\r\n\n",lasterror); lasterror=NULL; memset(backrel,0,sizeof(backrel)); for (i=0;i<6;i++) if (relarr[i]) backrel[relarr[i]-1]=i+1; cprintf("%-33s%s\n\r====================================================\n\r","Stare dobrodruzstvi","Nove dobrodruzstvi"); for(i=0;i<6;i++) { if (postavy[i].used) cprintf("%c%d.%-30s",backrel[i]?'*':' ',i+1,postavy[i].jmeno); else cprintf(" %d.%-30s",i+1,""); if (relarr[i]) cprintf("%c.%-30s",i+'a',postavy[relarr[i]-1].jmeno); else cprintf("%c.%-30s",i+'a',""); cputs("\n\r"); } cputs("\n\r"); cputs("[1]-[6] prenese postavu,\n\r" "[a]-[f] maze postavu.\n\r" "[SHIFT]+[1]-[6] info o postave\n\r" "[S] ulozit\n\r" "[Q] nebo [ESC] konec bez ulozeni\n\n\r"); cprintf("Doporuceny pocet postav v novem dobrodruzstvi je %d.\n\r",PLAYERS); putch('>'); i=_bios_keybrd(_KEYBRD_READ); c=toupper(i & 0xff);i>>=8; switch (c) { case 27: case 'Q':return 1; case 'S':return 0; default: if (i==0) lasterror="Prepni na anglickou klavesnici!!!"; if (i>=2 && i<=7) if (*(char *)0x417 & 0x3) c_info(i-2); else add_character(i-2); if (c>='A' && c<='F') del_character(c-'A'); break; } } while(1); } char *scan_saves(char *text,char *path,char mustexists) { int i; FILE *f; do { _clearscreen(_GCLEARSCREEN); cprintf("%s\n\r============================\n\r",text); if (lasterror!=NULL) cprintf("%s\x7\r\n\n",lasterror); lasterror=NULL; for(i=0;i<10;i++) { sprintf(szBuff,"%sSLOT%02d.SAV",path,i); cprintf("%d. ",(i+1)%10); f=fopen_icase(szBuff,"rb"); if (f!=NULL) { fread(szBuff,1,34,f);szBuff[34]=0; fclose(f); cprintf("%s\r\n",szBuff); } else cputs("\r\n"); } cputs("\nVyber [1]-[9] a [0] pozici.\n\r[ESC] zrusit.\n\r"); do i=_bios_keybrd(_KEYBRD_READ)>>8; while (i>11); if (i==1) return NULL; if (i==0) lasterror="Prepni na anglickou klavesnici!!!"; else { i-=2; sprintf(szBuff,"%sSLOT%02d.SAV",path,i); if (!mustexists || access(szBuff,F_OK)==0) return szBuff; } } while(1); } int tracemap(char *name) { FILE *f; void *section; int type; int32_t size,s; f=fopen_icase(name,"rb"); if (f==NULL) return -1; do { s=load_section(f,§ion,&type,&size); if (s!=size) { free(section); fclose(f); return -1; } if (type==A_MAPGLOB) { MAPGLOBAL mglob; memcpy(&mglob,section,sizeof(mglob)); startsect=mglob.start_sector; startsid=mglob.direction; } free(section); } while (type!=A_MAPEND); fclose(f); return 0; } void *build_gametmp(int *size) { int siz=*size; void *zac,*p; int i,crc; siz+=256; p=zac=malloc(siz); p=addmem(p,&s,sizeof(s)); //add game info //skip picks //skip items added i=0;//no spells; p=addmem(p,&i,4); p=addmem(p,postavy2,sizeof(postavy2)); p=addmem(p,&i,4); //no dialogs... *size=(char *)p-(char *)zac; crc=vypocet_crc(zac,*size); p=addmem(p,&crc,2); size[0]+=2; return zac; } void save_savegame(char *soubor) { FILE *f; void *p; int s; f=fopen_icase(soubor,"wb"); strcpy(szBuff,"TRANSAV"); fwrite(szBuff,SAVE_NAME_SIZE,1,f); strcpy(szBuff,"_GAME.TMP"); fwrite(szBuff,12,1,f); s=datablastsize; p=build_gametmp(&s); fwrite(&s,4,1,f); fwrite(p,s,1,f); free(p); szBuff[0]=0; fwrite(szBuff,12,1,f); fclose(f); } void begin_program(char *sourceadv,char *targetadv) { TSTR_LIST src,trg; char *c; src=read_config(sourceadv); if (src==NULL) { cprintf("Nemohu otevrit zdrojove dobrodruzstvi: %s\n\r",sourceadv); exit(1); } trg=read_config(targetadv); if (trg==NULL) { cprintf("Nemohu otevrit cilove dobrodruzstvi: %s\n\r",targetadv); exit(1); } c=get_text_field(trg,"DEFAULT_MAP"); if (c==NULL) { cprintf("Vystupni dobrodruzstvi %s musi obsahovat polozku DEFAULT_MAP\n\r", targetadv); exit(1); } strncpy(mapname,c,12);mapname[12]=0; c=get_text_field(trg,"CESTA_MAPY"); if (c==NULL) { cprintf("Vystupni dobrodruzstvi %s musi obsahovat polozku CESTA_MAPY\n\r", targetadv); exit(1); } sprintf(szBuff,"%s%s",c,mapname); if (tracemap(szBuff)) { cprintf("Nemohu precist mapu %s\n\r",szBuff); exit(1); } c=get_text_field(trg,"CESTA_POZICE"); if (c==NULL) { cprintf("Vystupni dobrodruzstvi %s musi obsahovat polozku CESTA_POZICE\n\r", targetadv); exit(1); } c=get_text_field(src,"CESTA_POZICE"); if (c==NULL) { cprintf("Vstupni dobrodruzstvi %s musi obsahovat polozku CESTA_POZICE\n\r", sourceadv); exit(1); } c=scan_saves("Vyber pozici:",c,1); if (c==NULL) exit(0); load_specific_file(c,"_GAME.TMP",&datablast,&datablastsize); if (datablast==NULL) { cprintf("Soubor %s: Pristup odmitnut - pozice je pozkozena!\n\r",c); exit(1); } unpack_save(datablast); do { do if (assign_players()) exit(1); while (!build_players()); zpet: c=get_text_field(trg,"CESTA_POZICE"); c=scan_saves("Ulozit na pozici:",c,0); } while (c==NULL); if (access(c,F_OK)==0) { cprintf("Prejes si prepsat existujici pozici? (A/cokoliv):"); if (toupper(getche())!='A') goto zpet; } save_savegame(c); } static char help1[]= "Tento program prenasi ulozene pozice mezi jednotlivymi dobrodruzstvimi.\n\r" "Jelikoz ulozena pozice je znacne zavisla na mapach a definicich, je mozne\n\r" "timto programem prenaset pouze charakteristiky postav. Navic se mohou \n\r" "objevit nejake komplikace vznikle s nemoznosti predvidat komplexnost obou\n\r" "dobrodruzstvi.\n\r\n" "Program ma dva zapisy parametru:\n\r" "================================\n\r\n" "TRANSAV \n\r\n" " Prenasi puvodni pozici ze hry Brany Skeldalu do noveho dobrodruzstvi\n\r\n" "TRANSAV \n\r\n" " Prenasi pozici mezi dvema dobrodruzstvi\n\r\n"; static char help2[]= "Jak uz bylo receno, prenasi se pouze charakteristiky postav. Neprenasi se\n\r" "predmety a runy. Nova pozice se jmenuje TRANSAV, pak si ji prejmenujte. \n\r" "Ihned po nahrati prenesene pozice okamzite tuto pozici opet ulozte, aby SKELDAL\n\r" "doplnil chybejici informace vztahujici se k novemu dobrodruzstvi. \n\r" "V pokrocilejsich castech hry mohou tyto chybejici informace zpusobovat nejake\n\r" "komplikace...\n\r\n" "Prenasec pozic pro Vas napsal Ondrej Novak, programator hry Brany Skeldalu.\n\r\n" "PS: Deaktivujte ovladace ceske klavesnice!!!\n\r"; void main(int argc,char **argv) { char szbuff[20]; if (argc!=2 && argc!=3) { cputs(help1); cputs("--- klavesu ---");getche();putch('\r'); cputs(help2); return; } memset(relarr,0,sizeof(relarr)); if (argc==2) begin_program("SKELDAL.INI",argv[1]); else begin_program(argv[1],argv[2]); }