bsnes/higan/sfc/alt/ppu-performance/cache/cache.cpp

120 lines
3.2 KiB
C++

PPU::Cache::Cache(PPU& self) : self(self) {
tiledata[0] = new uint8[262144]();
tiledata[1] = new uint8[131072]();
tiledata[2] = new uint8[ 65536]();
tilevalid[0] = new uint8[ 4096]();
tilevalid[1] = new uint8[ 2048]();
tilevalid[2] = new uint8[ 1024]();
}
auto PPU::Cache::tile_2bpp(uint tile) -> uint8* {
if(tilevalid[0][tile] == 0) {
tilevalid[0][tile] = 1;
uint8* output = (uint8*)tiledata[0] + (tile << 6);
uint offset = tile << 4;
uint y = 8;
uint color, d0, d1;
while(y--) {
d0 = ppu.vram[offset + 0];
d1 = ppu.vram[offset + 1];
#define render_line(mask) \
color = !!(d0 & mask) << 0; \
color |= !!(d1 & mask) << 1; \
*output++ = color
render_line(0x80);
render_line(0x40);
render_line(0x20);
render_line(0x10);
render_line(0x08);
render_line(0x04);
render_line(0x02);
render_line(0x01);
#undef render_line
offset += 2;
}
}
return tiledata[0] + (tile << 6);
}
auto PPU::Cache::tile_4bpp(uint tile) -> uint8* {
if(tilevalid[1][tile] == 0) {
tilevalid[1][tile] = 1;
uint8* output = (uint8*)tiledata[1] + (tile << 6);
uint offset = tile << 5;
uint y = 8;
uint color, d0, d1, d2, d3;
while(y--) {
d0 = ppu.vram[offset + 0];
d1 = ppu.vram[offset + 1];
d2 = ppu.vram[offset + 16];
d3 = ppu.vram[offset + 17];
#define render_line(mask) \
color = !!(d0 & mask) << 0; \
color |= !!(d1 & mask) << 1; \
color |= !!(d2 & mask) << 2; \
color |= !!(d3 & mask) << 3; \
*output++ = color
render_line(0x80);
render_line(0x40);
render_line(0x20);
render_line(0x10);
render_line(0x08);
render_line(0x04);
render_line(0x02);
render_line(0x01);
#undef render_line
offset += 2;
}
}
return tiledata[1] + (tile << 6);
}
auto PPU::Cache::tile_8bpp(uint tile) -> uint8* {
if(tilevalid[2][tile] == 0) {
tilevalid[2][tile] = 1;
uint8* output = (uint8*)tiledata[2] + (tile << 6);
uint offset = tile << 6;
uint y = 8;
uint color, d0, d1, d2, d3, d4, d5, d6, d7;
while(y--) {
d0 = ppu.vram[offset + 0];
d1 = ppu.vram[offset + 1];
d2 = ppu.vram[offset + 16];
d3 = ppu.vram[offset + 17];
d4 = ppu.vram[offset + 32];
d5 = ppu.vram[offset + 33];
d6 = ppu.vram[offset + 48];
d7 = ppu.vram[offset + 49];
#define render_line(mask) \
color = !!(d0 & mask) << 0; \
color |= !!(d1 & mask) << 1; \
color |= !!(d2 & mask) << 2; \
color |= !!(d3 & mask) << 3; \
color |= !!(d4 & mask) << 4; \
color |= !!(d5 & mask) << 5; \
color |= !!(d6 & mask) << 6; \
color |= !!(d7 & mask) << 7; \
*output++ = color
render_line(0x80);
render_line(0x40);
render_line(0x20);
render_line(0x10);
render_line(0x08);
render_line(0x04);
render_line(0x02);
render_line(0x01);
#undef render_line
offset += 2;
}
}
return tiledata[2] + (tile << 6);
}
auto PPU::Cache::tile(uint bpp, uint tile) -> uint8* {
switch(bpp) {
case 0: return tile_2bpp(tile);
case 1: return tile_4bpp(tile);
case 2: return tile_8bpp(tile);
}
}