#include #include #include #include #include "dat.h" #include "fns.h" uchar pic[160*144*4*9]; static void resolvetile(u8int tx, u8int ty, u8int toy, int window, u8int* tnl1, u8int *tnl2) { u16int tni, tnli; u8int tn; tni = 0x9800 + 32 * ((u16int)ty) + ((u16int)tx); if(window){ if(mem[LCDC] & WINDOWTILEMAP) tni += 0x400; }else if(mem[LCDC] & BGTILEMAP) tni += 0x400; tn = mem[tni]; if(mem[LCDC] & BGTILEDATA) tnli = 0x8000 + 16 * (u16int)tn; else tnli = 0x9000 + 16 * (u16int)(schar)tn; *tnl1 = mem[tnli + 2 * ((u16int)toy)]; *tnl2 = mem[tnli + 2 * ((u16int)toy) + 1]; } static void pixel(int x, int y, int val, int back) { int X, Y; uchar *p; val = (3 - val) * 0x55; if(scale > 1){ for(X = scale * x; X < scale * (x+1); X++) for(Y = scale * y; Y < scale * (y+1); Y++){ p = pic + Y * scale * 160 * 4 + X * 4; p[0] = val; p[1] = val; p[2] = val; p[3] = back ? 0 : 0xFF; } }else{ p = pic + y*160*4 + x*4; p[0] = val; p[1] = val; p[2] = val; p[3] = back ? 0 : 0xFF; } } static void pixelbelow(int x, int y, int val) { if(pic[y*scale*scale*160*4 + x*scale*4 + 3] == 0) pixel(x, y, val, 0); } static void drawbg(void) { u8int Y, x, y, ty, toy, tx, tox, tnl1, tnl2, pal, val,h; Y = mem[LY]; y = Y + mem[SCY]; ty = y / 8; toy = y % 8; tx = mem[SCX] / 8; tox = mem[SCX] % 8; resolvetile(tx, ty, toy, 0, &tnl1, &tnl2); tnl1 <<= (tox+1) % 8; tnl2 <<= (tox+1) % 8; pal = mem[BGP]; for(x = 0; x < 160; x++){ tox++; if((tox % 8) == 0){ tx++; resolvetile(tx%32, ty, toy, 0, &tnl1, &tnl2); } val = ((tnl1 & 0x80) >> 6) | ((tnl2 & 0x80) >> 5); h = val == 0; val = (pal >> val) & 3; pixel(x, Y, val, h); tnl1 <<= 1; tnl2 <<= 1; } } static void drawsprites(void) { u8int y, t, tnl1, tnl2, dx, ddx, val, pal; schar dy; u16int tnli; int i, x, big; struct { u8int y, x, t, f; } *s; y = mem[LY]; big = mem[LCDC] & SPRITE16; s = (void*)(mem + 0xFE00); for(i = 0; i < 40; i++, s++){ if(s->y == 0 || s->x == 0) continue; dy = y - s->y + 16; if(dy < 0 || dy >= (big ? 16 : 8)) continue; pal = (s->f & (1<<4)) ? mem[OBP1] : mem[OBP0]; if(s->f & (1<<6)) dy = (big ? 15 : 7) - dy; t = s->t; if(big){ if(dy >= 8){ t |= 1; dy -= 8; }else t &= ~1; } tnli = 0x8000 + 2 * (u16int)dy + 16 * (u16int) t; tnl1 = mem[tnli]; tnl2 = mem[tnli + 1]; x = s->x - 9; for(dx = 0; dx < 8; dx++, x++){ ddx = dx; if((s->f & (1<<5)) == 0) ddx = 7 - dx; val = ((tnl1 >> ddx) & 1) | (((tnl2 >> ddx) & 1) << 1); if(x < 0 || val == 0) continue; val = (pal >> (2 * val)) & 3; if(x >= 160) break; if(s->f & (1<<7)) pixelbelow(x, y, val); else pixel(x, y, val, 0); } } } static void drawwindow(void) { u8int wx, wy, Y, y, ty, toy, tx, tox, tnl1, tnl2, x, val, pal; if(mem[WX] < 7) return; wx = mem[WX] - 7; wy = mem[WY]; Y = mem[LY]; if(Y < wy) return; y = Y - wy; ty = y / 8; toy = y % 8; tx = 0; tox = 0; resolvetile(tx, ty, toy, 1, &tnl1, &tnl2); pal = mem[BGP]; for(x = wx; x < 160; x++){ tox++; if((tox & 7) == 0){ tx++; resolvetile(tx, ty, toy, 1, &tnl1, &tnl2); } val = ((tnl1 & 0x80) >> 6) | ((tnl2 & 0x80) >> 5); val = (pal >> val) & 3; pixel(x, Y, val, 0); tnl1 <<= 1; tnl2 <<= 1; } } void ppustep(void) { extern Rectangle picr; extern Image *tmp; if(mem[LY] == 144){ mem[STAT] &= ~3; mem[STAT] |= 1; interrupt(INTVBLANK); } if(mem[LY] == mem[LYC]){ mem[STAT] |= 4; if(mem[STAT] & 64) interrupt(INTLCDC); }else mem[STAT] &= ~4; if(mem[LY] < 144) mem[STAT] &= ~3; if(mem[LY] < 144 && (mem[LCDC] & LCDOP)){ if(mem[LCDC] & BGDISP) drawbg(); if(mem[LCDC] & WINDOWDISP) drawwindow(); if(mem[LCDC] & SPRITEDISP) drawsprites(); } mem[LY]++; if(mem[LY] > 160){ mem[LY] = 0; if(mem[LCDC] & LCDOP){ if(tmp){ loadimage(tmp, tmp->r, pic, 160*144*4*scale*scale); draw(screen, picr, tmp, nil, ZP); }else loadimage(screen, picr, pic, 160*144*4*scale*scale); flushimage(display, 1); memset(pic, sizeof pic, 0); } } }