From 0623d6ac2b785ccbb2b62521cb00dfe4a627b595 Mon Sep 17 00:00:00 2001 From: byuu <2107894+byuu@users.noreply.github.com> Date: Fri, 19 Jul 2019 00:44:09 +0900 Subject: [PATCH] v107.9 * started removing nall-specific components from the fast PPU renderer * corrected compilation issues with Super Game Boy support --- bsnes/emulator/emulator.hpp | 2 +- bsnes/sfc/ppu-fast/background.cpp | 25 ++- bsnes/sfc/ppu-fast/io.cpp | 308 +++++++++++++-------------- bsnes/sfc/ppu-fast/line.cpp | 54 ++--- bsnes/sfc/ppu-fast/mode7.cpp | 14 +- bsnes/sfc/ppu-fast/mode7hd.cpp | 26 +-- bsnes/sfc/ppu-fast/object.cpp | 44 ++-- bsnes/sfc/ppu-fast/ppu.cpp | 64 +++--- bsnes/sfc/ppu-fast/ppu.hpp | 100 ++++----- bsnes/sfc/ppu-fast/serialization.cpp | 24 +-- bsnes/sfc/ppu-fast/window.cpp | 12 +- bsnes/sfc/ppu/object.cpp | 2 +- bsnes/sfc/ppu/ppu.cpp | 13 +- bsnes/sfc/ppu/ppu.hpp | 1 - ruby/video/cgl.cpp | 2 +- 15 files changed, 345 insertions(+), 346 deletions(-) diff --git a/bsnes/emulator/emulator.hpp b/bsnes/emulator/emulator.hpp index ae546402..91881723 100644 --- a/bsnes/emulator/emulator.hpp +++ b/bsnes/emulator/emulator.hpp @@ -32,7 +32,7 @@ using namespace nall; namespace Emulator { static const string Name = "bsnes"; - static const string Version = "107.8"; + static const string Version = "107.9"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/bsnes/sfc/ppu-fast/background.cpp b/bsnes/sfc/ppu-fast/background.cpp index 1fa7bbd9..e34a0963 100644 --- a/bsnes/sfc/ppu-fast/background.cpp +++ b/bsnes/sfc/ppu-fast/background.cpp @@ -1,10 +1,10 @@ -auto PPUfast::Line::renderBackground(PPUfast::IO::Background& self, uint source) -> void { +auto PPU::Line::renderBackground(PPU::IO::Background& self, uint source) -> void { if(!self.aboveEnable && !self.belowEnable) return; if(self.tileMode == TileMode::Mode7) return renderMode7(self, source); if(self.tileMode == TileMode::Inactive) return; - array windowAbove; - array windowBelow; + bool windowAbove[256]; + bool windowBelow[256]; renderWindow(self.window, self.window.aboveEnable, windowAbove); renderWindow(self.window, self.window.belowEnable, windowBelow); @@ -23,13 +23,13 @@ auto PPUfast::Line::renderBackground(PPUfast::IO::Background& self, uint source) uint hscroll = self.hoffset; uint vscroll = self.voffset; - uint hmask = (width << self.tileSize << bit1(self.screenSize,0)) - 1; - uint vmask = (width << self.tileSize << bit1(self.screenSize,1)) - 1; + uint hmask = (width << self.tileSize << !!(self.screenSize & 1)) - 1; + uint vmask = (width << self.tileSize << !!(self.screenSize & 2)) - 1; uint y = this->y - (self.mosaicEnable ? this->y % (1 + io.mosaicSize) : 0); if(hires) { hscroll <<= 1; - if(io.interlace) y = y << 1 | ppufast.field(); + if(io.interlace) y = y << 1 | ppu.field(); } uint mosaicCounter = 1; @@ -79,7 +79,7 @@ auto PPUfast::Line::renderBackground(PPUfast::IO::Background& self, uint source) if(tileHeight == 4 && (bool(voffset & 8) ^ bool(mirrorY))) tileNumber += 16; tileNumber = (tileNumber & 0x03ff) + tiledataIndex & tileMask; - auto tiledata = ppufast.tilecache[self.tileMode] + (tileNumber << 6); + auto tiledata = ppu.tilecache[self.tileMode] + (tileNumber << 6); tiledata += (voffset & 7 ^ mirrorY) << 3; for(uint tileX = 0; tileX < 8; tileX++, x++) { @@ -101,7 +101,7 @@ auto PPUfast::Line::renderBackground(PPUfast::IO::Background& self, uint source) if(self.belowEnable && !windowBelow[x]) plotBelow(x, source, mosaicPriority, mosaicColor); } else { uint X = x >> 1; - if(!ppufast.hd()) { + if(!ppu.hd()) { if(x & 1) { if(self.aboveEnable && !windowAbove[X]) plotAbove(X, source, mosaicPriority, mosaicColor); } else { @@ -116,17 +116,16 @@ auto PPUfast::Line::renderBackground(PPUfast::IO::Background& self, uint source) } } -auto PPUfast::Line::getTile(PPUfast::IO::Background& self, uint hoffset, uint voffset) -> uint { +auto PPU::Line::getTile(PPU::IO::Background& self, uint hoffset, uint voffset) -> uint { bool hires = io.bgMode == 5 || io.bgMode == 6; uint tileHeight = 3 + self.tileSize; uint tileWidth = !hires ? tileHeight : 4; - uint screenX = (self.screenSize & 1) ? 32 << 5 : 0; - uint screenY = (self.screenSize & 2) ? 32 << 5 + (self.screenSize & 1) : 0; + uint screenX = self.screenSize & 1 ? 32 << 5 : 0; + uint screenY = self.screenSize & 2 ? 32 << 5 + (self.screenSize & 1) : 0; uint tileX = hoffset >> tileWidth; uint tileY = voffset >> tileHeight; uint offset = (tileY & 0x1f) << 5 | (tileX & 0x1f); if(tileX & 0x20) offset += screenX; if(tileY & 0x20) offset += screenY; - uint15 address = self.screenAddress + offset; - return ppufast.vram[address]; + return ppu.vram[self.screenAddress + offset & 0x7fff]; } diff --git a/bsnes/sfc/ppu-fast/io.cpp b/bsnes/sfc/ppu-fast/io.cpp index ba5a22ad..553b2a50 100644 --- a/bsnes/sfc/ppu-fast/io.cpp +++ b/bsnes/sfc/ppu-fast/io.cpp @@ -1,28 +1,28 @@ -auto PPUfast::latchCounters() -> void { +auto PPU::latchCounters() -> void { io.hcounter = cpu.hdot(); io.vcounter = cpu.vcounter(); latch.counters = 1; } -auto PPUfast::vramAddress() const -> uint15 { //uint15 for 64K VRAM; uint16 for 128K VRAM - uint15 address = io.vramAddress; +auto PPU::vramAddress() const -> uint { + uint address = io.vramAddress; switch(io.vramMapping) { - case 0: return address; - case 1: return bits(address, 8-15) << 8 | bits(address,0-4) << 3 | bits(address,5-7); - case 2: return bits(address, 9-15) << 9 | bits(address,0-5) << 3 | bits(address,6-8); - case 3: return bits(address,10-15) << 10 | bits(address,0-6) << 3 | bits(address,7-9); + case 0: return address & 0x7fff; + case 1: return address & 0x7f00 | address << 3 & 0x00f8 | address >> 5 & 7; + case 2: return address & 0x7e00 | address << 3 & 0x01f8 | address >> 6 & 7; + case 3: return address & 0x7c00 | address << 3 & 0x03f8 | address >> 7 & 7; } unreachable; } -auto PPUfast::readVRAM() -> uint16 { +auto PPU::readVRAM() -> uint16 { if(!io.displayDisable && cpu.vcounter() < vdisp()) return 0x0000; auto address = vramAddress(); return vram[address]; } template -auto PPUfast::writeVRAM(uint8 data) -> void { +auto PPU::writeVRAM(uint8_t data) -> void { if(!io.displayDisable && cpu.vcounter() < vdisp()) return; Line::flush(); auto address = vramAddress(); @@ -35,11 +35,11 @@ auto PPUfast::writeVRAM(uint8 data) -> void { updateTiledata(address); } -auto PPUfast::updateTiledata(uint address) -> void { - auto word = vram[address]; - auto line2bpp = tilecache[TileMode::BPP2] + ((address & 0x7fff) << 3); - auto line4bpp = tilecache[TileMode::BPP4] + ((address & 0x7ff0) << 2) + ((address & 7) << 3); - auto line8bpp = tilecache[TileMode::BPP8] + ((address & 0x7fe0) << 1) + ((address & 7) << 3); +auto PPU::updateTiledata(uint address) -> void { + auto word = vram[address & 0x7fff]; + auto line2bpp = tilecache[TileMode::BPP2] + (address << 3 & 0x3fff8); + auto line4bpp = tilecache[TileMode::BPP4] + (address << 2 & 0x1ffc0) + (address << 3 & 0x38); + auto line8bpp = tilecache[TileMode::BPP8] + (address << 1 & 0x0ffc0) + (address << 3 & 0x38); uint plane4bpp = address >> 2 & 2; uint plane8bpp = address >> 2 & 6; for(uint x : range(8)) { @@ -49,20 +49,20 @@ auto PPUfast::updateTiledata(uint address) -> void { } } -auto PPUfast::readOAM(uint10 address) -> uint8 { +auto PPU::readOAM(uint10 address) -> uint8 { if(!io.displayDisable && cpu.vcounter() < vdisp()) address = latch.oamAddress; return readObject(address); } -auto PPUfast::writeOAM(uint10 address, uint8 data) -> void { +auto PPU::writeOAM(uint10 address, uint8_t data) -> void { Line::flush(); - //Uniracers 2-player mode hack + //0x0218: Uniracers (2-player mode) hack; requires cycle timing for latch.oamAddress to be correct if(!io.displayDisable && cpu.vcounter() < vdisp()) address = 0x0218; //latch.oamAddress; return writeObject(address, data); } template -auto PPUfast::readCGRAM(uint8 address) -> uint8 { +auto PPU::readCGRAM(uint8_t address) -> uint8 { if(!io.displayDisable && cpu.vcounter() > 0 && cpu.vcounter() < vdisp() && cpu.hcounter() >= 88 && cpu.hcounter() < 1096 @@ -75,7 +75,7 @@ auto PPUfast::readCGRAM(uint8 address) -> uint8 { } } -auto PPUfast::writeCGRAM(uint8 address, uint15 data) -> void { +auto PPU::writeCGRAM(uint8_t address, uint15 data) -> void { if(!io.displayDisable && cpu.vcounter() > 0 && cpu.vcounter() < vdisp() && cpu.hcounter() >= 88 && cpu.hcounter() < 1096 @@ -83,8 +83,8 @@ auto PPUfast::writeCGRAM(uint8 address, uint15 data) -> void { cgram[address] = data; } -auto PPUfast::readIO(uint address, uint8 data) -> uint8 { - cpu.synchronize(ppufast); +auto PPU::readIO(uint address, uint8 data) -> uint8 { + cpu.synchronize(ppu); switch(address & 0xffff) { @@ -97,22 +97,22 @@ auto PPUfast::readIO(uint address, uint8 data) -> uint8 { } case 0x2134: { //MPYL - uint24 result = (int16)io.mode7.a * (int8)(io.mode7.b >> 8); - return latch.ppu1.mdr = bit8(result,0); + uint result = (int16_t)io.mode7.a * (int8_t)(io.mode7.b >> 8); + return latch.ppu1.mdr = result >> 0; } case 0x2135: { //MPYM - uint24 result = (int16)io.mode7.a * (int8)(io.mode7.b >> 8); - return latch.ppu1.mdr = bit8(result,1); + uint result = (int16_t)io.mode7.a * (int8_t)(io.mode7.b >> 8); + return latch.ppu1.mdr = result >> 8; } case 0x2136: { //MPYH - uint24 result = (int16)io.mode7.a * (int8)(io.mode7.b >> 8); - return latch.ppu1.mdr = bit8(result,2); + uint result = (int16_t)io.mode7.a * (int8_t)(io.mode7.b >> 8); + return latch.ppu1.mdr = result >> 16; } case 0x2137: { //SLHV - if(cbit1(cpu.pio(),7)) latchCounters(); + if(cpu.pio() & 0x80) latchCounters(); return data; //CPU MDR } @@ -142,9 +142,9 @@ auto PPUfast::readIO(uint address, uint8 data) -> uint8 { case 0x213b: { //CGDATAREAD if(io.cgramAddressLatch++ == 0) { - bits(latch.ppu2.mdr,0-7) = readCGRAM<0>(io.cgramAddress); + latch.ppu2.mdr = readCGRAM<0>(io.cgramAddress); } else { - bits(latch.ppu2.mdr,0-6) = readCGRAM<1>(io.cgramAddress++); + latch.ppu2.mdr = readCGRAM<1>(io.cgramAddress++) & 0x7f | latch.ppu2.mdr & 0x80; } return latch.ppu2.mdr; } @@ -152,10 +152,10 @@ auto PPUfast::readIO(uint address, uint8 data) -> uint8 { case 0x213c: { //OPHCT if(latch.hcounter == 0) { latch.hcounter = 1; - bits(latch.ppu2.mdr,0-7) = bits(io.hcounter,0-7); + latch.ppu2.mdr = io.hcounter; } else { latch.hcounter = 0; - bit1(latch.ppu2.mdr,0) = bit1(io.hcounter,8); + latch.ppu2.mdr = io.hcounter >> 8 | latch.ppu2.mdr & 0xfe; } return latch.ppu2.mdr; } @@ -163,34 +163,30 @@ auto PPUfast::readIO(uint address, uint8 data) -> uint8 { case 0x213d: { //OPVCT if(latch.vcounter == 0) { latch.vcounter = 1; - bits(latch.ppu2.mdr,0-7) = bits(io.vcounter,0-7); + latch.ppu2.mdr = io.vcounter; } else { latch.vcounter = 0; - bit1(latch.ppu2.mdr,0) = bit1(io.vcounter,8); + latch.ppu2.mdr = io.vcounter >> 8 | latch.ppu2.mdr & 0xfe; } return latch.ppu2.mdr; } case 0x213e: { //STAT77 - bits(latch.ppu1.mdr,0-3) = 1; //PPU1 version - bit1(latch.ppu1.mdr,5) = 0; - bit1(latch.ppu1.mdr,6) = io.obj.rangeOver; - bit1(latch.ppu1.mdr,7) = io.obj.timeOver; + latch.ppu1.mdr = 0x01 | io.obj.rangeOver << 6 | io.obj.timeOver << 7; return latch.ppu1.mdr; } case 0x213f: { //STAT78 latch.hcounter = 0; latch.vcounter = 0; - bits(latch.ppu2.mdr,0-3) = 3; //PPU2 version - bit1(latch.ppu2.mdr,4) = Region::PAL(); //0 = NTSC, 1 = PAL - if(!cbit1(cpu.pio(),7)) { - bit1(latch.ppu2.mdr,6) = 1; + latch.ppu2.mdr &= 1 << 5; + latch.ppu2.mdr |= 0x03 | Region::PAL() << 4 | field() << 7; + if(!(cpu.pio() & 0x80)) { + latch.ppu2.mdr |= 1 << 6; } else { - bit1(latch.ppu2.mdr,6) = latch.counters; + latch.ppu2.mdr |= latch.counters << 6; latch.counters = 0; } - bit1(latch.ppu2.mdr,7) = field(); return latch.ppu2.mdr; } @@ -199,22 +195,22 @@ auto PPUfast::readIO(uint address, uint8 data) -> uint8 { return data; } -auto PPUfast::writeIO(uint address, uint8 data) -> void { - cpu.synchronize(ppufast); +auto PPU::writeIO(uint address, uint8 data) -> void { + cpu.synchronize(ppu); switch(address & 0xffff) { case 0x2100: { //INIDISP if(io.displayDisable && cpu.vcounter() == vdisp()) oamAddressReset(); - io.displayBrightness = bits(data,0-3); - io.displayDisable = bit1(data,7); + io.displayBrightness = data >> 0 & 15; + io.displayDisable = data >> 7 & 1; return; } case 0x2101: { //OBSEL - io.obj.tiledataAddress = bits(data,0-2) << 13; - io.obj.nameselect = bits(data,3-4); - io.obj.baseSize = bits(data,5-7); + io.obj.tiledataAddress = (data & 7) << 13; + io.obj.nameselect = data >> 3 & 3; + io.obj.baseSize = data >> 5 & 7; return; } @@ -225,17 +221,17 @@ auto PPUfast::writeIO(uint address, uint8 data) -> void { } case 0x2103: { //OAMADDH - io.oamBaseAddress = bit1(data,0) << 9 | (io.oamBaseAddress & 0x01fe); - io.oamPriority = bit1(data,7); + io.oamBaseAddress = (data & 1) << 9 | io.oamBaseAddress & 0x01fe; + io.oamPriority = data >> 7 & 1; oamAddressReset(); return; } case 0x2104: { //OAMDATA - uint1 latchBit = io.oamAddress & 1; - uint10 address = io.oamAddress++; + bool latchBit = io.oamAddress & 1; + uint address = io.oamAddress++; if(latchBit == 0) latch.oam = data; - if(bit1(address,9)) { + if(address & 0x200) { writeOAM(address, data); } else if(latchBit == 1) { writeOAM((address & ~1) + 0, latch.oam); @@ -246,58 +242,58 @@ auto PPUfast::writeIO(uint address, uint8 data) -> void { } case 0x2105: { //BGMODE - io.bgMode = bits(data,0-2); - io.bgPriority = bit1(data,3); - io.bg1.tileSize = bit1(data,4); - io.bg2.tileSize = bit1(data,5); - io.bg3.tileSize = bit1(data,6); - io.bg4.tileSize = bit1(data,7); + io.bgMode = data >> 0 & 7; + io.bgPriority = data >> 3 & 1; + io.bg1.tileSize = data >> 4 & 1; + io.bg2.tileSize = data >> 5 & 1; + io.bg3.tileSize = data >> 6 & 1; + io.bg4.tileSize = data >> 7 & 1; updateVideoMode(); return; } case 0x2106: { //MOSAIC - io.bg1.mosaicEnable = bit1(data,0); - io.bg2.mosaicEnable = bit1(data,1); - io.bg3.mosaicEnable = bit1(data,2); - io.bg4.mosaicEnable = bit1(data,3); - io.mosaicSize = bits(data,4-7); + io.bg1.mosaicEnable = data >> 0 & 1; + io.bg2.mosaicEnable = data >> 1 & 1; + io.bg3.mosaicEnable = data >> 2 & 1; + io.bg4.mosaicEnable = data >> 3 & 1; + io.mosaicSize = data >> 4 & 15; return; } case 0x2107: { //BG1SC - io.bg1.screenSize = bits(data,0-1); - io.bg1.screenAddress = bits(data,2-7) << 10; + io.bg1.screenSize = data >> 0 & 3; + io.bg1.screenAddress = data >> 2 << 10; return; } case 0x2108: { //BG2SC - io.bg2.screenSize = bits(data,0-1); - io.bg2.screenAddress = bits(data,2-7) << 10; + io.bg2.screenSize = data >> 0 & 3; + io.bg2.screenAddress = data >> 2 << 10; return; } case 0x2109: { //BG3SC - io.bg3.screenSize = bits(data,0-1); - io.bg3.screenAddress = bits(data,2-7) << 10; + io.bg3.screenSize = data >> 0 & 3; + io.bg3.screenAddress = data >> 2 << 10; return; } case 0x210a: { //BG4SC - io.bg4.screenSize = bits(data,0-1); - io.bg4.screenAddress = bits(data,2-7) << 10; + io.bg4.screenSize = data >> 0 & 3; + io.bg4.screenAddress = data >> 2 << 10; return; } case 0x210b: { //BG12NBA - io.bg1.tiledataAddress = bits(data,0-3) << 12; - io.bg2.tiledataAddress = bits(data,4-7) << 12; + io.bg1.tiledataAddress = (data & 15) << 12; + io.bg2.tiledataAddress = (data >> 4) << 12; return; } case 0x210c: { //BG34NBA - io.bg3.tiledataAddress = bits(data,0-3) << 12; - io.bg4.tiledataAddress = bits(data,4-7) << 12; + io.bg3.tiledataAddress = (data & 15) << 12; + io.bg4.tiledataAddress = (data >> 4) << 12; return; } @@ -362,8 +358,8 @@ auto PPUfast::writeIO(uint address, uint8 data) -> void { case 0x2115: { //VMAIN static const uint size[4] = {1, 32, 128, 128}; io.vramIncrementSize = size[data & 3]; - io.vramMapping = bits(data,2-3); - io.vramIncrementMode = bit1(data,7); + io.vramMapping = data >> 2 & 3; + io.vramIncrementMode = data >> 7 & 1; return; } @@ -392,9 +388,9 @@ auto PPUfast::writeIO(uint address, uint8 data) -> void { } case 0x211a: { //M7SEL - io.mode7.hflip = bit1(data,0); - io.mode7.vflip = bit1(data,1); - io.mode7.repeat = bits(data,6-7); + io.mode7.hflip = data >> 0 & 1; + io.mode7.vflip = data >> 1 & 1; + io.mode7.repeat = data >> 6 & 3; return; } @@ -444,44 +440,44 @@ auto PPUfast::writeIO(uint address, uint8 data) -> void { if(io.cgramAddressLatch++ == 0) { latch.cgram = data; } else { - writeCGRAM(io.cgramAddress++, bits(data,0-6) << 8 | latch.cgram); + writeCGRAM(io.cgramAddress++, (data & 0x7f) << 8 | latch.cgram); } return; } case 0x2123: { //W12SEL - io.bg1.window.oneInvert = bit1(data,0); - io.bg1.window.oneEnable = bit1(data,1); - io.bg1.window.twoInvert = bit1(data,2); - io.bg1.window.twoEnable = bit1(data,3); - io.bg2.window.oneInvert = bit1(data,4); - io.bg2.window.oneEnable = bit1(data,5); - io.bg2.window.twoInvert = bit1(data,6); - io.bg2.window.twoEnable = bit1(data,7); + io.bg1.window.oneInvert = data >> 0 & 1; + io.bg1.window.oneEnable = data >> 1 & 1; + io.bg1.window.twoInvert = data >> 2 & 1; + io.bg1.window.twoEnable = data >> 3 & 1; + io.bg2.window.oneInvert = data >> 4 & 1; + io.bg2.window.oneEnable = data >> 5 & 1; + io.bg2.window.twoInvert = data >> 6 & 1; + io.bg2.window.twoEnable = data >> 7 & 1; return; } case 0x2124: { //W34SEL - io.bg3.window.oneInvert = bit1(data,0); - io.bg3.window.oneEnable = bit1(data,1); - io.bg3.window.twoInvert = bit1(data,2); - io.bg3.window.twoEnable = bit1(data,3); - io.bg4.window.oneInvert = bit1(data,4); - io.bg4.window.oneEnable = bit1(data,5); - io.bg4.window.twoInvert = bit1(data,6); - io.bg4.window.twoEnable = bit1(data,7); + io.bg3.window.oneInvert = data >> 0 & 1; + io.bg3.window.oneEnable = data >> 1 & 1; + io.bg3.window.twoInvert = data >> 2 & 1; + io.bg3.window.twoEnable = data >> 3 & 1; + io.bg4.window.oneInvert = data >> 4 & 1; + io.bg4.window.oneEnable = data >> 5 & 1; + io.bg4.window.twoInvert = data >> 6 & 1; + io.bg4.window.twoEnable = data >> 7 & 1; return; } case 0x2125: { //WOBJSEL - io.obj.window.oneInvert = bit1(data,0); - io.obj.window.oneEnable = bit1(data,1); - io.obj.window.twoInvert = bit1(data,2); - io.obj.window.twoEnable = bit1(data,3); - io.col.window.oneInvert = bit1(data,4); - io.col.window.oneEnable = bit1(data,5); - io.col.window.twoInvert = bit1(data,6); - io.col.window.twoEnable = bit1(data,7); + io.obj.window.oneInvert = data >> 0 & 1; + io.obj.window.oneEnable = data >> 1 & 1; + io.obj.window.twoInvert = data >> 2 & 1; + io.obj.window.twoEnable = data >> 3 & 1; + io.col.window.oneInvert = data >> 4 & 1; + io.col.window.oneEnable = data >> 5 & 1; + io.col.window.twoInvert = data >> 6 & 1; + io.col.window.twoEnable = data >> 7 & 1; return; } @@ -506,89 +502,89 @@ auto PPUfast::writeIO(uint address, uint8 data) -> void { } case 0x212a: { //WBGLOG - io.bg1.window.mask = bits(data,0-1); - io.bg2.window.mask = bits(data,2-3); - io.bg3.window.mask = bits(data,4-5); - io.bg4.window.mask = bits(data,6-7); + io.bg1.window.mask = data >> 0 & 3; + io.bg2.window.mask = data >> 2 & 3; + io.bg3.window.mask = data >> 4 & 3; + io.bg4.window.mask = data >> 6 & 3; return; } case 0x212b: { //WOBJLOG - io.obj.window.mask = bits(data,0-1); - io.col.window.mask = bits(data,2-3); + io.obj.window.mask = data >> 0 & 3; + io.col.window.mask = data >> 2 & 3; return; } case 0x212c: { //TM - io.bg1.aboveEnable = bit1(data,0); - io.bg2.aboveEnable = bit1(data,1); - io.bg3.aboveEnable = bit1(data,2); - io.bg4.aboveEnable = bit1(data,3); - io.obj.aboveEnable = bit1(data,4); + io.bg1.aboveEnable = data >> 0 & 1; + io.bg2.aboveEnable = data >> 1 & 1; + io.bg3.aboveEnable = data >> 2 & 1; + io.bg4.aboveEnable = data >> 3 & 1; + io.obj.aboveEnable = data >> 4 & 1; return; } case 0x212d: { //TS - io.bg1.belowEnable = bit1(data,0); - io.bg2.belowEnable = bit1(data,1); - io.bg3.belowEnable = bit1(data,2); - io.bg4.belowEnable = bit1(data,3); - io.obj.belowEnable = bit1(data,4); + io.bg1.belowEnable = data >> 0 & 1; + io.bg2.belowEnable = data >> 1 & 1; + io.bg3.belowEnable = data >> 2 & 1; + io.bg4.belowEnable = data >> 3 & 1; + io.obj.belowEnable = data >> 4 & 1; return; } case 0x212e: { //TMW - io.bg1.window.aboveEnable = bit1(data,0); - io.bg2.window.aboveEnable = bit1(data,1); - io.bg3.window.aboveEnable = bit1(data,2); - io.bg4.window.aboveEnable = bit1(data,3); - io.obj.window.aboveEnable = bit1(data,4); + io.bg1.window.aboveEnable = data >> 0 & 1; + io.bg2.window.aboveEnable = data >> 1 & 1; + io.bg3.window.aboveEnable = data >> 2 & 1; + io.bg4.window.aboveEnable = data >> 3 & 1; + io.obj.window.aboveEnable = data >> 4 & 1; return; } case 0x212f: { //TSW - io.bg1.window.belowEnable = bit1(data,0); - io.bg2.window.belowEnable = bit1(data,1); - io.bg3.window.belowEnable = bit1(data,2); - io.bg4.window.belowEnable = bit1(data,3); - io.obj.window.belowEnable = bit1(data,4); + io.bg1.window.belowEnable = data >> 0 & 1; + io.bg2.window.belowEnable = data >> 1 & 1; + io.bg3.window.belowEnable = data >> 2 & 1; + io.bg4.window.belowEnable = data >> 3 & 1; + io.obj.window.belowEnable = data >> 4 & 1; return; } case 0x2130: { //CGWSEL - io.col.directColor = bit1(data,0); - io.col.blendMode = bit1(data,1); - io.col.window.belowMask = bits(data,4-5); - io.col.window.aboveMask = bits(data,6-7); + io.col.directColor = data >> 0 & 1; + io.col.blendMode = data >> 1 & 1; + io.col.window.belowMask = data >> 4 & 3; + io.col.window.aboveMask = data >> 6 & 3; return; } case 0x2131: { //CGADDSUB - io.col.enable[Source::BG1 ] = bit1(data,0); - io.col.enable[Source::BG2 ] = bit1(data,1); - io.col.enable[Source::BG3 ] = bit1(data,2); - io.col.enable[Source::BG4 ] = bit1(data,3); + io.col.enable[Source::BG1 ] = data >> 0 & 1; + io.col.enable[Source::BG2 ] = data >> 1 & 1; + io.col.enable[Source::BG3 ] = data >> 2 & 1; + io.col.enable[Source::BG4 ] = data >> 3 & 1; io.col.enable[Source::OBJ1] = 0; - io.col.enable[Source::OBJ2] = bit1(data,4); - io.col.enable[Source::COL ] = bit1(data,5); - io.col.halve = bit1(data,6); - io.col.mathMode = bit1(data,7); + io.col.enable[Source::OBJ2] = data >> 4 & 1; + io.col.enable[Source::COL ] = data >> 5 & 1; + io.col.halve = data >> 6 & 1; + io.col.mathMode = data >> 7 & 1; return; } case 0x2132: { //COLDATA - if(bit1(data,5)) bits(io.col.fixedColor, 0- 4) = data & 31; - if(bit1(data,6)) bits(io.col.fixedColor, 5- 9) = data & 31; - if(bit1(data,7)) bits(io.col.fixedColor,10-14) = data & 31; + if(data & 0x20) io.col.fixedColor = io.col.fixedColor & 0b11111'11111'00000 | (data & 31) << 0; + if(data & 0x40) io.col.fixedColor = io.col.fixedColor & 0b11111'00000'11111 | (data & 31) << 5; + if(data & 0x80) io.col.fixedColor = io.col.fixedColor & 0b00000'11111'11111 | (data & 31) << 10; return; } case 0x2133: { //SETINI - io.interlace = bit1(data,0); - io.obj.interlace = bit1(data,1); - io.overscan = bit1(data,2); - io.pseudoHires = bit1(data,3); - io.extbg = bit1(data,6); + io.interlace = data >> 0 & 1; + io.obj.interlace = data >> 1 & 1; + io.overscan = data >> 2 & 1; + io.pseudoHires = data >> 3 & 1; + io.extbg = data >> 6 & 1; updateVideoMode(); return; } @@ -596,7 +592,7 @@ auto PPUfast::writeIO(uint address, uint8 data) -> void { } } -auto PPUfast::updateVideoMode() -> void { +auto PPU::updateVideoMode() -> void { ppubase.display.vdisp = !io.overscan ? 225 : 240; switch(io.bgMode) { diff --git a/bsnes/sfc/ppu-fast/line.cpp b/bsnes/sfc/ppu-fast/line.cpp index 887d03fd..ecd80746 100644 --- a/bsnes/sfc/ppu-fast/line.cpp +++ b/bsnes/sfc/ppu-fast/line.cpp @@ -1,29 +1,29 @@ -uint PPUfast::Line::start = 0; -uint PPUfast::Line::count = 0; +uint PPU::Line::start = 0; +uint PPU::Line::count = 0; -auto PPUfast::Line::flush() -> void { +auto PPU::Line::flush() -> void { if(Line::count) { #pragma omp parallel for if(Line::count >= 8) for(uint y = 0; y < Line::count; y++) { - ppufast.lines[Line::start + y].render(); + ppu.lines[Line::start + y].render(); } Line::start = 0; Line::count = 0; } } -auto PPUfast::Line::render() -> void { - uint y = this->y + (!ppufast.latch.overscan ? 7 : 0); +auto PPU::Line::render() -> void { + uint y = this->y + (!ppu.latch.overscan ? 7 : 0); - auto hd = ppufast.hd(); - auto ss = ppufast.ss(); - auto scale = ppufast.hdScale(); - auto output = ppufast.output + (!hd - ? (y * 1024 + (ppufast.interlace() && ppufast.field() ? 512 : 0)) + auto hd = ppu.hd(); + auto ss = ppu.ss(); + auto scale = ppu.hdScale(); + auto output = ppu.output + (!hd + ? (y * 1024 + (ppu.interlace() && ppu.field() ? 512 : 0)) : (y * 256 * scale * scale) ); auto width = (!hd - ? (!ppufast.hires() ? 256 : 512) + ? (!ppu.hires() ? 256 : 512) : (256 * scale * scale)); if(io.displayDisable) { @@ -33,9 +33,9 @@ auto PPUfast::Line::render() -> void { bool hires = io.pseudoHires || io.bgMode == 5 || io.bgMode == 6; auto aboveColor = cgram[0]; - auto belowColor = hires ? cgram[0] : (uint16)io.col.fixedColor; - uint xa = (hd || ss) && ppufast.interlace() && ppufast.field() ? 256 * scale * scale / 2 : 0; - uint xb = !(hd || ss) ? 256 : ppufast.interlace() && !ppufast.field() ? 256 * scale * scale / 2 : 256 * scale * scale; + auto belowColor = hires ? cgram[0] : (uint16_t)io.col.fixedColor; + uint xa = (hd || ss) && ppu.interlace() && ppu.field() ? 256 * scale * scale / 2 : 0; + uint xb = !(hd || ss) ? 256 : ppu.interlace() && !ppu.field() ? 256 * scale * scale / 2 : 256 * scale * scale; for(uint x = xa; x < xb; x++) { above[x] = {Source::COL, 0, aboveColor}; below[x] = {Source::COL, 0, belowColor}; @@ -49,7 +49,7 @@ auto PPUfast::Line::render() -> void { renderWindow(io.col.window, io.col.window.aboveMask, windowAbove); renderWindow(io.col.window, io.col.window.belowMask, windowBelow); - auto luma = ppufast.lightTable[io.displayBrightness]; + auto luma = ppu.lightTable[io.displayBrightness]; uint curr = 0, prev = 0; if(hd) for(uint x : range(256 * scale * scale)) { *output++ = luma[pixel(x / scale & 255, above[x], below[x])]; @@ -72,7 +72,7 @@ auto PPUfast::Line::render() -> void { } } -auto PPUfast::Line::pixel(uint x, Pixel above, Pixel below) const -> uint16 { +auto PPU::Line::pixel(uint x, Pixel above, Pixel below) const -> uint16_t { if(!windowAbove[x]) above.color = 0x0000; if(!windowBelow[x]) return above.color; if(!io.col.enable[above.source]) return above.color; @@ -80,7 +80,7 @@ auto PPUfast::Line::pixel(uint x, Pixel above, Pixel below) const -> uint16 { return blend(above.color, below.color, io.col.halve && windowAbove[x] && below.source != Source::COL); } -auto PPUfast::Line::blend(uint x, uint y, bool halve) const -> uint16 { +auto PPU::Line::blend(uint x, uint y, bool halve) const -> uint16_t { if(!io.col.mathMode) { //add if(!halve) { uint sum = x + y; @@ -100,7 +100,7 @@ auto PPUfast::Line::blend(uint x, uint y, bool halve) const -> uint16 { } } -auto PPUfast::Line::directColor(uint paletteIndex, uint paletteColor) const -> uint16 { +auto PPU::Line::directColor(uint paletteIndex, uint paletteColor) const -> uint16_t { //paletteIndex = bgr //paletteColor = BBGGGRRR //output = 0 BBb00 GGGg0 RRRr0 @@ -109,25 +109,25 @@ auto PPUfast::Line::directColor(uint paletteIndex, uint paletteColor) const -> u + (paletteColor << 7 & 0x6000) + (paletteIndex << 10 & 0x1000); //B } -auto PPUfast::Line::plotAbove(uint x, uint source, uint priority, uint color) -> void { - if(ppufast.hd()) return plotHD(above, x, source, priority, color, false, false); +auto PPU::Line::plotAbove(uint x, uint source, uint priority, uint color) -> void { + if(ppu.hd()) return plotHD(above, x, source, priority, color, false, false); if(priority > above[x].priority) above[x] = {source, priority, color}; } -auto PPUfast::Line::plotBelow(uint x, uint source, uint priority, uint color) -> void { - if(ppufast.hd()) return plotHD(below, x, source, priority, color, false, false); +auto PPU::Line::plotBelow(uint x, uint source, uint priority, uint color) -> void { + if(ppu.hd()) return plotHD(below, x, source, priority, color, false, false); if(priority > below[x].priority) below[x] = {source, priority, color}; } //todo: name these variables more clearly ... -auto PPUfast::Line::plotHD(Pixel* pixel, uint x, uint source, uint priority, uint color, bool hires, bool subpixel) -> void { - auto scale = ppufast.hdScale(); +auto PPU::Line::plotHD(Pixel* pixel, uint x, uint source, uint priority, uint color, bool hires, bool subpixel) -> void { + auto scale = ppu.hdScale(); int xss = hires && subpixel ? scale / 2 : 0; - int ys = ppufast.interlace() && ppufast.field() ? scale / 2 : 0; + int ys = ppu.interlace() && ppu.field() ? scale / 2 : 0; if(priority > pixel[x * scale + xss + ys * 256 * scale].priority) { Pixel p = {source, priority, color}; int xsm = hires && !subpixel ? scale / 2 : scale; - int ysm = ppufast.interlace() && !ppufast.field() ? scale / 2 : scale; + int ysm = ppu.interlace() && !ppu.field() ? scale / 2 : scale; for(int xs = xss; xs < xsm; xs++) { pixel[x * scale + xs + ys * 256 * scale] = p; } diff --git a/bsnes/sfc/ppu-fast/mode7.cpp b/bsnes/sfc/ppu-fast/mode7.cpp index 2471537d..eb73a980 100644 --- a/bsnes/sfc/ppu-fast/mode7.cpp +++ b/bsnes/sfc/ppu-fast/mode7.cpp @@ -1,11 +1,11 @@ -auto PPUfast::Line::renderMode7(PPUfast::IO::Background& self, uint source) -> void { +auto PPU::Line::renderMode7(PPU::IO::Background& self, uint source) -> void { //EXTBG is only really used by games to give the mode 7 layer two priority levels //especially with HD mode 7, it's just wasteful to render BG1 just to be overwritten by BG2 if(io.extbg && source == Source::BG1) return; //HD mode 7 support - if(!ppufast.hdMosaic() || !self.mosaicEnable || !io.mosaicSize) { - if(ppufast.hdScale() > 1) return renderMode7HD(self, source); + if(!ppu.hdMosaic() || !self.mosaicEnable || !io.mosaicSize) { + if(ppu.hdScale() > 1) return renderMode7HD(self, source); } int Y = this->y - (self.mosaicEnable ? this->y % (1 + io.mosaicSize) : 0); @@ -29,8 +29,8 @@ auto PPUfast::Line::renderMode7(PPUfast::IO::Background& self, uint source) -> v int originX = (a * clip(hoffset - hcenter) & ~63) + (b * clip(voffset - vcenter) & ~63) + (b * y & ~63) + (hcenter << 8); int originY = (c * clip(hoffset - hcenter) & ~63) + (d * clip(voffset - vcenter) & ~63) + (d * y & ~63) + (vcenter << 8); - array windowAbove; - array windowBelow; + bool windowAbove[256]; + bool windowBelow[256]; renderWindow(self.window, self.window.aboveEnable, windowAbove); renderWindow(self.window, self.window.belowEnable, windowBelow); @@ -43,8 +43,8 @@ auto PPUfast::Line::renderMode7(PPUfast::IO::Background& self, uint source) -> v bool outOfBounds = (pixelX | pixelY) & ~1023; uint15 tileAddress = tileY * 128 + tileX; uint15 paletteAddress = ((pixelY & 7) << 3) + (pixelX & 7); - uint8 tile = io.mode7.repeat == 3 && outOfBounds ? 0 : (ppufast.vram[tileAddress] & 0xff); - uint8 palette = io.mode7.repeat == 2 && outOfBounds ? 0 : (ppufast.vram[paletteAddress + (tile << 6)] >> 8); + uint8_t tile = io.mode7.repeat == 3 && outOfBounds ? 0 : ppu.vram[tileAddress] >> 0; + uint8_t palette = io.mode7.repeat == 2 && outOfBounds ? 0 : ppu.vram[paletteAddress + (tile << 6)] >> 8; uint priority; if(source == Source::BG1) { diff --git a/bsnes/sfc/ppu-fast/mode7hd.cpp b/bsnes/sfc/ppu-fast/mode7hd.cpp index 93d0adbf..0a721720 100644 --- a/bsnes/sfc/ppu-fast/mode7hd.cpp +++ b/bsnes/sfc/ppu-fast/mode7hd.cpp @@ -1,6 +1,6 @@ -auto PPUfast::Line::renderMode7HD(PPUfast::IO::Background& self, uint source) -> void { +auto PPU::Line::renderMode7HD(PPU::IO::Background& self, uint source) -> void { const bool extbg = source == Source::BG2; - const uint scale = ppufast.hdScale(); + const uint scale = ppu.hdScale(); Pixel pixel; Pixel* above = &this->above[-1]; @@ -9,10 +9,10 @@ auto PPUfast::Line::renderMode7HD(PPUfast::IO::Background& self, uint source) -> //find the first and last scanline for interpolation int y_a = y; int y_b = y; - #define isLineMode7(n) (ppufast.lines[n].io.bg1.tileMode == TileMode::Mode7 && ( \ - (ppufast.lines[n].io.bg1.aboveEnable || ppufast.lines[n].io.bg1.belowEnable) \ + #define isLineMode7(n) (ppu.lines[n].io.bg1.tileMode == TileMode::Mode7 && ( \ + (ppu.lines[n].io.bg1.aboveEnable || ppu.lines[n].io.bg1.belowEnable) \ )) - if(ppufast.hdPerspective()) { + if(ppu.hdPerspective()) { while(y_a > 1 && isLineMode7(y_a)) y_a--; y_a += 1; while(y_b < 239 && isLineMode7(y_b)) y_b++; y_b -= 8; } else { @@ -21,13 +21,13 @@ auto PPUfast::Line::renderMode7HD(PPUfast::IO::Background& self, uint source) -> } #undef isLineMode7 - Line line_a = ppufast.lines[y_a]; + Line line_a = ppu.lines[y_a]; float a_a = (int16)line_a.io.mode7.a; float b_a = (int16)line_a.io.mode7.b; float c_a = (int16)line_a.io.mode7.c; float d_a = (int16)line_a.io.mode7.d; - Line line_b = ppufast.lines[y_b]; + Line line_b = ppu.lines[y_b]; float a_b = (int16)line_b.io.mode7.a; float b_b = (int16)line_b.io.mode7.b; float c_b = (int16)line_b.io.mode7.c; @@ -43,8 +43,8 @@ auto PPUfast::Line::renderMode7HD(PPUfast::IO::Background& self, uint source) -> y_b = 255 - y_b; } - array windowAbove; - array windowBelow; + bool windowAbove[256]; + bool windowBelow[256]; renderWindow(self.window, self.window.aboveEnable, windowAbove); renderWindow(self.window, self.window.belowEnable, windowBelow); @@ -80,8 +80,8 @@ auto PPUfast::Line::renderMode7HD(PPUfast::IO::Background& self, uint source) -> //only compute color again when coordinates have changed if(pixelX != pixelXp || pixelY != pixelYp) { - uint tile = io.mode7.repeat == 3 && ((pixelX | pixelY) & ~1023) ? 0 : (ppufast.vram[(pixelY >> 3 & 127) * 128 + (pixelX >> 3 & 127)] & 0xff); - uint palette = io.mode7.repeat == 2 && ((pixelX | pixelY) & ~1023) ? 0 : (ppufast.vram[(((pixelY & 7) << 3) + (pixelX & 7)) + (tile << 6)] >> 8); + uint tile = io.mode7.repeat == 3 && ((pixelX | pixelY) & ~1023) ? 0 : (ppu.vram[(pixelY >> 3 & 127) * 128 + (pixelX >> 3 & 127)] & 0xff); + uint palette = io.mode7.repeat == 2 && ((pixelX | pixelY) & ~1023) ? 0 : (ppu.vram[(((pixelY & 7) << 3) + (pixelX & 7)) + (tile << 6)] >> 8); uint priority; if(!extbg) { @@ -110,7 +110,7 @@ auto PPUfast::Line::renderMode7HD(PPUfast::IO::Background& self, uint source) -> } } - if(ppufast.ss()) { + if(ppu.ss()) { uint divisor = scale * scale; for(uint p : range(256)) { uint ab = 0, bb = 0; @@ -139,7 +139,7 @@ auto PPUfast::Line::renderMode7HD(PPUfast::IO::Background& self, uint source) -> } //interpolation and extrapolation -auto PPUfast::Line::lerp(float pa, float va, float pb, float vb, float pr) -> float { +auto PPU::Line::lerp(float pa, float va, float pb, float vb, float pr) -> float { if(va == vb || pr == pa) return va; if(pr == pb) return vb; return va + (vb - va) / (pb - pa) * (pr - pa); diff --git a/bsnes/sfc/ppu-fast/object.cpp b/bsnes/sfc/ppu-fast/object.cpp index d4b96f11..d20d5d73 100644 --- a/bsnes/sfc/ppu-fast/object.cpp +++ b/bsnes/sfc/ppu-fast/object.cpp @@ -1,19 +1,19 @@ -auto PPUfast::Line::renderObject(PPUfast::IO::Object& self) -> void { +auto PPU::Line::renderObject(PPU::IO::Object& self) -> void { if(!self.aboveEnable && !self.belowEnable) return; - array windowAbove; - array windowBelow; + bool windowAbove[256]; + bool windowBelow[256]; renderWindow(self.window, self.window.aboveEnable, windowAbove); renderWindow(self.window, self.window.belowEnable, windowBelow); uint itemCount = 0; uint tileCount = 0; - for(auto n : range(ppufast.ItemLimit)) items[n].valid = false; - for(auto n : range(ppufast.TileLimit)) tiles[n].valid = false; + for(auto n : range(ppu.ItemLimit)) items[n].valid = false; + for(auto n : range(ppu.TileLimit)) tiles[n].valid = false; for(auto n : range(128)) { ObjectItem item{true, self.first + n}; - const auto& object = ppufast.objects[item.index]; + const auto& object = ppu.objects[item.index]; if(object.size == 0) { static const uint widths[] = { 8, 8, 8, 16, 16, 32, 16, 16}; @@ -33,16 +33,16 @@ auto PPUfast::Line::renderObject(PPUfast::IO::Object& self) -> void { if((y >= object.y && y < object.y + height) || (object.y + height >= 256 && y < (object.y + height & 255)) ) { - if(itemCount++ >= ppufast.ItemLimit) break; + if(itemCount++ >= ppu.ItemLimit) break; items[itemCount - 1] = item; } } - for(int n : reverse(range(ppufast.ItemLimit))) { + for(int n : reverse(range(ppu.ItemLimit))) { const auto& item = items[n]; if(!item.valid) continue; - const auto& object = ppufast.objects[item.index]; + const auto& object = ppu.objects[item.index]; uint tileWidth = item.width >> 3; int x = object.x; int y = this->y - object.y & 0xff; @@ -59,7 +59,7 @@ auto PPUfast::Line::renderObject(PPUfast::IO::Object& self) -> void { } if(self.interlace) { - y = !object.vflip ? y + ppufast.field() : y - ppufast.field(); + y = !object.vflip ? y + ppu.field() : y - ppu.field(); } x &= 511; @@ -85,22 +85,22 @@ auto PPUfast::Line::renderObject(PPUfast::IO::Object& self) -> void { uint address = tiledataAddress + ((characterY + (characterX + mirrorX & 15)) << 4); tile.number = address >> 4; - if(tileCount++ >= ppufast.TileLimit) break; + if(tileCount++ >= ppu.TileLimit) break; tiles[tileCount - 1] = tile; } } - ppufast.io.obj.rangeOver |= itemCount > ppufast.ItemLimit; - ppufast.io.obj.timeOver |= tileCount > ppufast.TileLimit; + ppu.io.obj.rangeOver |= itemCount > ppu.ItemLimit; + ppu.io.obj.timeOver |= tileCount > ppu.TileLimit; - uint8 palette[256] = {}; - uint8 priority[256] = {}; + uint8_t palette[256] = {}; + uint8_t priority[256] = {}; - for(uint n : range(ppufast.TileLimit)) { + for(uint n : range(ppu.TileLimit)) { const auto& tile = tiles[n]; if(!tile.valid) continue; - auto tiledata = ppufast.tilecache[TileMode::BPP4] + (tile.number << 6) + ((tile.y & 7) << 3); + auto tiledata = ppu.tilecache[TileMode::BPP4] + (tile.number << 6) + ((tile.y & 7) << 3); uint tileX = tile.x; uint mirrorX = tile.hflip ? 7 : 0; for(uint x : range(8)) { @@ -123,16 +123,16 @@ auto PPUfast::Line::renderObject(PPUfast::IO::Object& self) -> void { } } -auto PPUfast::oamAddressReset() -> void { +auto PPU::oamAddressReset() -> void { io.oamAddress = io.oamBaseAddress; oamSetFirstObject(); } -auto PPUfast::oamSetFirstObject() -> void { - io.obj.first = !io.oamPriority ? 0 : uint(io.oamAddress >> 2); +auto PPU::oamSetFirstObject() -> void { + io.obj.first = !io.oamPriority ? 0 : io.oamAddress >> 2; } -auto PPUfast::readObject(uint10 address) -> uint8 { +auto PPU::readObject(uint10 address) -> uint8 { if(!(address & 0x200)) { uint n = address >> 2; //object# address &= 3; @@ -161,7 +161,7 @@ auto PPUfast::readObject(uint10 address) -> uint8 { } } -auto PPUfast::writeObject(uint10 address, uint8 data) -> void { +auto PPU::writeObject(uint10 address, uint8 data) -> void { if(!(address & 0x200)) { uint n = address >> 2; //object# address &= 3; diff --git a/bsnes/sfc/ppu-fast/ppu.cpp b/bsnes/sfc/ppu-fast/ppu.cpp index 9af24a48..e4707c73 100644 --- a/bsnes/sfc/ppu-fast/ppu.cpp +++ b/bsnes/sfc/ppu-fast/ppu.cpp @@ -4,7 +4,10 @@ namespace SuperFamicom { PPU& ppubase = ppu; -PPUfast ppufast; +#define PPU PPUfast +#define ppu ppufast + +PPU ppu; #include "io.cpp" #include "line.cpp" #include "background.cpp" @@ -14,18 +17,20 @@ PPUfast ppufast; #include "window.cpp" #include "serialization.cpp" -auto PPUfast::interlace() const -> bool { return ppubase.display.interlace; } -auto PPUfast::overscan() const -> bool { return ppubase.display.overscan; } -auto PPUfast::vdisp() const -> uint { return ppubase.display.vdisp; } -auto PPUfast::hires() const -> bool { return latch.hires; } -auto PPUfast::hd() const -> bool { return latch.hd; } -auto PPUfast::ss() const -> bool { return latch.ss; } -auto PPUfast::hdScale() const -> uint { return configuration.hacks.ppu.mode7.scale; } -auto PPUfast::hdPerspective() const -> bool { return configuration.hacks.ppu.mode7.perspective; } -auto PPUfast::hdSupersample() const -> bool { return configuration.hacks.ppu.mode7.supersample; } -auto PPUfast::hdMosaic() const -> bool { return configuration.hacks.ppu.mode7.mosaic; } +auto PPU::interlace() const -> bool { return ppubase.display.interlace; } +auto PPU::overscan() const -> bool { return ppubase.display.overscan; } +auto PPU::vdisp() const -> uint { return ppubase.display.vdisp; } +auto PPU::hires() const -> bool { return latch.hires; } +auto PPU::hd() const -> bool { return latch.hd; } +auto PPU::ss() const -> bool { return latch.ss; } +#undef ppu +auto PPU::hdScale() const -> uint { return configuration.hacks.ppu.mode7.scale; } +auto PPU::hdPerspective() const -> bool { return configuration.hacks.ppu.mode7.perspective; } +auto PPU::hdSupersample() const -> bool { return configuration.hacks.ppu.mode7.supersample; } +auto PPU::hdMosaic() const -> bool { return configuration.hacks.ppu.mode7.mosaic; } +#define ppu ppufast -PPUfast::PPUfast() { +PPU::PPU() { for(uint l : range(16)) { for(uint r : range(32)) { for(uint g : range(32)) { @@ -34,38 +39,38 @@ PPUfast::PPUfast() { uint ar = (luma * r + 0.5); uint ag = (luma * g + 0.5); uint ab = (luma * b + 0.5); - lightTable[l][(r << 10) + (g << 5) + b] = (ab << 10) + (ag << 5) + ar; + lightTable[l][r << 10 | g << 5 | b << 0] = ab << 10 | ag << 5 | ar << 0; } } } } - tilecache[TileMode::BPP2] = new uint8[4096 * 8 * 8]; - tilecache[TileMode::BPP4] = new uint8[2048 * 8 * 8]; - tilecache[TileMode::BPP8] = new uint8[1024 * 8 * 8]; + tilecache[TileMode::BPP2] = new uint8_t[4096 * 8 * 8]; + tilecache[TileMode::BPP4] = new uint8_t[2048 * 8 * 8]; + tilecache[TileMode::BPP8] = new uint8_t[1024 * 8 * 8]; - for(uint y : range(lines.size())) { + for(uint y : range(240)) { lines[y].y = y; } } -PPUfast::~PPUfast() { +PPU::~PPU() { delete[] tilecache[TileMode::BPP2]; delete[] tilecache[TileMode::BPP4]; delete[] tilecache[TileMode::BPP8]; } -auto PPUfast::Enter() -> void { - while(true) scheduler.synchronize(), ppufast.main(); +auto PPU::Enter() -> void { + while(true) scheduler.synchronize(), ppu.main(); } -auto PPUfast::step(uint clocks) -> void { +auto PPU::step(uint clocks) -> void { tick(clocks); Thread::step(clocks); synchronize(cpu); } -auto PPUfast::main() -> void { +auto PPU::main() -> void { scanline(); if(system.frameCounter == 0) { @@ -86,7 +91,7 @@ auto PPUfast::main() -> void { step(lineclocks() - hcounter()); } -auto PPUfast::scanline() -> void { +auto PPU::scanline() -> void { if(vcounter() == 0) { ppubase.display.interlace = io.interlace; ppubase.display.overscan = io.overscan; @@ -114,7 +119,7 @@ auto PPUfast::scanline() -> void { } } -auto PPUfast::refresh() -> void { +auto PPU::refresh() -> void { if(system.frameCounter == 0) { auto output = this->output; uint pitch, width, height; @@ -148,17 +153,17 @@ auto PPUfast::refresh() -> void { if(system.frameCounter++ >= system.frameSkip) system.frameCounter = 0; } -auto PPUfast::load() -> bool { +auto PPU::load() -> bool { return true; } -auto PPUfast::power(bool reset) -> void { - create(Enter, system.cpuFrequency()); +auto PPU::power(bool reset) -> void { + Thread::create(Enter, system.cpuFrequency()); PPUcounter::reset(); memory::fill(output, 1024 * 960); - function uint8> reader{&PPUfast::readIO, this}; - function void> writer{&PPUfast::writeIO, this}; + function reader{&PPU::readIO, this}; + function writer{&PPU::writeIO, this}; bus.map(reader, writer, "00-3f,80-bf:2100-213f"); if(!reset) { @@ -174,6 +179,7 @@ auto PPUfast::power(bool reset) -> void { io = {}; updateVideoMode(); + #undef ppu ItemLimit = !configuration.hacks.ppu.noSpriteLimit ? 32 : 128; TileLimit = !configuration.hacks.ppu.noSpriteLimit ? 34 : 128; diff --git a/bsnes/sfc/ppu-fast/ppu.hpp b/bsnes/sfc/ppu-fast/ppu.hpp index e8809a04..9fcff3fd 100644 --- a/bsnes/sfc/ppu-fast/ppu.hpp +++ b/bsnes/sfc/ppu-fast/ppu.hpp @@ -5,7 +5,9 @@ //* vertical mosaic coordinates are not exact //* (hardware-mod) 128KB VRAM mode not supported -struct PPUfast : Thread, PPUcounter { +#define PPU PPUfast + +struct PPU : Thread, PPUcounter { alwaysinline auto interlace() const -> bool; alwaysinline auto overscan() const -> bool; alwaysinline auto vdisp() const -> uint; @@ -18,8 +20,8 @@ struct PPUfast : Thread, PPUcounter { alwaysinline auto hdMosaic() const -> bool; //ppu.cpp - PPUfast(); - ~PPUfast(); + PPU(); + ~PPU(); static auto Enter() -> void; alwaysinline auto step(uint clocks) -> void; @@ -47,24 +49,24 @@ public: bool hd = 0; bool ss = 0; - uint16 vram = 0; - uint8 oam = 0; - uint8 cgram = 0; + uint16_t vram = 0; + uint8_t oam = 0; + uint8_t cgram = 0; uint10 oamAddress = 0; - uint8 cgramAddress = 0; + uint8_t cgramAddress = 0; - uint8 mode7 = 0; + uint8_t mode7 = 0; bool counters = 0; bool hcounter = 0; //hdot bool vcounter = 0; - struct PPU { + struct PPUstate { //serialization.cpp auto serialize(serializer&) -> void; - uint8 mdr = 0; - uint8 bgofs = 0; + uint8_t mdr = 0; + uint8_t bgofs = 0; } ppu1, ppu2; }; @@ -114,10 +116,10 @@ public: //serialization.cpp auto serialize(serializer&) -> void; - uint8 oneLeft = 0; - uint8 oneRight = 0; - uint8 twoLeft = 0; - uint8 twoRight = 0; + uint8_t oneLeft = 0; + uint8_t oneRight = 0; + uint8_t twoLeft = 0; + uint8_t twoRight = 0; } window; struct WindowLayer { @@ -200,8 +202,8 @@ public: auto serialize(serializer&) -> void; uint9 x = 0; - uint8 y = 0; - uint8 character = 0; + uint8_t y = 0; + uint8_t character = 0; bool nameselect = 0; bool vflip = 0; bool hflip = 0; @@ -213,16 +215,16 @@ public: struct ObjectItem { bool valid = 0; uint7 index = 0; - uint8 width = 0; - uint8 height = 0; + uint8_t width = 0; + uint8_t height = 0; }; struct ObjectTile { bool valid = 0; uint9 x = 0; - uint8 y = 0; + uint8_t y = 0; uint2 priority = 0; - uint8 palette = 0; + uint8_t palette = 0; bool hflip = 0; uint11 number = 0; }; @@ -235,14 +237,14 @@ public: //io.cpp auto latchCounters() -> void; - alwaysinline auto vramAddress() const -> uint15; + alwaysinline auto vramAddress() const -> uint; alwaysinline auto readVRAM() -> uint16; - template alwaysinline auto writeVRAM(uint8 data) -> void; + template alwaysinline auto writeVRAM(uint8_t data) -> void; alwaysinline auto updateTiledata(uint address) -> void; alwaysinline auto readOAM(uint10 address) -> uint8; - alwaysinline auto writeOAM(uint10 address, uint8 data) -> void; - template alwaysinline auto readCGRAM(uint8 address) -> uint8; - alwaysinline auto writeCGRAM(uint8 address, uint15 data) -> void; + alwaysinline auto writeOAM(uint10 address, uint8_t data) -> void; + template alwaysinline auto readCGRAM(uint8_t address) -> uint8; + alwaysinline auto writeCGRAM(uint8_t address, uint15 data) -> void; auto readIO(uint address, uint8 data) -> uint8; auto writeIO(uint address, uint8 data) -> void; auto updateVideoMode() -> void; @@ -257,14 +259,14 @@ public: Latch latch; IO io; - uint16 vram[32 * 1024] = {}; - uint16 cgram[256] = {}; + uint16_t vram[32 * 1024] = {}; + uint16_t cgram[256] = {}; Object objects[128] = {}; //[unserialized] - uint16 output[2304 * 2160] = {}; - uint16 lightTable[16][32768] = {}; - uint8* tilecache[3] = {}; //bitplane -> bitmap tiledata + uint16_t output[2304 * 2160] = {}; + uint16_t lightTable[16][32768] = {}; + uint8_t* tilecache[3] = {}; //bitplane -> bitmap tiledata uint ItemLimit = 0; uint TileLimit = 0; @@ -272,51 +274,51 @@ public: //line.cpp static auto flush() -> void; auto render() -> void; - auto pixel(uint x, Pixel above, Pixel below) const -> uint16; - auto blend(uint x, uint y, bool halve) const -> uint16; - alwaysinline auto directColor(uint paletteIndex, uint paletteColor) const -> uint16; + auto pixel(uint x, Pixel above, Pixel below) const -> uint16_t; + auto blend(uint x, uint y, bool halve) const -> uint16_t; + alwaysinline auto directColor(uint paletteIndex, uint paletteColor) const -> uint16_t; alwaysinline auto plotAbove(uint x, uint source, uint priority, uint color) -> void; alwaysinline auto plotBelow(uint x, uint source, uint priority, uint color) -> void; alwaysinline auto plotHD(Pixel*, uint x, uint source, uint priority, uint color, bool hires, bool subpixel) -> void; //background.cpp - auto renderBackground(PPUfast::IO::Background&, uint source) -> void; - auto getTile(PPUfast::IO::Background&, uint hoffset, uint voffset) -> uint; + auto renderBackground(PPU::IO::Background&, uint source) -> void; + auto getTile(PPU::IO::Background&, uint hoffset, uint voffset) -> uint; //mode7.cpp - auto renderMode7(PPUfast::IO::Background&, uint source) -> void; + auto renderMode7(PPU::IO::Background&, uint source) -> void; //mode7hd.cpp - auto renderMode7HD(PPUfast::IO::Background&, uint source) -> void; + auto renderMode7HD(PPU::IO::Background&, uint source) -> void; alwaysinline auto lerp(float pa, float va, float pb, float vb, float pr) -> float; //object.cpp - auto renderObject(PPUfast::IO::Object&) -> void; + auto renderObject(PPU::IO::Object&) -> void; //window.cpp - auto renderWindow(PPUfast::IO::WindowLayer&, bool, array&) -> void; - auto renderWindow(PPUfast::IO::WindowColor&, uint, array&) -> void; + auto renderWindow(PPU::IO::WindowLayer&, bool enable, bool output[256]) -> void; + auto renderWindow(PPU::IO::WindowColor&, uint mask, bool output[256]) -> void; //[unserialized] uint9 y; //constant IO io; - array cgram; + uint16_t cgram[256]; - array items; //32 on real hardware - array tiles; //34 on real hardware; 1024 max (128 * 64-width tiles) + ObjectItem items[128]; //32 on real hardware + ObjectTile tiles[128]; //34 on real hardware; 1024 max (128 * 64-width tiles) Pixel above[256 * 9 * 9]; Pixel below[256 * 9 * 9]; - array windowAbove; - array windowBelow; + bool windowAbove[256]; + bool windowBelow[256]; //flush() static uint start; static uint count; }; - array lines; + Line lines[240]; //used to help detect when the video output size changes between frames to clear overscan area. struct Frame { @@ -326,4 +328,6 @@ public: } frame; }; -extern PPUfast ppufast; +extern PPU ppufast; + +#undef PPU diff --git a/bsnes/sfc/ppu-fast/serialization.cpp b/bsnes/sfc/ppu-fast/serialization.cpp index e578dda8..69500e87 100644 --- a/bsnes/sfc/ppu-fast/serialization.cpp +++ b/bsnes/sfc/ppu-fast/serialization.cpp @@ -1,4 +1,4 @@ -auto PPUfast::serialize(serializer& s) -> void { +auto PPU::serialize(serializer& s) -> void { Thread::serialize(s); PPUcounter::serialize(s); @@ -13,7 +13,7 @@ auto PPUfast::serialize(serializer& s) -> void { Line::count = 0; } -auto PPUfast::Latch::serialize(serializer& s) -> void { +auto PPU::Latch::serialize(serializer& s) -> void { s.integer(interlace); s.integer(overscan); s.integer(hires); @@ -32,12 +32,12 @@ auto PPUfast::Latch::serialize(serializer& s) -> void { ppu2.serialize(s); } -auto PPUfast::Latch::PPU::serialize(serializer& s) -> void { +auto PPU::Latch::PPUstate::serialize(serializer& s) -> void { s.integer(mdr); s.integer(bgofs); } -auto PPUfast::IO::serialize(serializer& s) -> void { +auto PPU::IO::serialize(serializer& s) -> void { s.integer(displayDisable); s.integer(displayBrightness); s.integer(oamBaseAddress); @@ -69,7 +69,7 @@ auto PPUfast::IO::serialize(serializer& s) -> void { col.serialize(s); } -auto PPUfast::IO::Mode7::serialize(serializer& s) -> void { +auto PPU::IO::Mode7::serialize(serializer& s) -> void { s.integer(hflip); s.integer(vflip); s.integer(repeat); @@ -83,14 +83,14 @@ auto PPUfast::IO::Mode7::serialize(serializer& s) -> void { s.integer(voffset); } -auto PPUfast::IO::Window::serialize(serializer& s) -> void { +auto PPU::IO::Window::serialize(serializer& s) -> void { s.integer(oneLeft); s.integer(oneRight); s.integer(twoLeft); s.integer(twoRight); } -auto PPUfast::IO::WindowLayer::serialize(serializer& s) -> void { +auto PPU::IO::WindowLayer::serialize(serializer& s) -> void { s.integer(oneEnable); s.integer(oneInvert); s.integer(twoEnable); @@ -100,7 +100,7 @@ auto PPUfast::IO::WindowLayer::serialize(serializer& s) -> void { s.integer(belowEnable); } -auto PPUfast::IO::WindowColor::serialize(serializer& s) -> void { +auto PPU::IO::WindowColor::serialize(serializer& s) -> void { s.integer(oneEnable); s.integer(oneInvert); s.integer(twoEnable); @@ -110,7 +110,7 @@ auto PPUfast::IO::WindowColor::serialize(serializer& s) -> void { s.integer(belowMask); } -auto PPUfast::IO::Background::serialize(serializer& s) -> void { +auto PPU::IO::Background::serialize(serializer& s) -> void { window.serialize(s); s.integer(aboveEnable); s.integer(belowEnable); @@ -125,7 +125,7 @@ auto PPUfast::IO::Background::serialize(serializer& s) -> void { s.array(priority); } -auto PPUfast::IO::Object::serialize(serializer& s) -> void { +auto PPU::IO::Object::serialize(serializer& s) -> void { window.serialize(s); s.integer(aboveEnable); s.integer(belowEnable); @@ -139,7 +139,7 @@ auto PPUfast::IO::Object::serialize(serializer& s) -> void { s.array(priority); } -auto PPUfast::IO::Color::serialize(serializer& s) -> void { +auto PPU::IO::Color::serialize(serializer& s) -> void { window.serialize(s); s.array(enable); s.integer(directColor); @@ -149,7 +149,7 @@ auto PPUfast::IO::Color::serialize(serializer& s) -> void { s.integer(fixedColor); } -auto PPUfast::Object::serialize(serializer& s) -> void { +auto PPU::Object::serialize(serializer& s) -> void { s.integer(x); s.integer(y); s.integer(character); diff --git a/bsnes/sfc/ppu-fast/window.cpp b/bsnes/sfc/ppu-fast/window.cpp index d6200776..1794b999 100644 --- a/bsnes/sfc/ppu-fast/window.cpp +++ b/bsnes/sfc/ppu-fast/window.cpp @@ -1,6 +1,6 @@ -auto PPUfast::Line::renderWindow(PPUfast::IO::WindowLayer& self, bool enable, array& output) -> void { +auto PPU::Line::renderWindow(PPU::IO::WindowLayer& self, bool enable, bool output[256]) -> void { if(!enable || (!self.oneEnable && !self.twoEnable)) { - output.fill(0); + memory::fill(output, 256, 0); return; } @@ -32,17 +32,17 @@ auto PPUfast::Line::renderWindow(PPUfast::IO::WindowLayer& self, bool enable, ar } } -auto PPUfast::Line::renderWindow(PPUfast::IO::WindowColor& self, uint mask, array& output) -> void { +auto PPU::Line::renderWindow(PPU::IO::WindowColor& self, uint mask, bool output[256]) -> void { bool set, clear; switch(mask) { - case 0: output.fill(1); return; //always + case 0: memory::fill(output, 256, 1); return; //always case 1: set = 1, clear = 0; break; //inside case 2: set = 0, clear = 1; break; //outside - case 3: output.fill(0); return; //never + case 3: memory::fill(output, 256, 0); return; //never } if(!self.oneEnable && !self.twoEnable) { - output.fill(clear); + memory::fill(output, 256, clear); return; } diff --git a/bsnes/sfc/ppu/object.cpp b/bsnes/sfc/ppu/object.cpp index 5405d820..5e3d495c 100644 --- a/bsnes/sfc/ppu/object.cpp +++ b/bsnes/sfc/ppu/object.cpp @@ -26,7 +26,7 @@ auto PPU::Object::scanline() -> void { auto oamTile = t.tile[t.active]; if(t.y == ppu.vdisp() && !ppu.io.displayDisable) addressReset(); - if(t.y >= ppu.vdisp() - 1) return; + if(t.y >= ppu.vdisp() - 1 || ppu.io.displayDisable) return; for(auto n : range(32)) oamItem[n].valid = false; for(auto n : range(34)) oamTile[n].valid = false; diff --git a/bsnes/sfc/ppu/ppu.cpp b/bsnes/sfc/ppu/ppu.cpp index f35d6a87..ee1dfcf4 100644 --- a/bsnes/sfc/ppu/ppu.cpp +++ b/bsnes/sfc/ppu/ppu.cpp @@ -62,7 +62,7 @@ auto PPU::main() -> void { bg3.begin(); bg4.begin(); - if(vcounter() <= 239) { + if(vcounter() < vdisp()) { for(int pixel = -7; pixel <= 255; pixel++) { bg1.run(1); bg2.run(1); @@ -210,16 +210,17 @@ auto PPU::power(bool reset) -> void { screen.power(); updateVideoMode(); - frame(); } auto PPU::scanline() -> void { if(vcounter() == 0) { - frame(); + display.interlace = io.interlace; + display.overscan = io.overscan; bg1.frame(); bg2.frame(); bg3.frame(); bg4.frame(); + obj.frame(); } bg1.scanline(); @@ -235,12 +236,6 @@ auto PPU::scanline() -> void { } } -auto PPU::frame() -> void { - obj.frame(); - display.interlace = io.interlace; - display.overscan = io.overscan; -} - auto PPU::refresh() -> void { if(system.fastPPU()) { return ppufast.refresh(); diff --git a/bsnes/sfc/ppu/ppu.hpp b/bsnes/sfc/ppu/ppu.hpp index 24a99306..5246d3e9 100644 --- a/bsnes/sfc/ppu/ppu.hpp +++ b/bsnes/sfc/ppu/ppu.hpp @@ -50,7 +50,6 @@ private: } display; auto scanline() -> void; - auto frame() -> void; auto refresh() -> void; struct { diff --git a/ruby/video/cgl.cpp b/ruby/video/cgl.cpp index 11a68a67..5407a46d 100755 --- a/ruby/video/cgl.cpp +++ b/ruby/video/cgl.cpp @@ -162,7 +162,7 @@ private: } -(void) reshape { - video->output(); + video->output(0, 0); } @end