mirror of https://github.com/bsnes-emu/bsnes.git
104 lines
2.6 KiB
C++
104 lines
2.6 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::beginMode7() -> void {
|
|
latch.hoffset = ppu.io.hoffsetMode7;
|
|
latch.voffset = ppu.io.voffsetMode7;
|
|
}
|
|
|
|
auto PPU::Background::runMode7() -> void {
|
|
int a = (int16)ppu.io.m7a;
|
|
int b = (int16)ppu.io.m7b;
|
|
int c = (int16)ppu.io.m7c;
|
|
int d = (int16)ppu.io.m7d;
|
|
|
|
int cx = (int13)ppu.io.m7x;
|
|
int cy = (int13)ppu.io.m7y;
|
|
int hoffset = (int13)latch.hoffset;
|
|
int voffset = (int13)latch.voffset;
|
|
|
|
if(Background::x++ & ~255) return;
|
|
uint x = mosaic.hoffset;
|
|
uint y = ppu.bg1.mosaic.voffset; //BG2 vertical mosaic uses BG1 mosaic size
|
|
|
|
if(--mosaic.hcounter == 0) {
|
|
mosaic.hcounter = io.mosaic + 1;
|
|
mosaic.hoffset += io.mosaic + 1;
|
|
}
|
|
|
|
if(ppu.io.hflipMode7) x = 255 - x;
|
|
if(ppu.io.vflipMode7) y = 255 - y;
|
|
|
|
int psx = ((a * clip(hoffset - cx)) & ~63) + ((b * clip(voffset - cy)) & ~63) + ((b * y) & ~63) + (cx << 8);
|
|
int psy = ((c * clip(hoffset - cx)) & ~63) + ((d * clip(voffset - cy)) & ~63) + ((d * y) & ~63) + (cy << 8);
|
|
|
|
int px = psx + (a * x);
|
|
int py = psy + (c * x);
|
|
|
|
//mask pseudo-FP bits
|
|
px >>= 8;
|
|
py >>= 8;
|
|
|
|
uint tile;
|
|
uint palette;
|
|
switch(ppu.io.repeatMode7) {
|
|
//screen repetition outside of screen area
|
|
case 0:
|
|
case 1:
|
|
px &= 1023;
|
|
py &= 1023;
|
|
tile = ppu.vram[(py >> 3) * 128 + (px >> 3)].byte(0);
|
|
palette = ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)].byte(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)].byte(0);
|
|
palette = ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)].byte(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)].byte(0);
|
|
}
|
|
palette = ppu.vram[(tile << 6) + ((py & 7) << 3) + (px & 7)].byte(1);
|
|
break;
|
|
}
|
|
|
|
uint priority;
|
|
if(id == ID::BG1) {
|
|
priority = io.priority[0];
|
|
} else if(id == ID::BG2) {
|
|
priority = io.priority[bool(palette & 0x80)];
|
|
palette &= 0x7f;
|
|
}
|
|
|
|
if(palette == 0) return;
|
|
|
|
if(io.aboveEnable) {
|
|
output.above.palette = palette;
|
|
output.above.priority = priority;
|
|
output.above.tile = 0;
|
|
}
|
|
|
|
if(io.belowEnable) {
|
|
output.below.palette = palette;
|
|
output.below.priority = priority;
|
|
output.below.tile = 0;
|
|
}
|
|
}
|