From 2be84e406c37733af2ec630f8c498364e7273f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Nov=C3=A1k?= Date: Wed, 29 Jan 2025 19:57:25 +0100 Subject: [PATCH] animations MGF works --- game/globals.h | 1 + game/kouzla.c | 37 +++++-- game/skeldal.c | 3 +- libs/event.c | 147 +-------------------------- libs/event.h | 33 +++--- libs/mgifmem.c | 190 +++++++++++++++++++++++++++-------- libs/mgifmem.h | 2 +- libs/mgifplaya.c | 89 +++------------- platform/sdl/sdl_context.cpp | 11 +- platform/sdl/sound.cpp | 4 +- 10 files changed, 224 insertions(+), 293 deletions(-) diff --git a/game/globals.h b/game/globals.h index a5535e3..f469006 100644 --- a/game/globals.h +++ b/game/globals.h @@ -631,6 +631,7 @@ void pcx_8bit_nopal(void **p,int32_t *s); void set_background(void **p,int32_t *s); void wav_load(void **p,int32_t *s); void load_mob_legacy_format(void **p, int32_t *s); +void load_spells_legacy_format(void **p, int32_t *s); void wire_main_functs(void); void ukaz_kompas(char mode); void *timming(EVENT_MSG *msg,void **data); diff --git a/game/kouzla.c b/game/kouzla.c index f662ca0..bd46e0a 100644 --- a/game/kouzla.c +++ b/game/kouzla.c @@ -106,7 +106,7 @@ static inline word _impl_get_word(unsigned char **c) { word r = (*c)[0] + 256* (*c)[1]; - c+=2; + (*c)+=2; return r; } #define GET_WORD(c) _impl_get_word(&c) @@ -135,15 +135,16 @@ static TTELEPLOCATION TelepLocation; 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) + word pc; //8 + short owner,accnum; //accnum = akumulacni cislo, owner = kdo kouzlo seslal //4 + int start; //4 + short cil; //2 //kladna cisla jsou postavy zaporna potvory (0 je bez urceni postavy) char povaha; + char traceon; //jinak noanim - neprehravaji se animace a zvuky + //paddding 1 byte 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[28]; word teleport_target; }TKOUZLO; @@ -184,6 +185,30 @@ static void animace_kouzla(int act,void *data, int ssize) } +void load_spells_legacy_format(void **p, int32_t *s) { + TKOUZLO *k = (*p); + TKOUZLO *end = (TKOUZLO *)((char *)(*p) + k->start); + ++k; + int count = 1; + while (k < end) { + ++count; + TKOUZLO *end2 = (TKOUZLO *)((char *)(*p) + k->start); + if (end2 < end) end = end2; + ++k; + } + SEND_LOG("(SPELL) Loading spell table: count %d", count); + k = (*p); + for (int i = 0; i < count; ++i) { + char *b = (char *)k; + char traceon = k->spellname[-1]; //traceon was there; + size_t bofs = offsetof(TKOUZLO, traceon); + size_t eofs = offsetof(TKOUZLO, spellname)-1; + memmove(b+bofs+1, b+bofs, eofs-bofs);\ + k->traceon = traceon; + ++k; + } +} + static void play_anim(va_list args) //tasked animation //#pragma aux play_anim parm [] diff --git a/game/skeldal.c b/game/skeldal.c index 1b7f322..3e7ca87 100644 --- a/game/skeldal.c +++ b/game/skeldal.c @@ -177,7 +177,7 @@ TDREGISTERS registred[]= {H_PZASAH,"pzasah.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, {H_BATTLE_CLICK,"souboje2.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, {H_SIPKY_END,"sipky.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, - {H_KOUZLA,"kouzla.dat",NULL,SR_MAP}, + {H_KOUZLA,"kouzla.dat",load_spells_legacy_format,SR_MAP}, {H_LEBKA,"death.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, {H_KOSTRA,"bones.pcx",pcx_fade_decomp,SR_BGRAFIKA}, {H_RUNEHOLE,"runehole.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, @@ -474,6 +474,7 @@ void load_mob_legacy_format(void **p, int32_t *s) { *s = count * sizeof(TMOB); } + void set_background(void **p,int32_t *s) { word *data; diff --git a/libs/event.c b/libs/event.c index 712ed71..9187c75 100644 --- a/libs/event.c +++ b/libs/event.c @@ -39,8 +39,6 @@ char exit_wait=0; T_EVENT_ROOT *ev_tree=NULL; char freeze_on_exit=0; -int32_t ev_buff_msg[EVENT_BUFF_SIZE]={0}; -void *ev_buff_dta[EVENT_BUFF_SIZE]={NULL}; int ev_poz=0; char *otevri_zavoru; @@ -188,22 +186,7 @@ void force_delete_curr (T_EVENT_ROOT **tree,T_EVENT_ROOT *r, T_EVENT_POINT *p) } } -/* -static void unsuspend_task(EVENT_MSG *msg) - { - int i; - int nt; - nt=nexttask; - for(i=1;imsg) - { - nexttask=i; - task_info[nexttask]&=~TASK_EVENT_WAITING; - task_sleep(msg->data); - } - nexttask=nt; - } -*/ void enter_event(T_EVENT_ROOT **tree,EVENT_MSG *msg) { T_EVENT_ROOT *r; @@ -282,14 +265,14 @@ static int call_proc(EVENT_MSG *msg, void *ctx) { return 0; } -T_EVENT_POINT *install_event(T_EVENT_ROOT **tree,int32_t ev_num,EV_PROC proc,void *procdata,char end) +T_EVENT_POINT *install_event(T_EVENT_ROOT **tree, EVENT_MSG *msg, EV_PROC proc,char end) //instaluje novou udalost; { void *user=NULL; T_EVENT_POINT *p; - call_proc_context ctx = {proc, &user}; - - send_message_to(call_proc,&ctx, E_INIT, procdata); + int ev_num = msg->msg; + msg->msg = E_INIT; + proc(msg, &user); p=add_event(tree,ev_num,proc,end); p->user_data=user; return p; @@ -322,11 +305,10 @@ void tree_basics(T_EVENT_ROOT **ev_tree,EVENT_MSG *msg) T_EVENT_POINT *r; shift_message(msg); EV_PROC proc = va_arg(msg->data, EV_PROC); - void *procdata = va_arg(msg->data, void *); find_event_msg_proc(*ev_tree,msg->msg,proc,r); assert(r==NULL); if (r==NULL) - install_event(ev_tree,msg->msg,proc,procdata,msg->msg==E_ADDEND); + install_event(ev_tree,msg,proc,msg->msg==E_ADDEND); return; } if (msg->msg==E_INIT) @@ -542,122 +524,3 @@ T_EVENT_ROOT *gate_basics(EVENT_MSG *msg, void **user_data) tree_basics((T_EVENT_ROOT **)user_data,msg); return p; } -/* -int create_task() - { - int i; - - for(i=1;i=taskcount) - { - taskcount++; - tasklist_sp=grealloc(tasklist_sp,taskcount*4); - tasklist_low=grealloc(tasklist_low,taskcount*4); - tasklist_top=grealloc(tasklist_top,taskcount*4); - task_info=grealloc(task_info,taskcount); - tasklist_events=grealloc(tasklist_events,taskcount*sizeof(int)); - } - return i; - } -*/ -void task_terminating(); -/* -int32_t getflags(); -#pragma aux getflags = \ - "pushfd"\ - "pop eax"\ - ;*/ -/* -int add_task(int stack,void *name,...) - { - int task,i; - int32_t *sp,*spp; - - task=create_task(); - if (task==-1) - { - send_message(E_MEMERROR); - return -1; - } - sp=malloc(stack); - if (sp==NULL) - { - send_message(E_MEMERROR); - return -1; - } - spp=(int32_t *)((char *)sp+stack-17*4); - memset(sp,0,stack); - memcpy(spp,&name,17*4); - *spp=(int32_t )task_terminating; - spp--;*spp=(int32_t)name; - for(i=0;i<9;i++) - { - spp--; - *spp=0; - if (i==5) *spp=(int32_t)((char *)sp+stack); - } - tasklist_low[task]=(void *)sp; - tasklist_top[task]=(void *)((char *)sp+stack); - tasklist_sp[task]=(void *)spp; - task_info[task]=TASK_RUNNING; - return task; - } - -void term_task(int id_num) - { - task_info[id_num]=TASK_TERMINATING; - return; - } - -char is_running(int id_num) - { - return tasklist_sp[id_num]!=NULL; - } - -static void suspend_task(int id_num,int msg) - { - task_info[id_num]|=TASK_EVENT_WAITING; - tasklist_events[id_num]=msg; - } - -void shut_down_task(int id_num) - { - free(tasklist_low[id_num]); - tasklist_sp[id_num]=0; - if (nexttask==id_num) nexttask=0; - } -*/ -/*void raise_error(int error_number) - { - longjmp(jmpenv,error_number); - } -*/ -/*static void unsuspend_task_by_event(EVENT_MSG *msg,int **idnum) - { - if (msg->msg==E_INIT) - { - *idnum=New(int); - **idnum=*(int *)msg->data; - } - else - { - int nt=nexttask; - - nexttask=**idnum; - free(*idnum); - *idnum=NULL; - task_info[nexttask]&=~TASK_EVENT_WAITING; - task_sleep(msg->data); - msg->msg=-2; - nexttask=nt; - } - } -*/ -/*void *task_wait_event(int32_t event_number) - { - if (!curtask) return NULL; - suspend_task(curtask,event_number); - return task_sleep(); - } -*/ diff --git a/libs/event.h b/libs/event.h index 65a5798..5e28750 100644 --- a/libs/event.h +++ b/libs/event.h @@ -35,26 +35,29 @@ #define TASK_RUNNING 0 #define TASK_TERMINATING 1 -#define TASK_EVENT_WAITING 2 + //#define shift_msg(msgg,tg) ((tg.msg=*(int32_t *)msgg->data),(tg.data=(void *)((int32_t *)msgg->data+1))) -#define EVENT_BUFF_SIZE 16 -typedef void (*EV_PROC)(void *,void *) ; + + + #define PROC_GROUP (EV_PROC )1 -//typedef struct event_list -// { -// int32_t *table; //tabulka udalosti -// EV_PROC *procs; //co se ma pri danne udalosti stat -// void *(*user_data); //ukazatel na uzivatelska data -// char *zavora; //1 znamena ze udalost je povolena -// int32_t max_events; // maximalni pocet udalosti, na ktere je system rezervova -// int32_t count; //aktualni pocet udalosti -// }EVENT_LIST; + +typedef struct event_msg + { + ///message ID + int32_t msg; + ///message data + va_list data; + }EVENT_MSG; + + typedef void (*EV_PROC)(const EVENT_MSG *,void **) ; + /* event procedura ma dva parametry @@ -87,12 +90,6 @@ typedef struct t_event_root T_EVENT_POINT *list; }T_EVENT_ROOT; -typedef struct event_msg - { - int32_t msg; - va_list data; - }EVENT_MSG; - extern char exit_wait; // 1 - opousti aktivni cekaci event; extern char freeze_on_exit; //1 - po opusteni udalosti cela cesta uzamcena extern char *otevri_zavoru; diff --git a/libs/mgifmem.c b/libs/mgifmem.c index d255752..67dc03f 100644 --- a/libs/mgifmem.c +++ b/libs/mgifmem.c @@ -74,17 +74,30 @@ void mgif_install_proc(MGIF_PROC proc) show_proc=proc; } +struct mgif_header load_mgif_header(char **mgif) { + struct mgif_header r; + char *iter = *mgif; + memcpy(r.sign, iter, 4); iter+=4; + memcpy(r.year, iter, 2); iter+=2; + r.eof = *iter++; + memcpy(&r.ver, iter, 2); iter+=2; + memcpy(&r.frames, iter, 4); iter+=4; + memcpy(&r.snd_chans, iter, 2); iter+=2; + memcpy(&r.snd_freq, iter, 4); iter+=4; + memcpy(r.ampl_table, iter, sizeof(r.ampl_table)); iter+=sizeof(r.ampl_table); + iter += 64; + *mgif = iter; + return r; +} + void *open_mgif(void *mgif) //vraci ukazatel na prvni frame { - char *c; - struct mgif_header *mgh; + char *c = mgif; + struct mgif_header mgh = load_mgif_header(&c); - c=mgif; - if (strncmp(c,MGIF,4)) return NULL; - mgh=mgif; - mgif_frames=mgh->frames; + if (strncmp(mgh.sign,MGIF,4)) return NULL; + mgif_frames=mgh.frames; cur_frame=0; - c+=sizeof(*mgh); init_lzw_compressor(8); if (lzw_buffer==NULL) lzw_buffer=getmem(LZW_BUFFER); return c; @@ -100,34 +113,22 @@ void close_mgif(void) //dealokuje buffery pro prehravani int input_code(void *source,int32_t *bitepos,int bitsize,int mask) { - int32_t ofs = *bitepos >> 3; - int32_t shf = *bitepos & 0x7; - uint8_t *src = source; - uint8_t val1 = src[ofs]; - uint8_t val2 = src[ofs+1]; - uint16_t val = val1 + val2 * 256; - *bitepos+=bitsize; - return val >> shf; -/* - __asm - { - mov esi,source - mov edi,bitepos - mov ebx,bitsize - mov edx,mask + uint8_t *esi = source; // mov esi,source + int32_t *edi = bitepos; // mov edi,bitepos + int ebx = bitsize; // mov ebx,bitsize + int edx = mask; // mov edx,mask - mov ecx,[edi] - mov eax,ecx - shr eax,3 - mov eax,[esi+eax] - and cl,7 - shr eax,cl - and eax,edx - add [edi],ebx - } - */ + int ecx = *edi; // mov ecx,[edi] + int eax = ecx; // mov eax,ecx + eax >>=3; // shr eax,3 + eax = esi[eax] | (esi[eax+1] << 8) | (esi[eax+2] << 16) | (esi[eax+3] << 24); + // mov eax,[esi+eax] + ecx &= 7; // and cl,7 + eax >>= ecx; // shr eax,cl + eax &= edx; // and eax,edx + (*edi) += ebx; // add [edi],ebx + return eax; } -//#pragma aux input_code parm [esi][edi][ebx][edx]=\ value[eax] modify [ecx]; int de_add_code(int group,int chr,int mask) @@ -144,10 +145,56 @@ int de_add_code(int group,int chr,int mask) return mask; } - -int fast_expand_code(DOUBLE_S *compress_dic, int code,uint8_t **target, uint8_t *old_value) +int fast_expand_code(const DOUBLE_S *compress_dic, int code,uint8_t **target, uint8_t *old_value) { + + int eax = code; //mov eax,code + uint8_t ** edi = target; //mov edi,target + //cmp eax,256 + if (eax < 256) { //jnc expand + uint8_t *esi = *edi; //mov esi,[edi] + ++(*edi); //inc dword ptr [edi] + uint8_t bl = (uint8_t)eax; //mov bl,al + uint8_t al = bl + *old_value; //add al,old_value + *esi = al; // mov [esi],al + *old_value = al; // mov old_value,al + return bl; // jmp end + } + + //expand: + const DOUBLE_S *ebx = compress_dic; // mov ebx,compress_dic + const DOUBLE_S *ecx = ebx+eax; // lea ecx,[eax*8+ebx] + eax = ecx->first; // movzx eax,short ptr [ecx+4] // first + *target += eax; // add [edi],eax + int save_eax = eax; // push eax + uint8_t *esi = *edi; // mov esi,[edi] //esi - target ptr + + do { //eloop: + + eax = ecx->chr; //movzx eax,short ptr [ecx+2] // chr + *esi = (uint8_t)(eax); //mov [esi],al + --esi; //dec esi + eax = ecx->group; //movzx eax,short ptr [ecx] //group + ecx = ebx+eax; //lea ecx,[eax*8+ebx] + //cmp eax,256 + } while (eax >= 256 ); //jnc eloop + uint8_t bl = (uint8_t)eax; //mov bl,al + uint8_t al = bl + *old_value; //add al,old_value + *esi = al; //mov [esi],al + ++(*edi); //inc dword ptr [edi] + int ecx2 = save_eax; //pop ecx + do { //elp2 + ++esi; //inc esi + al = al + *esi; //add al,[esi] + *esi = al; //mov [esi],al + --ecx2; //dec ecx + } while (ecx2 > 0); //jnz elp2 + *old_value =al; //mov old_value,al + return bl; //movzx eax,bl + + // } +#if 0 uint8_t out; uint8_t w; if (code >= 256) { @@ -178,10 +225,11 @@ int fast_expand_code(DOUBLE_S *compress_dic, int code,uint8_t **target, uint8_t out = (uint8_t) code; w = out + *old_value; *old_value = w; - **target = out; + **target = w; (*target)++; } return out; +#endif /* _asm { @@ -228,25 +276,24 @@ end: */ } - void lzw_decode(void *source,char *target) { int32_t bitpos=0; - register int code; + int code; int old,i; - //int group,chr; int old_first; - register int mask=0xff; + uint8_t old_value; for(i=0;i #include +#include void show_full_lfb12e(void *target, void *buff, void *paleta) { uint16_t *edi = (uint16_t *)target; @@ -20,77 +21,6 @@ void show_full_lfb12e(void *target, void *buff, void *paleta) { dl--; } while (dl != 0); } - - -/* -void show_full_lfb12e(void *target,void *buff,void *paleta) - { - __asm - { - mov edi,target - mov esi,buff - mov ebx,paleta - ;edi - target - ;esi - source - ;ebx - palette - push ebp - mov dl,180 -shfl2: mov ecx,160 -shfl1: lodsw - movzx ebp,al - movzx ebp,short ptr ds:[ebp*2+ebx] - movzx eax,ah - movzx eax,short ptr ds:[eax*2+ebx] - shl eax,16 - or eax,ebp - stosd - dec ecx - jnz shfl1 - dec dl - jnz shfl2 - pop ebp - } - } -*/ -/* -void show_delta_lfb12e(void *target, void *buff, void *paleta) { - uint8_t *edi = (uint8_t *)target; - uint8_t *esi = (uint8_t *)buff + 4; // skip pointer - uint8_t *ebx = (uint8_t *)paleta; - uint8_t cl = 180; // remaining lines - uint8_t ch, al; - uint16_t *edx = (uint16_t *)esi; // start of delta map - esi += *(uint32_t *)(esi - 4); // start of data - - while (cl > 0) { - uint8_t *line_address = edi; // save line address - ch = *edx++; // read _skip_ value - al = ch; - al |= 0x3F; // test if the two highest bits are set - al++; - if (al == 0) { // if yes - skip lines - ch &= 0x3F; // mask the upper 2 bits - edi += (ch == 0) ? 640 : 0; // skip line if ch is 0 - cl--; // decrement line counter - continue; // continue to next iteration - } - - uint32_t eax = (uint32_t)ch; // expand _skip_ value to eax - edi += eax * 4; // calculate new position on screen - ch = *edx++; // read _copy_ value - - for (uint8_t i = 0; i < ch; i++) { - uint16_t ebp = *(uint16_t *)(ebx + (al * 2)); // get color from palette - uint16_t color = *(uint16_t *)(ebx + (eax * 2)); // get color from palette - eax = (color << 16) | ebp; // combine colors - *(uint32_t *)edi = eax; // store the color - edi += 4; // move to the next pixel - } - edi += 640; // skip line - cl--; // decrement line counter - } -} -*/ static __inline uint32_t read_uint32(uint8_t *from) { uint32_t a = from[0]; uint32_t b = from[1]; @@ -117,6 +47,7 @@ void show_delta_lfb12e(void *target,void *buff,void *paleta) uint8_t cl = 180; // mov cl,180 ;cl pocet zbyvajicich radek uint32_t offset = read_uint32(esi); + assert(offset != 0); // add esi,4 ;preskoc ukazatel esi += 4; uint8_t *edx = esi; @@ -132,7 +63,7 @@ void show_delta_lfb12e(void *target,void *buff,void *paleta) // inc edx // or al,03fh ;test zda jsou 2 nejvyssi bity nastaveny // inc al - if ((ch & 0xC0) == 0) { + if ((ch & 0xC0) != 0xC0) { // jz shdl3 ;ano - preskakovani radku edi += ((uint32_t)ch) << 1; // movzx eax,ch ;expanduj _skip_ hodnotu do eax @@ -141,6 +72,7 @@ void show_delta_lfb12e(void *target,void *buff,void *paleta) // mov ch,[edx] ;cti _copy_ hodnotu // inc edx + assert(ch <= 160); while (ch) { uint8_t a = *data++; *edi++ = ebx[a]; @@ -162,10 +94,15 @@ void show_delta_lfb12e(void *target,void *buff,void *paleta) // jmp shdl2 ;pokracuj _skip_ hodnotou } else { ch &= 0x3F; - ++ch; - if (ch > cl) ch = cl; - line_beg += 320*ch; - cl -= ch; + if (ch == 0) { + line_beg += 320; + --cl; + } else { + ++ch; + assert(ch <= cl); + cl-=ch; + line_beg += 320*(int)ch; + } edi = line_beg; } diff --git a/platform/sdl/sdl_context.cpp b/platform/sdl/sdl_context.cpp index 8177b07..17d9144 100644 --- a/platform/sdl/sdl_context.cpp +++ b/platform/sdl/sdl_context.cpp @@ -80,7 +80,7 @@ void SDLContext::init_screen(DisplayMode mode, const char *title) { } _window.reset(window); - SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), -1, SDL_RENDERER_SOFTWARE); + SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), -1, 0); if (!renderer) { snprintf(buff,sizeof(buff), "Chyba při vytváření rendereru: %s\n", SDL_GetError()); throw std::runtime_error(buff); @@ -178,13 +178,14 @@ void SDLContext::event_loop(std::stop_token stp) { int button = e.button.button; int up = e.type == SDL_MOUSEBUTTONUP?1:0; ms_event.event = 1; - ms_event.event_type = (1<<(2*button-1+up)); + int shift = 0; switch (button) { default: break; - case 1: ms_event.tl1 = !up; break; - case 2: ms_event.tl3 = !up; break; - case 3: ms_event.tl2 = !up; break; + case 1: ms_event.tl1 = !up; shift = 1; break; + case 2: ms_event.tl3 = !up; shift = 5; break; + case 3: ms_event.tl2 = !up; shift = 3; break; } + ms_event.event_type = (1<<(shift+up)); } } diff --git a/platform/sdl/sound.cpp b/platform/sdl/sound.cpp index ae81de7..839d426 100644 --- a/platform/sdl/sound.cpp +++ b/platform/sdl/sound.cpp @@ -1,6 +1,7 @@ #include "../platform.h" #include +#include void set_mixing_device(int mix_dev,int mix_freq,...) { } @@ -67,7 +68,8 @@ void *PrepareVideoSound(int mixfreq, int buffsize) { return 0; } char LoadNextVideoFrame(void *buffer, char *data, int size, short *xlat, short *accnums, int32_t *writepos) { - return 0; + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + return 1; } void DoneVideoSound(void *buffer) {