Login

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download | RSS feed

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;
}