mirror of https://github.com/bsnes-emu/bsnes.git
104 lines
2.7 KiB
C++
104 lines
2.7 KiB
C++
auto PPU::Background::clip(int n) -> int {
|
|
//13-bit sign extend: --s---nnnnnnnnnn -> ssssssnnnnnnnnnn
|
|
return n & 0x2000 ? (n | ~1023) : (n & 1023);
|
|
}
|
|
|
|
//H = 28
|
|
auto PPU::Background::begin_mode7() -> void {
|
|
cache.hoffset = self.regs.mode7_hoffset;
|
|
cache.voffset = self.regs.mode7_voffset;
|
|
}
|
|
|
|
auto PPU::Background::run_mode7() -> void {
|
|
signed a = sclip<16>(self.regs.m7a);
|
|
signed b = sclip<16>(self.regs.m7b);
|
|
signed c = sclip<16>(self.regs.m7c);
|
|
signed d = sclip<16>(self.regs.m7d);
|
|
|
|
signed cx = sclip<13>(self.regs.m7x);
|
|
signed cy = sclip<13>(self.regs.m7y);
|
|
signed hoffset = sclip<13>(cache.hoffset);
|
|
signed voffset = sclip<13>(cache.voffset);
|
|
|
|
if(Background::x++ & ~255) return;
|
|
unsigned x = mosaic.hoffset;
|
|
unsigned y = self.bg1.mosaic.voffset; //BG2 vertical mosaic uses BG1 mosaic size
|
|
|
|
if(--mosaic.hcounter == 0) {
|
|
mosaic.hcounter = regs.mosaic + 1;
|
|
mosaic.hoffset += regs.mosaic + 1;
|
|
}
|
|
|
|
if(self.regs.mode7_hflip) x = 255 - x;
|
|
if(self.regs.mode7_vflip) y = 255 - y;
|
|
|
|
signed psx = ((a * clip(hoffset - cx)) & ~63) + ((b * clip(voffset - cy)) & ~63) + ((b * y) & ~63) + (cx << 8);
|
|
signed psy = ((c * clip(hoffset - cx)) & ~63) + ((d * clip(voffset - cy)) & ~63) + ((d * y) & ~63) + (cy << 8);
|
|
|
|
signed px = psx + (a * x);
|
|
signed py = psy + (c * x);
|
|
|
|
//mask pseudo-FP bits
|
|
px >>= 8;
|
|
py >>= 8;
|
|
|
|
unsigned tile;
|
|
unsigned palette;
|
|
switch(self.regs.mode7_repeat) {
|
|
//screen repetition outside of screen area
|
|
case 0:
|
|
case 1:
|
|
px &= 1023;
|
|
py &= 1023;
|
|
tile = ppu.vram[((py >> 3) * 128 + (px >> 3)) << 1];
|
|
palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
|
break;
|
|
|
|
//palette color 0 outside of screen area
|
|
case 2:
|
|
if((px | py) & ~1023) {
|
|
palette = 0;
|
|
} else {
|
|
px &= 1023;
|
|
py &= 1023;
|
|
tile = ppu.vram[((py >> 3) * 128 + (px >> 3)) << 1];
|
|
palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
|
}
|
|
break;
|
|
|
|
//character 0 repetition outside of screen area
|
|
case 3:
|
|
if((px | py) & ~1023) {
|
|
tile = 0;
|
|
} else {
|
|
px &= 1023;
|
|
py &= 1023;
|
|
tile = ppu.vram[((py >> 3) * 128 + (px >> 3)) << 1];
|
|
}
|
|
palette = ppu.vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
|
break;
|
|
}
|
|
|
|
unsigned priority;
|
|
if(id == ID::BG1) {
|
|
priority = regs.priority0;
|
|
} else if(id == ID::BG2) {
|
|
priority = (palette & 0x80 ? regs.priority1 : regs.priority0);
|
|
palette &= 0x7f;
|
|
}
|
|
|
|
if(palette == 0) return;
|
|
|
|
if(regs.main_enable) {
|
|
output.main.palette = palette;
|
|
output.main.priority = priority;
|
|
output.main.tile = 0;
|
|
}
|
|
|
|
if(regs.sub_enable) {
|
|
output.sub.palette = palette;
|
|
output.sub.priority = priority;
|
|
output.sub.tile = 0;
|
|
}
|
|
}
|