gates_of_skeldal/VIDEO/PLAYCNM.C
2025-01-24 18:27:22 +01:00

356 lines
6.7 KiB
C

#include <types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <bgraph.h>
#include <i86.h>
#include <bios.h>
#include "anipack.h"
#include "cinema.h"
#include <memman.h>
#define CINEMA ".cnm"
#define PLATNO_X 640
#define PLATNO_Y 184
#define PLATNO_S (PLATNO_X*PLATNO_Y)
#define POZICE (60)
#define DECOMP_BUFF 150000
FILE *anim;
word *playscreen;
word *playscreen2;
word *paleta;
word *show_place;
char *decomp_buff;
char *ip;
word direct_line_len=640*8;
char direct=0;
char fusing=1;
char ifuse=0;
char interlaced=0;
char sdiff=0;
char test_frame[120000];
void priponu(char *source,char *target,int n)
{
char *c,*d;
c=strrchr(source,'.');
d=strrchr(source,'\\');
strncpy(target,source,n);
if (c==NULL || c<d) strcat(target,CINEMA);
}
char col_table[]={0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4};
void decompr_box(word *adr)
{
char mode;
word palxlat[16];
int i;
mode=*ip++;
if (mode==0)
{
if ((*ip)--)
{
ip--;
return;
}
*ip=0;
mode=1;
}
if (mode==255)
{
ip--;
return;
}
if ((mode>16 && mode<64) || mode>64) exit(0);
if (mode<64)
{
for(i=0;i<mode;i++) palxlat[i]=paleta[*ip++];
mode=col_table[mode-1];
}
else mode=8;
switch (mode)
{
case 0:load_0bit(adr,palxlat);break;
case 1:ip=load_1bit(ip,adr,palxlat);break;
case 2:ip=load_2bit(ip,adr,palxlat);break;
case 3:ip=load_3bit(ip,adr,palxlat);break;
case 4:ip=load_4bit(ip,adr,palxlat);break;
case 8:ip=load_8bit(ip,adr,paleta);break;
}
}
void decompr_pict()
{
int x;
int y,yy;
ip=decomp_buff;
yy=0;
for (y=0;y<23;y++,yy+=direct_line_len)
for (x=0;x<640;x+=8)
decompr_box(playscreen+x+yy);
}
void load_frame(FILE *anim)
{
int size;
fread(&size,1,sizeof(size),anim);
fread(decomp_buff,1,size,anim);
decomp_buff[size]=0xff;
memcpy(test_frame,decomp_buff,size);
}
void load_palette(FILE *anim)
{
word i;
word size;
fread(&i,1,2,anim);
fread(&size,1,2,anim);
fread(&paleta[i],2,size,anim);
//if (fusing) for(i=1;i<256;i++) paleta[i]&=0x7bdf;
if (sdiff) paleta[0]=0;
}
void init_cinema()
{
playscreen=getmem(PLATNO_S*sizeof(*playscreen));
memset(playscreen,0xff,PLATNO_S*sizeof(*playscreen));
playscreen2=getmem(PLATNO_S*sizeof(*playscreen));
memset(playscreen2,0xff,PLATNO_S*sizeof(*playscreen));
paleta=getmem(512);
memset(paleta,0xff,sizeof(paleta));
if (banking) show_place=(word *)(POZICE*2048);else show_place=lbuffer+POZICE*640;
curcolor=0;bar(0,0,639,479);
showview(0,0,0,0);
decomp_buff=getmem(DECOMP_BUFF);
}
void done_cinema()
{
free(playscreen);
free(playscreen2);
free(paleta);
free(decomp_buff);
}
void fuse_frames()
{
long *p=(long *)playscreen,*q=(long *)playscreen2;
int i=PLATNO_S/2;
do
{
*q=(*q & 0x7bde7bde)+(*p & 0x7bde7bde)>>1;
q++;p++;i--;
}
while (i);
}
void copy_frames()
{
memcpy(playscreen2,playscreen,PLATNO_S*2);
}
void display_interlaced(word *playscreen2,int ofs)
{
word *p,*q;
int i=180;
p=show_place+ofs;
q=playscreen2;
do
{
if (banking) memcpy(mapvesaadr1(p),q,1280);else memcpy(p,q,1280);
q+=640;
p+=banking?2048:1280;i--;
}
while (i);
}
void display_full_lfb(word *playscreen2)
{
word *p,*q;
int i=180;
p=show_place;
q=playscreen2;
do
{
int j=320;
memcpy(p,q,1280);
p+=640;
do
{
*(long *)p=(*(long *)q & 0x7bde7bde)+(*(long *)(q+640) & 0x7bde7bde)>>1;q+=2;p+=2;j--;
}
while(j);
i--;
}
while (i);
}
void display_full_bank(word *playscreen2)
{
word *p,*q;
long *z;
int i=180;
p=show_place;
q=playscreen2;
do
{
int j=320;
memcpy(mapvesaadr1(p),q,1280);
p+=1024;
z=(long *)mapvesaadr1(p);
do
{
*z=(*(long *)q & 0x7bde7bde)+(*(long *)(q+640) & 0x7bde7bde)>>1;q+=2;z++;j--;
}
while(j);
p+=1024;
i--;
}
while (i);
}
void show_play_screen()
{
if (interlaced)
{
if (fusing)
{
if (ifuse) display_interlaced(playscreen,(banking?1024:640));
else
{
if (!banking) display_interlaced_fused_lfb(playscreen,playscreen2,show_place);
else display_interlaced_fused_bank(playscreen,playscreen2,show_place);
}
delay(30);
}
display_interlaced(playscreen,0);
}
else
{
if (fusing)
{
fuse_frames();
if (banking) display_full_bank(playscreen2);else display_full_lfb(playscreen2);
delay(30);
copy_frames();
}
if (banking) display_full_bank(playscreen);else display_full_lfb(playscreen);
}
}
void set_direct_mode()
{
fusing=0;
if (!banking)
{
direct=1;
playscreen=show_place;
anim_line_len=1280*2;
direct_line_len=640*16;
}
}
void play_cinema(FILE *anim)
{
char i;
do
{
fread(&i,1,1,anim);
switch (i)
{
case TRACK_VIDEO:
load_frame(anim);
decompr_pict();
break;
case TRACK_PALETTE:
load_palette(anim);
break;
case TRACK_MUSIC:break;
case TRACK_END:return;
case TRACK_DELAY:
if (!direct)
show_play_screen();
break;
default: return;
}
if (_bios_keybrd(_KEYBRD_READY)) return;
}
while (1);
}
void analyze_params(char *c)
{
while (*c)
switch (*c++)
{
case 'i':
case 'I':interlaced=1;break;
case 's':
case 'S':fusing=0;break;
case 'd':
case 'D':direct=1;break;
case 'v':
case 'V':sdiff=1;break;
case 'f':
case 'F':ifuse=1;interlaced=1;fusing=1;break;
}
}
void main(int argc,char **argv)
{
char filename[129];
if (argc<2)
{
puts("Pouziti: PLAYCNM film[.cnm] [I][D][S]");
puts(" I - Interlaced, prokladane");
puts(" S -Skip,vypina dvojnasobny pocet Framu");
puts(" D - Direct, prima dekomprese do LFB (totez jako IS, ale rychle)");
puts(" V - View differences, zobrazuje pouze rozdily (jen ty dulezite)");
puts(" F - Zapina specialni prokladaci rezim + I, ignoruje pri D");
return;
}
if (argc>=3) analyze_params(argv[2]);
priponu(argv[1],filename,124);
anim=fopen(filename,"rb");
if (anim==NULL)
{
printf("Nemohu otevrit soubor %s.\n",filename);
return;
}
if (initmode32(NULL))
{
puts("Tento program vyzaduje grafickou kartu, ktera podporuje HICOLOR 32768 barev") ;
return;
}
delay(1000);
init_cinema();
if (direct) set_direct_mode();
do
{
play_cinema(anim);
fseek(anim,0,SEEK_SET);
}
while (!_bios_keybrd(_KEYBRD_READY));
done_cinema();
closemode();
fclose(anim);
}