From 7fd2bf4de451dcc5a0323b3bedc25d739a372ad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Fri, 5 Feb 2021 19:28:47 +0100 Subject: [PATCH] almost finished adding ppu's registers --- sources/Debugger/RegisterViewer.cpp | 239 +++++++++++++++++++++++++++- sources/Debugger/RegisterViewer.hpp | 4 +- sources/PPU/PPU.cpp | 8 +- sources/PPU/PPU.hpp | 13 +- tests/PPU/testPpuWriteFromVmain.cpp | 12 +- 5 files changed, 254 insertions(+), 22 deletions(-) diff --git a/sources/Debugger/RegisterViewer.cpp b/sources/Debugger/RegisterViewer.cpp index b11cdff..a58c5cd 100644 --- a/sources/Debugger/RegisterViewer.cpp +++ b/sources/Debugger/RegisterViewer.cpp @@ -5,6 +5,7 @@ #include "RegisterViewer.hpp" #include "../SNES.hpp" #include "../Utility/Utility.hpp" +#include namespace ComSquare::Debugger { @@ -143,11 +144,241 @@ namespace ComSquare::Debugger model->addRegister(Register(0x2106, ":4-7", "Size", [ppuRegisters](SNES &) { return ppuRegisters._mosaic.pixelSize; }, nullptr, Integer)); + /* model->addRegister(Register(0x2106, ":4-7", "Value", [](SNES &) { + return "A lot"; + }, nullptr, String)); */ - // BG1SC 0x2107 - model->addRegister(Register(0x2107, "", "BG1SC", [ppuRegisters](SNES &) { - return ppuRegisters._bgsc[0].raw; + // BGNSC 0x2107 รจ 0x210A + for (int i = 0; i < 4; i++) { + model->addRegister(Register(0x2107 + i, "", "BG" + std::to_string(i + 1) + "SC", [ppuRegisters, i](SNES &) { + return ppuRegisters._bgsc[i].raw; + }, nullptr, EightBits)); + model->addRegister(Register(0x2107 + i, ":0", "BG" + std::to_string(i + 1) + " Tilemap H mirroring", [ppuRegisters, i](SNES &) { + return ppuRegisters._bgsc[i].tilemapHorizontalMirroring; + }, nullptr, Boolean)); + model->addRegister(Register(0x2107 + i, ":1", "BG" + std::to_string(i + 1) + " Tilemap V mirroring", [ppuRegisters, i](SNES &) { + return ppuRegisters._bgsc[i].tilemapVerticalMirroring; + }, nullptr, Boolean)); + model->addRegister(Register(0x2107 + i, ":2-7", "BG" + std::to_string(i + 1) + " Tilemap addr", [ppuRegisters, i](SNES &) { + return ppuRegisters._bgsc[i].tilemapAddress; + }, nullptr, EightBits)); + } + + // BGnxNBA 0x210B 0x210C + for (int i = 0; i < 2; i++) { + model->addRegister(Register(0x210B + i, "", "BG" + std::string(i ? "34" : "12") + "NBA", [ppuRegisters, i](SNES &) { + return ppuRegisters._bgnba[i].raw; + }, nullptr, EightBits)); + model->addRegister(Register(0x210B + i, ":0-3", "BG" + std::string((i ? "3" : "1")) + " Base addr", [ppuRegisters, i](SNES &) { + return ppuRegisters._bgnba[i].baseAddressBg1a3; + }, nullptr, EightBits)); + model->addRegister(Register(0x210B + i, ":4-7", "BG" + std::string((i ? "4" : "2")) + " Base addr", [ppuRegisters, i](SNES &) { + return ppuRegisters._bgnba[i].baseAddressBg2a4; + }, nullptr, EightBits)); + } + + // BGnxOFS M7nOFS 0x210D - 0x2114 + for (int i = 0; i < 4; i++) { + int tmp = i * 2; + model->addRegister(Register(0x210D + tmp, "", "BG" + std::to_string(i + 1) + "HOFS", [ppuRegisters, tmp](SNES &) { + return ppuRegisters._bgofs[tmp].offsetBg; + }, nullptr, SixteenBits)); + tmp++; + model->addRegister(Register(0x210D + tmp, "", "BG" + std::to_string(i + 1) + "VOFS", [ppuRegisters, tmp](SNES &) { + return ppuRegisters._bgofs[tmp].offsetBg; + }, nullptr, SixteenBits)); + } + + // VMAIN 0x2115 + model->addRegister(Register(0x2115, "", "VMAIN", [ppuRegisters](SNES &) { + return ppuRegisters._vmain.raw; }, nullptr, EightBits)); + model->addRegister(Register(0x2115, ":0-1", "Increment amount", [ppuRegisters](SNES &) { + return ppuRegisters._vmain.incrementAmount; + }, nullptr, Integer)); + model->addRegister(Register(0x2115, ":3-4", "Addr remapping", [ppuRegisters](SNES &) { + return ppuRegisters._vmain.addressRemapping; + }, nullptr, Integer)); + model->addRegister(Register(0x2115, ":7", "Increment on high byte", [ppuRegisters](SNES &) { + return ppuRegisters._vmain.incrementMode; + }, nullptr, Boolean)); + + // VMADDL VMADDH 0x2116 0x2117 + model->addRegister(Register(0x2116, "/7", "VMADD", [ppuRegisters](SNES &) { + return ppuRegisters._vmadd.vmadd; + }, nullptr, SixteenBits)); + + // VMDATAL VMDATAH 0x2118 0x2119 + model->addRegister(Register(0x2118, "/9", "VMDATA", [ppuRegisters](SNES &) { + return ppuRegisters._vmdata.vmdata; + }, nullptr, SixteenBits)); + + // M7SEL 0x211a + model->addRegister(Register(0x211a, "", "M7SEL", [ppuRegisters](SNES &) { + return ppuRegisters._m7sel.raw; + }, nullptr, EightBits)); + model->addRegister(Register(0x211a, ":0", "M7 H mirroring", [ppuRegisters](SNES &) { + return ppuRegisters._m7sel.horizontalMirroring; + }, nullptr, Boolean)); + model->addRegister(Register(0x211a, ":1", "M7 V mirroring", [ppuRegisters](SNES &) { + return ppuRegisters._m7sel.verticalMirroring; + }, nullptr, Boolean)); + model->addRegister(Register(0x211a, ":6", "Empty space fill", [ppuRegisters](SNES &) { + return ppuRegisters._m7sel.emptySpaceFill; + }, nullptr, Boolean)); + model->addRegister(Register(0x211a, ":7", "Large Tilemap", [ppuRegisters](SNES &) { + return ppuRegisters._m7sel.playingFieldSize; + }, nullptr, Boolean)); + + // M7x 0x211B - 0x211E + for (int i = 0; i < 4; i++) { + std::stringstream tmpStr; + tmpStr << "M7" << static_cast(i + 'A'); + model->addRegister(Register(0x211B + i, "", tmpStr.str(), [ppuRegisters, i](SNES &) { + return ppuRegisters._m7[i].m7; + }, nullptr, SixteenBits)); + } + + // M7X 0x211F + model->addRegister(Register(0x211F, "","M7X", [ppuRegisters](SNES &) { + return ppuRegisters._m7x.value; + }, nullptr, SixteenBits)); + + // M7Y 0x2120 + model->addRegister(Register(0x2120, "","M7Y", [ppuRegisters](SNES &) { + return ppuRegisters._m7y.value; + }, nullptr, SixteenBits)); + + // CGADD 0x2121 + model->addRegister(Register(0x2121, "","CGADD", [ppuRegisters](SNES &) { + return ppuRegisters._cgadd; + }, nullptr, EightBits)); + + // CGDATA 0x2122 + model->addRegister(Register(0x2122, "","CGDATA", [ppuRegisters](SNES &) { + return ppuRegisters._cgdata.raw; + }, nullptr, SixteenBits)); + + // W12SEL W34SEL WOBJSEL 0x2123 - 0X2125 + + for (int i = 0; i < 3; i++) { + std::array arr; + switch (i) { + case 0: + arr[0] = "W12SEL"; + arr[1] = "BG1"; + arr[2] = "BG2"; + break; + case 1: + arr[0] = "W34SEL"; + arr[1] = "BG3"; + arr[2] = "BG4"; + break; + case 2: + default: + arr[0] = "WOBJSEL"; + arr[1] = "OAM"; + arr[2] = "Color"; + break; + } + model->addRegister(Register(0x2123 + i, "",arr[0], [ppuRegisters, i](SNES &) { + return ppuRegisters._wsel[i].raw; + }, nullptr, EightBits)); + model->addRegister(Register(0x2123 + i, ":0",arr[1] + " Window 1 inverted", [ppuRegisters, i](SNES &) { + return ppuRegisters._wsel[i].window1InversionForBg1Bg3Obj; + }, nullptr, Boolean)); + model->addRegister(Register(0x2123 + i, ":1",arr[1] + " Window 1 enabled", [ppuRegisters, i](SNES &) { + return ppuRegisters._wsel[i].enableWindow1ForBg1Bg3Obj; + }, nullptr, Boolean)); + model->addRegister(Register(0x2123 + i, ":2",arr[1] + " Window 2 inverted", [ppuRegisters, i](SNES &) { + return ppuRegisters._wsel[i].window2InversionForBg1Bg3Obj; + }, nullptr, Boolean)); + model->addRegister(Register(0x2123 + i, ":3",arr[1] + " Window 2 enabled", [ppuRegisters, i](SNES &) { + return ppuRegisters._wsel[i].enableWindow2ForBg1Bg3Obj; + }, nullptr, Boolean)); + + model->addRegister(Register(0x2123 + i, ":4",arr[2] + " Window 1 inverted", [ppuRegisters, i](SNES &) { + return ppuRegisters._wsel[i].window1InversionForBg2Bg4Color; + }, nullptr, Boolean)); + model->addRegister(Register(0x2123 + i, ":5",arr[2] + " Window 1 enabled", [ppuRegisters, i](SNES &) { + return ppuRegisters._wsel[i].enableWindow1ForBg2Bg4Color; + }, nullptr, Boolean)); + model->addRegister(Register(0x2123 + i, ":6",arr[2] + " Window 2 inverted", [ppuRegisters, i](SNES &) { + return ppuRegisters._wsel[i].window2InversionForBg2Bg4Color; + }, nullptr, Boolean)); + model->addRegister(Register(0x2123 + i, ":7",arr[2] + " Window 2 enabled", [ppuRegisters, i](SNES &) { + return ppuRegisters._wsel[i].enableWindow1ForBg2Bg4Color; + }, nullptr, Boolean)); + } + + // WHx 0x2126 - 0x2129 + for (int tmp = 0; tmp < 2; tmp++) { + int i = tmp * 2; + model->addRegister(Register(0x2126 + i, "", "Window " + std::to_string(tmp + 1) + " Left", [ppuRegisters, i](SNES &) { + return ppuRegisters._wh[i]; + }, nullptr, EightBits)); + model->addRegister(Register(0x2126 + i + 1, "", "Window " + std::to_string(tmp + 1) + " Right", [ppuRegisters, i](SNES &) { + return ppuRegisters._wh[i + 1]; + }, nullptr, EightBits)); + } + + // WBGLOG 0x212A + model->addRegister(Register(0x212A, "", "WBGLOG", [ppuRegisters](SNES &) { + return ppuRegisters._wbglog.raw; + }, nullptr, EightBits)); + model->addRegister(Register(0x212B, "", "WOBJLOG", [ppuRegisters](SNES &) { + return ppuRegisters._wobjlog.raw; + }, nullptr, EightBits)); + model->addRegister(Register(0x212A, ":0-1", "BG1 Window mask", [ppuRegisters](SNES &) { + return ppuRegisters._wbglog.maskLogicBg1; + }, nullptr, Integer)); + model->addRegister(Register(0x212A, ":2-3", "BG2 Window mask", [ppuRegisters](SNES &) { + return ppuRegisters._wbglog.maskLogicBg2; + }, nullptr, Integer)); + model->addRegister(Register(0x212A, ":4-5", "BG3 Window mask", [ppuRegisters](SNES &) { + return ppuRegisters._wbglog.maskLogicBg3; + }, nullptr, Integer)); + model->addRegister(Register(0x212A, ":6-7", "BG4 Window mask", [ppuRegisters](SNES &) { + return ppuRegisters._wbglog.maskLogicBg4; + }, nullptr, Integer)); + model->addRegister(Register(0x212B, ":0-1", "OBJ Window mask", [ppuRegisters](SNES &) { + return ppuRegisters._wobjlog.maskLogicObj; + }, nullptr, Integer)); + model->addRegister(Register(0x212B, ":2-3", "Color Window mask", [ppuRegisters](SNES &) { + return ppuRegisters._wobjlog.maskLogicColor; + }, nullptr, Integer)); + + // TM TS 0x212c 0x212d + for (int j = 0; j < 2; j++) { + model->addRegister(Register(0x212C + j, "", std::string((j ? "TS" : "TM")), [ppuRegisters, j](SNES &) { + return ppuRegisters._t[j].raw; + }, nullptr, EightBits)); + for (int i = 0; i < 4; i ++) { + model->addRegister(Register(0x212C + j, ":" + std::to_string(i), "BG" + std::to_string(i + 1) + " Enabled", + [ppuRegisters, i, j](SNES &) { + return (ppuRegisters._t[j].raw >> i) & 1; + }, nullptr, Boolean)); + } + model->addRegister(Register(0x212C + j, ":4", "OBJ Enabled", [ppuRegisters, j](SNES &) { + return ppuRegisters._t[j].enableWindowDisplayObj; + }, nullptr, Boolean)); + } + + // TMW TSW 0x212e 0x212f + for (int j = 0; j < 2; j++) { + model->addRegister(Register(0x212e + j, "", std::string((j ? "TSW" : "TMW")), [ppuRegisters, j](SNES &) { + return ppuRegisters._tw[j].raw; + }, nullptr, EightBits)); + for (int i = 0; i < 4; i ++) { + model->addRegister(Register(0x212e + j, ":" + std::to_string(i), "BG" + std::to_string(i + 1) + " Window Mask Enabled", + [ppuRegisters, i, j](SNES &) { + return (ppuRegisters._tw[j].raw >> i) & 1; + }, nullptr, Boolean)); + } + model->addRegister(Register(0x212e + j, ":4", "OBJ Window Mask Enabled", [ppuRegisters, j](SNES &) { + return ppuRegisters._tw[j].enableWindowMaskingObj; + }, nullptr, Boolean)); + } this->_ui.ppuRegisters->setModel(model); } @@ -226,6 +457,8 @@ QVariant RegistersViewerModel::data(const QModelIndex &index, int role) const switch (reg.type) { case Boolean: return QString(reg.get(this->_snes) ? "True" : "False"); + case String: + return QString(reg.get(this->_snes)); case Integer: return QString::number(reg.get(this->_snes)); case EightBits: diff --git a/sources/Debugger/RegisterViewer.hpp b/sources/Debugger/RegisterViewer.hpp index ee206e4..c519f36 100644 --- a/sources/Debugger/RegisterViewer.hpp +++ b/sources/Debugger/RegisterViewer.hpp @@ -89,7 +89,9 @@ namespace ComSquare //! @brief A 24 bits hexadecimal value. TwentyFourBits, //! @brief Just like printf(%d, myVar); - Integer + Integer, + //! @brief a simple string + String }; //! @brief Struct containing information about a register. diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 00dc8d5..2d87009 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -395,16 +395,16 @@ namespace ComSquare::PPU this->_registers._wsel[addr - PpuRegisters::w12sel].raw = data; break; case PpuRegisters::wh0: - this->_registers._wh0 = data; + this->_registers._wh[0] = data; break; case PpuRegisters::wh1: - this->_registers._wh1 = data; + this->_registers._wh[1] = data; break; case PpuRegisters::wh2: - this->_registers._wh2 = data; + this->_registers._wh[2] = data; break; case PpuRegisters::wh3: - this->_registers._wh3 = data; + this->_registers._wh[3] = data; break; case PpuRegisters::wbjlog: this->_registers._wbglog.raw = data; diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index a743258..258fff5 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -342,7 +342,7 @@ namespace ComSquare::PPU uint16_t _: 3; uint16_t value: 13; }; - uint16_t center = 0; + uint16_t raw = 0; } _m7x; //! @brief M7Y Register (Mode 7 Center Y) union { // Not sure if it is done correctly @@ -350,7 +350,7 @@ namespace ComSquare::PPU uint16_t _: 3; uint16_t value: 13; }; - uint16_t center = 0; + uint16_t raw = 0; } _m7y; //! @brief CGADD Register (CGRAM Address) uint8_t _cgadd = 0; @@ -380,19 +380,16 @@ namespace ComSquare::PPU uint8_t window1InversionForBg2Bg4Color: 1; uint8_t enableWindow2ForBg1Bg3Obj: 1; uint8_t window2InversionForBg1Bg3Obj: 1; - uint8_t enableWindow1ForBg1Bg2Obj: 1; - uint8_t window1InversionForBg1Bg2Obj: 1; + uint8_t enableWindow1ForBg1Bg3Obj: 1; + uint8_t window1InversionForBg1Bg3Obj: 1; }; uint8_t raw = 0; } _wsel[3]; //! @brief WH0 Register (Window 1 Left Position) - uint8_t _wh0 = 0; //! @brief WH1 Register (Window 1 Right Position) - uint8_t _wh1 = 0; //! @brief WH2 Register (Window 2 Left Position) - uint8_t _wh2 = 0; //! @brief WH3 Register (Window 2 Right Position) - uint8_t _wh3 = 0; + uint8_t _wh[4] = {0}; //! @brief WBGLOG Register (Window mask logic for BGs) union { struct { diff --git a/tests/PPU/testPpuWriteFromVmain.cpp b/tests/PPU/testPpuWriteFromVmain.cpp index 5d7ec3a..92fe56a 100644 --- a/tests/PPU/testPpuWriteFromVmain.cpp +++ b/tests/PPU/testPpuWriteFromVmain.cpp @@ -138,8 +138,8 @@ Test(PPU_write_2, w12sel_data_full) { Init() snes.bus->write(0x2123, 0b11111111); - cr_assert_eq(snes.ppu->_registers._wsel[0].window1InversionForBg1Bg2Obj, true); - cr_assert_eq(snes.ppu->_registers._wsel[0].enableWindow1ForBg1Bg2Obj, true); + cr_assert_eq(snes.ppu->_registers._wsel[0].window1InversionForBg1Bg3Obj, true); + cr_assert_eq(snes.ppu->_registers._wsel[0].enableWindow1ForBg1Bg3Obj, true); cr_assert_eq(snes.ppu->_registers._wsel[0].window2InversionForBg1Bg3Obj, true); cr_assert_eq(snes.ppu->_registers._wsel[0].enableWindow2ForBg1Bg3Obj, true); cr_assert_eq(snes.ppu->_registers._wsel[0].window1InversionForBg2Bg4Color, true); @@ -152,8 +152,8 @@ Test(PPU_write_2, w34sel_data_full) { Init() snes.bus->write(0x2124, 0b10101010); - cr_assert_eq(snes.ppu->_registers._wsel[1].window1InversionForBg1Bg2Obj, true); - cr_assert_eq(snes.ppu->_registers._wsel[1].enableWindow1ForBg1Bg2Obj, false); + cr_assert_eq(snes.ppu->_registers._wsel[1].window1InversionForBg1Bg3Obj, true); + cr_assert_eq(snes.ppu->_registers._wsel[1].enableWindow1ForBg1Bg3Obj, false); cr_assert_eq(snes.ppu->_registers._wsel[1].window2InversionForBg1Bg3Obj, true); cr_assert_eq(snes.ppu->_registers._wsel[1].enableWindow2ForBg1Bg3Obj, false); cr_assert_eq(snes.ppu->_registers._wsel[1].window1InversionForBg2Bg4Color, true); @@ -166,8 +166,8 @@ Test(PPU_write_2, wobjsel_data_full) { Init() snes.bus->write(0x2125, 0b10110001); - cr_assert_eq(snes.ppu->_registers._wsel[2].window1InversionForBg1Bg2Obj, true); - cr_assert_eq(snes.ppu->_registers._wsel[2].enableWindow1ForBg1Bg2Obj, false); + cr_assert_eq(snes.ppu->_registers._wsel[2].window1InversionForBg1Bg3Obj, true); + cr_assert_eq(snes.ppu->_registers._wsel[2].enableWindow1ForBg1Bg3Obj, false); cr_assert_eq(snes.ppu->_registers._wsel[2].window2InversionForBg1Bg3Obj, true); cr_assert_eq(snes.ppu->_registers._wsel[2].enableWindow2ForBg1Bg3Obj, true); cr_assert_eq(snes.ppu->_registers._wsel[2].window1InversionForBg2Bg4Color, false);