auto VDP::Background::scanline() -> void { state.x = 0; state.y = vdp.io.vcounter; } auto VDP::Background::run() -> void { uint8 hoffset = state.x++; uint9 voffset = state.y; if(voffset >= vdp.vlines() || hoffset < (vdp.io.hscroll & 7) ) { output.color = 0; output.palette = 0; output.priority = 0; return; } bool hscroll = !vdp.io.horizontalScrollLock || voffset >= 16; bool vscroll = !vdp.io.verticalScrollLock || hoffset <= 191; if(hscroll) hoffset -= vdp.io.hscroll; if(vscroll) voffset += vdp.io.vscroll; uint14 nameTableAddress; if(vdp.vlines() == 192) { if(voffset >= 224) voffset -= 224; nameTableAddress = vdp.io.nameTableAddress << 11; } else { voffset &= 255; nameTableAddress = (vdp.io.nameTableAddress & ~1) << 11 | 0x700; } nameTableAddress += ((voffset >> 3) << 6) + ((hoffset >> 3) << 1); uint16 tiledata; tiledata = vdp.vram[nameTableAddress + 0] << 0; tiledata |= vdp.vram[nameTableAddress + 1] << 8; uint14 patternAddress = tiledata.bits(0,8) << 5; if(tiledata.bit(9)) hoffset ^= 7; if(tiledata.bit(10)) voffset ^= 7; output.palette = tiledata.bit(11); output.priority = tiledata.bit(12); auto index = 7 - (hoffset & 7); patternAddress += (voffset & 7) << 2; output.color.bit(0) = vdp.vram[patternAddress + 0].bit(index); output.color.bit(1) = vdp.vram[patternAddress + 1].bit(index); output.color.bit(2) = vdp.vram[patternAddress + 2].bit(index); output.color.bit(3) = vdp.vram[patternAddress + 3].bit(index); } auto VDP::Background::power() -> void { memory::fill(&state, sizeof(State)); memory::fill(&output, sizeof(Output)); }