const int sprhgt=16;
const int sprwid=16;
int sprnr,curaddr,spraddr,sprpg;
unsigned char sprite[16][16];
unsigned char tspraddr[16384];
unsigned char foutbuf[16385];
int foutbufpos;
unsigned char *mempos;
inline void foutflush(void)
{
int off;
//ЄрсышЎр ъєёърьш яю 256 ёяЁрщЄют
off=256+(sprnr&255)+(sprnr>>8)*768;
tspraddr[off+0 ]=spraddr;
tspraddr[off+256]=spraddr>>8;
tspraddr[off+512]=sprpg^0xff; //pg
memcpy(mempos,foutbuf,foutbufpos);
mempos+=foutbufpos;
foutbufpos=0;
}
inline void wrbyte(unsigned char b)
{
//BlockWrite(fout,b,1);
foutbuf[foutbufpos++]=b;
++curaddr;
}
inline bool sprisempty(void)
{
int i,j;
for(i=0;i<16;++i)
{
for(j=0;j<16;++j)
{
if(sprite[i][j]<16) return false;//transparent_color
}
}
return true;
}
inline bool colisempty(unsigned char col1,unsigned char col2)
{
return (col1>=16)&&(col2>=16); //transparent_color
}
inline unsigned char coltopixel(unsigned char col1,unsigned char col2)
{
//transparent_color and $0f = 0!!!
return ((col1&0x08)<<3) + (col1&0x07) + ((col2&0x08)<<4) + ((col2&0x07)<<3);
}
inline unsigned char coltomask(unsigned char col1,unsigned char col2)
{
unsigned char mask;
mask=0;
if(col1>=16) mask =0x47;
if(col2>=16) mask|=0xb8;
return mask;
}
void mksprite(void)
{
int x,y;
unsigned char mask,pixel;
int curscraddr,oldscraddr,scraddrdelta,oldde;
x=6;
oldde=65536; //false value
while(x>=0) //4 layers
{
//start of the layer
wrbyte(225); //pop hl
oldscraddr=0;
curscraddr=0;
while(x<sprwid) //layer columns
{
for(y=0;y<16;++y)
{
scraddrdelta=curscraddr-oldscraddr;
if(!colisempty(sprite[y][x],sprite[y][x+1]))
{
if(scraddrdelta)
{
if(scraddrdelta!=40)
{
if(scraddrdelta!=oldde)
{
if((oldde!=65536) && ((scraddrdelta&0xff00)==(oldde&0xff00)))
{//ld e,N
wrbyte(30); //ld e,N
wrbyte(scraddrdelta);
}
else
{//ld de,N
wrbyte(17); //ld de,N
wrbyte(scraddrdelta);
wrbyte(scraddrdelta>>8);
}
oldde=scraddrdelta;
}
wrbyte(25); //add hl,de
}
else
{//scraddrdelta=40
wrbyte(9); //add hl,bc
}
}
oldscraddr=curscraddr;
mask =coltomask (sprite[y][x],sprite[y][x+1]);
pixel=coltopixel(sprite[y][x],sprite[y][x+1]);
if(!mask)
{
if(!pixel)
{
wrbyte(112); //ld (hl),b
}
else
{
wrbyte(54); //ld (hl),N
wrbyte(pixel);
}
}
else
{//mask<>0
wrbyte(126); //ld a,(hl)
wrbyte(230); //and N
wrbyte(mask);
if(pixel)
{
wrbyte(246); //or N
wrbyte(pixel);
}
wrbyte(119); //ld (hl),a
}
} //nonempty
curscraddr+=40;
} //y
curscraddr=curscraddr-(40*sprhgt)+1;
x+=8;
} //x in layer
x=x-sprwid-2;
} //layers
wrbyte(0xfd); //$fd
wrbyte(233); //jp (iy)
}
void mkspr_init(int page)
{
int i,off;
sprnr=0;
curaddr=0; //todo +$0200?
sprpg=page; //todo $10?
foutbufpos=0;
mempos=mem;
memset(tspraddr,0,sizeof(tspraddr));
for(i=0;i<256*21;++i)
{
off=256+(i&255)+(i>>8)*768;
tspraddr[off+0 ]=0;
tspraddr[off+256]=0; //todo $02?
tspraddr[off+512]=0xeb; //pg
}
}
int mkspr_add(const char *filename, int sprite_slot, FILE * fileOutAsm, int * pageNumCntr)
{
FILE *fin;
int i,j,x,y,pp,size,bshift,wdt,hgt,bpp,rle;
unsigned char *data;
fin=fopen(filename,"rb");//256c 256x256
if(!fin)
{
printf("ERR: Can't open sprite sheet BMP (%s)\n",filename);
return -1;
}
fseek(fin,0,SEEK_END);
size=ftell(fin);
fseek(fin,0,SEEK_SET);
data=(unsigned char*)malloc(size);
fread(data,size,1,fin);
fclose(fin);
bshift=read_dword(&data[10]);
wdt=read_dword(&data[18]);
hgt=read_dword(&data[22]);
bpp=read_word (&data[28]);
rle=read_dword(&data[30]);
if((wdt&15)||(hgt&15))
{
printf("ERR: Width and height should be 16px aligned (%s)\n",filename);
free(data);
return -1;
}
if(rle!=0||bpp!=8)
{
printf("ERR: Sprite sheet should be 256 colors uncompressed BMP (%s)\n",filename);
free(data);
return -1;
}
/* Code to generate:
dup 4
pop hl
dup ?
dup ?
[ld de,N:add hl,de]/[add hl,bc]
ld (hl),N / ld a,(hl):and N:or N:ld (hl),a
edup ;bytes
edup ;columns
edup ;layers
jp (iy)
*/
for(y=0;y<hgt;y+=16)
{
for(x=0;x<wdt;x+=16)
{
if(sprnr>=5376) break;//юъЁєуы╕ээюх (16384/768) *256
//ъюяшЁютрэшх ёяЁрщЄр шч шчюсЁрцхэш т сєЇхЁ
for(i=0;i<16;++i)
{
pp=bshift+((hgt-1-(y+i))*wdt)+x;
for(j=0;j<16;++j)
{
sprite[i][j]=data[pp++];
}
}
//sprite 16 x 16 (sprwid x sprhgt)
spraddr=curaddr;
mksprite();
if(curaddr<16384)
{
foutflush();
}
else
{//page overflow
page_save(sprite_slot,sprpg,"spriteData",*pageNumCntr,fileOutAsm);
mempos=mem;
(*pageNumCntr)++;
++sprpg;
curaddr=0;//-=spraddr; //todo +$0200?
spraddr=0;
foutbufpos=0;
mksprite();
foutflush();
}
++sprnr;
}
}
free(data);
return sprpg;
}