From 2e2a19cda6c5b155f8930bddb376198bd208b6b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Fri, 21 Feb 2020 16:28:34 +0100 Subject: [PATCH 01/59] merge --- sources/PPU/PPU.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index 0836011..bace955 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -421,13 +421,13 @@ namespace ComSquare::PPU }; uint8_t raw; } _wsel[3]; - //! @brief WH0 Register (CWindow 1 Left Position) + //! @brief WH0 Register (Window 1 Left Position) uint8_t _wh0; - //! @brief WH1 Register (CWindow 1 Right Position) + //! @brief WH1 Register (Window 1 Right Position) uint8_t _wh1; - //! @brief WH2 Register (CWindow 2 Left Position) + //! @brief WH2 Register (Window 2 Left Position) uint8_t _wh2; - //! @brief WH3 Register (CWindow 2 Right Position) + //! @brief WH3 Register (Window 2 Right Position) uint8_t _wh3; //! @brief WBGLOG Register (Window mask logic for BGs) union { From 532508b078480db5ee9b09ac733b31e670e574e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Fri, 20 Mar 2020 14:55:15 +0100 Subject: [PATCH 02/59] init all ppu registers to 0 --- sources/PPU/PPU.cpp | 126 ++++++++++++++++++++++---------------------- sources/PPU/PPU.hpp | 69 ++++-------------------- 2 files changed, 72 insertions(+), 123 deletions(-) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 3784e0e..7716bff 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -14,11 +14,11 @@ namespace ComSquare::PPU { switch (addr) { case 0x34: - return this->mpy.mpyl; + return this->_registers.mpy.mpyl; case 0x35: - return this->mpy.mpym; + return this->_registers.mpy.mpym; case 0x36: - return this->mpy.mpyh; + return this->_registers.mpy.mpyh; default: throw InvalidAddress("PPU Internal Registers read", addr); } @@ -28,40 +28,40 @@ namespace ComSquare::PPU { switch (addr) { case ppuRegisters::inidisp: - this->_inidisp.raw = data; + this->_registers._inidisp.raw = data; break; case ppuRegisters::obsel: - this->_obsel.raw = data; + this->_registers._obsel.raw = data; break; case ppuRegisters::oamaddl: - this->_oamadd.oamaddl = data; + this->_registers._oamadd.oamaddl = data; break; case ppuRegisters::oamaddh: - this->_oamadd.oamaddh = data; + this->_registers._oamadd.oamaddh = data; break; case ppuRegisters::oamdata: - this->_oamdata = data; + this->_registers._oamdata = data; //throw InvalidAddress("oamdata", addr); std::cout << "oamdata" << std::endl; // the oamAddress have to be calculated if fblank or not (not implemented) - _oamram.write(this->_oamadd.oamAddress, this->_oamdata); - this->_oamadd.oamAddress++; + _oamram.write(this->_registers._oamadd.oamAddress, this->_registers._oamdata); + this->_registers._oamadd.oamAddress++; break; case ppuRegisters::bgmode: - this->_bgmode.raw = data; + this->_registers._bgmode.raw = data; break; case ppuRegisters::mosaic: - this->_mosaic.raw = data; + this->_registers._mosaic.raw = data; break; case ppuRegisters::bg1sc: case ppuRegisters::bg2sc: case ppuRegisters::bg3sc: case ppuRegisters::bg4sc: - this->_bgsc[addr - 0x07].raw = data; + this->_registers._bgsc[addr - 0x07].raw = data; break; case ppuRegisters::bg12nba: case ppuRegisters::bg34nba: - this->_bgnba[addr - 0x0B].raw = data; + this->_registers._bgnba[addr - 0x0B].raw = data; break; case ppuRegisters::bg1hofs: case ppuRegisters::bg1vofs: @@ -73,115 +73,115 @@ namespace ComSquare::PPU case ppuRegisters::bg4vofs: // Work in progress ! if (addr == ppuRegisters::bg1hofs || addr == ppuRegisters::bg1vofs) - this->_m7ofs[addr - ppuRegisters::bg1hofs].raw = data; - this->_bgofs[addr - ppuRegisters::bg1hofs].raw = data; + this->_registers._m7ofs[addr - ppuRegisters::bg1hofs].raw = data; + this->_registers._bgofs[addr - ppuRegisters::bg1hofs].raw = data; break; case ppuRegisters::vmain: - this->_vmain.raw = data; - switch (this->_vmain.incrementAmount) { + this->_registers._vmain.raw = data; + switch (this->_registers._vmain.incrementAmount) { case 0b00: - this->_incrementAmount = 1; + this->_registers._incrementAmount = 1; break; case 0b01: - this->_incrementAmount = 32; + this->_registers._incrementAmount = 32; break; case 0b10: case 0b11: - this->_incrementAmount = 128; + this->_registers._incrementAmount = 128; } break; case ppuRegisters::vmaddl: - this->_vmadd.vmaddl = data; + this->_registers._vmadd.vmaddl = data; break; case ppuRegisters::vmaddh: - this->_vmadd.vmaddh = data; + this->_registers._vmadd.vmaddh = data; break; case ppuRegisters::vmdatal: //throw InvalidAddress("vmdata", addr); std::cout << "vmdatal" << std::endl; - if (!this->_inidisp.fblank) { - this->_vmdata.vmdatal = data; - this->_vram.write(getVramAddress(), this->_vmdata.vmdata); + if (!this->_registers._inidisp.fblank) { + this->_registers._vmdata.vmdatal = data; + this->_vram.write(getVramAddress(), this->_registers._vmdata.vmdata); } - if (!this->_vmain.incrementMode) - this->_vmadd.vmadd += this->_incrementAmount; + if (!this->_registers._vmain.incrementMode) + this->_registers._vmadd.vmadd += this->_registers._incrementAmount; break; case ppuRegisters::vmdatah: std::cout << "vmdatah" << std::endl; - if (!this->_inidisp.fblank) { - this->_vmdata.vmdatah = data; - this->_vram.write(getVramAddress(), this->_vmdata.vmdata); + if (!this->_registers._inidisp.fblank) { + this->_registers._vmdata.vmdatah = data; + this->_vram.write(getVramAddress(), this->_registers._vmdata.vmdata); } - if (this->_vmain.incrementMode) - this->_vmadd.vmadd += this->_incrementAmount; + if (this->_registers._vmain.incrementMode) + this->_registers._vmadd.vmadd += this->_registers._incrementAmount; break; case ppuRegisters::m7sel: - this->_m7sel.raw = data; + this->_registers._m7sel.raw = data; break; case ppuRegisters::cgadd: std::cout << "cgadd addr : " << std::bitset<8>(data) << std::endl; - this->_cgadd = data; - this->_isLowByte = true; + this->_registers._cgadd = data; + this->_registers._isLowByte = true; break; case ppuRegisters::cgdata: //throw InvalidAddress("cgdata", addr); - if (this->_isLowByte) { + if (this->_registers._isLowByte) { std::cout << "cgadatal w data " << std::bitset<8>(data) << std::endl; - this->_cgdata.cgdatal = data; - //this->_cgram.write(this->_cgadd, this->_cgdata.raw); - //this->_cgadd++; + this->_registers._cgdata.cgdatal = data; + //this->_registers._cgram.write(this->_registers._cgadd, this->_registers._cgdata.raw); + //this->_registers._cgadd++; } else { - std::cout << "data for h " << std::bitset<8>(data) << std::endl; - this->_cgdata.cgdatah = data; - this->_cgram.write(this->_cgadd, this->_cgdata.raw); - std::cout << "cgadatah at addr: " << this->_cgadd << " valeur : " << std::bitset<16>(this->_cgdata.raw) << std::endl; - this->_cgadd++; + std::cout << "cgdatah w data " << std::bitset<8>(data) << std::endl; + this->_registers._cgdata.cgdatah = data; + this->_cgram.write(this->_registers._cgadd, this->_registers._cgdata.raw); + std::cout << "cgadatah at addr: " << this->_registers._cgadd << " valeur : " << std::bitset<16>(this->_registers._cgdata.raw) << std::endl; + this->_registers._cgadd++; } - this->_isLowByte = !this->_isLowByte; + this->_registers._isLowByte = !this->_registers._isLowByte; break; case ppuRegisters::w12sel: case ppuRegisters::w34sel: case ppuRegisters::wobjsel: - this->_wsel[addr - ppuRegisters::w12sel].raw = data; + this->_registers._wsel[addr - ppuRegisters::w12sel].raw = data; break; case ppuRegisters::wh0: - this->_wh0 = data; + this->_registers._wh0 = data; break; case ppuRegisters::wh1: - this->_wh1 = data; + this->_registers._wh1 = data; break; case ppuRegisters::wh2: - this->_wh2 = data; + this->_registers._wh2 = data; break; case ppuRegisters::wh3: - this->_wh3 = data; + this->_registers._wh3 = data; break; case ppuRegisters::wbjlog: - this->_wbglog.raw = data; + this->_registers._wbglog.raw = data; break; case ppuRegisters::wobjlog: - this->_wobjlog.raw = data; + this->_registers._wobjlog.raw = data; break; case ppuRegisters::tm: case ppuRegisters::ts: - this->_t[addr - ppuRegisters::tm].raw = data; + this->_registers._t[addr - ppuRegisters::tm].raw = data; break; case ppuRegisters::tmw: case ppuRegisters::tsw: - this->_tw[addr - ppuRegisters::tmw].raw = data; + this->_registers._tw[addr - ppuRegisters::tmw].raw = data; break; case ppuRegisters::cgwsel: - this->_cgwsel.raw = data; + this->_registers._cgwsel.raw = data; break; case ppuRegisters::cgadsub: - this->_cgadsub.raw = data; + this->_registers._cgadsub.raw = data; break; case ppuRegisters::coldata: - this->_coldata.raw = data; + this->_registers._coldata.raw = data; break; case ppuRegisters::setini: - this->_setini.raw = data; + this->_registers._setini.raw = data; break; //TODO adding the rest of the registers. oaf ! default: @@ -191,9 +191,9 @@ namespace ComSquare::PPU uint8_t PPU::getVramAddress() { - uint16_t vanillaAddress = this->_vmadd.vmadd; + uint16_t vanillaAddress = this->_registers._vmadd.vmadd; - switch (this->_vmain.addressRemapping) { + switch (this->_registers._vmain.addressRemapping) { case 0b00: return vanillaAddress; case 0b01: @@ -214,7 +214,7 @@ namespace ComSquare::PPU uint8_t blue; uint32_t pixelTmp = 0x000000FF; //std::cout << "update" << std::endl; - if (!this->_inidisp.fblank) { + if (!this->_registers._inidisp.fblank) { for (int y = 0; y <= 255; y++) { tmp = this->_cgram.read(y); @@ -245,6 +245,6 @@ namespace ComSquare::PPU _oamram(544), _cgram(512) { - this->_isLowByte = true; + this->_registers._isLowByte = true; } } \ No newline at end of file diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index bace955..60e083c 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -155,65 +155,7 @@ namespace ComSquare::PPU stat78 = 0x3F }; - //! @brief The class containing all the registers the PPU - class PPU : public Memory::IMemory { - private: - /* struct _layerInfo { - bool _characterSize; - }; - - struct { - unsigned int _height; - unsigned int _width; - bool verticalMirroring; - bool horizontalMirroring; - int verticalOffset; - int horizontalOffset; - //! @brief A Character is the base unit of the background it can be 16x16 or 8x8 (16x8 under certain circumstances) - unsigned char characterHeight; - unsigned char characterWidth; - } _BG[4]; - - struct object { - bool verticalMirroring; - bool horizontalMirroring; - bool priority; - unsigned short graphicAddress; - }; - - //! @brief INIDISP variables (F-blank and Brightness) - struct { - bool _fBlank; - //! @brief F=max, 0="off". - unsigned short _brightness; - } _inidisp; - - //! @brief OBSEL variables (Object Size and Character Address) - struct { - //! @brief "OamMode" this contains the size of the Objects (ex: 8x8 and 16x16) - unsigned char _objectSize; - //! @brief "OamBaseAddress" - unsigned char _baseSelect; - //! @brief "OamAddressOffset" - unsigned char _nameSelect; - } _obsel; - - //! @brief OAMADD variables (OAM Address and Obj Priority) - struct { - uint16_t _oamAddress; - bool _objPriority; - } _oamadd; - - //! @brief BGMODE (BG Mode and Character Size) - struct { - unsigned char _bgMode; - bool _mode1Bg3Priority; - _layerInfo layers[4]; - } _bgmode;*/ - - - - + struct Registers { //! @brief INIDISP Register (F-blank and Brightness) union { struct { @@ -542,8 +484,15 @@ namespace ComSquare::PPU uint8_t mpym; uint8_t mpyh; }; - uint32_t mpy; + uint32_t mpy; } mpy; + }; + + //! @brief The class containing all the registers the PPU + class PPU : public Memory::IMemory { + private: + //! @brief Init ppuRegisters + Registers _registers{}; Renderer::IRenderer &_renderer; std::shared_ptr _bus; Ram::ExtendedRam _vram; From df187e5e6af0020e6f495dc2d6a613f0fb7c747b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Thu, 26 Mar 2020 12:20:06 +0100 Subject: [PATCH 03/59] fix a documentation (test cannot compile will be fixed quickly) --- sources/PPU/PPU.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index 11c5f69..28c9d03 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -310,8 +310,7 @@ namespace ComSquare::PPU }; uint8_t raw; } _m7sel; - //! M7A M7B M7C M7D i didn't understand how they works so they will be added later. - + //! @brief M7A M7B M7C M7C registers, M7A and M7B are also used with ($2134/6) (multiplactions registers) union { struct { uint8_t m7l; From a02c201628040e70898a9fdeee42f70e5b308a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Thu, 26 Mar 2020 13:39:53 +0100 Subject: [PATCH 04/59] unit test compiling and passing --- tests/PPU/testPpuWrite.cpp | 164 ++++++++++---------- tests/PPU/testPpuWriteFromVmain.cpp | 223 +++++++++++++++------------- tests/testMemoryBus.cpp | 4 +- 3 files changed, 203 insertions(+), 188 deletions(-) diff --git a/tests/PPU/testPpuWrite.cpp b/tests/PPU/testPpuWrite.cpp index 814edb9..036d214 100644 --- a/tests/PPU/testPpuWrite.cpp +++ b/tests/PPU/testPpuWrite.cpp @@ -15,91 +15,91 @@ Test(PPU_write, inidisp_data_full_ones) { Init() snes._bus->write(0x2100, 0b11111111); - cr_assert_eq(snes.ppu->_inidisp.fblank, true); - cr_assert_eq(snes.ppu->_inidisp.brightness, 0xF); + cr_assert_eq(snes.ppu->_registers._inidisp.fblank, true); + cr_assert_eq(snes.ppu->_registers._inidisp.brightness, 0xF); } Test(PPU_write, inidisp_data_full_zeros) { Init() snes._bus->write(0x2100, 0b00000000); - cr_assert_eq(snes.ppu->_inidisp.fblank, false); - cr_assert_eq(snes.ppu->_inidisp.brightness, 0x0); + cr_assert_eq(snes.ppu->_registers._inidisp.fblank, false); + cr_assert_eq(snes.ppu->_registers._inidisp.brightness, 0x0); } Test(PPU_write, inidisp_data_fBlank_on_brghtness_off) { Init() snes._bus->write(0x2100, 0b10000000); - cr_assert_eq(snes.ppu->_inidisp.fblank, true); - cr_assert_eq(snes.ppu->_inidisp.brightness, 0x0); + cr_assert_eq(snes.ppu->_registers._inidisp.fblank, true); + cr_assert_eq(snes.ppu->_registers._inidisp.brightness, 0x0); } Test(PPU_write, inidisp_data_fBlank_off_brghtness_max) { Init() snes._bus->write(0x2100, 0b00001111); - cr_assert_eq(snes.ppu->_inidisp.fblank, false); - cr_assert_eq(snes.ppu->_inidisp.brightness, 0xF); + cr_assert_eq(snes.ppu->_registers._inidisp.fblank, false); + cr_assert_eq(snes.ppu->_registers._inidisp.brightness, 0xF); } Test(PPU_write, inidisp_data_fBlank_off_brghtness_half) { Init() snes._bus->write(0x2100, 0b00000101); - cr_assert_eq(snes.ppu->_inidisp.fblank, false); - cr_assert_eq(snes.ppu->_inidisp.brightness, 0x5); + cr_assert_eq(snes.ppu->_registers._inidisp.fblank, false); + cr_assert_eq(snes.ppu->_registers._inidisp.brightness, 0x5); } Test(PPU_write, obsel_111_object_size_and_all_null) { Init() snes._bus->write(0x2101, 0b11100000); - cr_assert_eq(snes.ppu->_obsel.objectSize, 0b111); - cr_assert_eq(snes.ppu->_obsel.nameSelect, 0b00); - cr_assert_eq(snes.ppu->_obsel.nameBaseSelect, 0b000); + cr_assert_eq(snes.ppu->_registers._obsel.objectSize, 0b111); + cr_assert_eq(snes.ppu->_registers._obsel.nameSelect, 0b00); + cr_assert_eq(snes.ppu->_registers._obsel.nameBaseSelect, 0b000); } Test(PPU_write, obsel_data_full) { Init() snes._bus->write(0x2101, 0b11111111); - cr_assert_eq(snes.ppu->_obsel.objectSize, 0b111); - cr_assert_eq(snes.ppu->_obsel.nameSelect, 0b11); - cr_assert_eq(snes.ppu->_obsel.nameBaseSelect, 0b111); + cr_assert_eq(snes.ppu->_registers._obsel.objectSize, 0b111); + cr_assert_eq(snes.ppu->_registers._obsel.nameSelect, 0b11); + cr_assert_eq(snes.ppu->_registers._obsel.nameBaseSelect, 0b111); } Test(PPU_write, obsel_data_full_nameselect) { Init() snes._bus->write(0x2101, 0b00011000); - cr_assert_eq(snes.ppu->_obsel.objectSize, 0b000); - cr_assert_eq(snes.ppu->_obsel.nameSelect, 0b11); - cr_assert_eq(snes.ppu->_obsel.nameBaseSelect, 0b000); + cr_assert_eq(snes.ppu->_registers._obsel.objectSize, 0b000); + cr_assert_eq(snes.ppu->_registers._obsel.nameSelect, 0b11); + cr_assert_eq(snes.ppu->_registers._obsel.nameBaseSelect, 0b000); } Test(PPU_write, obsel_data_full_baseselect) { Init() snes._bus->write(0x2101, 0b00000111); - cr_assert_eq(snes.ppu->_obsel.objectSize, 0b000); - cr_assert_eq(snes.ppu->_obsel.nameSelect, 0b00); - cr_assert_eq(snes.ppu->_obsel.nameBaseSelect, 0b111); + cr_assert_eq(snes.ppu->_registers._obsel.objectSize, 0b000); + cr_assert_eq(snes.ppu->_registers._obsel.nameSelect, 0b00); + cr_assert_eq(snes.ppu->_registers._obsel.nameBaseSelect, 0b111); } Test(PPU_write, oamaddl_data_full) { Init() snes._bus->write(0x2102, 0b11111111); - cr_assert_eq(snes.ppu->_oamadd.oamAddress, 0b011111111); + cr_assert_eq(snes.ppu->_registers._oamadd.oamAddress, 0b011111111); } Test(PPU_write, oamaddh_data_full) { Init() snes._bus->write(0x2103, 0b11111111); - cr_assert_eq(snes.ppu->_oamadd.objPriorityActivationBit, true); - cr_assert_eq(snes.ppu->_oamadd.oamAddress, 0b100000000); + cr_assert_eq(snes.ppu->_registers._oamadd.objPriorityActivationBit, true); + cr_assert_eq(snes.ppu->_registers._oamadd.oamAddress, 0b100000000); } Test(PPU_write, oamaddlh_data_full) @@ -107,8 +107,8 @@ Test(PPU_write, oamaddlh_data_full) Init() snes._bus->write(0x2102, 0b11111111); snes._bus->write(0x2103, 0b11111111); - cr_assert_eq(snes.ppu->_oamadd.objPriorityActivationBit, true); - cr_assert_eq(snes.ppu->_oamadd.oamAddress, 0b111111111); + cr_assert_eq(snes.ppu->_registers._oamadd.objPriorityActivationBit, true); + cr_assert_eq(snes.ppu->_registers._oamadd.oamAddress, 0b111111111); } Test(PPU_write, oamaddlh_data_full_priorityBit_off) @@ -116,8 +116,8 @@ Test(PPU_write, oamaddlh_data_full_priorityBit_off) Init() snes._bus->write(0x2102, 0b11111111); snes._bus->write(0x2103, 0b01111111); - cr_assert_eq(snes.ppu->_oamadd.objPriorityActivationBit, false); - cr_assert_eq(snes.ppu->_oamadd.oamAddress, 0b111111111); + cr_assert_eq(snes.ppu->_registers._oamadd.objPriorityActivationBit, false); + cr_assert_eq(snes.ppu->_registers._oamadd.oamAddress, 0b111111111); } Test(PPU_write, oamaddlh_oamAdress_11_priorityBit_on) @@ -125,141 +125,141 @@ Test(PPU_write, oamaddlh_oamAdress_11_priorityBit_on) Init() snes._bus->write(0x2102, 0b00001011); snes._bus->write(0x2103, 0b10011100); - cr_assert_eq(snes.ppu->_oamadd.objPriorityActivationBit, true); - cr_assert_eq(snes.ppu->_oamadd.oamAddress, 11); + cr_assert_eq(snes.ppu->_registers._oamadd.objPriorityActivationBit, true); + cr_assert_eq(snes.ppu->_registers._oamadd.oamAddress, 11); } Test(PPU_write, bgmode_data_full) { Init() snes._bus->write(0x2105, 0b11111111); - cr_assert_eq(snes.ppu->_bgmode.bgMode, 7); - cr_assert_eq(snes.ppu->_bgmode.characterSizeBg1, true); - cr_assert_eq(snes.ppu->_bgmode.characterSizeBg2, true); - cr_assert_eq(snes.ppu->_bgmode.characterSizeBg3, true); - cr_assert_eq(snes.ppu->_bgmode.characterSizeBg4, true); - cr_assert_eq(snes.ppu->_bgmode.mode1Bg3PriorityBit, true); + cr_assert_eq(snes.ppu->_registers._bgmode.bgMode, 7); + cr_assert_eq(snes.ppu->_registers._bgmode.characterSizeBg1, true); + cr_assert_eq(snes.ppu->_registers._bgmode.characterSizeBg2, true); + cr_assert_eq(snes.ppu->_registers._bgmode.characterSizeBg3, true); + cr_assert_eq(snes.ppu->_registers._bgmode.characterSizeBg4, true); + cr_assert_eq(snes.ppu->_registers._bgmode.mode1Bg3PriorityBit, true); } Test(PPU_write, bgmode_bgmode_5_and_bg24_on) { Init() snes._bus->write(0x2105, 0b10100101); - cr_assert_eq(snes.ppu->_bgmode.bgMode, 5); - cr_assert_eq(snes.ppu->_bgmode.characterSizeBg1, false); - cr_assert_eq(snes.ppu->_bgmode.characterSizeBg2, true); - cr_assert_eq(snes.ppu->_bgmode.characterSizeBg3, false); - cr_assert_eq(snes.ppu->_bgmode.characterSizeBg4, true); - cr_assert_eq(snes.ppu->_bgmode.mode1Bg3PriorityBit, false); + cr_assert_eq(snes.ppu->_registers._bgmode.bgMode, 5); + cr_assert_eq(snes.ppu->_registers._bgmode.characterSizeBg1, false); + cr_assert_eq(snes.ppu->_registers._bgmode.characterSizeBg2, true); + cr_assert_eq(snes.ppu->_registers._bgmode.characterSizeBg3, false); + cr_assert_eq(snes.ppu->_registers._bgmode.characterSizeBg4, true); + cr_assert_eq(snes.ppu->_registers._bgmode.mode1Bg3PriorityBit, false); } Test(PPU_write, mosaic_data_full) { Init() snes._bus->write(0x2106, 0b11111111); - cr_assert_eq(snes.ppu->_mosaic.affectBg1, true); - cr_assert_eq(snes.ppu->_mosaic.affectBg2, true); - cr_assert_eq(snes.ppu->_mosaic.affectBg3, true); - cr_assert_eq(snes.ppu->_mosaic.affectBg4, true); - cr_assert_eq(snes.ppu->_mosaic.pixelSize, 0xF); + cr_assert_eq(snes.ppu->_registers._mosaic.affectBg1, true); + cr_assert_eq(snes.ppu->_registers._mosaic.affectBg2, true); + cr_assert_eq(snes.ppu->_registers._mosaic.affectBg3, true); + cr_assert_eq(snes.ppu->_registers._mosaic.affectBg4, true); + cr_assert_eq(snes.ppu->_registers._mosaic.pixelSize, 0xF); } Test(PPU_write, mosaic_affectbg23_w_1x1_size) { Init() snes._bus->write(0x2106, 0b00000110); - cr_assert_eq(snes.ppu->_mosaic.affectBg1, false); - cr_assert_eq(snes.ppu->_mosaic.affectBg2, true); - cr_assert_eq(snes.ppu->_mosaic.affectBg3, true); - cr_assert_eq(snes.ppu->_mosaic.affectBg4, false); - cr_assert_eq(snes.ppu->_mosaic.pixelSize, 0x0); + cr_assert_eq(snes.ppu->_registers._mosaic.affectBg1, false); + cr_assert_eq(snes.ppu->_registers._mosaic.affectBg2, true); + cr_assert_eq(snes.ppu->_registers._mosaic.affectBg3, true); + cr_assert_eq(snes.ppu->_registers._mosaic.affectBg4, false); + cr_assert_eq(snes.ppu->_registers._mosaic.pixelSize, 0x0); } Test(PPU_write, mosaic_affectbg14_w_2x2_size) { Init() snes._bus->write(0x2106, 0b00101001); - cr_assert_eq(snes.ppu->_mosaic.affectBg1, true); - cr_assert_eq(snes.ppu->_mosaic.affectBg2, false); - cr_assert_eq(snes.ppu->_mosaic.affectBg3, false); - cr_assert_eq(snes.ppu->_mosaic.affectBg4, true); - cr_assert_eq(snes.ppu->_mosaic.pixelSize, 0x2); + cr_assert_eq(snes.ppu->_registers._mosaic.affectBg1, true); + cr_assert_eq(snes.ppu->_registers._mosaic.affectBg2, false); + cr_assert_eq(snes.ppu->_registers._mosaic.affectBg3, false); + cr_assert_eq(snes.ppu->_registers._mosaic.affectBg4, true); + cr_assert_eq(snes.ppu->_registers._mosaic.pixelSize, 0x2); } Test(PPU_write, bg1sc_data_full) { Init() snes._bus->write(0x2107, 0b11111111); - cr_assert_eq(snes.ppu->_bgsc[0].tilemapAddress, 0b111111); - cr_assert_eq(snes.ppu->_bgsc[0].tilemapHorizontalMirroring, true); - cr_assert_eq(snes.ppu->_bgsc[0].tilemapVerticalMirroring, true); + cr_assert_eq(snes.ppu->_registers._bgsc[0].tilemapAddress, 0b111111); + cr_assert_eq(snes.ppu->_registers._bgsc[0].tilemapHorizontalMirroring, true); + cr_assert_eq(snes.ppu->_registers._bgsc[0].tilemapVerticalMirroring, true); } Test(PPU_write, bg2sc_data_full) { Init() snes._bus->write(0x2108, 0b11111111); - cr_assert_eq(snes.ppu->_bgsc[1].tilemapAddress, 0b111111); - cr_assert_eq(snes.ppu->_bgsc[1].tilemapHorizontalMirroring, true); - cr_assert_eq(snes.ppu->_bgsc[1].tilemapVerticalMirroring, true); + cr_assert_eq(snes.ppu->_registers._bgsc[1].tilemapAddress, 0b111111); + cr_assert_eq(snes.ppu->_registers._bgsc[1].tilemapHorizontalMirroring, true); + cr_assert_eq(snes.ppu->_registers._bgsc[1].tilemapVerticalMirroring, true); } Test(PPU_write, bg3sc_data_full) { Init() snes._bus->write(0x2109, 0b11111111); - cr_assert_eq(snes.ppu->_bgsc[2].tilemapAddress, 0b111111); - cr_assert_eq(snes.ppu->_bgsc[2].tilemapHorizontalMirroring, true); - cr_assert_eq(snes.ppu->_bgsc[2].tilemapVerticalMirroring, true); + cr_assert_eq(snes.ppu->_registers._bgsc[2].tilemapAddress, 0b111111); + cr_assert_eq(snes.ppu->_registers._bgsc[2].tilemapHorizontalMirroring, true); + cr_assert_eq(snes.ppu->_registers._bgsc[2].tilemapVerticalMirroring, true); } Test(PPU_write, bg4sc_data_full) { Init() snes._bus->write(0x210A, 0b11111111); - cr_assert_eq(snes.ppu->_bgsc[3].tilemapAddress, 0b111111); - cr_assert_eq(snes.ppu->_bgsc[3].tilemapHorizontalMirroring, true); - cr_assert_eq(snes.ppu->_bgsc[3].tilemapVerticalMirroring, true); + cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapAddress, 0b111111); + cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapHorizontalMirroring, true); + cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapVerticalMirroring, true); } Test(PPU_write, bg4sc_data_null) { Init() snes._bus->write(0x210A, 0b00000000); - cr_assert_eq(snes.ppu->_bgsc[3].tilemapAddress, 0); - cr_assert_eq(snes.ppu->_bgsc[3].tilemapHorizontalMirroring, false); - cr_assert_eq(snes.ppu->_bgsc[3].tilemapVerticalMirroring, false); + cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapAddress, 0); + cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapHorizontalMirroring, false); + cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapVerticalMirroring, false); } Test(PPU_write, bg4sc_horizontal_off_vertical_on_random_tilemapAdress) { Init() snes._bus->write(0x210A, 0b11000110); - cr_assert_eq(snes.ppu->_bgsc[3].tilemapAddress, 0b110001); - cr_assert_eq(snes.ppu->_bgsc[3].tilemapHorizontalMirroring, false); - cr_assert_eq(snes.ppu->_bgsc[3].tilemapVerticalMirroring, true); + cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapAddress, 0b110001); + cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapHorizontalMirroring, false); + cr_assert_eq(snes.ppu->_registers._bgsc[3].tilemapVerticalMirroring, true); } Test(PPU_write, bg12nba_data_full) { Init() snes._bus->write(0x210B, 0b11111111); - cr_assert_eq(snes.ppu->_bgnba[0].baseAddressBg1a3, 0b1111); - cr_assert_eq(snes.ppu->_bgnba[0].baseAddressBg2a4, 0b1111); + cr_assert_eq(snes.ppu->_registers._bgnba[0].baseAddressBg1a3, 0b1111); + cr_assert_eq(snes.ppu->_registers._bgnba[0].baseAddressBg2a4, 0b1111); } Test(PPU_write, bg34nba_data_full) { Init() snes._bus->write(0x210C, 0b11111111); - cr_assert_eq(snes.ppu->_bgnba[1].baseAddressBg1a3, 0b1111); - cr_assert_eq(snes.ppu->_bgnba[1].baseAddressBg2a4, 0b1111); + cr_assert_eq(snes.ppu->_registers._bgnba[1].baseAddressBg1a3, 0b1111); + cr_assert_eq(snes.ppu->_registers._bgnba[1].baseAddressBg2a4, 0b1111); } Test(PPU_write, bg12nba_data_random_data) { Init() snes._bus->write(0x210B, 0b10101010); - cr_assert_eq(snes.ppu->_bgnba[0].baseAddressBg1a3, 0b1010); - cr_assert_eq(snes.ppu->_bgnba[0].baseAddressBg2a4, 0b1010); + cr_assert_eq(snes.ppu->_registers._bgnba[0].baseAddressBg1a3, 0b1010); + cr_assert_eq(snes.ppu->_registers._bgnba[0].baseAddressBg2a4, 0b1010); } \ No newline at end of file diff --git a/tests/PPU/testPpuWriteFromVmain.cpp b/tests/PPU/testPpuWriteFromVmain.cpp index d8fdae7..5fe1fb7 100644 --- a/tests/PPU/testPpuWriteFromVmain.cpp +++ b/tests/PPU/testPpuWriteFromVmain.cpp @@ -15,36 +15,36 @@ Test(PPU_write_2, vmain_data_full) { Init() snes._bus->write(0x2115, 0b11111111); - cr_assert_eq(snes.ppu->_vmain.incrementMode, true); - cr_assert_eq(snes.ppu->_vmain.addressRemapping, 0b11); - cr_assert_eq(snes.ppu->_vmain.incrementAmount, 0b11); + cr_assert_eq(snes.ppu->_registers._vmain.incrementMode, true); + cr_assert_eq(snes.ppu->_registers._vmain.addressRemapping, 0b11); + cr_assert_eq(snes.ppu->_registers._vmain.incrementAmount, 0b11); } Test(PPU_write_2, vmain_incrementmode_off_false_else_full) { Init() snes._bus->write(0x2115, 0b01111111); - cr_assert_eq(snes.ppu->_vmain.incrementMode, false); - cr_assert_eq(snes.ppu->_vmain.addressRemapping, 0b11); - cr_assert_eq(snes.ppu->_vmain.incrementAmount, 0b11); + cr_assert_eq(snes.ppu->_registers._vmain.incrementMode, false); + cr_assert_eq(snes.ppu->_registers._vmain.addressRemapping, 0b11); + cr_assert_eq(snes.ppu->_registers._vmain.incrementAmount, 0b11); } Test(PPU_write_2, vmain_addressremaping_null_else_full) { Init() snes._bus->write(0x2115, 0b11110011); - cr_assert_eq(snes.ppu->_vmain.incrementMode, true); - cr_assert_eq(snes.ppu->_vmain.addressRemapping, 0b00); - cr_assert_eq(snes.ppu->_vmain.incrementAmount, 0b11); + cr_assert_eq(snes.ppu->_registers._vmain.incrementMode, true); + cr_assert_eq(snes.ppu->_registers._vmain.addressRemapping, 0b00); + cr_assert_eq(snes.ppu->_registers._vmain.incrementAmount, 0b11); } Test(PPU_write_2, vmain_incrementamount_null_else_full) { Init() snes._bus->write(0x2115, 0b11111100); - cr_assert_eq(snes.ppu->_vmain.incrementMode, true); - cr_assert_eq(snes.ppu->_vmain.addressRemapping, 0b11); - cr_assert_eq(snes.ppu->_vmain.incrementAmount, 0b00); + cr_assert_eq(snes.ppu->_registers._vmain.incrementMode, true); + cr_assert_eq(snes.ppu->_registers._vmain.addressRemapping, 0b11); + cr_assert_eq(snes.ppu->_registers._vmain.incrementAmount, 0b00); } Test(PPU_write_2, vmadd_full_data) @@ -52,7 +52,7 @@ Test(PPU_write_2, vmadd_full_data) Init() snes._bus->write(0x2116, 0b11111111); snes._bus->write(0x2117, 0b11111111); - cr_assert_eq(snes.ppu->_vmadd.vmadd, 0b1111111111111111); + cr_assert_eq(snes.ppu->_registers._vmadd.vmadd, 0b1111111111111111); } Test(PPU_write_2, vmadd_full_high_byte_null) @@ -60,7 +60,7 @@ Test(PPU_write_2, vmadd_full_high_byte_null) Init() snes._bus->write(0x2116, 0b11111111); snes._bus->write(0x2117, 0b00000000); - cr_assert_eq(snes.ppu->_vmadd.vmadd, 0b0000000011111111); + cr_assert_eq(snes.ppu->_registers._vmadd.vmadd, 0b0000000011111111); } Test(PPU_write_2, vmdata_full_data) @@ -68,7 +68,7 @@ Test(PPU_write_2, vmdata_full_data) Init() snes._bus->write(0x2118, 0b11111111); snes._bus->write(0x2119, 0b11111111); - cr_assert_eq(snes.ppu->_vmdata.vmdata, 0b1111111111111111); + cr_assert_eq(snes.ppu->_registers._vmdata.vmdata, 0b1111111111111111); } Test(PPU_write_2, vmdata_full_high_byte_null) @@ -76,15 +76,15 @@ Test(PPU_write_2, vmdata_full_high_byte_null) Init() snes._bus->write(0x2118, 0b11111111); snes._bus->write(0x2119, 0b00000000); - cr_assert_eq(snes.ppu->_vmdata.vmdata, 0b0000000011111111); + cr_assert_eq(snes.ppu->_registers._vmdata.vmdata, 0b0000000011111111); } Test(PPU_write_2, cgadd_full_high_byte_null) { Init() snes._bus->write(0x2121, 0b11111111); - cr_assert_eq(snes.ppu->_cgadd, 0b11111111); - cr_assert_eq(snes.ppu->_isLowByte, true); + cr_assert_eq(snes.ppu->_registers._cgadd, 0b11111111); + cr_assert_eq(snes.ppu->_registers._isLowByte, true); } Test(PPU_write_2, cgdata_data_full) @@ -92,181 +92,196 @@ Test(PPU_write_2, cgdata_data_full) Init() snes._bus->write(0x2121, 0x0); snes._bus->write(0x2122, 0b11111111); - cr_assert_eq(snes.ppu->_cgdata.cgdatal, 0b11111111); - cr_assert_eq(snes.ppu->_isLowByte, false); - int address = snes.ppu->_cgadd; + cr_assert_eq(snes.ppu->_registers._cgdata.cgdatal, 0b11111111); + cr_assert_eq(snes.ppu->_registers._isLowByte, false); + int address = snes.ppu->_registers._cgadd; snes._bus->write(0x2122, 0b11111000); - cr_assert_eq(snes.ppu->_cgdata.cgdatah, 0b11111000); - cr_assert_eq(snes.ppu->_isLowByte, true); - cr_assert_eq(snes.ppu->_cgadd, address + 1); + cr_assert_eq(snes.ppu->_registers._cgdata.cgdatah, 0b11111000); + cr_assert_eq(snes.ppu->_registers._isLowByte, true); + cr_assert_eq(snes.ppu->_registers._cgadd, address + 1); } Test(PPU_write_2, m7sel_data_full) { Init() snes._bus->write(0x211A, 0b11111111); - cr_assert_eq(snes.ppu->_m7sel.playingFieldSize, true); - cr_assert_eq(snes.ppu->_m7sel.emptySpaceFill, true); - cr_assert_eq(snes.ppu->_m7sel.horizontalMirroring, true); - cr_assert_eq(snes.ppu->_m7sel.verticalMirroring, true); + cr_assert_eq(snes.ppu->_registers._m7sel.playingFieldSize, true); + cr_assert_eq(snes.ppu->_registers._m7sel.emptySpaceFill, true); + cr_assert_eq(snes.ppu->_registers._m7sel.horizontalMirroring, true); + cr_assert_eq(snes.ppu->_registers._m7sel.verticalMirroring, true); } Test(PPU_write_2, m7sel_data_actual) { Init() snes._bus->write(0x211A, 0b01111101); - cr_assert_eq(snes.ppu->_m7sel.playingFieldSize, false); - cr_assert_eq(snes.ppu->_m7sel.emptySpaceFill, true); - cr_assert_eq(snes.ppu->_m7sel.horizontalMirroring, true); - cr_assert_eq(snes.ppu->_m7sel.verticalMirroring, false); + cr_assert_eq(snes.ppu->_registers._m7sel.playingFieldSize, false); + cr_assert_eq(snes.ppu->_registers._m7sel.emptySpaceFill, true); + cr_assert_eq(snes.ppu->_registers._m7sel.horizontalMirroring, true); + cr_assert_eq(snes.ppu->_registers._m7sel.verticalMirroring, false); } Test(PPU_write_2, w12sel_data_full) { Init() snes._bus->write(0x2123, 0b11111111); - cr_assert_eq(snes.ppu->_wsel[0].window1InversionForBg1Bg2Obj, true); - cr_assert_eq(snes.ppu->_wsel[0].enableWindow1ForBg1Bg2Obj, true); - cr_assert_eq(snes.ppu->_wsel[0].window2InversionForBg1Bg3Obj, true); - cr_assert_eq(snes.ppu->_wsel[0].enableWindow2ForBg1Bg3Obj, true); - cr_assert_eq(snes.ppu->_wsel[0].window1InversionForBg2Bg4Color, true); - cr_assert_eq(snes.ppu->_wsel[0].enableWindow1ForBg2Bg4Color, true); - cr_assert_eq(snes.ppu->_wsel[0].window2InversionForBg2Bg4Color, true); - cr_assert_eq(snes.ppu->_wsel[0].enableWindow2ForBg2Bg4Color, true); + 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].window2InversionForBg1Bg3Obj, true); + cr_assert_eq(snes.ppu->_registers._wsel[0].enableWindow2ForBg1Bg3Obj, true); + cr_assert_eq(snes.ppu->_registers._wsel[0].window1InversionForBg2Bg4Color, true); + cr_assert_eq(snes.ppu->_registers._wsel[0].enableWindow1ForBg2Bg4Color, true); + cr_assert_eq(snes.ppu->_registers._wsel[0].window2InversionForBg2Bg4Color, true); + cr_assert_eq(snes.ppu->_registers._wsel[0].enableWindow2ForBg2Bg4Color, true); } Test(PPU_write_2, w34sel_data_full) { Init() snes._bus->write(0x2124, 0b10101010); - cr_assert_eq(snes.ppu->_wsel[1].window1InversionForBg1Bg2Obj, true); - cr_assert_eq(snes.ppu->_wsel[1].enableWindow1ForBg1Bg2Obj, false); - cr_assert_eq(snes.ppu->_wsel[1].window2InversionForBg1Bg3Obj, true); - cr_assert_eq(snes.ppu->_wsel[1].enableWindow2ForBg1Bg3Obj, false); - cr_assert_eq(snes.ppu->_wsel[1].window1InversionForBg2Bg4Color, true); - cr_assert_eq(snes.ppu->_wsel[1].enableWindow1ForBg2Bg4Color, false); - cr_assert_eq(snes.ppu->_wsel[1].window2InversionForBg2Bg4Color, true); - cr_assert_eq(snes.ppu->_wsel[1].enableWindow2ForBg2Bg4Color, false); + 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].window2InversionForBg1Bg3Obj, true); + cr_assert_eq(snes.ppu->_registers._wsel[1].enableWindow2ForBg1Bg3Obj, false); + cr_assert_eq(snes.ppu->_registers._wsel[1].window1InversionForBg2Bg4Color, true); + cr_assert_eq(snes.ppu->_registers._wsel[1].enableWindow1ForBg2Bg4Color, false); + cr_assert_eq(snes.ppu->_registers._wsel[1].window2InversionForBg2Bg4Color, true); + cr_assert_eq(snes.ppu->_registers._wsel[1].enableWindow2ForBg2Bg4Color, false); } Test(PPU_write_2, wobjsel_data_full) { Init() snes._bus->write(0x2125, 0b10110001); - cr_assert_eq(snes.ppu->_wsel[2].window1InversionForBg1Bg2Obj, true); - cr_assert_eq(snes.ppu->_wsel[2].enableWindow1ForBg1Bg2Obj, false); - cr_assert_eq(snes.ppu->_wsel[2].window2InversionForBg1Bg3Obj, true); - cr_assert_eq(snes.ppu->_wsel[2].enableWindow2ForBg1Bg3Obj, true); - cr_assert_eq(snes.ppu->_wsel[2].window1InversionForBg2Bg4Color, false); - cr_assert_eq(snes.ppu->_wsel[2].enableWindow1ForBg2Bg4Color, false); - cr_assert_eq(snes.ppu->_wsel[2].window2InversionForBg2Bg4Color, false); - cr_assert_eq(snes.ppu->_wsel[2].enableWindow2ForBg2Bg4Color, true); + 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].window2InversionForBg1Bg3Obj, true); + cr_assert_eq(snes.ppu->_registers._wsel[2].enableWindow2ForBg1Bg3Obj, true); + cr_assert_eq(snes.ppu->_registers._wsel[2].window1InversionForBg2Bg4Color, false); + cr_assert_eq(snes.ppu->_registers._wsel[2].enableWindow1ForBg2Bg4Color, false); + cr_assert_eq(snes.ppu->_registers._wsel[2].window2InversionForBg2Bg4Color, false); + cr_assert_eq(snes.ppu->_registers._wsel[2].enableWindow2ForBg2Bg4Color, true); } Test(PPU_write_2, wbglog_data_full) { Init() snes._bus->write(0x212A, 0b10110001); - cr_assert_eq(snes.ppu->_wbglog.maskLogicBg1, 0b10); - cr_assert_eq(snes.ppu->_wbglog.maskLogicBg2, 0b11); - cr_assert_eq(snes.ppu->_wbglog.maskLogicBg3, 0b00); - cr_assert_eq(snes.ppu->_wbglog.maskLogicBg4, 0b01); + cr_assert_eq(snes.ppu->_registers._wbglog.maskLogicBg1, 0b10); + cr_assert_eq(snes.ppu->_registers._wbglog.maskLogicBg2, 0b11); + cr_assert_eq(snes.ppu->_registers._wbglog.maskLogicBg3, 0b00); + cr_assert_eq(snes.ppu->_registers._wbglog.maskLogicBg4, 0b01); } Test(PPU_write_2, wobjlog_data_full) { Init() snes._bus->write(0x212B, 0b10110001); - cr_assert_eq(snes.ppu->_wobjlog.maskLogicObj, 0b01); - cr_assert_eq(snes.ppu->_wobjlog.maskLogicColor, 0b00); + cr_assert_eq(snes.ppu->_registers._wobjlog.maskLogicObj, 0b01); + cr_assert_eq(snes.ppu->_registers._wobjlog.maskLogicColor, 0b00); } Test(PPU_write_2, tm_data_full) { Init() snes._bus->write(0x212C, 0b10110001); - cr_assert_eq(snes.ppu->_t[0].enableWindowDisplayBg1, true); - cr_assert_eq(snes.ppu->_t[0].enableWindowDisplayBg2, false); - cr_assert_eq(snes.ppu->_t[0].enableWindowDisplayBg3, false); - cr_assert_eq(snes.ppu->_t[0].enableWindowDisplayBg4, false); - cr_assert_eq(snes.ppu->_t[0].enableWindowDisplayObj, true); + cr_assert_eq(snes.ppu->_registers._t[0].enableWindowDisplayBg1, true); + cr_assert_eq(snes.ppu->_registers._t[0].enableWindowDisplayBg2, false); + cr_assert_eq(snes.ppu->_registers._t[0].enableWindowDisplayBg3, false); + cr_assert_eq(snes.ppu->_registers._t[0].enableWindowDisplayBg4, false); + cr_assert_eq(snes.ppu->_registers._t[0].enableWindowDisplayObj, true); } Test(PPU_write_2, ts_data_full) { Init() snes._bus->write(0x212D, 0b10101110); - cr_assert_eq(snes.ppu->_t[1].enableWindowDisplayBg1, false); - cr_assert_eq(snes.ppu->_t[1].enableWindowDisplayBg2, true); - cr_assert_eq(snes.ppu->_t[1].enableWindowDisplayBg3, true); - cr_assert_eq(snes.ppu->_t[1].enableWindowDisplayBg4, true); - cr_assert_eq(snes.ppu->_t[1].enableWindowDisplayObj, false); + cr_assert_eq(snes.ppu->_registers._t[1].enableWindowDisplayBg1, false); + cr_assert_eq(snes.ppu->_registers._t[1].enableWindowDisplayBg2, true); + cr_assert_eq(snes.ppu->_registers._t[1].enableWindowDisplayBg3, true); + cr_assert_eq(snes.ppu->_registers._t[1].enableWindowDisplayBg4, true); + cr_assert_eq(snes.ppu->_registers._t[1].enableWindowDisplayObj, false); } Test(PPU_write_2, tmw_data_full) { Init() snes._bus->write(0x212E, 0b10101110); - cr_assert_eq(snes.ppu->_tw[0].enableWindowMaskingBg1, false); - cr_assert_eq(snes.ppu->_tw[0].enableWindowMaskingBg2, true); - cr_assert_eq(snes.ppu->_tw[0].enableWindowMaskingBg3, true); - cr_assert_eq(snes.ppu->_tw[0].enableWindowMaskingBg4, true); - cr_assert_eq(snes.ppu->_tw[0].enableWindowMaskingObj, false); + cr_assert_eq(snes.ppu->_registers._tw[0].enableWindowMaskingBg1, false); + cr_assert_eq(snes.ppu->_registers._tw[0].enableWindowMaskingBg2, true); + cr_assert_eq(snes.ppu->_registers._tw[0].enableWindowMaskingBg3, true); + cr_assert_eq(snes.ppu->_registers._tw[0].enableWindowMaskingBg4, true); + cr_assert_eq(snes.ppu->_registers._tw[0].enableWindowMaskingObj, false); } Test(PPU_write_2, tsw_data_full) { Init() snes._bus->write(0x212F, 0b10100011); - cr_assert_eq(snes.ppu->_tw[1].enableWindowMaskingBg1, true); - cr_assert_eq(snes.ppu->_tw[1].enableWindowMaskingBg2, true); - cr_assert_eq(snes.ppu->_tw[1].enableWindowMaskingBg3, false); - cr_assert_eq(snes.ppu->_tw[1].enableWindowMaskingBg4, false); - cr_assert_eq(snes.ppu->_tw[1].enableWindowMaskingObj, false); + cr_assert_eq(snes.ppu->_registers._tw[1].enableWindowMaskingBg1, true); + cr_assert_eq(snes.ppu->_registers._tw[1].enableWindowMaskingBg2, true); + cr_assert_eq(snes.ppu->_registers._tw[1].enableWindowMaskingBg3, false); + cr_assert_eq(snes.ppu->_registers._tw[1].enableWindowMaskingBg4, false); + cr_assert_eq(snes.ppu->_registers._tw[1].enableWindowMaskingObj, false); } Test(PPU_write_2, cgwsel_data_full) { Init() snes._bus->write(0x2130, 0b10111001); - cr_assert_eq(snes.ppu->_cgwsel.clipColorToBlackBeforeMath, 0b10); - cr_assert_eq(snes.ppu->_cgwsel.preventColorMath, 0b11); - cr_assert_eq(snes.ppu->_cgwsel.addSubscreen, false); - cr_assert_eq(snes.ppu->_cgwsel.directColorMode, true); + cr_assert_eq(snes.ppu->_registers._cgwsel.clipColorToBlackBeforeMath, 0b10); + cr_assert_eq(snes.ppu->_registers._cgwsel.preventColorMath, 0b11); + cr_assert_eq(snes.ppu->_registers._cgwsel.addSubscreen, false); + cr_assert_eq(snes.ppu->_registers._cgwsel.directColorMode, true); } Test(PPU_write_2, cgadsub_data_full) { Init() snes._bus->write(0x2131, 0b10111001); - cr_assert_eq(snes.ppu->_cgadsub.addSubtractSelect, true); - cr_assert_eq(snes.ppu->_cgadsub.halfColorMath, false); - cr_assert_eq(snes.ppu->_cgadsub.enableColorMathBackdrop, true); - cr_assert_eq(snes.ppu->_cgadsub.enableColorMathObj, true); - cr_assert_eq(snes.ppu->_cgadsub.enableColorMathBg4, true); - cr_assert_eq(snes.ppu->_cgadsub.enableColorMathBg3, false); - cr_assert_eq(snes.ppu->_cgadsub.enableColorMathBg2, false); - cr_assert_eq(snes.ppu->_cgadsub.enableColorMathBg1, true); + cr_assert_eq(snes.ppu->_registers._cgadsub.addSubtractSelect, true); + cr_assert_eq(snes.ppu->_registers._cgadsub.halfColorMath, false); + cr_assert_eq(snes.ppu->_registers._cgadsub.enableColorMathBackdrop, true); + cr_assert_eq(snes.ppu->_registers._cgadsub.enableColorMathObj, true); + cr_assert_eq(snes.ppu->_registers._cgadsub.enableColorMathBg4, true); + cr_assert_eq(snes.ppu->_registers._cgadsub.enableColorMathBg3, false); + cr_assert_eq(snes.ppu->_registers._cgadsub.enableColorMathBg2, false); + cr_assert_eq(snes.ppu->_registers._cgadsub.enableColorMathBg1, true); } Test(PPU_write_2, coldata_data_full) { Init() snes._bus->write(0x2132, 0b10111001); - cr_assert_eq(snes.ppu->_coldata.blue, true); - cr_assert_eq(snes.ppu->_coldata.green, false); - cr_assert_eq(snes.ppu->_coldata.red, true); - cr_assert_eq(snes.ppu->_coldata.colorIntensity, 0b11001); + cr_assert_eq(snes.ppu->_registers._coldata.blue, true); + cr_assert_eq(snes.ppu->_registers._coldata.green, false); + cr_assert_eq(snes.ppu->_registers._coldata.red, true); + cr_assert_eq(snes.ppu->_registers._coldata.colorIntensity, 0b11001); } Test(PPU_write_2, setini_data_full) { Init() snes._bus->write(0x2133, 0b10111001); - cr_assert_eq(snes.ppu->_setini.externalSync, true); - cr_assert_eq(snes.ppu->_setini.mode7ExtBg, false); - cr_assert_eq(snes.ppu->_setini.enablePseudoHiresMode, true); - cr_assert_eq(snes.ppu->_setini.overscanMode, false); - cr_assert_eq(snes.ppu->_setini.objInterlace, false); - cr_assert_eq(snes.ppu->_setini.screenInterlace, true); + cr_assert_eq(snes.ppu->_registers._setini.externalSync, true); + cr_assert_eq(snes.ppu->_registers._setini.mode7ExtBg, false); + cr_assert_eq(snes.ppu->_registers._setini.enablePseudoHiresMode, true); + cr_assert_eq(snes.ppu->_registers._setini.overscanMode, false); + cr_assert_eq(snes.ppu->_registers._setini.objInterlace, false); + cr_assert_eq(snes.ppu->_registers._setini.screenInterlace, true); +} + +Test(PPU_write_2, m7a_data_full) +{ + Init() + snes._bus->write(0x211B, 0b10111001); + cr_assert_eq(snes.ppu->_registers._m7[0].m7l, 0b10111001); +} + +Test(PPU_write_2, m7c_data_low_and_high_byte) +{ + Init() + snes._bus->write(0x211D, 0b10111001); + snes._bus->write(0x211D, 0b11111111); + cr_assert_eq(snes.ppu->_registers._m7[2].m7, 0b1011100111111111); } \ No newline at end of file diff --git a/tests/testMemoryBus.cpp b/tests/testMemoryBus.cpp index f1d27f8..81600be 100644 --- a/tests/testMemoryBus.cpp +++ b/tests/testMemoryBus.cpp @@ -350,7 +350,7 @@ Test(BusRead, ReadPPU) Init() uint8_t data; - snes.ppu->mpy.mpyl = 123; + snes.ppu->_registers._mpy.mpyl = 123; data = snes._bus->read(0x002134); cr_assert_eq(data, 123); } @@ -428,7 +428,7 @@ Test(BusWrite, WritePPU) Init() snes._bus->write(0x002106, 123); - cr_assert_eq(snes.ppu->_mosaic.raw, 123); + cr_assert_eq(snes.ppu->_registers._mosaic.raw, 123); } Test(BusWrite, WriteCPU) From 6cf44c8fa319d1701e203da15d99931ca6049359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Thu, 26 Mar 2020 15:47:28 +0100 Subject: [PATCH 05/59] fix the stz of the CPU exemple red.asm working (cgram write and display) --- sources/CPU/CPU.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index afe5d53..1dfe1cb 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -255,10 +255,10 @@ namespace ComSquare::CPU case Instructions::STY_DP: this->STX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0; case Instructions::STY_DPX: this->STX(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0; - case Instructions::STZ_ABS: this->STX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m; - case Instructions::STZ_DP: this->STX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0; - case Instructions::STZ_ABSX: this->STX(this->_getAbsoluteIndexedByXAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0; - case Instructions::STZ_DPX: this->STX(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0; + case Instructions::STZ_ABS: this->STZ(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m; + case Instructions::STZ_DP: this->STZ(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0; + case Instructions::STZ_ABSX: this->STZ(this->_getAbsoluteIndexedByXAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0; + case Instructions::STZ_DPX: this->STZ(this->_getDirectIndexedByXAddr()); return 4 + !this->_registers.p.m + this->_registers.dl != 0; case Instructions::LDA_IM: this->LDA(this->_getImmediateAddrForA()); return 2 + !this->_registers.p.m; case Instructions::LDA_ABS: this->LDA(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m; From 71f1d8f12db7e75c042a2e32b71bf559753e169c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Thu, 26 Mar 2020 18:00:17 +0100 Subject: [PATCH 06/59] cgram colors fixed now got the right color, and the brightness is now effective --- sources/PPU/PPU.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index b9f3e1c..459f555 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -227,27 +227,22 @@ namespace ComSquare::PPU uint8_t red; uint8_t green; uint8_t blue; - uint32_t pixelTmp = 0x000000FF; - //std::cout << "update" << std::endl; + uint32_t pixelTmp = 0x0; if (!this->_registers._inidisp.fblank) { for (int y = 0; y <= 255; y++) { tmp = this->_cgram.read(y); - //std::cout << "tmp " << std::bitset<16>(tmp) << std::endl; blue = (tmp & 0x7D00U) >> 10U; green = (tmp & 0x03E0U) >> 5U; red = (tmp & 0x001FU); - //std::cout << "red " << std::bitset<8>(red) << std::endl; - //std::cout << "green " << std::bitset<8>(green) << std::endl; - //std::cout << "blue " << std::bitset<8>(blue) << std::endl; - pixelTmp += (red * 256U / 32U) << 24U; - pixelTmp += (green * 256U / 32U) << 16U; - pixelTmp += (blue * 256U / 32U) << 8U; - //std::cout << "value of pixel " << std::hex << pixelTmp << " pour inc " << std::dec << y << std::endl; + pixelTmp = this->_registers._inidisp.brightness * 255U / 15U; + pixelTmp += (red * 255U / 31U) << 24U; + pixelTmp += (green * 255U / 31U) << 16U; + pixelTmp += (blue * 255U / 31U) << 8U; + for (int x = 0; x < 100; x++) this->_renderer.putPixel(x, y, pixelTmp); - pixelTmp = 0xFF; } } this->_renderer.drawScreen(); @@ -390,7 +385,7 @@ namespace ComSquare::PPU case ppuRegisters::stat78: return "STAT78"; default: - return "PPU : Unknown register"; + return "PPU : ???"; } } From 1354c86a4ae507e0db31d0318ec33b340713c0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Fri, 27 Mar 2020 18:52:41 +0100 Subject: [PATCH 07/59] starting implementing cgram debugger --- CMakeLists.txt | 2 +- sources/Debugger/cgramDebug.cpp | 75 +++++++++++ sources/Debugger/cgramDebug.hpp | 89 ++++++++++++ sources/PPU/PPU.cpp | 19 +-- sources/PPU/PPU.hpp | 10 +- sources/SNES.cpp | 25 ++++ sources/SNES.hpp | 4 + ui/cgramView.ui | 231 ++++++++++++++++++++++++++++++++ 8 files changed, 443 insertions(+), 12 deletions(-) create mode 100644 sources/Debugger/cgramDebug.cpp create mode 100644 sources/Debugger/cgramDebug.hpp create mode 100644 ui/cgramView.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c2d8c4..9d5d68c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,7 +200,7 @@ add_executable(ComSquare sources/Debugger/MemoryBusDebug.cpp sources/Debugger/MemoryBusDebug.hpp sources/Debugger/ClosableWindow.hpp - sources/Models/Components.hpp) + sources/Models/Components.hpp sources/Debugger/cgramDebug.cpp sources/Debugger/cgramDebug.hpp) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) diff --git a/sources/Debugger/cgramDebug.cpp b/sources/Debugger/cgramDebug.cpp new file mode 100644 index 0000000..af897b3 --- /dev/null +++ b/sources/Debugger/cgramDebug.cpp @@ -0,0 +1,75 @@ +// +// Created by cbihan on 3/27/20. +// + +#include "cgramDebug.hpp" +#include "../SNES.hpp" +#include +#include "../Utility/Utility.hpp" +#include "../Exceptions/InvalidAction.hpp" +#include "../Exceptions/InvalidAddress.hpp" + +namespace ComSquare::cgramDebugger +{ + cgramDebug::cgramDebug(SNES &snes, ComSquare::PPU::PPU &ppu) + : _window(new ClosableWindow(*this, &cgramDebug::disableViewer)), + _snes(snes), + _ui(), + _model(), + _ppu(ppu), + { + this->_window->setContextMenuPolicy(Qt::NoContextMenu); + this->_window->setAttribute(Qt::WA_QuitOnClose, false); + this->_window->setAttribute(Qt::WA_DeleteOnClose); + + this->_ui.setupUi(this->_window); + this->_ui.log->setModel(&this->_model); + this->_ui.log->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); + //this->_ui.log->horizontalHeader()->setStretchLastSection(true); + this->_ui.log->horizontalHeader()->setSectionsMovable(false); + for (int i = 0; i < this->_model.column; i++) + this->_ui.log->setColumnWidth(i, this->_ui.log->width()); + + this->_window->show(); + } + + void cgramDebug::disableViewer() + { + this->_snes.disableCgramDebugging(); + } + + void cgramDebug::focus() + { + this->_window->activateWindow(); + } + + bool cgramDebug::isDebugger() + { + return true; + } + + uint16_t cgramDebug::read(uint8_t addr) + { + return this->_ppu.cgramRead(addr); + } +} + +int cgramModel::rowCount(const QModelIndex &) const +{ + return this->rows; +} + +int cgramModel::columnCount(const QModelIndex &) const +{ + return this->column; +} + +QVariant cgramModel::data(const QModelIndex &index, int role) const +{ + if (role == Qt::TextAlignmentRole) + return Qt::AlignCenter; + if (role != Qt::DisplayRole) + return QVariant(); + if (role == Qt::BackgroundRole) + +} \ No newline at end of file diff --git a/sources/Debugger/cgramDebug.hpp b/sources/Debugger/cgramDebug.hpp new file mode 100644 index 0000000..1f23d1c --- /dev/null +++ b/sources/Debugger/cgramDebug.hpp @@ -0,0 +1,89 @@ +// +// Created by cbihan on 3/27/20. +// + +#ifndef COMSQUARE_CGRAMDEBUG_HPP +#define COMSQUARE_CGRAMDEBUG_HPP + +#include +#include "../PPU/PPU.hpp" +#include "../../ui/ui_cgramView.h" +#include +#include "ClosableWindow.hpp" + +/*namespace ComSquare::cgramDebugger +{ + //! @brief The struct used to represent memory bus logs. + struct BusLog { + BusLog(bool write, uint24_t addr, std::shared_ptr &accessor, uint8_t oldData, uint8_t newData); + + bool write; + uint24_t addr; + std::shared_ptr accessor; + uint8_t oldData; + uint8_t newData; + }; +}*/ + + +//! @brief The qt model that bind the logs to the view. +class cgramModel : public QAbstractTableModel +{ +Q_OBJECT +public: + //! @brief The number of columns + const int column = 16; + //! @brief The number of rows + const int rows = 16; + cgramModel() = default; + cgramModel(const cgramModel &) = delete; + const cgramModel &operator=(const cgramModel &) = delete; + ~cgramModel() override = default; + + //! @brief The number of row the table has. + int rowCount(const QModelIndex &parent) const override; + //! @brief The number of column the table has. + int columnCount(const QModelIndex &parent) const override; + //! @brief Return a data representing the table cell. + QVariant data(const QModelIndex &index, int role) const override; +}; + + +namespace ComSquare::cgramDebugger +{ + //! @brief window that allow the user to view all data going through the memory bus. + class cgramDebug { + private: + //! @brief The QT window for this debugger. + ClosableWindow *_window; + //! @brief A reference to the snes (to disable the debugger). + SNES &_snes; + //! @brief A widget that contain the whole UI. + Ui::cgramView _ui; + //! @brief The Log visualizer model for QT. + cgramModel _model; + //! @brief A reference to the ppu + ComSquare::PPU::PPU &_ppu; + public: + //! @brief Called when the window is closed. Turn off the debugger. + void disableViewer(); + public: + explicit cgramDebug(SNES &snes, ComSquare::PPU::PPU &ppu); + cgramDebug(const cgramDebug &) = delete; + cgramDebug &operator=(const cgramDebug &) = delete; + ~cgramDebug() = default; + + //! @brief Read data at the CGRAM address send it to the debugger. + //! @param addr The address to read from. + //! @return The color value in BGR, looks like this xbbbbbgggggrrrrr. + uint16_t read(uint8_t addr) override; + + //! @brief Focus the debugger's window. + void focus(); + + //! @brief Return true if the Bus is overloaded with debugging features. + bool isDebugger() override; + }; +} + +#endif //COMSQUARE_CGRAMDEBUG_HPP diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 459f555..4390bc4 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -134,23 +134,16 @@ namespace ComSquare::PPU this->_registers._m7[addr - ppuRegisters::m7a].m7 = (this->_registers._m7[addr - ppuRegisters::m7a].m7 << 8) | data; break; case ppuRegisters::cgadd: - std::cout << "cgadd addr : " << std::bitset<8>(data) << std::endl; this->_registers._cgadd = data; this->_registers._isLowByte = true; break; case ppuRegisters::cgdata: - //throw InvalidAddress("cgdata", addr); if (this->_registers._isLowByte) { - std::cout << "cgadatal w data " << std::bitset<8>(data) << std::endl; this->_registers._cgdata.cgdatal = data; - //this->_registers._cgram.write(this->_registers._cgadd, this->_registers._cgdata.raw); - //this->_registers._cgadd++; } else { - std::cout << "cgdatah w data " << std::bitset<8>(data) << std::endl; this->_registers._cgdata.cgdatah = data; this->_cgram.write(this->_registers._cgadd, this->_registers._cgdata.raw); - std::cout << "cgadatah at addr: " << this->_registers._cgadd << " valeur : " << std::bitset<16>(this->_registers._cgdata.raw) << std::endl; this->_registers._cgadd++; } this->_registers._isLowByte = !this->_registers._isLowByte; @@ -385,7 +378,7 @@ namespace ComSquare::PPU case ppuRegisters::stat78: return "STAT78"; default: - return "PPU : ???"; + return "???"; } } @@ -393,4 +386,14 @@ namespace ComSquare::PPU { return Ppu; } + + bool PPU::isDebugger() + { + return false; + } + + uint16_t PPU::cgramRead(uint8_t addr) + { + return this->_cgram.read(addr); + } } \ No newline at end of file diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index 28c9d03..272b6dd 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -494,7 +494,7 @@ namespace ComSquare::PPU } _mpy; }; - //! @brief The class containing all the registers the PPU + //! @brief The class containing all the registers of the PPU class PPU : public Memory::AMemory { private: //! @brief Init ppuRegisters @@ -526,11 +526,15 @@ namespace ComSquare::PPU //! @brief Update the PPU of n cycles. //! @param The number of cycles to update. - void update(unsigned cycles); + virtual void update(unsigned cycles); //! @brief Give the Vram Address with the right Address remapping uint8_t getVramAddress(); - //! @brief Give the name of the Address register + //! @brief Give the name of the Address register (used for debug) std::string getValueName(uint24_t addr); + //! @brief Return true if the CPU is overloaded with debugging features. + virtual bool isDebugger(); + //! @brief Allow others components to read the CGRAM (Debuggers) + uint16_t cgramRead(uint8_t addr); }; } #endif //COMSQUARE_PPU_HPP diff --git a/sources/SNES.cpp b/sources/SNES.cpp index 3dc9674..ffc3d67 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -126,4 +126,29 @@ namespace ComSquare std::cerr << "Debugging features are not enabled. You can't enable the debugger." << std::endl; #endif } + + void SNES::enableCgramDebugging() + { + #ifdef DEBUGGER_ENABLED + if (this->_bus->isDebugger()) + std::static_pointer_cast(this->_bus)->focus(); + else + { + this->_bus = std::make_shared(*this, *this->_bus); + this->cpu->setMemoryBus(this->_bus); + } + #else + std::cerr << "Debugging features are not enabled. You can't enable the debugger." << std::endl; + #endif + } + + void SNES::disableCgramDebugging() + { + #ifdef DEBUGGER_ENABLED + this->_bus = std::make_shared(*this->_bus); + this->cpu->setMemoryBus(this->_bus); + #else + std::cerr << "Debugging features are not enabled. You can't enable the debugger." << std::endl; + #endif + } } diff --git a/sources/SNES.hpp b/sources/SNES.hpp index 25fb99e..893ec3e 100644 --- a/sources/SNES.hpp +++ b/sources/SNES.hpp @@ -70,6 +70,10 @@ namespace ComSquare void disableMemoryBusDebugging(); //! @brief Enable the Memory Bus's debugging window. void enableMemoryBusDebugging(); + //! @brief Disable the Cgram's debugging window. + void disableCgramDebugging(); + //! @brief Enable the Cgram's debugging window. + void enableCgramDebugging(); //! @brief Create all the components using a common memory bus for all of them. SNES(const std::string &ramPath, Renderer::IRenderer &renderer); diff --git a/ui/cgramView.ui b/ui/cgramView.ui new file mode 100644 index 0000000..317cd78 --- /dev/null +++ b/ui/cgramView.ui @@ -0,0 +1,231 @@ + + + MainWindow + + + + 0 + 0 + 461 + 346 + + + + Palette Viewer + + + + :/resources/Logo.png:/resources/Logo.png + + + + + + + true + + + + 300 + 300 + + + + + 300 + 300 + + + + true + + + + 0 + 0 + 0 + + + + false + + + + + + + + + Index + + + + + + + + 70 + 16777215 + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + false + + + + + + + Value + + + + + + + + 70 + 16777215 + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + false + + + + + + + R + + + + + + + + 70 + 16777215 + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + false + + + + + + + G + + + + + + + + 70 + 16777215 + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + false + + + + + + + B + + + + + + + + 70 + 16777215 + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + false + + + + + + + Hex + + + + + + + + 70 + 16777215 + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + false + + + + + + + + + + + 0 + 0 + 461 + 22 + + + + + + + + + From 8d4e507489c2d2b94862b568f12e6ebdb8de3796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Fri, 27 Mar 2020 19:05:31 +0100 Subject: [PATCH 08/59] the project compile but you can't access the cgram debugger --- sources/Debugger/cgramDebug.cpp | 10 +++++----- sources/Debugger/cgramDebug.hpp | 8 ++++---- sources/SNES.cpp | 1 + ui/cgramView.ui | 4 ++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/sources/Debugger/cgramDebug.cpp b/sources/Debugger/cgramDebug.cpp index af897b3..8733de5 100644 --- a/sources/Debugger/cgramDebug.cpp +++ b/sources/Debugger/cgramDebug.cpp @@ -9,26 +9,26 @@ #include "../Exceptions/InvalidAction.hpp" #include "../Exceptions/InvalidAddress.hpp" -namespace ComSquare::cgramDebugger +namespace ComSquare::Debugger { cgramDebug::cgramDebug(SNES &snes, ComSquare::PPU::PPU &ppu) : _window(new ClosableWindow(*this, &cgramDebug::disableViewer)), _snes(snes), _ui(), _model(), - _ppu(ppu), + _ppu(ppu) { this->_window->setContextMenuPolicy(Qt::NoContextMenu); this->_window->setAttribute(Qt::WA_QuitOnClose, false); this->_window->setAttribute(Qt::WA_DeleteOnClose); - this->_ui.setupUi(this->_window); + /*this->_ui.setupUi(this->_window); this->_ui.log->setModel(&this->_model); this->_ui.log->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); //this->_ui.log->horizontalHeader()->setStretchLastSection(true); this->_ui.log->horizontalHeader()->setSectionsMovable(false); for (int i = 0; i < this->_model.column; i++) - this->_ui.log->setColumnWidth(i, this->_ui.log->width()); + this->_ui.log->setColumnWidth(i, this->_ui.log->width());*/ this->_window->show(); } @@ -71,5 +71,5 @@ QVariant cgramModel::data(const QModelIndex &index, int role) const if (role != Qt::DisplayRole) return QVariant(); if (role == Qt::BackgroundRole) - + return 1; } \ No newline at end of file diff --git a/sources/Debugger/cgramDebug.hpp b/sources/Debugger/cgramDebug.hpp index 1f23d1c..a41e5f2 100644 --- a/sources/Debugger/cgramDebug.hpp +++ b/sources/Debugger/cgramDebug.hpp @@ -49,7 +49,7 @@ public: }; -namespace ComSquare::cgramDebugger +namespace ComSquare::Debugger { //! @brief window that allow the user to view all data going through the memory bus. class cgramDebug { @@ -59,7 +59,7 @@ namespace ComSquare::cgramDebugger //! @brief A reference to the snes (to disable the debugger). SNES &_snes; //! @brief A widget that contain the whole UI. - Ui::cgramView _ui; + Ui::CgramView _ui; //! @brief The Log visualizer model for QT. cgramModel _model; //! @brief A reference to the ppu @@ -76,13 +76,13 @@ namespace ComSquare::cgramDebugger //! @brief Read data at the CGRAM address send it to the debugger. //! @param addr The address to read from. //! @return The color value in BGR, looks like this xbbbbbgggggrrrrr. - uint16_t read(uint8_t addr) override; + uint16_t read(uint8_t addr); //! @brief Focus the debugger's window. void focus(); //! @brief Return true if the Bus is overloaded with debugging features. - bool isDebugger() override; + bool isDebugger(); }; } diff --git a/sources/SNES.cpp b/sources/SNES.cpp index ffc3d67..2547b8f 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -9,6 +9,7 @@ #include "Debugger/CPUDebug.hpp" #include "Debugger/APUDebug.hpp" #include "Debugger/MemoryBusDebug.hpp" +#include "Debugger/cgramDebug.hpp" #endif diff --git a/ui/cgramView.ui b/ui/cgramView.ui index 317cd78..a110630 100644 --- a/ui/cgramView.ui +++ b/ui/cgramView.ui @@ -1,7 +1,7 @@ - MainWindow - + CgramView + 0 From 618c708df628c91ca619e90903ef39c0c59d99f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sat, 28 Mar 2020 14:52:42 +0100 Subject: [PATCH 09/59] adding the window of the cgram debugger (-g to activate) --- sources/Debugger/cgramDebug.cpp | 20 +++++++++--------- sources/Debugger/cgramDebug.hpp | 37 +++++++++++++++++++++++++++++++++ sources/SNES.cpp | 30 ++++++++++---------------- sources/SNES.hpp | 3 +++ sources/main.cpp | 6 +++++- 5 files changed, 66 insertions(+), 30 deletions(-) diff --git a/sources/Debugger/cgramDebug.cpp b/sources/Debugger/cgramDebug.cpp index 8733de5..835fc1e 100644 --- a/sources/Debugger/cgramDebug.cpp +++ b/sources/Debugger/cgramDebug.cpp @@ -22,13 +22,7 @@ namespace ComSquare::Debugger this->_window->setAttribute(Qt::WA_QuitOnClose, false); this->_window->setAttribute(Qt::WA_DeleteOnClose); - /*this->_ui.setupUi(this->_window); - this->_ui.log->setModel(&this->_model); - this->_ui.log->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); - //this->_ui.log->horizontalHeader()->setStretchLastSection(true); - this->_ui.log->horizontalHeader()->setSectionsMovable(false); - for (int i = 0; i < this->_model.column; i++) - this->_ui.log->setColumnWidth(i, this->_ui.log->width());*/ + this->_ui.setupUi(this->_window); this->_window->show(); } @@ -68,8 +62,14 @@ QVariant cgramModel::data(const QModelIndex &index, int role) const { if (role == Qt::TextAlignmentRole) return Qt::AlignCenter; - if (role != Qt::DisplayRole) - return QVariant(); if (role == Qt::BackgroundRole) return 1; -} \ No newline at end of file + this->_ppu.cgramRead(0); + if (role != Qt::DisplayRole) + return QVariant(); +} + +void cgramModel::ppu(const ComSquare::PPU::PPU &ppu) +{ + this->_ppu = ppu; +} diff --git a/sources/Debugger/cgramDebug.hpp b/sources/Debugger/cgramDebug.hpp index a41e5f2..e3f342c 100644 --- a/sources/Debugger/cgramDebug.hpp +++ b/sources/Debugger/cgramDebug.hpp @@ -11,6 +11,38 @@ #include #include "ClosableWindow.hpp" + +/*namespace ComSquare +{ + class SNES; + namespace Debugger + { + //! @brief Window that show the header of the currently running game. + class cgramViewer { + private: + //! @brief The QT window for this debugger. + ClosableWindow *_window{}; + //! @brief A reference to the snes (to disable the debugger). + SNES &_snes; + //! @brief The layout of the viewer. + Ui::CgramView _ui; + //! @brief The ppu containing the cgram. + ComSquare::PPU::PPU &_ppu; + public slots: + //! @brief Called when the window is closed. Turn off the debugger and revert to a basic CPU. + void disableDebugger(); + public: + //! @brief Focus the debugger's window. + void focus(); + + explicit cgramViewer(SNES &snes, ComSquare::PPU::PPU &ppu); + cgramViewer(const cgramViewer &) = delete; + cgramViewer &operator=(const cgramViewer &) = delete; + ~cgramViewer() = default; + }; + } +}*/ + /*namespace ComSquare::cgramDebugger { //! @brief The struct used to represent memory bus logs. @@ -30,6 +62,9 @@ class cgramModel : public QAbstractTableModel { Q_OBJECT +private: + //! @brief The ppu to log the cgram. + ComSquare::PPU::PPU &_ppu; public: //! @brief The number of columns const int column = 16; @@ -40,6 +75,8 @@ public: const cgramModel &operator=(const cgramModel &) = delete; ~cgramModel() override = default; + //! @brief set the reference to the ppu + void ppu(const ComSquare::PPU::PPU &ppu); //! @brief The number of row the table has. int rowCount(const QModelIndex &parent) const override; //! @brief The number of column the table has. diff --git a/sources/SNES.cpp b/sources/SNES.cpp index 2547b8f..bdeac42 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -130,26 +130,18 @@ namespace ComSquare void SNES::enableCgramDebugging() { - #ifdef DEBUGGER_ENABLED - if (this->_bus->isDebugger()) - std::static_pointer_cast(this->_bus)->focus(); + #ifdef DEBUGGER_ENABLED + if (this->_cgramViewer) + this->_cgramViewer->focus(); else - { - this->_bus = std::make_shared(*this, *this->_bus); - this->cpu->setMemoryBus(this->_bus); - } - #else - std::cerr << "Debugging features are not enabled. You can't enable the debugger." << std::endl; - #endif - } + this->_cgramViewer = std::make_unique(*this, *this->ppu); + #endif + } - void SNES::disableCgramDebugging() - { - #ifdef DEBUGGER_ENABLED - this->_bus = std::make_shared(*this->_bus); - this->cpu->setMemoryBus(this->_bus); - #else - std::cerr << "Debugging features are not enabled. You can't enable the debugger." << std::endl; - #endif + void SNES::disableCgramDebugging() + { + #ifdef DEBUGGER_ENABLED + this->_cgramViewer = nullptr; + #endif } } diff --git a/sources/SNES.hpp b/sources/SNES.hpp index 893ec3e..825367a 100644 --- a/sources/SNES.hpp +++ b/sources/SNES.hpp @@ -15,6 +15,7 @@ #ifdef DEBUGGER_ENABLED #include "Debugger/MemoryViewer.hpp" #include "Debugger/HeaderViewer.hpp" +#include "Debugger/cgramDebug.hpp" #endif @@ -28,6 +29,8 @@ namespace ComSquare std::unique_ptr _ramViewer; //! @brief The window that allow the user to view the cartridge's header. std::unique_ptr _headerViewer; + //! @brief The window that allow the user to view the CGRAM. + std::unique_ptr _cgramViewer; #endif //! @brief The memory bus that map addresses to components. std::shared_ptr _bus; diff --git a/sources/main.cpp b/sources/main.cpp index f01c0c2..3a4ba82 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -32,10 +32,11 @@ void parseArguments(int argc, char **argv, SNES &snes) {"memory", no_argument, 0, 'm'}, {"header", no_argument, 0, 'h'}, {"bus", no_argument, 0, 'b'}, + {"cgram", no_argument, 0, 'g'}, {0, 0, 0, 0} }; - int c = getopt_long(argc, argv, "camhb", long_options, &option_index); + int c = getopt_long(argc, argv, "camhbg", long_options, &option_index); if (c == -1) break; switch (c) { @@ -57,6 +58,9 @@ void parseArguments(int argc, char **argv, SNES &snes) case 'b': snes.enableMemoryBusDebugging(); break; + case 'g': + snes.enableCgramDebugging(); + break; default: break; } From e5fbde350f997a78399e8d646204f746e8a3d285 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Sat, 28 Mar 2020 14:58:30 +0100 Subject: [PATCH 10/59] Solving compilation issues --- CMakeLists.txt | 2 +- .../{cgramDebug.cpp => CGramDebug.cpp} | 31 +++++++++---------- .../{cgramDebug.hpp => CGramDebug.hpp} | 26 +++++++--------- sources/SNES.cpp | 4 +-- sources/SNES.hpp | 4 +-- 5 files changed, 31 insertions(+), 36 deletions(-) rename sources/Debugger/{cgramDebug.cpp => CGramDebug.cpp} (62%) rename sources/Debugger/{cgramDebug.hpp => CGramDebug.hpp} (84%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d5d68c..0edbfec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,7 +200,7 @@ add_executable(ComSquare sources/Debugger/MemoryBusDebug.cpp sources/Debugger/MemoryBusDebug.hpp sources/Debugger/ClosableWindow.hpp - sources/Models/Components.hpp sources/Debugger/cgramDebug.cpp sources/Debugger/cgramDebug.hpp) + sources/Models/Components.hpp sources/Debugger/CGramDebug.cpp sources/Debugger/CGramDebug.hpp) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) diff --git a/sources/Debugger/cgramDebug.cpp b/sources/Debugger/CGramDebug.cpp similarity index 62% rename from sources/Debugger/cgramDebug.cpp rename to sources/Debugger/CGramDebug.cpp index 835fc1e..a32ea1a 100644 --- a/sources/Debugger/cgramDebug.cpp +++ b/sources/Debugger/CGramDebug.cpp @@ -2,7 +2,7 @@ // Created by cbihan on 3/27/20. // -#include "cgramDebug.hpp" +#include "CGramDebug.hpp" #include "../SNES.hpp" #include #include "../Utility/Utility.hpp" @@ -11,11 +11,11 @@ namespace ComSquare::Debugger { - cgramDebug::cgramDebug(SNES &snes, ComSquare::PPU::PPU &ppu) - : _window(new ClosableWindow(*this, &cgramDebug::disableViewer)), + CGramDebug::CGramDebug(SNES &snes, ComSquare::PPU::PPU &ppu) + : _window(new ClosableWindow(*this, &CGramDebug::disableViewer)), _snes(snes), _ui(), - _model(), + _model(ppu), _ppu(ppu) { this->_window->setContextMenuPolicy(Qt::NoContextMenu); @@ -27,38 +27,40 @@ namespace ComSquare::Debugger this->_window->show(); } - void cgramDebug::disableViewer() + void CGramDebug::disableViewer() { this->_snes.disableCgramDebugging(); } - void cgramDebug::focus() + void CGramDebug::focus() { this->_window->activateWindow(); } - bool cgramDebug::isDebugger() + bool CGramDebug::isDebugger() { return true; } - uint16_t cgramDebug::read(uint8_t addr) + uint16_t CGramDebug::read(uint8_t addr) { return this->_ppu.cgramRead(addr); } } -int cgramModel::rowCount(const QModelIndex &) const +CGramModel::CGramModel(ComSquare::PPU::PPU &ppu) : _ppu(ppu) {} + +int CGramModel::rowCount(const QModelIndex &) const { return this->rows; } -int cgramModel::columnCount(const QModelIndex &) const +int CGramModel::columnCount(const QModelIndex &) const { return this->column; } -QVariant cgramModel::data(const QModelIndex &index, int role) const +QVariant CGramModel::data(const QModelIndex &index, int role) const { if (role == Qt::TextAlignmentRole) return Qt::AlignCenter; @@ -67,9 +69,4 @@ QVariant cgramModel::data(const QModelIndex &index, int role) const this->_ppu.cgramRead(0); if (role != Qt::DisplayRole) return QVariant(); -} - -void cgramModel::ppu(const ComSquare::PPU::PPU &ppu) -{ - this->_ppu = ppu; -} +} \ No newline at end of file diff --git a/sources/Debugger/cgramDebug.hpp b/sources/Debugger/CGramDebug.hpp similarity index 84% rename from sources/Debugger/cgramDebug.hpp rename to sources/Debugger/CGramDebug.hpp index e3f342c..3629795 100644 --- a/sources/Debugger/cgramDebug.hpp +++ b/sources/Debugger/CGramDebug.hpp @@ -59,7 +59,7 @@ //! @brief The qt model that bind the logs to the view. -class cgramModel : public QAbstractTableModel +class CGramModel : public QAbstractTableModel { Q_OBJECT private: @@ -70,13 +70,11 @@ public: const int column = 16; //! @brief The number of rows const int rows = 16; - cgramModel() = default; - cgramModel(const cgramModel &) = delete; - const cgramModel &operator=(const cgramModel &) = delete; - ~cgramModel() override = default; + explicit CGramModel(ComSquare::PPU::PPU &ppu); + CGramModel(const CGramModel &) = delete; + const CGramModel &operator=(const CGramModel &) = delete; + ~CGramModel() override = default; - //! @brief set the reference to the ppu - void ppu(const ComSquare::PPU::PPU &ppu); //! @brief The number of row the table has. int rowCount(const QModelIndex &parent) const override; //! @brief The number of column the table has. @@ -89,26 +87,26 @@ public: namespace ComSquare::Debugger { //! @brief window that allow the user to view all data going through the memory bus. - class cgramDebug { + class CGramDebug { private: //! @brief The QT window for this debugger. - ClosableWindow *_window; + ClosableWindow *_window; //! @brief A reference to the snes (to disable the debugger). SNES &_snes; //! @brief A widget that contain the whole UI. Ui::CgramView _ui; //! @brief The Log visualizer model for QT. - cgramModel _model; + CGramModel _model; //! @brief A reference to the ppu ComSquare::PPU::PPU &_ppu; public: //! @brief Called when the window is closed. Turn off the debugger. void disableViewer(); public: - explicit cgramDebug(SNES &snes, ComSquare::PPU::PPU &ppu); - cgramDebug(const cgramDebug &) = delete; - cgramDebug &operator=(const cgramDebug &) = delete; - ~cgramDebug() = default; + explicit CGramDebug(SNES &snes, ComSquare::PPU::PPU &ppu); + CGramDebug(const CGramDebug &) = delete; + CGramDebug &operator=(const CGramDebug &) = delete; + ~CGramDebug() = default; //! @brief Read data at the CGRAM address send it to the debugger. //! @param addr The address to read from. diff --git a/sources/SNES.cpp b/sources/SNES.cpp index bdeac42..88e796d 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -9,7 +9,7 @@ #include "Debugger/CPUDebug.hpp" #include "Debugger/APUDebug.hpp" #include "Debugger/MemoryBusDebug.hpp" -#include "Debugger/cgramDebug.hpp" +#include "Debugger/CGramDebug.hpp" #endif @@ -134,7 +134,7 @@ namespace ComSquare if (this->_cgramViewer) this->_cgramViewer->focus(); else - this->_cgramViewer = std::make_unique(*this, *this->ppu); + this->_cgramViewer = std::make_unique(*this, *this->ppu); #endif } diff --git a/sources/SNES.hpp b/sources/SNES.hpp index 825367a..19dcbb4 100644 --- a/sources/SNES.hpp +++ b/sources/SNES.hpp @@ -15,7 +15,7 @@ #ifdef DEBUGGER_ENABLED #include "Debugger/MemoryViewer.hpp" #include "Debugger/HeaderViewer.hpp" -#include "Debugger/cgramDebug.hpp" +#include "Debugger/CGramDebug.hpp" #endif @@ -30,7 +30,7 @@ namespace ComSquare //! @brief The window that allow the user to view the cartridge's header. std::unique_ptr _headerViewer; //! @brief The window that allow the user to view the CGRAM. - std::unique_ptr _cgramViewer; + std::unique_ptr _cgramViewer; #endif //! @brief The memory bus that map addresses to components. std::shared_ptr _bus; From d36b7fab1a98d478ac2b6ee195206512c863d66c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sat, 28 Mar 2020 16:33:13 +0100 Subject: [PATCH 11/59] cgram debugger getting logs --- sources/Debugger/CGramDebug.cpp | 30 +++++++++++++++++++++++++----- sources/Debugger/CGramDebug.hpp | 1 - ui/cgramView.ui | 3 +++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/sources/Debugger/CGramDebug.cpp b/sources/Debugger/CGramDebug.cpp index a32ea1a..902cb7e 100644 --- a/sources/Debugger/CGramDebug.cpp +++ b/sources/Debugger/CGramDebug.cpp @@ -5,6 +5,7 @@ #include "CGramDebug.hpp" #include "../SNES.hpp" #include +#include #include "../Utility/Utility.hpp" #include "../Exceptions/InvalidAction.hpp" #include "../Exceptions/InvalidAddress.hpp" @@ -23,6 +24,7 @@ namespace ComSquare::Debugger this->_window->setAttribute(Qt::WA_DeleteOnClose); this->_ui.setupUi(this->_window); + this->_ui.cgram_view->setModel(&this->_model); this->_window->show(); } @@ -62,11 +64,29 @@ int CGramModel::columnCount(const QModelIndex &) const QVariant CGramModel::data(const QModelIndex &index, int role) const { - if (role == Qt::TextAlignmentRole) - return Qt::AlignCenter; - if (role == Qt::BackgroundRole) - return 1; - this->_ppu.cgramRead(0); + u_int16_t addressValue; + uint8_t red; + uint8_t green; + uint8_t blue; + //std::cout << "test1" << std::endl; + //if (role == Qt::TextAlignmentRole) + // return Qt::AlignCenter; + //std::cout << "test2" << std::endl; + //if (role == Qt::BackgroundRole) { + // std::cout << "test" << std::endl; + // return 1; + //} + //std::cout << "test3" << std::endl; if (role != Qt::DisplayRole) return QVariant(); + addressValue = this->_ppu.cgramRead(index.column() * 16 + index.row()); + + blue = (addressValue & 0x7D00U) >> 10U; + green = (addressValue & 0x03E0U) >> 5U; + red = (addressValue & 0x001FU); + + red = (red * 255U / 31U) << 24U; + green = (green * 255U / 31U) << 16U; + blue = (blue * 255U / 31U) << 8U; + return QColor(red, green,blue,255); } \ No newline at end of file diff --git a/sources/Debugger/CGramDebug.hpp b/sources/Debugger/CGramDebug.hpp index 3629795..8cdcbff 100644 --- a/sources/Debugger/CGramDebug.hpp +++ b/sources/Debugger/CGramDebug.hpp @@ -83,7 +83,6 @@ public: QVariant data(const QModelIndex &index, int role) const override; }; - namespace ComSquare::Debugger { //! @brief window that allow the user to view all data going through the memory bus. diff --git a/ui/cgramView.ui b/ui/cgramView.ui index a110630..73c9102 100644 --- a/ui/cgramView.ui +++ b/ui/cgramView.ui @@ -49,6 +49,9 @@ false + + false + From 0a0dd428ee9ded40b61e8ae9b3014719efa8ece6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sat, 28 Mar 2020 16:36:26 +0100 Subject: [PATCH 12/59] debugging the debugger --- sources/Debugger/CGramDebug.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sources/Debugger/CGramDebug.cpp b/sources/Debugger/CGramDebug.cpp index 902cb7e..e8efde0 100644 --- a/sources/Debugger/CGramDebug.cpp +++ b/sources/Debugger/CGramDebug.cpp @@ -69,16 +69,18 @@ QVariant CGramModel::data(const QModelIndex &index, int role) const uint8_t green; uint8_t blue; //std::cout << "test1" << std::endl; - //if (role == Qt::TextAlignmentRole) - // return Qt::AlignCenter; + if (role == Qt::TextAlignmentRole) + return Qt::AlignCenter; //std::cout << "test2" << std::endl; - //if (role == Qt::BackgroundRole) { - // std::cout << "test" << std::endl; - // return 1; - //} + //std::cout << "test3" << std::endl; if (role != Qt::DisplayRole) return QVariant(); + if (role == Qt::BackgroundRole) { + // std::cout << "test" << std::endl; + //unreachable + return 1; + } addressValue = this->_ppu.cgramRead(index.column() * 16 + index.row()); blue = (addressValue & 0x7D00U) >> 10U; @@ -88,5 +90,5 @@ QVariant CGramModel::data(const QModelIndex &index, int role) const red = (red * 255U / 31U) << 24U; green = (green * 255U / 31U) << 16U; blue = (blue * 255U / 31U) << 8U; - return QColor(red, green,blue,255); + return QColor(red, green, blue); } \ No newline at end of file From 1b0d243c0e9554b8e5b78f9867f293e0bbe6abe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sat, 28 Mar 2020 17:11:08 +0100 Subject: [PATCH 13/59] cgram debugger shows the cgram with it's colors and the debugger view of the colors is fix but the selection isn't working --- sources/Debugger/CGramDebug.cpp | 19 ++++--------- ui/cgramView.ui | 50 ++++++++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/sources/Debugger/CGramDebug.cpp b/sources/Debugger/CGramDebug.cpp index e8efde0..9c3e4e3 100644 --- a/sources/Debugger/CGramDebug.cpp +++ b/sources/Debugger/CGramDebug.cpp @@ -6,6 +6,7 @@ #include "../SNES.hpp" #include #include +#include #include "../Utility/Utility.hpp" #include "../Exceptions/InvalidAction.hpp" #include "../Exceptions/InvalidAddress.hpp" @@ -68,27 +69,19 @@ QVariant CGramModel::data(const QModelIndex &index, int role) const uint8_t red; uint8_t green; uint8_t blue; - //std::cout << "test1" << std::endl; + if (role == Qt::TextAlignmentRole) return Qt::AlignCenter; - //std::cout << "test2" << std::endl; - - //std::cout << "test3" << std::endl; - if (role != Qt::DisplayRole) + if (role != Qt::BackgroundRole) return QVariant(); - if (role == Qt::BackgroundRole) { - // std::cout << "test" << std::endl; - //unreachable - return 1; - } addressValue = this->_ppu.cgramRead(index.column() * 16 + index.row()); blue = (addressValue & 0x7D00U) >> 10U; green = (addressValue & 0x03E0U) >> 5U; red = (addressValue & 0x001FU); - red = (red * 255U / 31U) << 24U; - green = (green * 255U / 31U) << 16U; - blue = (blue * 255U / 31U) << 8U; + red = red * 255U / 31U; + green = green * 255U / 31U; + blue = blue * 255U / 31U; return QColor(red, green, blue); } \ No newline at end of file diff --git a/ui/cgramView.ui b/ui/cgramView.ui index 73c9102..efefb37 100644 --- a/ui/cgramView.ui +++ b/ui/cgramView.ui @@ -6,8 +6,8 @@ 0 0 - 461 - 346 + 472 + 380 @@ -26,16 +26,34 @@ - 300 - 300 + 324 + 324 - 300 - 300 + 324 + 324 + + false + + + QFrame::Box + + + QFrame::Sunken + + + 0 + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + true @@ -49,9 +67,27 @@ false + + 20 + + + 20 + + + false + false + + 20 + + + 20 + + + false + @@ -221,7 +257,7 @@ 0 0 - 461 + 472 22 From be44a54d30863ad54ec7192573b88649cc1d6017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sat, 28 Mar 2020 19:22:46 +0100 Subject: [PATCH 14/59] added palette viewer debugger to the drop down menu of debuggers --- sources/Debugger/CGramDebug.cpp | 21 ++++++++++++++++++--- sources/Debugger/CGramDebug.hpp | 4 ++-- sources/Renderer/QtRenderer/QtSFML.cpp | 9 +++++++++ sources/Renderer/QtRenderer/QtSFML.hpp | 2 ++ sources/main.cpp | 3 ++- 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/sources/Debugger/CGramDebug.cpp b/sources/Debugger/CGramDebug.cpp index 9c3e4e3..16a6050 100644 --- a/sources/Debugger/CGramDebug.cpp +++ b/sources/Debugger/CGramDebug.cpp @@ -7,9 +7,8 @@ #include #include #include +#include #include "../Utility/Utility.hpp" -#include "../Exceptions/InvalidAction.hpp" -#include "../Exceptions/InvalidAddress.hpp" namespace ComSquare::Debugger { @@ -26,7 +25,7 @@ namespace ComSquare::Debugger this->_ui.setupUi(this->_window); this->_ui.cgram_view->setModel(&this->_model); - + updateInfoTile(0); this->_window->show(); } @@ -49,6 +48,22 @@ namespace ComSquare::Debugger { return this->_ppu.cgramRead(addr); } + + void CGramDebug::updateInfoTile(uint8_t addr) + { + uint16_t cgramValue = this->_ppu.cgramRead(addr); + std::cout << "val " << cgramValue << std::endl; + uint8_t blue = (cgramValue & 0x7D00U) >> 10U; + uint8_t green = (cgramValue & 0x03E0U) >> 5U; + uint8_t red = (cgramValue & 0x001FU); + + this->_ui.indexLineEdit->setText(std::to_string(addr).c_str()); + this->_ui.valueLineEdit->setText(std::to_string(cgramValue).c_str()); + this->_ui.rLineEdit->setText(std::to_string(red).c_str()); + this->_ui.gLineEdit->setText(std::to_string(green).c_str()); + this->_ui.bLineEdit->setText(std::to_string(blue).c_str()); + this->_ui.hexLineEdit->setText(Utility::to_hex(cgramValue).c_str()); + } } CGramModel::CGramModel(ComSquare::PPU::PPU &ppu) : _ppu(ppu) {} diff --git a/sources/Debugger/CGramDebug.hpp b/sources/Debugger/CGramDebug.hpp index 8cdcbff..5be7822 100644 --- a/sources/Debugger/CGramDebug.hpp +++ b/sources/Debugger/CGramDebug.hpp @@ -111,12 +111,12 @@ namespace ComSquare::Debugger //! @param addr The address to read from. //! @return The color value in BGR, looks like this xbbbbbgggggrrrrr. uint16_t read(uint8_t addr); - //! @brief Focus the debugger's window. void focus(); - //! @brief Return true if the Bus is overloaded with debugging features. bool isDebugger(); + //! @brief Update the text fields with corresponding tile info + void updateInfoTile(uint8_t addr); }; } diff --git a/sources/Renderer/QtRenderer/QtSFML.cpp b/sources/Renderer/QtRenderer/QtSFML.cpp index 0471f67..d90a581 100644 --- a/sources/Renderer/QtRenderer/QtSFML.cpp +++ b/sources/Renderer/QtRenderer/QtSFML.cpp @@ -59,6 +59,10 @@ namespace ComSquare::Renderer busDebugger->setShortcut(Qt::Key_F5); QMainWindow::connect(busDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableDebugBus); debugger->addAction(busDebugger); + QAction *cgramDebugger = new QAction("Palette Viewer", &this->_window); + cgramDebugger->setShortcut(Qt::Key_F6); + QMainWindow::connect(cgramDebugger, &QAction::triggered, this->_sfWidget.get(), &QtFullSFML::enableCgramViewer); + debugger->addAction(cgramDebugger); this->_window.show(); } @@ -119,4 +123,9 @@ namespace ComSquare::Renderer { this->_snes.enableMemoryBusDebugging(); } + + void QtFullSFML::enableCgramViewer() + { + this->_snes.enableCgramDebugging(); + } } \ No newline at end of file diff --git a/sources/Renderer/QtRenderer/QtSFML.hpp b/sources/Renderer/QtRenderer/QtSFML.hpp index b971b82..661422c 100644 --- a/sources/Renderer/QtRenderer/QtSFML.hpp +++ b/sources/Renderer/QtRenderer/QtSFML.hpp @@ -33,6 +33,8 @@ namespace ComSquare::Renderer void enableDebugAPU(); //! @brief Action called when clicking on the enable Memory Bus debugger button. void enableDebugBus(); + //! @brief Action called when clicking on the enable Palette viewer button. + void enableCgramViewer(); //! @brief Action called when clicking on the reset button. void reset(); QtFullSFML(SNES &snes, QWidget* parent, const QPoint& position, const QSize& size, int frameRate = 0); diff --git a/sources/main.cpp b/sources/main.cpp index 3a4ba82..9c4de9b 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -19,7 +19,8 @@ void usage(char *bin) << "\t-c, --cpu: \tEnable the debugger of the CPU." << std::endl << "\t-m, --memory: \tEnable the memory viewer panel." << std::endl << "\t-h, --header: \tShow the header of the cartridge." << std::endl - << "\t-b, --bus: \tShow the memory bus's log." << std::endl; + << "\t-b, --bus: \tShow the memory bus's log." << std::endl + << "\t-g, --cgram: \tShow the palette viewer." << std::endl; } void parseArguments(int argc, char **argv, SNES &snes) From 7fc2871faa9ed4bc219164fb2c40deaffcf1d349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sat, 28 Mar 2020 19:34:51 +0100 Subject: [PATCH 15/59] fixed the updateInfoTile --- sources/Debugger/CGramDebug.cpp | 7 +++++-- ui/cgramView.ui | 12 ++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/sources/Debugger/CGramDebug.cpp b/sources/Debugger/CGramDebug.cpp index 16a6050..d2923a7 100644 --- a/sources/Debugger/CGramDebug.cpp +++ b/sources/Debugger/CGramDebug.cpp @@ -52,17 +52,20 @@ namespace ComSquare::Debugger void CGramDebug::updateInfoTile(uint8_t addr) { uint16_t cgramValue = this->_ppu.cgramRead(addr); - std::cout << "val " << cgramValue << std::endl; uint8_t blue = (cgramValue & 0x7D00U) >> 10U; uint8_t green = (cgramValue & 0x03E0U) >> 5U; uint8_t red = (cgramValue & 0x001FU); + uint24_t hexColorValue = 0; this->_ui.indexLineEdit->setText(std::to_string(addr).c_str()); this->_ui.valueLineEdit->setText(std::to_string(cgramValue).c_str()); this->_ui.rLineEdit->setText(std::to_string(red).c_str()); this->_ui.gLineEdit->setText(std::to_string(green).c_str()); this->_ui.bLineEdit->setText(std::to_string(blue).c_str()); - this->_ui.hexLineEdit->setText(Utility::to_hex(cgramValue).c_str()); + hexColorValue += (red * 255U / 31U) << 16U; + hexColorValue += (green * 255U / 31U) << 8U; + hexColorValue += (blue * 255U / 31U); + this->_ui.hexLineEdit->setText(Utility::to_hex(hexColorValue).c_str()); } } diff --git a/ui/cgramView.ui b/ui/cgramView.ui index efefb37..64a7c21 100644 --- a/ui/cgramView.ui +++ b/ui/cgramView.ui @@ -103,7 +103,7 @@ - 70 + 75 16777215 @@ -129,7 +129,7 @@ - 70 + 75 16777215 @@ -155,7 +155,7 @@ - 70 + 75 16777215 @@ -181,7 +181,7 @@ - 70 + 75 16777215 @@ -207,7 +207,7 @@ - 70 + 75 16777215 @@ -233,7 +233,7 @@ - 70 + 75 16777215 From c23341093cfabef700c15e3b0b4aeb6ceebd554a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sun, 29 Mar 2020 00:00:10 +0100 Subject: [PATCH 16/59] fixed some parameters of the ui --- ui/cgramView.ui | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ui/cgramView.ui b/ui/cgramView.ui index 64a7c21..d0bf2dd 100644 --- a/ui/cgramView.ui +++ b/ui/cgramView.ui @@ -49,7 +49,10 @@ 0 - QAbstractItemView::NoEditTriggers + QAbstractItemView::CurrentChanged|QAbstractItemView::SelectedClicked + + + QAbstractItemView::NoDragDrop QAbstractItemView::SingleSelection @@ -57,6 +60,12 @@ true + + false + + + false + 0 From 65a00f55a206ecfc6198c5e4a3bbd4b8183f3a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sat, 4 Apr 2020 22:49:31 +0200 Subject: [PATCH 17/59] cgram oamram and vram are now RAM type and the storage method need to be fix --- CMakeLists.txt | 2 +- sources/PPU/PPU.cpp | 36 ++++++++++++++++++++++++++++-------- sources/PPU/PPU.hpp | 11 +++++++---- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d92bce..b64b32b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -208,7 +208,7 @@ add_executable(ComSquare sources/Models/Components.hpp sources/Debugger/CGramDebug.cpp sources/Debugger/CGramDebug.hpp -) + ) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 4390bc4..5a242e7 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -7,14 +7,15 @@ #include "PPU.hpp" #include "../Exceptions/NotImplementedException.hpp" #include "../Exceptions/InvalidAddress.hpp" +#include "../Ram/Ram.hpp" namespace ComSquare::PPU { PPU::PPU(Renderer::IRenderer &renderer): _renderer(renderer), - _vram(65536), - _oamram(544), - _cgram(512) + _vram(65536, ComSquare::VRam, "VRAM"), + _oamram(544, ComSquare::OAMRam, "OAMRAM"), + _cgram(512, ComSquare::CGRam, "CGRAM") { this->_registers._isLowByte = true; } @@ -29,8 +30,9 @@ namespace ComSquare::PPU case 0x36: return this->_registers._mpy.mpyh; default: - throw InvalidAddress("PPU Internal Registers read", addr); - } + //throw InvalidAddress("PPU Internal Registers read", addr); + std::cout << "PPU Internal Registers read" << addr << std::endl; + } } void PPU::write(uint24_t addr, uint8_t data) @@ -143,7 +145,9 @@ namespace ComSquare::PPU } else { this->_registers._cgdata.cgdatah = data; - this->_cgram.write(this->_registers._cgadd, this->_registers._cgdata.raw); + this->_cgram.write(this->_registers._cgadd, this->_registers._cgdata.cgdatah); + this->_registers._cgadd++; + this->_cgram.write(this->_registers._cgadd, this->_registers._cgdata.cgdatal); this->_registers._cgadd++; } this->_registers._isLowByte = !this->_registers._isLowByte; @@ -222,9 +226,9 @@ namespace ComSquare::PPU uint8_t blue; uint32_t pixelTmp = 0x0; if (!this->_registers._inidisp.fblank) { - for (int y = 0; y <= 255; y++) { + for (int y = 0; y <= 255; y += 2) { tmp = this->_cgram.read(y); - + tmp += this->_cgram.read( y + 1) << 8; blue = (tmp & 0x7D00U) >> 10U; green = (tmp & 0x03E0U) >> 5U; red = (tmp & 0x001FU); @@ -396,4 +400,20 @@ namespace ComSquare::PPU { return this->_cgram.read(addr); } + + void PPU::renderBackground(int bgNumber, std::vector characterSize, int bpp, bool priority) + { + int nbCharactersHeight = (this->_registers._bgsc[bgNumber].tilemapVerticalMirroring) ? 64 : 32; + int nbCharactersWidth = (this->_registers._bgsc[bgNumber].tilemapHorizontalMirroring) ? 64 : 32; + uint16_t vramAddress = this->_registers._bgsc[bgNumber].tilemapAddress >> 8U; + uint16_t tilemapValue; + + for (int i = 0; i < nbCharactersHeight * nbCharactersWidth; i++) { + for (int j = 0; j < 0x800; j++) { + tilemapValue = this->_vram.read(vramAddress); + vramAddress++; + + } + } + } } \ No newline at end of file diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index 272b6dd..ccea871 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -9,7 +9,8 @@ #include "../Memory/AMemory.hpp" #include "../Memory/MemoryBus.hpp" #include "../Renderer/IRenderer.hpp" -#include "../Ram/ExtendedRam.hpp" +//#include "../Ram/ExtendedRam.hpp" +#include "../Ram/Ram.hpp" //#define max2BitTiles 4096 //#define max4BitTiles 2048 @@ -500,9 +501,9 @@ namespace ComSquare::PPU //! @brief Init ppuRegisters Registers _registers{}; Renderer::IRenderer &_renderer; - Ram::ExtendedRam _vram; - Ram::ExtendedRam _oamram; - Ram::ExtendedRam _cgram; + Ram::Ram _vram; + Ram::Ram _oamram; + Ram::Ram _cgram; public: explicit PPU(Renderer::IRenderer &renderer); PPU(const PPU &) = delete; @@ -535,6 +536,8 @@ namespace ComSquare::PPU virtual bool isDebugger(); //! @brief Allow others components to read the CGRAM (Debuggers) uint16_t cgramRead(uint8_t addr); + //! @brief Render a background on the screen + void renderBackground(int bgNumber, std::vector characterSize, int bpp, bool priority); }; } #endif //COMSQUARE_PPU_HPP From 30198a5ad26ba9dbcb035dc4d2ad2c106fb57a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sun, 5 Apr 2020 15:52:06 +0200 Subject: [PATCH 18/59] adding getters to ppus maps and modifing ram writes --- sources/Debugger/MemoryViewer.cpp | 8 +++---- sources/PPU/PPU.cpp | 36 ++++++++++++++++++++++--------- sources/PPU/PPU.hpp | 6 ++++++ 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/sources/Debugger/MemoryViewer.cpp b/sources/Debugger/MemoryViewer.cpp index f3880fc..acc55a2 100644 --- a/sources/Debugger/MemoryViewer.cpp +++ b/sources/Debugger/MemoryViewer.cpp @@ -80,7 +80,7 @@ namespace ComSquare::Debugger this->_ui.tabs->addTab("&WRam"); this->_ui.tabs->addTab("&SRam"); this->_ui.tabs->addTab("&Rom"); -// this->_ui.tabs->addTab("&VRam"); + //this->_ui.tabs->addTab("&CGRam"); QMainWindow::connect(this->_ui.actionGoto, &QAction::triggered, this, &MemoryViewer::gotoAddr); QMainWindow::connect(this->_ui.actionGoto_Absolute, &QAction::triggered, this, &MemoryViewer::gotoAbsoluteAddr); QObject::connect(this->_ui.tabs, &QTabBar::currentChanged, this, &MemoryViewer::changeRam); @@ -105,9 +105,9 @@ namespace ComSquare::Debugger case 2: this->_model.setMemory(this->_snes.cartridge); break; -// case 3: -// this->_model.setMemory(this->_snes.vram); -// break; + // case 3: + // this->_model.setMemory(std::make_shared(this->_snes.ppu->getPpuCgRam())); + // break; } } diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 5a242e7..05bc892 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -55,7 +55,7 @@ namespace ComSquare::PPU //throw InvalidAddress("oamdata", addr); std::cout << "oamdata" << std::endl; // the oamAddress have to be calculated if fblank or not (not implemented) - _oamram.write(this->_registers._oamadd.oamAddress, this->_registers._oamdata); + _oamram.write_internal(this->_registers._oamadd.oamAddress, this->_registers._oamdata); this->_registers._oamadd.oamAddress++; break; case ppuRegisters::bgmode: @@ -109,19 +109,20 @@ namespace ComSquare::PPU break; case ppuRegisters::vmdatal: //throw InvalidAddress("vmdata", addr); - std::cout << "vmdatal" << std::endl; + //std::cout << "vmdatal" << std::endl; if (!this->_registers._inidisp.fblank) { this->_registers._vmdata.vmdatal = data; - this->_vram.write(getVramAddress(), this->_registers._vmdata.vmdata); + this->_vram.write_internal(getVramAddress(), this->_registers._vmdata.vmdata); } if (!this->_registers._vmain.incrementMode) this->_registers._vmadd.vmadd += this->_registers._incrementAmount; break; case ppuRegisters::vmdatah: - std::cout << "vmdatah" << std::endl; + //std::cout << "vmdatah" << std::endl; if (!this->_registers._inidisp.fblank) { this->_registers._vmdata.vmdatah = data; - this->_vram.write(getVramAddress(), this->_registers._vmdata.vmdata); + this->_vram.write_internal(getVramAddress(), this->_registers._vmdata.vmdatal); + this->_vram.write_internal(getVramAddress(), this->_registers._vmdata.vmdatah); } if (this->_registers._vmain.incrementMode) this->_registers._vmadd.vmadd += this->_registers._incrementAmount; @@ -145,9 +146,9 @@ namespace ComSquare::PPU } else { this->_registers._cgdata.cgdatah = data; - this->_cgram.write(this->_registers._cgadd, this->_registers._cgdata.cgdatah); + this->_cgram.write_internal(this->_registers._cgadd, this->_registers._cgdata.cgdatal); this->_registers._cgadd++; - this->_cgram.write(this->_registers._cgadd, this->_registers._cgdata.cgdatal); + this->_cgram.write_internal(this->_registers._cgadd, this->_registers._cgdata.cgdatah); this->_registers._cgadd++; } this->_registers._isLowByte = !this->_registers._isLowByte; @@ -227,8 +228,8 @@ namespace ComSquare::PPU uint32_t pixelTmp = 0x0; if (!this->_registers._inidisp.fblank) { for (int y = 0; y <= 255; y += 2) { - tmp = this->_cgram.read(y); - tmp += this->_cgram.read( y + 1) << 8; + tmp = this->_cgram.read_internal(y); + tmp += this->_cgram.read_internal( y + 1) << 8; blue = (tmp & 0x7D00U) >> 10U; green = (tmp & 0x03E0U) >> 5U; red = (tmp & 0x001FU); @@ -398,7 +399,7 @@ namespace ComSquare::PPU uint16_t PPU::cgramRead(uint8_t addr) { - return this->_cgram.read(addr); + return this->_cgram.read_internal(addr); } void PPU::renderBackground(int bgNumber, std::vector characterSize, int bpp, bool priority) @@ -416,4 +417,19 @@ namespace ComSquare::PPU } } } + + Ram::Ram &PPU::getPpuCgRam() + { + return this->_cgram; + } + + Ram::Ram &PPU::getPpuVRam() + { + return this->_vram; + } + + Ram::Ram &PPU::getPpuOAMRam() + { + return this->_oamram; + } } \ No newline at end of file diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index ccea871..ed2a16a 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -536,6 +536,12 @@ namespace ComSquare::PPU virtual bool isDebugger(); //! @brief Allow others components to read the CGRAM (Debuggers) uint16_t cgramRead(uint8_t addr); + //! @brief Allow Memory Viewer debugger to access the CGRAM + Ram::Ram &getPpuCgRam(); + //! @brief Allow Memory Viewer debugger to access the VRAM + Ram::Ram &getPpuVRam(); + //! @brief Allow Memory Viewer debugger to access the OAMRAM + Ram::Ram &getPpuOAMRam(); //! @brief Render a background on the screen void renderBackground(int bgNumber, std::vector characterSize, int bpp, bool priority); }; From 63d4ac94ab3e21227377a836ac5ee5df901a5773 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Sun, 5 Apr 2020 16:22:01 +0200 Subject: [PATCH 19/59] Adding PPU's Ram to the debugger --- sources/Debugger/MemoryViewer.cpp | 16 +++++++++--- sources/PPU/PPU.cpp | 41 ++++++++++--------------------- sources/PPU/PPU.hpp | 13 +++------- 3 files changed, 29 insertions(+), 41 deletions(-) diff --git a/sources/Debugger/MemoryViewer.cpp b/sources/Debugger/MemoryViewer.cpp index acc55a2..2e1b6b4 100644 --- a/sources/Debugger/MemoryViewer.cpp +++ b/sources/Debugger/MemoryViewer.cpp @@ -80,7 +80,9 @@ namespace ComSquare::Debugger this->_ui.tabs->addTab("&WRam"); this->_ui.tabs->addTab("&SRam"); this->_ui.tabs->addTab("&Rom"); - //this->_ui.tabs->addTab("&CGRam"); + this->_ui.tabs->addTab("&CGRam"); + this->_ui.tabs->addTab("&VRam"); + this->_ui.tabs->addTab("&OAMRam"); QMainWindow::connect(this->_ui.actionGoto, &QAction::triggered, this, &MemoryViewer::gotoAddr); QMainWindow::connect(this->_ui.actionGoto_Absolute, &QAction::triggered, this, &MemoryViewer::gotoAbsoluteAddr); QObject::connect(this->_ui.tabs, &QTabBar::currentChanged, this, &MemoryViewer::changeRam); @@ -105,9 +107,15 @@ namespace ComSquare::Debugger case 2: this->_model.setMemory(this->_snes.cartridge); break; - // case 3: - // this->_model.setMemory(std::make_shared(this->_snes.ppu->getPpuCgRam())); - // break; + case 3: + this->_model.setMemory(this->_snes.ppu->cgram); + break; + case 4: + this->_model.setMemory(this->_snes.ppu->vram); + break; + case 5: + this->_model.setMemory(this->_snes.ppu->oamram); + break; } } diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 05bc892..1813238 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -13,9 +13,9 @@ namespace ComSquare::PPU { PPU::PPU(Renderer::IRenderer &renderer): _renderer(renderer), - _vram(65536, ComSquare::VRam, "VRAM"), - _oamram(544, ComSquare::OAMRam, "OAMRAM"), - _cgram(512, ComSquare::CGRam, "CGRAM") + vram(new Ram::Ram(65536, ComSquare::VRam, "VRAM")), + oamram(new Ram::Ram(544, ComSquare::OAMRam, "OAMRAM")), + cgram(new Ram::Ram(512, ComSquare::CGRam, "CGRAM")) { this->_registers._isLowByte = true; } @@ -55,7 +55,7 @@ namespace ComSquare::PPU //throw InvalidAddress("oamdata", addr); std::cout << "oamdata" << std::endl; // the oamAddress have to be calculated if fblank or not (not implemented) - _oamram.write_internal(this->_registers._oamadd.oamAddress, this->_registers._oamdata); + oamram->write_internal(this->_registers._oamadd.oamAddress, this->_registers._oamdata); this->_registers._oamadd.oamAddress++; break; case ppuRegisters::bgmode: @@ -112,7 +112,7 @@ namespace ComSquare::PPU //std::cout << "vmdatal" << std::endl; if (!this->_registers._inidisp.fblank) { this->_registers._vmdata.vmdatal = data; - this->_vram.write_internal(getVramAddress(), this->_registers._vmdata.vmdata); + this->vram->write_internal(getVramAddress(), this->_registers._vmdata.vmdata); } if (!this->_registers._vmain.incrementMode) this->_registers._vmadd.vmadd += this->_registers._incrementAmount; @@ -121,8 +121,8 @@ namespace ComSquare::PPU //std::cout << "vmdatah" << std::endl; if (!this->_registers._inidisp.fblank) { this->_registers._vmdata.vmdatah = data; - this->_vram.write_internal(getVramAddress(), this->_registers._vmdata.vmdatal); - this->_vram.write_internal(getVramAddress(), this->_registers._vmdata.vmdatah); + this->vram->write_internal(getVramAddress(), this->_registers._vmdata.vmdatal); + this->vram->write_internal(getVramAddress(), this->_registers._vmdata.vmdatah); } if (this->_registers._vmain.incrementMode) this->_registers._vmadd.vmadd += this->_registers._incrementAmount; @@ -146,9 +146,9 @@ namespace ComSquare::PPU } else { this->_registers._cgdata.cgdatah = data; - this->_cgram.write_internal(this->_registers._cgadd, this->_registers._cgdata.cgdatal); + this->cgram->write_internal(this->_registers._cgadd, this->_registers._cgdata.cgdatal); this->_registers._cgadd++; - this->_cgram.write_internal(this->_registers._cgadd, this->_registers._cgdata.cgdatah); + this->cgram->write_internal(this->_registers._cgadd, this->_registers._cgdata.cgdatah); this->_registers._cgadd++; } this->_registers._isLowByte = !this->_registers._isLowByte; @@ -228,8 +228,8 @@ namespace ComSquare::PPU uint32_t pixelTmp = 0x0; if (!this->_registers._inidisp.fblank) { for (int y = 0; y <= 255; y += 2) { - tmp = this->_cgram.read_internal(y); - tmp += this->_cgram.read_internal( y + 1) << 8; + tmp = this->cgram->read_internal(y); + tmp += this->cgram->read_internal(y + 1) << 8; blue = (tmp & 0x7D00U) >> 10U; green = (tmp & 0x03E0U) >> 5U; red = (tmp & 0x001FU); @@ -399,7 +399,7 @@ namespace ComSquare::PPU uint16_t PPU::cgramRead(uint8_t addr) { - return this->_cgram.read_internal(addr); + return this->cgram->read_internal(addr); } void PPU::renderBackground(int bgNumber, std::vector characterSize, int bpp, bool priority) @@ -411,25 +411,10 @@ namespace ComSquare::PPU for (int i = 0; i < nbCharactersHeight * nbCharactersWidth; i++) { for (int j = 0; j < 0x800; j++) { - tilemapValue = this->_vram.read(vramAddress); + tilemapValue = this->vram->read(vramAddress); vramAddress++; } } } - - Ram::Ram &PPU::getPpuCgRam() - { - return this->_cgram; - } - - Ram::Ram &PPU::getPpuVRam() - { - return this->_vram; - } - - Ram::Ram &PPU::getPpuOAMRam() - { - return this->_oamram; - } } \ No newline at end of file diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index ed2a16a..272d6b6 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -501,10 +501,11 @@ namespace ComSquare::PPU //! @brief Init ppuRegisters Registers _registers{}; Renderer::IRenderer &_renderer; - Ram::Ram _vram; - Ram::Ram _oamram; - Ram::Ram _cgram; public: + std::shared_ptr vram; + std::shared_ptr oamram; + std::shared_ptr cgram; + explicit PPU(Renderer::IRenderer &renderer); PPU(const PPU &) = delete; PPU &operator=(const PPU &) = delete; @@ -536,12 +537,6 @@ namespace ComSquare::PPU virtual bool isDebugger(); //! @brief Allow others components to read the CGRAM (Debuggers) uint16_t cgramRead(uint8_t addr); - //! @brief Allow Memory Viewer debugger to access the CGRAM - Ram::Ram &getPpuCgRam(); - //! @brief Allow Memory Viewer debugger to access the VRAM - Ram::Ram &getPpuVRam(); - //! @brief Allow Memory Viewer debugger to access the OAMRAM - Ram::Ram &getPpuOAMRam(); //! @brief Render a background on the screen void renderBackground(int bgNumber, std::vector characterSize, int bpp, bool priority); }; From d6bf2e1b567a62b7ab5254538aa4e82ad4b1ac93 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Sun, 5 Apr 2020 17:08:37 +0200 Subject: [PATCH 20/59] Displaying ??? when we don't know what we read on the bus's debugger --- sources/Debugger/MemoryBusDebug.cpp | 10 ++++++---- sources/Debugger/MemoryBusDebug.hpp | 4 ++-- sources/PPU/PPU.cpp | 3 +-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/sources/Debugger/MemoryBusDebug.cpp b/sources/Debugger/MemoryBusDebug.cpp index e1548e5..f8997fe 100644 --- a/sources/Debugger/MemoryBusDebug.cpp +++ b/sources/Debugger/MemoryBusDebug.cpp @@ -161,17 +161,17 @@ namespace ComSquare::Debugger void MemoryBusDebug::write(uint24_t addr, uint8_t data) { auto accessor = this->getAccessor(addr); - uint8_t value; + std::optional value; try { value = accessor->read(addr - accessor->getStart()); } catch (InvalidAddress &) { - value = 0; + value = std::nullopt; } this->_model.log(BusLog(true, addr, accessor, value, data)); MemoryBus::write(addr, data); } - BusLog::BusLog(bool _write, uint24_t _addr, std::shared_ptr &_accessor, uint8_t _oldData, uint8_t _newData) : + BusLog::BusLog(bool _write, uint24_t _addr, std::shared_ptr &_accessor, std::optional _oldData, uint8_t _newData) : write(_write), addr(_addr), accessor(std::move(_accessor)), oldData(_oldData), newData(_newData) {} } @@ -203,7 +203,9 @@ QVariant BusLogModel::data(const QModelIndex &index, int role) const case 3: return QString(log.accessor ? log.accessor->getValueName(log.addr - log.accessor->getStart()).c_str() : "Open bus"); case 4: - return QString(ComSquare::Utility::to_hex(log.oldData).c_str()); + if (!log.oldData) + return QString("???"); + return QString(ComSquare::Utility::to_hex(*log.oldData).c_str()); case 5: return QString(ComSquare::Utility::to_hex(log.newData).c_str()); default: diff --git a/sources/Debugger/MemoryBusDebug.hpp b/sources/Debugger/MemoryBusDebug.hpp index 6f7ff3b..9e6cbd8 100644 --- a/sources/Debugger/MemoryBusDebug.hpp +++ b/sources/Debugger/MemoryBusDebug.hpp @@ -15,12 +15,12 @@ namespace ComSquare::Debugger { //! @brief The struct used to represent memory bus logs. struct BusLog { - BusLog(bool write, uint24_t addr, std::shared_ptr &accessor, uint8_t oldData, uint8_t newData); + BusLog(bool write, uint24_t addr, std::shared_ptr &accessor, std::optional oldData, uint8_t newData); bool write; uint24_t addr; std::shared_ptr accessor; - uint8_t oldData; + std::optional oldData; uint8_t newData; }; diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 1813238..4b6748e 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -30,8 +30,7 @@ namespace ComSquare::PPU case 0x36: return this->_registers._mpy.mpyh; default: - //throw InvalidAddress("PPU Internal Registers read", addr); - std::cout << "PPU Internal Registers read" << addr << std::endl; + throw InvalidAddress("PPU Internal Registers read", addr); } } From 33dfb9e09cb840df2e3812c43d79259a1b3441d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sun, 5 Apr 2020 17:14:03 +0200 Subject: [PATCH 21/59] fiw the prototype of getVramAddress uint8 -> uint16 --- sources/PPU/PPU.cpp | 9 ++++----- sources/PPU/PPU.hpp | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 1813238..fc944fb 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -30,8 +30,8 @@ namespace ComSquare::PPU case 0x36: return this->_registers._mpy.mpyh; default: - //throw InvalidAddress("PPU Internal Registers read", addr); - std::cout << "PPU Internal Registers read" << addr << std::endl; + throw InvalidAddress("PPU Internal Registers read", addr); + //std::cout << "PPU Internal Registers read" << addr << std::endl; } } @@ -112,7 +112,7 @@ namespace ComSquare::PPU //std::cout << "vmdatal" << std::endl; if (!this->_registers._inidisp.fblank) { this->_registers._vmdata.vmdatal = data; - this->vram->write_internal(getVramAddress(), this->_registers._vmdata.vmdata); + this->vram->write_internal(getVramAddress(), this->_registers._vmdata.vmdatal); } if (!this->_registers._vmain.incrementMode) this->_registers._vmadd.vmadd += this->_registers._incrementAmount; @@ -121,7 +121,6 @@ namespace ComSquare::PPU //std::cout << "vmdatah" << std::endl; if (!this->_registers._inidisp.fblank) { this->_registers._vmdata.vmdatah = data; - this->vram->write_internal(getVramAddress(), this->_registers._vmdata.vmdatal); this->vram->write_internal(getVramAddress(), this->_registers._vmdata.vmdatah); } if (this->_registers._vmain.incrementMode) @@ -202,7 +201,7 @@ namespace ComSquare::PPU } } - uint8_t PPU::getVramAddress() + uint16_t PPU::getVramAddress() { uint16_t vanillaAddress = this->_registers._vmadd.vmadd; diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index 272d6b6..cd54117 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -530,7 +530,7 @@ namespace ComSquare::PPU //! @param The number of cycles to update. virtual void update(unsigned cycles); //! @brief Give the Vram Address with the right Address remapping - uint8_t getVramAddress(); + uint16_t getVramAddress(); //! @brief Give the name of the Address register (used for debug) std::string getValueName(uint24_t addr); //! @brief Return true if the CPU is overloaded with debugging features. From bb2111f3ee151192c7dcf9f511a07420d49a6971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sun, 5 Apr 2020 17:24:12 +0200 Subject: [PATCH 22/59] ppu read use ppuRegisters enum instead of their real address --- sources/PPU/PPU.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index fc944fb..3e7ea0d 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -23,14 +23,14 @@ namespace ComSquare::PPU uint8_t PPU::read(uint24_t addr) { switch (addr) { - case 0x34: + case ppuRegisters::mpyl: return this->_registers._mpy.mpyl; - case 0x35: + case ppuRegisters::mpym: return this->_registers._mpy.mpym; - case 0x36: + case ppuRegisters::mpyh: return this->_registers._mpy.mpyh; default: - throw InvalidAddress("PPU Internal Registers read", addr); + throw InvalidAddress("PPU Internal Registers read ", addr); //std::cout << "PPU Internal Registers read" << addr << std::endl; } } From 8fa40ad5e09ed2e8bd7b2300980c4942e578381e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sun, 5 Apr 2020 18:29:06 +0200 Subject: [PATCH 23/59] the CGRam debugger is fixed display correctly the cgram and cgram value getter supports all 512 entries of the ram --- sources/Debugger/CGramDebug.cpp | 8 +++++++- sources/PPU/PPU.cpp | 2 +- sources/PPU/PPU.hpp | 2 +- sources/Ram/Ram.hpp | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/sources/Debugger/CGramDebug.cpp b/sources/Debugger/CGramDebug.cpp index 7d46c6f..7150d9f 100644 --- a/sources/Debugger/CGramDebug.cpp +++ b/sources/Debugger/CGramDebug.cpp @@ -5,7 +5,9 @@ #include "CGramDebug.hpp" #include "../SNES.hpp" #include +#include #include +#include #include "../Utility/Utility.hpp" namespace ComSquare::Debugger @@ -50,6 +52,7 @@ namespace ComSquare::Debugger void CGramDebug::updateInfoTile(uint8_t addr) { uint16_t cgramValue = this->_ppu.cgramRead(addr); + cgramValue += this->_ppu.cgramRead(addr + 1) << 8; uint8_t blue = (cgramValue & 0x7D00U) >> 10U; uint8_t green = (cgramValue & 0x03E0U) >> 5U; uint8_t red = (cgramValue & 0x001FU); @@ -90,7 +93,10 @@ QVariant CGramModel::data(const QModelIndex &index, int role) const return Qt::AlignCenter; if (role != Qt::BackgroundRole) return QVariant(); - addressValue = this->_ppu.cgramRead(index.column() * 16 + index.row()); + int idDisplayTile = index.row() * 16 + index.column(); + uint16_t cgramAddress = idDisplayTile / 8 * 16 + (idDisplayTile % 8 * 2); + addressValue = this->_ppu.cgramRead(cgramAddress); + addressValue += this->_ppu.cgramRead(cgramAddress + 1) << 8U; blue = (addressValue & 0x7D00U) >> 10U; green = (addressValue & 0x03E0U) >> 5U; diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 3e7ea0d..3eacb63 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -396,7 +396,7 @@ namespace ComSquare::PPU return false; } - uint16_t PPU::cgramRead(uint8_t addr) + uint16_t PPU::cgramRead(uint16_t addr) { return this->cgram->read_internal(addr); } diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index cd54117..97987a1 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -536,7 +536,7 @@ namespace ComSquare::PPU //! @brief Return true if the CPU is overloaded with debugging features. virtual bool isDebugger(); //! @brief Allow others components to read the CGRAM (Debuggers) - uint16_t cgramRead(uint8_t addr); + uint16_t cgramRead(uint16_t addr); //! @brief Render a background on the screen void renderBackground(int bgNumber, std::vector characterSize, int bpp, bool priority); }; diff --git a/sources/Ram/Ram.hpp b/sources/Ram/Ram.hpp index d9297e7..b7ba17e 100644 --- a/sources/Ram/Ram.hpp +++ b/sources/Ram/Ram.hpp @@ -13,7 +13,7 @@ namespace ComSquare::Ram protected: //! @brief The ram. (Can be used for WRam, SRam, VRam etc) uint8_t *_data; - //! @brief The size of the ram (iny bytes). + //! @brief The size of the ram (in bytes). size_t _size; //! @brief An id identifying the type of memory this is (for the debugger) Component _ramType; From 4c6a5e9030794fec7e25cb439e0c225b47b3b972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sun, 5 Apr 2020 18:53:09 +0200 Subject: [PATCH 24/59] removing unused headers in cgramdebug.cpp --- sources/Debugger/CGramDebug.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/sources/Debugger/CGramDebug.cpp b/sources/Debugger/CGramDebug.cpp index 7150d9f..6694841 100644 --- a/sources/Debugger/CGramDebug.cpp +++ b/sources/Debugger/CGramDebug.cpp @@ -5,9 +5,7 @@ #include "CGramDebug.hpp" #include "../SNES.hpp" #include -#include #include -#include #include "../Utility/Utility.hpp" namespace ComSquare::Debugger From 4015538404bb6424d3a5f697850cee6e64b4f22a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Sun, 5 Apr 2020 19:05:01 +0200 Subject: [PATCH 25/59] fixing the test cgram_data_full (address is now incremented twice) --- tests/PPU/testPpuWriteFromVmain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PPU/testPpuWriteFromVmain.cpp b/tests/PPU/testPpuWriteFromVmain.cpp index 5fe1fb7..df4f295 100644 --- a/tests/PPU/testPpuWriteFromVmain.cpp +++ b/tests/PPU/testPpuWriteFromVmain.cpp @@ -98,7 +98,7 @@ Test(PPU_write_2, cgdata_data_full) snes._bus->write(0x2122, 0b11111000); cr_assert_eq(snes.ppu->_registers._cgdata.cgdatah, 0b11111000); cr_assert_eq(snes.ppu->_registers._isLowByte, true); - cr_assert_eq(snes.ppu->_registers._cgadd, address + 1); + cr_assert_eq(snes.ppu->_registers._cgadd, address + 2); } Test(PPU_write_2, m7sel_data_full) From 8a48900c7f6989f095a3960518eff33bcdbd082c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Mon, 6 Apr 2020 02:01:45 +0200 Subject: [PATCH 26/59] CGRAM debugger supports mouse clicks on tiles and the PPU's constructor init the cgram (debug) --- sources/Debugger/CGramDebug.cpp | 30 +++++++++++++++++++++++++----- sources/Debugger/CGramDebug.hpp | 15 +++++++++++++-- sources/PPU/PPU.cpp | 5 ++++- ui/cgramView.ui | 11 ++++++++++- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/sources/Debugger/CGramDebug.cpp b/sources/Debugger/CGramDebug.cpp index 6694841..f2ae435 100644 --- a/sources/Debugger/CGramDebug.cpp +++ b/sources/Debugger/CGramDebug.cpp @@ -6,6 +6,8 @@ #include "../SNES.hpp" #include #include +#include +#include #include "../Utility/Utility.hpp" namespace ComSquare::Debugger @@ -22,9 +24,11 @@ namespace ComSquare::Debugger this->_window->setAttribute(Qt::WA_DeleteOnClose); this->_ui.setupUi(this->_window); + QMainWindow::connect(this->_ui.cgram_view, &QTableView::pressed, this, &CGramDebug::tileClicked); this->_ui.cgram_view->setModel(&this->_model); - updateInfoTile(0); + updateInfoTile(0, 0); this->_window->show(); + QEvent::registerEventType(); } void CGramDebug::disableViewer() @@ -47,8 +51,10 @@ namespace ComSquare::Debugger return this->_ppu.cgramRead(addr); } - void CGramDebug::updateInfoTile(uint8_t addr) + void CGramDebug::updateInfoTile(int row, int column) { + int idTile = row * 16 + column; + uint16_t addr = idTile / 8 * 16 + (idTile % 8 * 2); uint16_t cgramValue = this->_ppu.cgramRead(addr); cgramValue += this->_ppu.cgramRead(addr + 1) << 8; uint8_t blue = (cgramValue & 0x7D00U) >> 10U; @@ -56,8 +62,8 @@ namespace ComSquare::Debugger uint8_t red = (cgramValue & 0x001FU); uint24_t hexColorValue = 0; - this->_ui.indexLineEdit->setText(std::to_string(addr).c_str()); - this->_ui.valueLineEdit->setText(std::to_string(cgramValue).c_str()); + this->_ui.indexLineEdit->setText(std::to_string(addr / 2).c_str()); + this->_ui.valueLineEdit->setText(Utility::to_hex(cgramValue).c_str()); this->_ui.rLineEdit->setText(std::to_string(red).c_str()); this->_ui.gLineEdit->setText(std::to_string(green).c_str()); this->_ui.bLineEdit->setText(std::to_string(blue).c_str()); @@ -66,6 +72,13 @@ namespace ComSquare::Debugger hexColorValue += (blue * 255U / 31U); this->_ui.hexLineEdit->setText(Utility::to_hex(hexColorValue).c_str()); } + + void CGramDebug::tileClicked(const QModelIndex &index) + { + if (!index.isValid()) + return; + this->updateInfoTile(index.row(), index.column()); + } } CGramModel::CGramModel(ComSquare::PPU::PPU &ppu) : _ppu(ppu) {} @@ -104,4 +117,11 @@ QVariant CGramModel::data(const QModelIndex &index, int role) const green = green * 255U / 31U; blue = blue * 255U / 31U; return QColor(red, green, blue); -} \ No newline at end of file +} + +void CGramModel::enterEvent(QMouseEvent *event) +{ + this->x = event->x(); + this->y = event->y(); + emit mouseEnter(); +} diff --git a/sources/Debugger/CGramDebug.hpp b/sources/Debugger/CGramDebug.hpp index 5be7822..018b2e6 100644 --- a/sources/Debugger/CGramDebug.hpp +++ b/sources/Debugger/CGramDebug.hpp @@ -9,6 +9,9 @@ #include "../PPU/PPU.hpp" #include "../../ui/ui_cgramView.h" #include +#include +#include +#include #include "ClosableWindow.hpp" @@ -70,6 +73,8 @@ public: const int column = 16; //! @brief The number of rows const int rows = 16; + int x; + int y; explicit CGramModel(ComSquare::PPU::PPU &ppu); CGramModel(const CGramModel &) = delete; const CGramModel &operator=(const CGramModel &) = delete; @@ -81,12 +86,16 @@ public: int columnCount(const QModelIndex &parent) const override; //! @brief Return a data representing the table cell. QVariant data(const QModelIndex &index, int role) const override; + //! @brief Qt Mouse hover enter event + void enterEvent(QMouseEvent *event); +signals: + void mouseEnter(); }; namespace ComSquare::Debugger { //! @brief window that allow the user to view all data going through the memory bus. - class CGramDebug { + class CGramDebug : public QObject { private: //! @brief The QT window for this debugger. ClosableWindow *_window; @@ -116,7 +125,9 @@ namespace ComSquare::Debugger //! @brief Return true if the Bus is overloaded with debugging features. bool isDebugger(); //! @brief Update the text fields with corresponding tile info - void updateInfoTile(uint8_t addr); + void updateInfoTile(int row, int column); + //! @brief Update call updateInfoTile with the correct address + void tileClicked(const QModelIndex &index); }; } diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 3eacb63..c6c337c 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -17,7 +17,11 @@ namespace ComSquare::PPU oamram(new Ram::Ram(544, ComSquare::OAMRam, "OAMRAM")), cgram(new Ram::Ram(512, ComSquare::CGRam, "CGRAM")) { + uint8_t data = 1; this->_registers._isLowByte = true; + for (int i = 0; i < 512; i++, data += 11) { + this->cgram->write_internal(i, data); + } } uint8_t PPU::read(uint24_t addr) @@ -31,7 +35,6 @@ namespace ComSquare::PPU return this->_registers._mpy.mpyh; default: throw InvalidAddress("PPU Internal Registers read ", addr); - //std::cout << "PPU Internal Registers read" << addr << std::endl; } } diff --git a/ui/cgramView.ui b/ui/cgramView.ui index d0bf2dd..23f9a6e 100644 --- a/ui/cgramView.ui +++ b/ui/cgramView.ui @@ -36,6 +36,9 @@ 324 + + true + false @@ -45,11 +48,17 @@ QFrame::Sunken + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + 0 - QAbstractItemView::CurrentChanged|QAbstractItemView::SelectedClicked + QAbstractItemView::AnyKeyPressed|QAbstractItemView::CurrentChanged|QAbstractItemView::SelectedClicked QAbstractItemView::NoDragDrop From 94039b658b6ca312482582025599ddce7210ff40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Mon, 6 Apr 2020 02:03:44 +0200 Subject: [PATCH 27/59] colors are now init with random (note : same seed ise used everytime) --- sources/PPU/PPU.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index c6c337c..f9e8610 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -17,10 +17,9 @@ namespace ComSquare::PPU oamram(new Ram::Ram(544, ComSquare::OAMRam, "OAMRAM")), cgram(new Ram::Ram(512, ComSquare::CGRam, "CGRAM")) { - uint8_t data = 1; this->_registers._isLowByte = true; - for (int i = 0; i < 512; i++, data += 11) { - this->cgram->write_internal(i, data); + for (int i = 0; i < 512; i++) { + this->cgram->write_internal(i, random() % 255); } } From 8eef2dc865dcef1bc4024f2aa0731a1e04ca4689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Mon, 6 Apr 2020 02:07:58 +0200 Subject: [PATCH 28/59] removing old debug function in CGramDebug.cpp --- sources/Debugger/CGramDebug.cpp | 9 +-------- sources/Debugger/CGramDebug.hpp | 4 ---- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/sources/Debugger/CGramDebug.cpp b/sources/Debugger/CGramDebug.cpp index f2ae435..1a273fb 100644 --- a/sources/Debugger/CGramDebug.cpp +++ b/sources/Debugger/CGramDebug.cpp @@ -117,11 +117,4 @@ QVariant CGramModel::data(const QModelIndex &index, int role) const green = green * 255U / 31U; blue = blue * 255U / 31U; return QColor(red, green, blue); -} - -void CGramModel::enterEvent(QMouseEvent *event) -{ - this->x = event->x(); - this->y = event->y(); - emit mouseEnter(); -} +} \ No newline at end of file diff --git a/sources/Debugger/CGramDebug.hpp b/sources/Debugger/CGramDebug.hpp index 018b2e6..03c5d62 100644 --- a/sources/Debugger/CGramDebug.hpp +++ b/sources/Debugger/CGramDebug.hpp @@ -86,10 +86,6 @@ public: int columnCount(const QModelIndex &parent) const override; //! @brief Return a data representing the table cell. QVariant data(const QModelIndex &index, int role) const override; - //! @brief Qt Mouse hover enter event - void enterEvent(QMouseEvent *event); -signals: - void mouseEnter(); }; namespace ComSquare::Debugger From 59841cdf0a9d8ae9eefc583a8aa43a9585726d9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Mon, 6 Apr 2020 02:11:27 +0200 Subject: [PATCH 29/59] removing Qt selection display on the table view --- ui/cgramView.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/cgramView.ui b/ui/cgramView.ui index 23f9a6e..bfc6606 100644 --- a/ui/cgramView.ui +++ b/ui/cgramView.ui @@ -64,7 +64,7 @@ QAbstractItemView::NoDragDrop - QAbstractItemView::SingleSelection + QAbstractItemView::NoSelection true From abe445d202ed19f5d3a6ded9babb2b0af36c9df8 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Tue, 28 Apr 2020 23:12:43 +0200 Subject: [PATCH 30/59] Adding the BIT instruction --- sources/CPU/CPU.hpp | 12 ++--- sources/CPU/Instructions/BitsInstructions.cpp | 28 ++++++++++++ tests/CPU/testBits.cpp | 44 +++++++++++++++++++ 3 files changed, 79 insertions(+), 5 deletions(-) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 2d72b91..1bbe317 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -419,6 +419,8 @@ namespace ComSquare::CPU int TSB(uint24_t, AddressingMode); //! @brief Exchange the B and A Accumulators int XBA(uint24_t, AddressingMode); + //! @brief Test Memory Bits against Accumulator + int BIT(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -459,7 +461,7 @@ namespace ComSquare::CPU {&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 21 {&CPU::JSL, 8, "jsl", AddressingMode::AbsoluteLong, 4}, // 22 {&CPU::AND, 4, "and", AddressingMode::StackRelative, 2}, // 23 - {&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 24 + {&CPU::BIT, 3, "bit", AddressingMode::DirectPage, 2}, // 24 {&CPU::AND, 3, "and", AddressingMode::DirectPage, 2}, // 25 {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 26 {&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectLong, 2}, // 27 @@ -467,7 +469,7 @@ namespace ComSquare::CPU {&CPU::AND, 2, "and", AddressingMode::ImmediateForA, 2}, // 29 {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 2A {&CPU::PLD, 5, "pld", AddressingMode::Implied, 1}, // 2B - {&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 2C + {&CPU::BIT, 4, "bit", AddressingMode::Absolute, 3}, // 2C {&CPU::AND, 4, "and", AddressingMode::Absolute, 3}, // 2D {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 2E {&CPU::AND, 5, "and", AddressingMode::AbsoluteLong, 4}, // 2F @@ -475,7 +477,7 @@ namespace ComSquare::CPU {&CPU::AND, 5, "and", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 31 {&CPU::AND, 5, "and", AddressingMode::DirectPageIndirect, 2}, // 32 {&CPU::AND, 7, "and", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 33 - {&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 34 + {&CPU::BIT, 4, "bit", AddressingMode::DirectPageIndexedByX, 2}, // 34 {&CPU::AND, 4, "and", AddressingMode::DirectPageIndexedByX, 2}, // 35 {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 36 {&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 37 @@ -483,7 +485,7 @@ namespace ComSquare::CPU {&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByY, 3}, // 39 {&CPU::DEC, 2, "dec", AddressingMode::Implied, 1}, // 3A {&CPU::TSC, 2, "tsc", AddressingMode::Implied, 1}, // 3B - {&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 3C + {&CPU::BIT, 4, "bit", AddressingMode::AbsoluteIndexedByX, 3}, // 3C {&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByX, 3}, // 3D {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 3E {&CPU::AND, 5, "and", AddressingMode::AbsoluteIndexedByXLong, 4}, // 3F @@ -560,7 +562,7 @@ namespace ComSquare::CPU {&CPU::STX, 3, "stx", AddressingMode::DirectPage, 2}, // 86 {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndirectLong, 2}, // 87 {&CPU::DEY, 2, "dey", AddressingMode::Implied, 1}, // 88 - {&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 89 + {&CPU::BIT, 2, "bit", AddressingMode::ImmediateForA, 2}, // 89 {&CPU::TXA, 2, "txa", AddressingMode::Implied, 2}, // 8A {&CPU::PHB, 3, "phb", AddressingMode::Implied, 1}, // 8B {&CPU::STY, 4, "sty", AddressingMode::Absolute, 3}, // 8C diff --git a/sources/CPU/Instructions/BitsInstructions.cpp b/sources/CPU/Instructions/BitsInstructions.cpp index 737bdc9..41848f6 100644 --- a/sources/CPU/Instructions/BitsInstructions.cpp +++ b/sources/CPU/Instructions/BitsInstructions.cpp @@ -27,4 +27,32 @@ namespace ComSquare::CPU cycles += this->_registers.dl != 0; return cycles; } + + int CPU::BIT(uint24_t valueAddr, AddressingMode mode) + { + unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; + unsigned value = this->_bus->read(valueAddr); + if (!this->_registers.p.m) + value += this->_bus->read(valueAddr + 1) << 8u; + + if (mode != ImmediateForA) { + this->_registers.p.n = value & negativeMask; + this->_registers.p.v = value & (negativeMask >> 1u); + } + this->_registers.p.z = (value & this->_registers.a) == 0; + + int cycles = !this->_registers.p.m; + switch (mode) { + case DirectPage: + case DirectPageIndexedByX: + cycles += this->_registers.dl != 0; + break; + case AbsoluteIndexedByX: + cycles += this->_hasIndexCrossedPageBoundary; + break; + default: + break; + } + return cycles; + } } \ No newline at end of file diff --git a/tests/CPU/testBits.cpp b/tests/CPU/testBits.cpp index 5c4b334..9e8e5dd 100644 --- a/tests/CPU/testBits.cpp +++ b/tests/CPU/testBits.cpp @@ -71,3 +71,47 @@ Test(TSB, nativeTest) cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); } +Test(BIT, immediate) +{ + Init() + snes.wram->_data[0] = 0xFF; + snes.wram->_data[1] = 0x00; + snes.cpu->_registers.p.m = false; + snes.cpu->_registers.a = 0x8008; + snes.cpu->_registers.p.v = false; + snes.cpu->_registers.p.n = false; + snes.cpu->BIT(0x0, ComSquare::CPU::AddressingMode::ImmediateForA); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.v, false, "The overflow flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(BIT, immediateZero) +{ + Init() + snes.wram->_data[0] = 0x00; + snes.wram->_data[1] = 0xFF; + snes.cpu->_registers.p.m = false; + snes.cpu->_registers.a = 0x0008; + snes.cpu->_registers.p.v = true; + snes.cpu->_registers.p.n = true; + snes.cpu->BIT(0x0, ComSquare::CPU::AddressingMode::ImmediateForA); + cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.v, true, "The overflow flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set."); +} + +Test(BIT, other) +{ + Init() + snes.wram->_data[0] = 0x00; + snes.wram->_data[1] = 0xFF; + snes.cpu->_registers.p.m = false; + snes.cpu->_registers.a = 0x8008; + snes.cpu->_registers.p.v = false; + snes.cpu->_registers.p.n = false; + snes.cpu->BIT(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.v, true, "The overflow flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set."); +} \ No newline at end of file From 3e811db9cdda2e89a47d4ad7b3f5122e00f372a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Tue, 12 May 2020 00:10:44 +0200 Subject: [PATCH 31/59] adding missing registers to stop trowing --- sources/PPU/PPU.cpp | 14 ++++++++++++ sources/PPU/PPU.hpp | 52 ++++++++++++++++++++++++++++++++++++++++++++- ui/ui_cpu.h | 2 +- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index f9e8610..1106959 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -32,6 +32,16 @@ namespace ComSquare::PPU return this->_registers._mpy.mpym; case ppuRegisters::mpyh: return this->_registers._mpy.mpyh; + case ppuRegisters::slhv: + return this->_registers._slhv; + case ppuRegisters::oamdataread: + case ppuRegisters::vmdatalread: + case ppuRegisters::vmdatahread: + case ppuRegisters::ophct: + case ppuRegisters::opvct: + case ppuRegisters::stat77: + case ppuRegisters::stat78: + return 0; default: throw InvalidAddress("PPU Internal Registers read ", addr); } @@ -137,6 +147,10 @@ namespace ComSquare::PPU case ppuRegisters::m7d: this->_registers._m7[addr - ppuRegisters::m7a].m7 = (this->_registers._m7[addr - ppuRegisters::m7a].m7 << 8) | data; break; + case ppuRegisters::m7x: + case ppuRegisters::m7y: + // TODO these registers + break; case ppuRegisters::cgadd: this->_registers._cgadd = data; this->_registers._isLowByte = true; diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index 97987a1..1e52f33 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -482,7 +482,7 @@ namespace ComSquare::PPU uint8_t raw; } _setini; - // not in priority + // //! @brief MPYL - MPYM - MPYH Registers (Multiplication Result) union { @@ -493,6 +493,56 @@ namespace ComSquare::PPU }; uint32_t mpy; } _mpy; + //! @brief SLHV - Software Latch for H/V Counter + uint8_t _slhv; + //! @brief OAMDATAREAD - Data for OAM read + uint8_t _oamdataread; + //! @brief VMDATALREAD/VMDATAHREAD - VRAM Data Read low/high byte + union { + struct { + uint8_t vmDataLRead; + uint8_t vmDataHRead; + }; + uint16_t raw; + } _vmdataread; + //! @brief CGRAM Data read + union { + struct { + uint8_t cgDataLRead; + uint8_t cgDataHRead; + }; + uint16_t raw; + } _cgdataread; + //! @brief OPHCT/OPVCT - Horizontal/Vertical Scanline Location + union { + struct { + uint16_t opct: 9; + uint8_t _: 7; + }; + uint16_t raw; + } _opct; + //! @brief STAT77 - PPU Status Flag and Version + union { + struct { + uint8_t chipVersionNumber: 4; + bool _: 1; + bool modeSelect: 1; + bool rangeOverFlag: 1; + bool timeOverFlag: 1; + }; + uint8_t raw; + } _stat77; + //! @brief STAT78 - PPU Status Flag and Version + union { + struct { + uint8_t chipVersionNumber: 4; + bool mode: 1; + bool _: 1; + bool externalLatchFlag: 1; + bool interlaceField: 1; + }; + uint8_t raw; + } _stat78; }; //! @brief The class containing all the registers of the PPU diff --git a/ui/ui_cpu.h b/ui/ui_cpu.h index 97769dd..5bb8f98 100644 --- a/ui/ui_cpu.h +++ b/ui/ui_cpu.h @@ -1,7 +1,7 @@ /******************************************************************************** ** Form generated from reading UI file 'cpu.ui' ** -** Created by: Qt User Interface Compiler version 5.14.1 +** Created by: Qt User Interface Compiler version 5.13.2 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ From ffe1b8fc1b5b3d8a23934546e3abb662eacec15a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Wed, 13 May 2020 13:07:20 +0200 Subject: [PATCH 32/59] adding Vector2 in Models and starting drawBgTile loop --- CMakeLists.txt | 2 +- sources/Models/Vector2.hpp | 112 +++++++++++++++++++++++++++++++++++++ sources/PPU/PPU.cpp | 29 +++++++++- sources/PPU/PPU.hpp | 4 ++ sources/PPU/PPUUtils.hpp | 24 ++++++++ 5 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 sources/Models/Vector2.hpp create mode 100644 sources/PPU/PPUUtils.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 36966d6..9726007 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -212,7 +212,7 @@ add_executable(ComSquare sources/Models/Components.hpp sources/Debugger/CGramDebug.cpp sources/Debugger/CGramDebug.hpp -) + sources/Models/Vector2.hpp) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) diff --git a/sources/Models/Vector2.hpp b/sources/Models/Vector2.hpp new file mode 100644 index 0000000..cfe8d01 --- /dev/null +++ b/sources/Models/Vector2.hpp @@ -0,0 +1,112 @@ +// +// Created by cbihan on 5/13/20. +// + +#ifndef COMSQUARE_VECTOR2_HPP +#define COMSQUARE_VECTOR2_HPP + +#include +#include + +namespace ComSquare +{ + template + class Vector2 + { + public: + T x; + T y; + + Vector2() + : x(0), y(0) {} + + Vector2(T x, T y) + : x(x), y(y) {} + + Vector2(sf::Vector2 v) + : x(v.x), y(v.y) {} + + template + Vector2 &operator+=(const Vector2 &vec) + { + this->x += vec.x; + this->y += vec.y; + return *this; + } + + template + Vector2 operator+(const Vector2 &vec) const + { + return Vector2(this->x + vec.x, this->y + vec.y); + } + + template + Vector2 &operator-=(const Vector2 &vec) + { + this->x -= vec.x; + this->y -= vec.y; + return *this; + } + + template + Vector2 &operator*=(T2 d) + { + this->x *= d; + this->y *= d; + return *this; + } + + template + Vector2 operator*(T2 d) const + { + return Vector2(this->x * d, this->y * d); + } + + template + T operator*(Vector2 &b) const + { + return this->x * b.x + this->y * b.y; + } + + template + Vector2 operator/=(Vector2 &b) + { + this->x /= b.x; + this->y /= b.y; + return this; + } + + template + Vector2 operator/(Vector2 &b) const + { + return Vector2(this->x / b.x, this->y / b.y); + } + + template + Vector2 operator/=(T2 b) + { + this->x /= b; + this->y /= b; + return this; + } + + template + Vector2 operator/(T2 b) const + { + return Vector2(this->x / b, this->y / b); + } + }; + + typedef Vector2 Vector2f; + typedef Vector2 Vector2u; + typedef Vector2 Vector2i; +} + +template +std::ostream &operator<<(std::ostream &s, const ComSquare::Vector2 &v) +{ + s << v.x << " " << v.y; + return s; +} + +#endif //COMSQUARE_VECTOR2_HPP diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 1106959..ff33d45 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -5,9 +5,11 @@ #include #include #include "PPU.hpp" +#include "PPUUtils.hpp" #include "../Exceptions/NotImplementedException.hpp" #include "../Exceptions/InvalidAddress.hpp" #include "../Ram/Ram.hpp" +#include "../Models/Vector2.hpp" namespace ComSquare::PPU { @@ -421,15 +423,36 @@ namespace ComSquare::PPU { int nbCharactersHeight = (this->_registers._bgsc[bgNumber].tilemapVerticalMirroring) ? 64 : 32; int nbCharactersWidth = (this->_registers._bgsc[bgNumber].tilemapHorizontalMirroring) ? 64 : 32; - uint16_t vramAddress = this->_registers._bgsc[bgNumber].tilemapAddress >> 8U; + uint16_t vramAddress = this->_registers._bgsc[bgNumber].tilemapAddress << 1U; uint16_t tilemapValue; for (int i = 0; i < nbCharactersHeight * nbCharactersWidth; i++) { for (int j = 0; j < 0x800; j++) { - tilemapValue = this->vram->read(vramAddress); - vramAddress++; + tilemapValue = this->vram->read_internal(vramAddress); + tilemapValue += this->vram->read_internal(vramAddress + 1) << 8U; + vramAddress += 2; } } } + + uint16_t PPU::getGraphicVramAddress(int x, int y, int bg, int bpp) + { + uint16_t baseAddress = this->_registers._bgnba[bg > 2].raw; + int step = bpp * 8; + + baseAddress = (bg % 2) ? baseAddress & 0xFU : (baseAddress & 0xFU) >> 4U; + baseAddress = baseAddress << 12U; + return baseAddress + (x * 16 * step) + (y * step); + } + + void PPU::drawBgTile(uint16_t data, Vector2 pos, int bg, int bpp) + { + uint16_t graphicAddress; + union TileMapData tileData; + + tileData.raw = data; + graphicAddress = this->getGraphicVramAddress(tileData.posX, tileData.posY, bg, bpp); + // loop on all pixels of the tile 8x8 6x16 16x8 8x16 + } } \ No newline at end of file diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index 1e52f33..9cb04e3 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -589,6 +589,10 @@ namespace ComSquare::PPU uint16_t cgramRead(uint16_t addr); //! @brief Render a background on the screen void renderBackground(int bgNumber, std::vector characterSize, int bpp, bool priority); + //! @brief Get the correct Vram address for a gien x and y + uint16_t getGraphicVramAddress(int x, int y, int bg, int bpp); + //! @brief Draw a tile on the screen at x y pos + void drawBgTile(uint16_t data, std::vector pos, int bg, int bpp); }; } #endif //COMSQUARE_PPU_HPP diff --git a/sources/PPU/PPUUtils.hpp b/sources/PPU/PPUUtils.hpp new file mode 100644 index 0000000..94db8d3 --- /dev/null +++ b/sources/PPU/PPUUtils.hpp @@ -0,0 +1,24 @@ +// +// Created by cbihan on 1/27/20. +// + +#ifndef COMSQUARE_PPU_UTILS_HPP +#define COMSQUARE_PPU_UTILS_HPP + + + +namespace ComSquare::PPU +{ + union TileMapData { + struct { + uint8_t posY: 4; + uint8_t posX: 6; + uint8_t palette: 3; + bool tilePriority: 1; + bool horizontalFlip: 1; + bool verticalFlip: 1; + }; + uint16_t raw; + }; +} +#endif //COMSQUARE_PPU_UTILS_HPP From e90db35c8871658f88dda23a813fbf4a4336c2d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Wed, 13 May 2020 13:08:31 +0200 Subject: [PATCH 33/59] fixing prototype of drawBgTile in PPU.hpp --- sources/PPU/PPU.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index 9cb04e3..c567aa2 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -11,6 +11,7 @@ #include "../Renderer/IRenderer.hpp" //#include "../Ram/ExtendedRam.hpp" #include "../Ram/Ram.hpp" +#include "../Models/Vector2.hpp" //#define max2BitTiles 4096 //#define max4BitTiles 2048 @@ -592,7 +593,7 @@ namespace ComSquare::PPU //! @brief Get the correct Vram address for a gien x and y uint16_t getGraphicVramAddress(int x, int y, int bg, int bpp); //! @brief Draw a tile on the screen at x y pos - void drawBgTile(uint16_t data, std::vector pos, int bg, int bpp); + void drawBgTile(uint16_t data, Vector2 pos, int bg, int bpp); }; } #endif //COMSQUARE_PPU_HPP From 66f82dc5f0582c71db4be570ff2d4719e2ca2e1f Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Wed, 13 May 2020 14:11:58 +0200 Subject: [PATCH 34/59] Implementing ASL --- sources/CPU/CPU.hpp | 12 +++--- sources/CPU/Instructions/BitsInstructions.cpp | 40 +++++++++++++++++++ tests/CPU/testBits.cpp | 38 ++++++++++++++++++ 3 files changed, 85 insertions(+), 5 deletions(-) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 1bbe317..a65944c 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -421,6 +421,8 @@ namespace ComSquare::CPU int XBA(uint24_t, AddressingMode); //! @brief Test Memory Bits against Accumulator int BIT(uint24_t, AddressingMode); + //! @brief Arithmetic Shift Left + int ASL(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -431,15 +433,15 @@ namespace ComSquare::CPU {&CPU::ORA, 4, "ora", AddressingMode::StackRelative, 2}, // 03 {&CPU::TSB, 5, "tsb", AddressingMode::DirectPage, 2}, // 04 {&CPU::ORA, 3, "ora", AddressingMode::DirectPage, 2}, // 05 - {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 06 + {&CPU::ASL, 5, "asl", AddressingMode::DirectPage, 2}, // 06 {&CPU::ORA, 6, "ora", AddressingMode::DirectPageIndirectLong, 2}, // 07 {&CPU::PHP, 3, "php", AddressingMode::Implied, 3}, // 08 {&CPU::ORA, 2, "ora", AddressingMode::ImmediateForA, 2}, // 09 - {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 0A + {&CPU::ASL, 2, "asl", AddressingMode::Implied, 1}, // 0A {&CPU::PHD, 4, "phd", AddressingMode::Implied, 1}, // 0B {&CPU::TSB, 6, "tsb", AddressingMode::Absolute, 3}, // 0C {&CPU::ORA, 3, "ora", AddressingMode::Absolute, 4}, // 0D - {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 0E + {&CPU::ASL, 6, "asl", AddressingMode::Absolute, 3}, // 0E {&CPU::ORA, 5, "ora", AddressingMode::AbsoluteLong, 5}, // 0F {&CPU::BPL, 7, "bpl", AddressingMode::Immediate8bits, 2}, // 10 {&CPU::ORA, 5, "ora", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 11 @@ -447,7 +449,7 @@ namespace ComSquare::CPU {&CPU::ORA, 7, "ora", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 13 {&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // 14 {&CPU::ORA, 4, "ora", AddressingMode::DirectPageIndexedByX, 2}, // 15 - {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 16 + {&CPU::ASL, 6, "asl", AddressingMode::DirectPageIndexedByX, 2}, // 16 {&CPU::ORA, 6, "ora", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 17 {&CPU::CLC, 2, "clc", AddressingMode::Implied, 1}, // 18 {&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByY, 3}, // 19 @@ -455,7 +457,7 @@ namespace ComSquare::CPU {&CPU::TCS, 2, "tcs", AddressingMode::Implied, 1}, // 1B {&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // 1C {&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByX, 3}, // 1D - {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 1E + {&CPU::ASL, 7, "asl", AddressingMode::AbsoluteIndexedByX, 3}, // 1E {&CPU::ORA, 5, "ora", AddressingMode::AbsoluteIndexedByXLong, 4}, // 1F {&CPU::JSR, 6, "jsr", AddressingMode::Absolute, 3}, // 20 {&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 21 diff --git a/sources/CPU/Instructions/BitsInstructions.cpp b/sources/CPU/Instructions/BitsInstructions.cpp index 41848f6..7ad9f83 100644 --- a/sources/CPU/Instructions/BitsInstructions.cpp +++ b/sources/CPU/Instructions/BitsInstructions.cpp @@ -55,4 +55,44 @@ namespace ComSquare::CPU } return cycles; } + + int CPU::ASL(uint24_t valueAddr, AddressingMode mode) + { + unsigned highByte = this->_registers.p.m ? 0x80u : 0x8000u; + + if (mode == Implied) { + this->_registers.a <<= 1u; + this->_registers.p.n = this->_registers.a & highByte; + this->_registers.p.z = this->_registers.a == 0; + return 0; + } + + uint16_t value = this->_bus->read(valueAddr); + if (!this->_registers.p.m) + value += this->_bus->read(valueAddr + 1) << 8u; + + this->_registers.p.c = value & highByte; + + value <<= 1u; + this->_bus->write(valueAddr, value); + if (!this->_registers.p.m) + this->_bus->write(valueAddr + 1, value >> 8u); + + this->_registers.p.n = value & highByte; + this->_registers.p.z = value == 0; + + int cycles = 2 * !this->_registers.p.m; + switch (mode) { + case DirectPage: + case DirectPageIndexedByX: + cycles += this->_registers.dl != 0; + break; + case AbsoluteIndexedByX: + cycles += this->_hasIndexCrossedPageBoundary; + break; + default: + break; + } + return cycles; + } } \ No newline at end of file diff --git a/tests/CPU/testBits.cpp b/tests/CPU/testBits.cpp index 9e8e5dd..1e94a0a 100644 --- a/tests/CPU/testBits.cpp +++ b/tests/CPU/testBits.cpp @@ -114,4 +114,42 @@ Test(BIT, other) cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); cr_assert_eq(snes.cpu->_registers.p.v, true, "The overflow flag should be set."); cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set."); +} + +Test(ASL, emulationTest) +{ + Init() + snes.wram->_data[0] = 0b10110011; + snes.cpu->_registers.p.m = true; + snes.cpu->ASL(0x0, ComSquare::CPU::AddressingMode::Absolute); + cr_assert_eq(snes.wram->_data[0], 0b01100110, "The data in ram should be 0b01100110 but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(ASL, nativeTest) +{ + Init() + snes.wram->_data[0] = 0b10110011; + snes.wram->_data[1] = 0b10000011; + snes.cpu->_registers.p.m = false; + snes.cpu->ASL(0x0, ComSquare::CPU::AddressingMode::Absolute); + cr_assert_eq(snes.wram->_data[0], 0b01100110, "The data in ram should be 0b01100110 but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.wram->_data[1], 0b00000111, "The data in ram should be 0b00000111 but it was %x", snes.wram->_data[1]); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(ASL, accumulator) +{ + Init() + snes.cpu->_registers.a = 0b10110011; + snes.cpu->_registers.p.m = true; + snes.cpu->ASL(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.al, 0b01100110, "The accumulator should be 0b01100110 but it was %x", snes.cpu->_registers.al); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); } \ No newline at end of file From 475986580d2b737877e0b8df1fa9dbdc4675f7f0 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Wed, 13 May 2020 14:39:46 +0200 Subject: [PATCH 35/59] Implementing LSR --- sources/CPU/CPU.hpp | 12 +++--- sources/CPU/Instructions/BitsInstructions.cpp | 42 ++++++++++++++++++- tests/CPU/testBits.cpp | 38 +++++++++++++++++ 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index a65944c..a4c69be 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -423,6 +423,8 @@ namespace ComSquare::CPU int BIT(uint24_t, AddressingMode); //! @brief Arithmetic Shift Left int ASL(uint24_t, AddressingMode); + // !@brief Logical Shift Right + int LSR(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -497,15 +499,15 @@ namespace ComSquare::CPU {&CPU::EOR, 4, "eor", AddressingMode::StackRelative, 2}, // 43 {&CPU::BRK, 7, "mvp #-#", AddressingMode::Implied, 2}, // 44 {&CPU::EOR, 3, "eor", AddressingMode::DirectPage, 2}, // 45 - {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 46 + {&CPU::LSR, 5, "lsr", AddressingMode::DirectPage, 2}, // 46 {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectLong, 2}, // 47 {&CPU::PHA, 3, "pha", AddressingMode::Implied, 1}, // 48 {&CPU::EOR, 2, "eor", AddressingMode::ImmediateForA, 2}, // 49 - {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 4A + {&CPU::LSR, 2, "lsr", AddressingMode::Implied, 1}, // 4A {&CPU::PHK, 3, "phk", AddressingMode::Implied, 1}, // 4B {&CPU::JMP, 3, "jmp", AddressingMode::Absolute, 3}, // 4C {&CPU::EOR, 4, "eor", AddressingMode::Absolute, 3}, // 4D - {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 4E + {&CPU::LSR, 6, "lsr", AddressingMode::Absolute, 3}, // 4E {&CPU::EOR, 5, "eor", AddressingMode::AbsoluteLong, 4}, // 4F {&CPU::BVC, 2, "bvc", AddressingMode::Immediate8bits, 2}, // 50 {&CPU::EOR, 5, "eor", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 51 @@ -513,7 +515,7 @@ namespace ComSquare::CPU {&CPU::EOR, 4, "eor", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 53 {&CPU::BRK, 7, "mvn #-#", AddressingMode::Implied, 2}, // 54 {&CPU::EOR, 4, "eor", AddressingMode::DirectPageIndexedByX, 2}, // 55 - {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 56 + {&CPU::LSR, 6, "lsr", AddressingMode::DirectPageIndexedByX, 2}, // 56 {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 57 {&CPU::CLI, 2, "cli", AddressingMode::Implied, 1}, // 58 {&CPU::EOR, 4, "eor", AddressingMode::AbsoluteIndexedByY, 3}, // 59 @@ -521,7 +523,7 @@ namespace ComSquare::CPU {&CPU::TCD, 2, "tcd", AddressingMode::Implied, 1}, // 5B {&CPU::JML, 4, "jml", AddressingMode::Implied, 4}, // 5C {&CPU::EOR, 4, "eor", AddressingMode::AbsoluteIndexedByX, 3}, // 5D - {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 5E + {&CPU::LSR, 7, "lsr", AddressingMode::AbsoluteIndexedByX, 3}, // 5E {&CPU::EOR, 5, "eor", AddressingMode::AbsoluteIndexedByXLong, 4}, // 5F {&CPU::RTL, 6, "rtl", AddressingMode::Implied, 1}, // 60 {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 61 diff --git a/sources/CPU/Instructions/BitsInstructions.cpp b/sources/CPU/Instructions/BitsInstructions.cpp index 7ad9f83..629655e 100644 --- a/sources/CPU/Instructions/BitsInstructions.cpp +++ b/sources/CPU/Instructions/BitsInstructions.cpp @@ -61,6 +61,7 @@ namespace ComSquare::CPU unsigned highByte = this->_registers.p.m ? 0x80u : 0x8000u; if (mode == Implied) { + this->_registers.p.c = this->_registers.a & highByte; this->_registers.a <<= 1u; this->_registers.p.n = this->_registers.a & highByte; this->_registers.p.z = this->_registers.a == 0; @@ -72,15 +73,52 @@ namespace ComSquare::CPU value += this->_bus->read(valueAddr + 1) << 8u; this->_registers.p.c = value & highByte; - value <<= 1u; + this->_registers.p.n = value & highByte; + this->_registers.p.z = value == 0; + this->_bus->write(valueAddr, value); if (!this->_registers.p.m) this->_bus->write(valueAddr + 1, value >> 8u); - this->_registers.p.n = value & highByte; + int cycles = 2 * !this->_registers.p.m; + switch (mode) { + case DirectPage: + case DirectPageIndexedByX: + cycles += this->_registers.dl != 0; + break; + case AbsoluteIndexedByX: + cycles += this->_hasIndexCrossedPageBoundary; + break; + default: + break; + } + return cycles; + } + + int CPU::LSR(uint24_t valueAddr, AddressingMode mode) + { + this->_registers.p.n = false; + + if (mode == Implied) { + this->_registers.p.c = this->_registers.a & 1u; + this->_registers.a >>= 1u; + this->_registers.p.z = this->_registers.a == 0; + return 0; + } + + uint16_t value = this->_bus->read(valueAddr); + if (!this->_registers.p.m) + value += this->_bus->read(valueAddr + 1) << 8u; + + this->_registers.p.c = value & 1u; + value >>= 1u; this->_registers.p.z = value == 0; + this->_bus->write(valueAddr, value); + if (!this->_registers.p.m) + this->_bus->write(valueAddr + 1, value >> 8u); + int cycles = 2 * !this->_registers.p.m; switch (mode) { case DirectPage: diff --git a/tests/CPU/testBits.cpp b/tests/CPU/testBits.cpp index 1e94a0a..c21757a 100644 --- a/tests/CPU/testBits.cpp +++ b/tests/CPU/testBits.cpp @@ -150,6 +150,44 @@ Test(ASL, accumulator) snes.cpu->ASL(0x0, ComSquare::CPU::AddressingMode::Implied); cr_assert_eq(snes.cpu->_registers.al, 0b01100110, "The accumulator should be 0b01100110 but it was %x", snes.cpu->_registers.al); cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(LSR, emulationTest) +{ + Init() + snes.wram->_data[0] = 0b01100110; + snes.cpu->_registers.p.m = true; + snes.cpu->LSR(0x0, ComSquare::CPU::AddressingMode::Absolute); + cr_assert_eq(snes.wram->_data[0], 0b00110011, "The data in ram should be 0b00110011 but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flag should not be set."); cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(LSR, nativeTest) +{ + Init() + snes.wram->_data[0] = 0b10110011; + snes.wram->_data[1] = 0b10000011; + snes.cpu->_registers.p.m = false; + snes.cpu->LSR(0x0, ComSquare::CPU::AddressingMode::Absolute); + cr_assert_eq(snes.wram->_data[0], 0b11011001, "The data in ram should be 0b11011001 but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.wram->_data[1], 0b01000001, "The data in ram should be 0b01000001 but it was %x", snes.wram->_data[1]); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(LSR, accumulator) +{ + Init() + snes.cpu->_registers.a = 0b10110011; + snes.cpu->_registers.p.m = true; + snes.cpu->LSR(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.al, 0b01011001, "The accumulator should be 0b01011001 but it was %x", snes.cpu->_registers.al); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); } \ No newline at end of file From deab98dac03f342cd7e92bef8f8f9301709d0492 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Wed, 13 May 2020 14:58:37 +0200 Subject: [PATCH 36/59] Implementing ROL --- sources/CPU/CPU.hpp | 12 +++-- sources/CPU/Instructions/BitsInstructions.cpp | 43 +++++++++++++++ tests/CPU/testBits.cpp | 53 +++++++++++++++++++ 3 files changed, 103 insertions(+), 5 deletions(-) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index a4c69be..92cf17e 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -425,6 +425,8 @@ namespace ComSquare::CPU int ASL(uint24_t, AddressingMode); // !@brief Logical Shift Right int LSR(uint24_t, AddressingMode); + // !@brief Rotate Left + int ROL(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -467,15 +469,15 @@ namespace ComSquare::CPU {&CPU::AND, 4, "and", AddressingMode::StackRelative, 2}, // 23 {&CPU::BIT, 3, "bit", AddressingMode::DirectPage, 2}, // 24 {&CPU::AND, 3, "and", AddressingMode::DirectPage, 2}, // 25 - {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 26 + {&CPU::ROL, 5, "rol", AddressingMode::DirectPage, 2}, // 26 {&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectLong, 2}, // 27 {&CPU::PLP, 4, "plp", AddressingMode::Implied, 1}, // 28 {&CPU::AND, 2, "and", AddressingMode::ImmediateForA, 2}, // 29 - {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 2A + {&CPU::ROL, 2, "rol", AddressingMode::Implied, 1}, // 2A {&CPU::PLD, 5, "pld", AddressingMode::Implied, 1}, // 2B {&CPU::BIT, 4, "bit", AddressingMode::Absolute, 3}, // 2C {&CPU::AND, 4, "and", AddressingMode::Absolute, 3}, // 2D - {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 2E + {&CPU::ROL, 6, "rol", AddressingMode::Absolute, 3}, // 2E {&CPU::AND, 5, "and", AddressingMode::AbsoluteLong, 4}, // 2F {&CPU::BMI, 2, "bmi", AddressingMode::Immediate8bits, 2}, // 30 {&CPU::AND, 5, "and", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 31 @@ -483,7 +485,7 @@ namespace ComSquare::CPU {&CPU::AND, 7, "and", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 33 {&CPU::BIT, 4, "bit", AddressingMode::DirectPageIndexedByX, 2}, // 34 {&CPU::AND, 4, "and", AddressingMode::DirectPageIndexedByX, 2}, // 35 - {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 36 + {&CPU::ROL, 6, "rol", AddressingMode::DirectPageIndexedByX, 2}, // 36 {&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 37 {&CPU::SEC, 2, "sec", AddressingMode::Implied, 1}, // 38 {&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByY, 3}, // 39 @@ -491,7 +493,7 @@ namespace ComSquare::CPU {&CPU::TSC, 2, "tsc", AddressingMode::Implied, 1}, // 3B {&CPU::BIT, 4, "bit", AddressingMode::AbsoluteIndexedByX, 3}, // 3C {&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByX, 3}, // 3D - {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 3E + {&CPU::ROL, 7, "rol", AddressingMode::AbsoluteIndexedByX, 3}, // 3E {&CPU::AND, 5, "and", AddressingMode::AbsoluteIndexedByXLong, 4}, // 3F {&CPU::RTI, 6, "rti", AddressingMode::Implied, 1}, // 40 {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 41 diff --git a/sources/CPU/Instructions/BitsInstructions.cpp b/sources/CPU/Instructions/BitsInstructions.cpp index 629655e..db67ab0 100644 --- a/sources/CPU/Instructions/BitsInstructions.cpp +++ b/sources/CPU/Instructions/BitsInstructions.cpp @@ -133,4 +133,47 @@ namespace ComSquare::CPU } return cycles; } + + int CPU::ROL(uint24_t valueAddr, AddressingMode mode) + { + unsigned highByte = this->_registers.p.m ? 0x80u : 0x8000u; + bool oldCarry = this->_registers.p.c; + + if (mode == Implied) { + this->_registers.p.c = this->_registers.a & highByte; + this->_registers.a <<= 1u; + this->_registers.a |= oldCarry; + this->_registers.p.n = this->_registers.a & highByte; + this->_registers.p.z = this->_registers.a == 0; + return 0; + } + + uint16_t value = this->_bus->read(valueAddr); + if (!this->_registers.p.m) + value += this->_bus->read(valueAddr + 1) << 8u; + + this->_registers.p.c = value & highByte; + value <<= 1u; + value |= oldCarry; + this->_registers.p.n = value & highByte; + this->_registers.p.z = value == 0; + + this->_bus->write(valueAddr, value); + if (!this->_registers.p.m) + this->_bus->write(valueAddr + 1, value >> 8u); + + int cycles = 2 * !this->_registers.p.m; + switch (mode) { + case DirectPage: + case DirectPageIndexedByX: + cycles += this->_registers.dl != 0; + break; + case AbsoluteIndexedByX: + cycles += this->_hasIndexCrossedPageBoundary; + break; + default: + break; + } + return cycles; + } } \ No newline at end of file diff --git a/tests/CPU/testBits.cpp b/tests/CPU/testBits.cpp index c21757a..ae59ee6 100644 --- a/tests/CPU/testBits.cpp +++ b/tests/CPU/testBits.cpp @@ -190,4 +190,57 @@ Test(LSR, accumulator) cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(ROL, emulationTest) +{ + Init() + snes.wram->_data[0] = 0b10110011; + snes.cpu->_registers.p.m = true; + snes.cpu->ROL(0x0, ComSquare::CPU::AddressingMode::Absolute); + cr_assert_eq(snes.wram->_data[0], 0b01100110, "The data in ram should be 0b01100110 but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(ROL, emulationTestWithCarry) +{ + Init() + snes.wram->_data[0] = 0b10110011; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.p.c = true; + snes.cpu->ROL(0x0, ComSquare::CPU::AddressingMode::Absolute); + cr_assert_eq(snes.wram->_data[0], 0b01100111, "The data in ram should be 0b01100111 but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(ROL, nativeTest) +{ + Init() + snes.wram->_data[0] = 0b10110011; + snes.wram->_data[1] = 0b10000011; + snes.cpu->_registers.p.m = false; + snes.cpu->_registers.p.c = true; + snes.cpu->ROL(0x0, ComSquare::CPU::AddressingMode::Absolute); + cr_assert_eq(snes.wram->_data[0], 0b01100111, "The data in ram should be 0b01100111 but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.wram->_data[1], 0b00000111, "The data in ram should be 0b00000111 but it was %x", snes.wram->_data[1]); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(ROL, accumulator) +{ + Init() + snes.cpu->_registers.a = 0b10110011; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.p.c = true; + snes.cpu->ROL(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.al, 0b01100111, "The accumulator should be 0b01100111 but it was %x", snes.cpu->_registers.al); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); } \ No newline at end of file From 4c4cc6b655a6a25f344e3e3c834dbb9ed57f16cb Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Wed, 13 May 2020 16:35:13 +0200 Subject: [PATCH 37/59] Implementing ROR --- sources/CPU/CPU.hpp | 12 +++-- sources/CPU/Instructions/BitsInstructions.cpp | 42 +++++++++++++++ tests/CPU/testBits.cpp | 54 +++++++++++++++++++ 3 files changed, 103 insertions(+), 5 deletions(-) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 92cf17e..b87704e 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -427,6 +427,8 @@ namespace ComSquare::CPU int LSR(uint24_t, AddressingMode); // !@brief Rotate Left int ROL(uint24_t, AddressingMode); + // !@brief Rotate Right + int ROR(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -533,15 +535,15 @@ namespace ComSquare::CPU {&CPU::ADC, 4, "adc", AddressingMode::StackRelative, 2}, // 63 {&CPU::STZ, 3, "stz", AddressingMode::DirectPage, 2}, // 64 {&CPU::ADC, 3, "adc", AddressingMode::DirectPage, 2}, // 65 - {&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 66 + {&CPU::ROR, 5, "ror", AddressingMode::DirectPage, 2}, // 66 {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectLong, 2}, // 67 {&CPU::PLA, 4, "pla", AddressingMode::Implied, 1}, // 68 {&CPU::ADC, 2, "adc", AddressingMode::ImmediateForA, 2}, // 69 - {&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 6A + {&CPU::ROR, 2, "ror", AddressingMode::Implied, 1}, // 6A {&CPU::RTS, 6, "rts", AddressingMode::Implied, 1}, // 6B {&CPU::JMP, 5, "jmp", AddressingMode::AbsoluteIndirect, 3}, // 6C {&CPU::ADC, 4, "adc", AddressingMode::Absolute, 3}, // 6D - {&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 6E + {&CPU::ROR, 6, "ror", AddressingMode::Absolute, 3}, // 6E {&CPU::ADC, 5, "adc", AddressingMode::AbsoluteLong, 4}, // 6F {&CPU::BVS, 2, "bvs", AddressingMode::Immediate8bits, 2}, // 70 {&CPU::ADC, 5, "adc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 71 @@ -549,7 +551,7 @@ namespace ComSquare::CPU {&CPU::ADC, 7, "adc", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 73 {&CPU::STZ, 4, "stz", AddressingMode::DirectPageIndexedByX, 2}, // 74 {&CPU::ADC, 4, "adc", AddressingMode::DirectPageIndexedByX, 2}, // 75 - {&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 76 + {&CPU::ROR, 6, "ror", AddressingMode::DirectPageIndexedByX, 2}, // 76 {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 77 {&CPU::SEI, 2, "sei", AddressingMode::Implied, 1}, // 78 {&CPU::ADC, 4, "adc", AddressingMode::AbsoluteIndexedByY, 2}, // 79 @@ -557,7 +559,7 @@ namespace ComSquare::CPU {&CPU::TDC, 2, "tdc", AddressingMode::Implied, 1}, // 7B {&CPU::JMP, 6, "jmp", AddressingMode::AbsoluteIndirectIndexedByX, 3}, // 7C {&CPU::ADC, 4, "adc", AddressingMode::AbsoluteIndexedByX, 3}, // 7D - {&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 7E + {&CPU::ROR, 7, "ror", AddressingMode::AbsoluteIndexedByX, 3}, // 7E {&CPU::ADC, 5, "adc", AddressingMode::AbsoluteIndexedByXLong, 4}, // 7F {&CPU::BRA, 3, "bra", AddressingMode::Immediate8bits, 2}, // 80 {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndexedByX, 2}, // 81 diff --git a/sources/CPU/Instructions/BitsInstructions.cpp b/sources/CPU/Instructions/BitsInstructions.cpp index db67ab0..81205b7 100644 --- a/sources/CPU/Instructions/BitsInstructions.cpp +++ b/sources/CPU/Instructions/BitsInstructions.cpp @@ -176,4 +176,46 @@ namespace ComSquare::CPU } return cycles; } + + int CPU::ROR(uint24_t valueAddr, AddressingMode mode) + { + this->_registers.p.n = false; + bool oldCarry = this->_registers.p.c; + unsigned highByteIndex = this->_registers.p.m ? 7 : 15; + + if (mode == Implied) { + this->_registers.p.c = this->_registers.a & 1u; + this->_registers.a >>= 1u; + this->_registers.a |= oldCarry << highByteIndex; + this->_registers.p.z = this->_registers.a == 0; + return 0; + } + + uint16_t value = this->_bus->read(valueAddr); + if (!this->_registers.p.m) + value += this->_bus->read(valueAddr + 1) << 8u; + + this->_registers.p.c = value & 1u; + value >>= 1u; + value |= oldCarry << highByteIndex; + this->_registers.p.z = value == 0; + + this->_bus->write(valueAddr, value); + if (!this->_registers.p.m) + this->_bus->write(valueAddr + 1, value >> 8u); + + int cycles = 2 * !this->_registers.p.m; + switch (mode) { + case DirectPage: + case DirectPageIndexedByX: + cycles += this->_registers.dl != 0; + break; + case AbsoluteIndexedByX: + cycles += this->_hasIndexCrossedPageBoundary; + break; + default: + break; + } + return cycles; + } } \ No newline at end of file diff --git a/tests/CPU/testBits.cpp b/tests/CPU/testBits.cpp index ae59ee6..b8ef723 100644 --- a/tests/CPU/testBits.cpp +++ b/tests/CPU/testBits.cpp @@ -243,4 +243,58 @@ Test(ROL, accumulator) cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(ROR, emulationTestWithtoutCarry) +{ + Init() + snes.wram->_data[0] = 0b01100110; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.p.c = false; + snes.cpu->ROR(0x0, ComSquare::CPU::AddressingMode::Absolute); + cr_assert_eq(snes.wram->_data[0], 0b00110011, "The data in ram should be 0b00110011 but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(ROR, emulationTest) +{ + Init() + snes.wram->_data[0] = 0b01100110; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.p.c = true; + snes.cpu->ROR(0x0, ComSquare::CPU::AddressingMode::Absolute); + cr_assert_eq(snes.wram->_data[0], 0b10110011, "The data in ram should be 0b10110011 but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(ROR, nativeTest) +{ + Init() + snes.wram->_data[0] = 0b10110011; + snes.wram->_data[1] = 0b10000011; + snes.cpu->_registers.p.m = false; + snes.cpu->_registers.p.c = true; + snes.cpu->ROR(0x0, ComSquare::CPU::AddressingMode::Absolute); + cr_assert_eq(snes.wram->_data[0], 0b11011001, "The data in ram should be 0b11011001 but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.wram->_data[1], 0b11000001, "The data in ram should be 0b11000001 but it was %x", snes.wram->_data[1]); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(ROR, accumulator) +{ + Init() + snes.cpu->_registers.a = 0b10110011; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.p.c = true; + snes.cpu->ROR(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.al, 0b11011001, "The accumulator should be 0b11011001 but it was %x", snes.cpu->_registers.al); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); } \ No newline at end of file From b29d1c4216751bbcd9e7ad69f13a53d2e227584a Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Wed, 13 May 2020 17:04:14 +0200 Subject: [PATCH 38/59] Implementing TRB --- sources/CPU/CPU.hpp | 6 ++-- sources/CPU/Instructions/BitsInstructions.cpp | 21 +++++++++++ tests/CPU/testBits.cpp | 35 +++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index b87704e..1c6be7d 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -417,6 +417,8 @@ namespace ComSquare::CPU int TYX(uint24_t, AddressingMode); //! @brief Test and Set Memory Bits Against Accumulator int TSB(uint24_t, AddressingMode); + //! @brief Test and Reset Memory Bits Against Accumulator + int TRB(uint24_t, AddressingMode); //! @brief Exchange the B and A Accumulators int XBA(uint24_t, AddressingMode); //! @brief Test Memory Bits against Accumulator @@ -453,7 +455,7 @@ namespace ComSquare::CPU {&CPU::ORA, 5, "ora", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 11 {&CPU::ORA, 5, "ora", AddressingMode::DirectPageIndirect, 2}, // 12 {&CPU::ORA, 7, "ora", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 13 - {&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // 14 + {&CPU::TRB, 5, "trb", AddressingMode::DirectPage, 2}, // 14 {&CPU::ORA, 4, "ora", AddressingMode::DirectPageIndexedByX, 2}, // 15 {&CPU::ASL, 6, "asl", AddressingMode::DirectPageIndexedByX, 2}, // 16 {&CPU::ORA, 6, "ora", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 17 @@ -461,7 +463,7 @@ namespace ComSquare::CPU {&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByY, 3}, // 19 {&CPU::INC, 2, "inc", AddressingMode::Implied, 1}, // 1A {&CPU::TCS, 2, "tcs", AddressingMode::Implied, 1}, // 1B - {&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // 1C + {&CPU::TRB, 6, "trb", AddressingMode::Absolute, 3}, // 1C {&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByX, 3}, // 1D {&CPU::ASL, 7, "asl", AddressingMode::AbsoluteIndexedByX, 3}, // 1E {&CPU::ORA, 5, "ora", AddressingMode::AbsoluteIndexedByXLong, 4}, // 1F diff --git a/sources/CPU/Instructions/BitsInstructions.cpp b/sources/CPU/Instructions/BitsInstructions.cpp index 81205b7..2332114 100644 --- a/sources/CPU/Instructions/BitsInstructions.cpp +++ b/sources/CPU/Instructions/BitsInstructions.cpp @@ -28,6 +28,27 @@ namespace ComSquare::CPU return cycles; } + int CPU::TRB(uint24_t valueAddr, AddressingMode mode) + { + uint16_t value = this->_bus->read(valueAddr); + if (!this->_registers.p.m) + value += this->_bus->read(valueAddr + 1) << 8u; + + uint16_t newValue = value & ~this->_registers.a; + this->_bus->write(valueAddr, newValue); + if (!this->_registers.p.m) + this->_bus->write(valueAddr + 1, newValue >> 8u); + + this->_registers.p.z = (value & this->_registers.a) == 0; + + int cycles = 0; + if (!this->_registers.p.m) + cycles += 2; + if (mode == DirectPage) + cycles += this->_registers.dl != 0; + return cycles; + } + int CPU::BIT(uint24_t valueAddr, AddressingMode mode) { unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; diff --git a/tests/CPU/testBits.cpp b/tests/CPU/testBits.cpp index b8ef723..a4bd5de 100644 --- a/tests/CPU/testBits.cpp +++ b/tests/CPU/testBits.cpp @@ -297,4 +297,39 @@ Test(ROR, accumulator) cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set."); cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); +} + +Test(TRB, emulationTest) +{ + Init() + snes.wram->_data[0] = 0xFF; + snes.cpu->_registers.a = 0b00110111; + snes.cpu->_registers.p.m = true; + snes.cpu->TRB(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.wram->_data[0], 0b11001000, "The data in ram should be 0b11001000 but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); +} + +Test(TRB, nativeTest) +{ + Init() + snes.wram->_data[0] = 0xF0; + snes.wram->_data[1] = 0x0F; + snes.cpu->_registers.a = 0x0F0F; + snes.cpu->_registers.p.m = false; + snes.cpu->TRB(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.wram->_data[0], 0xF0, "The first data in ram should be 0xF0 but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.wram->_data[1], 0x00, "The second data in ram should be 0x00 but it was %x", snes.wram->_data[1]); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set."); +} + +Test(TRB, zero) +{ + Init() + snes.wram->_data[0] = 0xFF; + snes.cpu->_registers.a = 0b0; + snes.cpu->_registers.p.m = true; + snes.cpu->TRB(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.wram->_data[0], 0xFF, "The data in ram should be 0xFF but it was %x", snes.wram->_data[0]); + cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set."); } \ No newline at end of file From 876b78a5c9ca3c75fc2f8a5a8fb5ce688703bf78 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Wed, 13 May 2020 17:52:47 +0200 Subject: [PATCH 39/59] Implementing PER --- sources/CPU/AddressingModes.cpp | 7 +++++++ sources/CPU/CPU.cpp | 6 ++---- sources/CPU/CPU.hpp | 10 +++++++--- sources/CPU/Instruction.hpp | 1 + sources/CPU/Instructions/InternalInstruction.cpp | 9 +++++++++ tests/CPU/testInternal.cpp | 13 +++++++++++++ 6 files changed, 39 insertions(+), 7 deletions(-) diff --git a/sources/CPU/AddressingModes.cpp b/sources/CPU/AddressingModes.cpp index d19a985..3f649c2 100644 --- a/sources/CPU/AddressingModes.cpp +++ b/sources/CPU/AddressingModes.cpp @@ -14,6 +14,13 @@ namespace ComSquare::CPU return ret; } + uint24_t CPU::_getImmediateAddr16Bits() + { + uint24_t ret = this->_registers.pac; + this->_registers.pc += 2; + return ret; + } + uint24_t CPU::_getImmediateAddrForA() { uint24_t effective = this->_registers.pac; diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index 8116408..34a01ae 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -6,9 +6,7 @@ #include #include -#include "../Exceptions/NotImplementedException.hpp" #include "../Exceptions/InvalidAddress.hpp" -#include "../Exceptions/InvalidOpcode.hpp" namespace ComSquare::CPU { @@ -218,6 +216,8 @@ namespace ComSquare::CPU return 0; case Immediate8bits: return this->_getImmediateAddr8Bits(); + case Immediate16bits: + return this->_getImmediateAddr16Bits(); case ImmediateForA: return this->_getImmediateAddrForA(); case ImmediateForX: @@ -264,8 +264,6 @@ namespace ComSquare::CPU case AbsoluteIndirectIndexedByX: return this->_getAbsoluteIndirectIndexedByXAddr(); - default: - return 0; } } diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 1c6be7d..d0b0d47 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -198,8 +198,10 @@ namespace ComSquare::CPU //! @brief True if an addressing mode with an iterator (x, y) has crossed the page. (Used because crossing the page boundary take one more cycle to run certain instructions). bool _hasIndexCrossedPageBoundary = false; - //! @brief Immediate address mode is specified with a value in 8. (This functions returns the 24bit space address of the value). + //! @brief Immediate address mode is specified with a value in 8 bits. (This functions returns the 24bit space address of the value). uint24_t _getImmediateAddr8Bits(); + //! @brief Immediate address mode is specified with a value in 16 bits. (This functions returns the 24bit space address of the value). + uint24_t _getImmediateAddr16Bits(); //! @brief Immediate address mode is specified with a value in 8 or 16 bits. The value is 16 bits if the m flag is unset. (This functions returns the 24bit space address of the value). uint24_t _getImmediateAddrForA(); //! @brief Immediate address mode is specified with a value in 8 or 16 bits. The value is 16 bits if the x flag is unset. (This functions returns the 24bit space address of the value). @@ -431,6 +433,8 @@ namespace ComSquare::CPU int ROL(uint24_t, AddressingMode); // !@brief Rotate Right int ROR(uint24_t, AddressingMode); + //! @brief Push Effective PC Relative Indirect Address + int PER(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -533,7 +537,7 @@ namespace ComSquare::CPU {&CPU::EOR, 5, "eor", AddressingMode::AbsoluteIndexedByXLong, 4}, // 5F {&CPU::RTL, 6, "rtl", AddressingMode::Implied, 1}, // 60 {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 61 - {&CPU::BRK, 7, "per #-#", AddressingMode::Implied, 2}, // 62 + {&CPU::PER, 6, "per", AddressingMode::Immediate16bits, 3}, // 62 {&CPU::ADC, 4, "adc", AddressingMode::StackRelative, 2}, // 63 {&CPU::STZ, 3, "stz", AddressingMode::DirectPage, 2}, // 64 {&CPU::ADC, 3, "adc", AddressingMode::DirectPage, 2}, // 65 @@ -606,7 +610,7 @@ namespace ComSquare::CPU {&CPU::TAY, 2, "tay", AddressingMode::Implied, 1}, // A8 {&CPU::LDA, 2, "lda", AddressingMode::ImmediateForA, 2}, // A9 {&CPU::TAX, 2, "tax", AddressingMode::Implied, 1}, // AA - {&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // AB + {&CPU::BRK, 7, "plb #-#", AddressingMode::Implied, 2}, // AB {&CPU::LDY, 4, "ldy", AddressingMode::Absolute, 4}, // AC {&CPU::LDA, 4, "lda", AddressingMode::Absolute, 3}, // AD {&CPU::LDX, 4, "ldx", AddressingMode::Absolute, 3}, // AE diff --git a/sources/CPU/Instruction.hpp b/sources/CPU/Instruction.hpp index 8061d1e..f6ef811 100644 --- a/sources/CPU/Instruction.hpp +++ b/sources/CPU/Instruction.hpp @@ -17,6 +17,7 @@ namespace ComSquare::CPU Implied, Immediate8bits, + Immediate16bits, ImmediateForA, ImmediateForX, diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp index 1fc020a..d3ee972 100644 --- a/sources/CPU/Instructions/InternalInstruction.cpp +++ b/sources/CPU/Instructions/InternalInstruction.cpp @@ -184,6 +184,15 @@ namespace ComSquare::CPU return !this->_registers.p.x_b; } + int CPU::PER(uint24_t valueAddr, AddressingMode) + { + uint16_t value = this->_bus->read(valueAddr); + value += this->_bus->read(valueAddr + 1) << 8u; + value += this->_registers.pc; + this->_push(value); + return 0; + } + int CPU::XCE(uint24_t, AddressingMode) { bool oldCarry = this->_registers.p.c; diff --git a/tests/CPU/testInternal.cpp b/tests/CPU/testInternal.cpp index 0619ece..6710426 100644 --- a/tests/CPU/testInternal.cpp +++ b/tests/CPU/testInternal.cpp @@ -914,4 +914,17 @@ Test(JML, simpleJump) snes.cpu->_registers.pc = 0x8000; snes.cpu->JML(0x10AB00, ComSquare::CPU::AddressingMode::Implied); cr_assert_eq(snes.cpu->_registers.pac, 0x10AB00, "The program counter should be equal to 0x10AB00 but it was 0x%x.", snes.cpu->_registers.pac); +} + +Test(PER, simple) +{ + Init() + snes.cpu->_registers.pac = 0x008005; + snes.cpu->_registers.s = 0x1FFF; + snes.wram->_data[0x0] = 0xFF; + snes.wram->_data[0x1] = 0xFF; + snes.cpu->PER(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.s, 0x1FFD, "The stack pointer should be equal to 0x1FFD but it was 0x%x.", snes.cpu->_registers.s); + uint16_t value = snes.cpu->_pop16(); + cr_assert_eq(value, 0x8004, "The pushed value should be equal to 0x8004 but it was 0x%x.", value); } \ No newline at end of file From fea20fee703fc86ce4a17a1deaa6cf54bdbcbe2c Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Wed, 13 May 2020 18:10:56 +0200 Subject: [PATCH 40/59] Implemnting PEI --- sources/CPU/CPU.cpp | 2 ++ sources/CPU/CPU.hpp | 4 +++- sources/CPU/Instructions/InternalInstruction.cpp | 6 ++++++ sources/Exceptions/InvalidOpcode.hpp | 5 +++++ tests/CPU/testInternal.cpp | 12 ++++++++++++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index 34a01ae..7e3ba69 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -7,6 +7,7 @@ #include #include #include "../Exceptions/InvalidAddress.hpp" +#include "../Exceptions/InvalidOpcode.hpp" namespace ComSquare::CPU { @@ -265,6 +266,7 @@ namespace ComSquare::CPU case AbsoluteIndirectIndexedByX: return this->_getAbsoluteIndirectIndexedByXAddr(); } + throw InvalidOpcode("Unknown addressing mode for."); } unsigned CPU::_executeInstruction(uint8_t opcode) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index d0b0d47..364fc81 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -435,6 +435,8 @@ namespace ComSquare::CPU int ROR(uint24_t, AddressingMode); //! @brief Push Effective PC Relative Indirect Address int PER(uint24_t, AddressingMode); + //! @brief Push Effective Indirect Address + int PEI(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -651,7 +653,7 @@ namespace ComSquare::CPU {&CPU::CMP, 5, "cmp", AddressingMode::DirectPageIndirectIndexedByY, 2}, // D1 {&CPU::CMP, 5, "cmp", AddressingMode::DirectPageIndirect, 2}, // D2 {&CPU::CMP, 7, "cmp", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // D3 - {&CPU::BRK, 7, "pei #-#", AddressingMode::Implied, 2}, // D4 + {&CPU::PEI, 6, "pei", AddressingMode::DirectPage, 2}, // D4 {&CPU::CMP, 4, "cmp", AddressingMode::DirectPageIndexedByX, 2}, // D5 {&CPU::DEC, 6, "dec", AddressingMode::DirectPageIndexedByX, 2}, // D6 {&CPU::CMP, 6, "cmp", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // D7 diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp index d3ee972..0f01df9 100644 --- a/sources/CPU/Instructions/InternalInstruction.cpp +++ b/sources/CPU/Instructions/InternalInstruction.cpp @@ -193,6 +193,12 @@ namespace ComSquare::CPU return 0; } + int CPU::PEI(uint24_t value, AddressingMode) + { + this->_push(static_cast(value)); + return 0; + } + int CPU::XCE(uint24_t, AddressingMode) { bool oldCarry = this->_registers.p.c; diff --git a/sources/Exceptions/InvalidOpcode.hpp b/sources/Exceptions/InvalidOpcode.hpp index 57e990d..b4b1ae7 100644 --- a/sources/Exceptions/InvalidOpcode.hpp +++ b/sources/Exceptions/InvalidOpcode.hpp @@ -17,6 +17,11 @@ namespace ComSquare private: std::string _msg; public: + explicit InvalidOpcode(const std::string &what) + { + this->_msg = what; + } + explicit InvalidOpcode(const std::string &pu, unsigned opcode) { std::stringstream stream; diff --git a/tests/CPU/testInternal.cpp b/tests/CPU/testInternal.cpp index 6710426..3eabc41 100644 --- a/tests/CPU/testInternal.cpp +++ b/tests/CPU/testInternal.cpp @@ -927,4 +927,16 @@ Test(PER, simple) cr_assert_eq(snes.cpu->_registers.s, 0x1FFD, "The stack pointer should be equal to 0x1FFD but it was 0x%x.", snes.cpu->_registers.s); uint16_t value = snes.cpu->_pop16(); cr_assert_eq(value, 0x8004, "The pushed value should be equal to 0x8004 but it was 0x%x.", value); +} + +Test(PEI, simple) +{ + Init() + snes.cpu->_registers.s = 0x1FFF; + snes.wram->_data[0x0] = 0xFF; + snes.wram->_data[0x1] = 0xFF; + snes.cpu->PER(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.s, 0x1FFD, "The stack pointer should be equal to 0x1FFD but it was 0x%x.", snes.cpu->_registers.s); + uint16_t value = snes.cpu->_pop16(); + cr_assert_eq(value, 0xFFFF, "The pushed value should be equal to 0xFFFF but it was 0x%x.", value); } \ No newline at end of file From 051d1d7596a006ed71e79aa62b55bf7e594c45fc Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Wed, 13 May 2020 18:19:21 +0200 Subject: [PATCH 41/59] Adding PEA --- sources/CPU/CPU.hpp | 4 +++- sources/CPU/Instructions/InternalInstruction.cpp | 6 ++++++ tests/CPU/testInternal.cpp | 12 +++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 364fc81..a4746a3 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -437,6 +437,8 @@ namespace ComSquare::CPU int PER(uint24_t, AddressingMode); //! @brief Push Effective Indirect Address int PEI(uint24_t, AddressingMode); + //! @brief Push Effective Absolute Address + int PEA(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -685,7 +687,7 @@ namespace ComSquare::CPU {&CPU::SBC, 5, "sbc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // F1 {&CPU::SBC, 5, "sbc", AddressingMode::DirectPageIndirect, 2}, // F2 {&CPU::SBC, 7, "sbc", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // F3 - {&CPU::BRK, 7, "pea #-#", AddressingMode::Implied, 2}, // F4 + {&CPU::PEA, 5, "pea", AddressingMode::Immediate16bits, 3}, // F4 {&CPU::SBC, 4, "sbc", AddressingMode::DirectPageIndexedByX, 2}, // F5 {&CPU::INC, 6, "inc", AddressingMode::DirectPageIndexedByX, 2}, // F6 {&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // F7 diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp index 0f01df9..bb06b87 100644 --- a/sources/CPU/Instructions/InternalInstruction.cpp +++ b/sources/CPU/Instructions/InternalInstruction.cpp @@ -193,6 +193,12 @@ namespace ComSquare::CPU return 0; } + int CPU::PEA(uint24_t value, AddressingMode) + { + this->_push(static_cast(value)); + return 0; + } + int CPU::PEI(uint24_t value, AddressingMode) { this->_push(static_cast(value)); diff --git a/tests/CPU/testInternal.cpp b/tests/CPU/testInternal.cpp index 3eabc41..63f6f5c 100644 --- a/tests/CPU/testInternal.cpp +++ b/tests/CPU/testInternal.cpp @@ -930,12 +930,22 @@ Test(PER, simple) } Test(PEI, simple) +{ + Init() + snes.cpu->_registers.s = 0x1FFF; + snes.cpu->PEI(0xFFFF, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.s, 0x1FFD, "The stack pointer should be equal to 0x1FFD but it was 0x%x.", snes.cpu->_registers.s); + uint16_t value = snes.cpu->_pop16(); + cr_assert_eq(value, 0xFFFF, "The pushed value should be equal to 0xFFFF but it was 0x%x.", value); +} + +Test(PEA, simple) { Init() snes.cpu->_registers.s = 0x1FFF; snes.wram->_data[0x0] = 0xFF; snes.wram->_data[0x1] = 0xFF; - snes.cpu->PER(0x0, ComSquare::CPU::AddressingMode::Implied); + snes.cpu->PEA(0xFFFF, ComSquare::CPU::AddressingMode::Implied); cr_assert_eq(snes.cpu->_registers.s, 0x1FFD, "The stack pointer should be equal to 0x1FFD but it was 0x%x.", snes.cpu->_registers.s); uint16_t value = snes.cpu->_pop16(); cr_assert_eq(value, 0xFFFF, "The pushed value should be equal to 0xFFFF but it was 0x%x.", value); From fd9da7085bf66cd2fc18e5878b1e0d2baee80ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Wed, 13 May 2020 18:34:20 +0200 Subject: [PATCH 42/59] adding rendering bg1 --- sources/Models/Vector2.hpp | 5 ++ sources/PPU/PPU.cpp | 93 +++++++++++++++++++++++++++++---- sources/PPU/PPU.hpp | 8 ++- sources/Renderer/SFRenderer.cpp | 2 +- sources/main.cpp | 2 +- 5 files changed, 97 insertions(+), 13 deletions(-) diff --git a/sources/Models/Vector2.hpp b/sources/Models/Vector2.hpp index cfe8d01..0d58acd 100644 --- a/sources/Models/Vector2.hpp +++ b/sources/Models/Vector2.hpp @@ -7,6 +7,11 @@ #include #include +#include +#include +#include +#include +#include namespace ComSquare { diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index ff33d45..54e8542 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -260,6 +260,7 @@ namespace ComSquare::PPU this->_renderer.putPixel(x, y, pixelTmp); } } + renderBackground(1, {0, 0}, 4, false); this->_renderer.drawScreen(); } @@ -421,17 +422,20 @@ namespace ComSquare::PPU void PPU::renderBackground(int bgNumber, std::vector characterSize, int bpp, bool priority) { - int nbCharactersHeight = (this->_registers._bgsc[bgNumber].tilemapVerticalMirroring) ? 64 : 32; - int nbCharactersWidth = (this->_registers._bgsc[bgNumber].tilemapHorizontalMirroring) ? 64 : 32; - uint16_t vramAddress = this->_registers._bgsc[bgNumber].tilemapAddress << 1U; - uint16_t tilemapValue; + int nbCharactersHeight = (this->_registers._bgsc[bgNumber - 1].tilemapVerticalMirroring) ? 64 : 32; + int nbCharactersWidth = (this->_registers._bgsc[bgNumber - 1].tilemapHorizontalMirroring) ? 64 : 32; + uint16_t vramAddress = this->_registers._bgsc[bgNumber - 1].tilemapAddress << 1U; + int size = 8; + uint16_t tileMapValue; - for (int i = 0; i < nbCharactersHeight * nbCharactersWidth; i++) { - for (int j = 0; j < 0x800; j++) { - tilemapValue = this->vram->read_internal(vramAddress); - tilemapValue += this->vram->read_internal(vramAddress + 1) << 8U; + if (this->_registers._bgmode.raw & (1U << (bgNumber + 3U))) + size = 16; + for (int i = 0; i < nbCharactersHeight; i++) { + for (int j = 0; j < nbCharactersWidth; j++) { + tileMapValue = this->vram->read_internal(vramAddress); + tileMapValue += this->vram->read_internal(vramAddress + 1) << 8U; vramAddress += 2; - + drawBgTile(tileMapValue, {i * size, j * size}, bgNumber, bpp, size); } } } @@ -446,13 +450,82 @@ namespace ComSquare::PPU return baseAddress + (x * 16 * step) + (y * step); } - void PPU::drawBgTile(uint16_t data, Vector2 pos, int bg, int bpp) + void PPU::drawBgTile(uint16_t data, Vector2 pos, int bg, int bpp, int size) { uint16_t graphicAddress; union TileMapData tileData; + std::vector palette; + int index = 0; + uint16_t tmp; + uint8_t reference = 0; + uint32_t color = 0; tileData.raw = data; graphicAddress = this->getGraphicVramAddress(tileData.posX, tileData.posY, bg, bpp); // loop on all pixels of the tile 8x8 6x16 16x8 8x16 + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + palette = getPalette(tileData.palette); + reference = getTilePixelReference(graphicAddress, bpp, index); + color = getRealColor(palette[reference]); + this->_renderer.putPixel(pos.x, pos.y, color); + index++; + pos.x++; + if (index == 8 / bpp - 1) { + index = 0; + graphicAddress++; + } + } + index = 0; + pos.x -= size; + pos.y++; + } + } + + std::vector PPU::getPalette(int nbPalette) + { + std::vector palette(0xF); + + uint16_t addr = nbPalette * 0x10; + for (int i = 0; i < 0xF; i++) { + palette[i] = this->cgramRead(addr); + palette[i] += this->cgramRead(addr + 1) << 8U; + } + return palette; + } + + uint32_t PPU::getRealColor(uint16_t color) + { + uint8_t blue; + uint8_t red; + uint8_t green; + uint32_t pixelTmp; + + blue = (color & 0x7D00U) >> 10U; + green = (color & 0x03E0U) >> 5U; + red = (color & 0x001FU); + + pixelTmp = this->_registers._inidisp.brightness * 255U / 15U; + pixelTmp += (red * 255U / 31U) << 24U; + pixelTmp += (green * 255U / 31U) << 16U; + pixelTmp += (blue * 255U / 31U) << 8U; + return pixelTmp; + } + + uint8_t PPU::getTilePixelReference(uint16_t addr, int bpp, int nb) + { + uint8_t reference = this->vram->read_internal(addr); + + switch (bpp) { + case 8: + return reference; + case 4: + return (reference & (0xFU << ((1 - nb) * 4U))) >> (1 - nb) * 4U; + case 2: + return (reference & (0x3U << ((3 - nb) * 2U))) >> (3 - nb) * 2U; + default: + break; + } + return 0; } } \ No newline at end of file diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index c567aa2..7c8bd82 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -593,7 +593,13 @@ namespace ComSquare::PPU //! @brief Get the correct Vram address for a gien x and y uint16_t getGraphicVramAddress(int x, int y, int bg, int bpp); //! @brief Draw a tile on the screen at x y pos - void drawBgTile(uint16_t data, Vector2 pos, int bg, int bpp); + void drawBgTile(uint16_t data, Vector2 pos, int bg, int bpp, int size); + //! @brief Get a palette from the number of the palette (0 - 7) + std::vector getPalette(int nbPalette); + //! @brief Transform SNES color code BGR to uint32_t RGB + uint32_t getRealColor(uint16_t color); + //! @brief Get the color reference of a nb pixel tile + uint8_t getTilePixelReference(uint16_t addr, int bpp, int nb); }; } #endif //COMSQUARE_PPU_HPP diff --git a/sources/Renderer/SFRenderer.cpp b/sources/Renderer/SFRenderer.cpp index 90149d6..d9de9a5 100644 --- a/sources/Renderer/SFRenderer.cpp +++ b/sources/Renderer/SFRenderer.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include namespace ComSquare::Renderer diff --git a/sources/main.cpp b/sources/main.cpp index b0f0afe..0095428 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -76,7 +76,7 @@ int main(int argc, char **argv) } QApplication app(argc, argv); QApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton); - Renderer::QtSFML renderer(600, 800); + Renderer::QtSFML renderer(1080, 1920); try { SNES snes(argv[1], renderer); renderer.createWindow(snes, 60); From 50949b5eb43546d97e9ace99ffb8a9d19393cbaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Wed, 13 May 2020 18:38:06 +0200 Subject: [PATCH 43/59] resizing the window --- sources/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/main.cpp b/sources/main.cpp index 0095428..99bbc08 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -76,7 +76,7 @@ int main(int argc, char **argv) } QApplication app(argc, argv); QApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton); - Renderer::QtSFML renderer(1080, 1920); + Renderer::QtSFML renderer(1100, 1100); try { SNES snes(argv[1], renderer); renderer.createWindow(snes, 60); From 7fe28a8bcc75ba62dcb2d33f3d6216e3680dbb21 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Wed, 13 May 2020 19:14:53 +0200 Subject: [PATCH 44/59] Implemnting the STP --- sources/CPU/CPU.cpp | 2 ++ sources/CPU/CPU.hpp | 6 +++++- sources/CPU/Instructions/InternalInstruction.cpp | 6 ++++++ sources/CPU/Instructions/Interrupts.cpp | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index 7e3ba69..4f2a727 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -205,6 +205,8 @@ namespace ComSquare::CPU { unsigned cycles = 0; + if (this->_isStopped) + return 0xFF; for (int i = 0; i < 0xFF; i++) cycles += this->_executeInstruction(this->readPC()); return cycles; diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index a4746a3..1baa090 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -188,6 +188,8 @@ namespace ComSquare::CPU Registers _registers{}; //! @brief Is the CPU running in emulation mode (in 8bits) bool _isEmulationMode = true; + //! @brief If the processor is stopped (using an STP instruction), the clock is stopped and no instruction will be run until a manual reset. + bool _isStopped = false; //! @brief Internal registers of the CPU (accessible from the bus via addr $4200 to $421F). InternalRegisters _internalRegisters{}; //! @brief The memory bus to use for read/write. @@ -439,6 +441,8 @@ namespace ComSquare::CPU int PEI(uint24_t, AddressingMode); //! @brief Push Effective Absolute Address int PEA(uint24_t, AddressingMode); + //! @brief Stop the processor + int STP(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -662,7 +666,7 @@ namespace ComSquare::CPU {&CPU::CLD, 2, "cld", AddressingMode::Implied, 2}, // D8 {&CPU::CMP, 4, "cmp", AddressingMode::AbsoluteIndexedByY, 3}, // D9 {&CPU::PHX, 3, "phx", AddressingMode::Implied, 1}, // DA - {&CPU::BRK, 7, "stp #-#", AddressingMode::Implied, 2}, // DB + {&CPU::STP, 3, "stp", AddressingMode::Implied, 1}, // DB {&CPU::JML, 7, "jml", AddressingMode::AbsoluteIndirectLong, 2}, // DC {&CPU::CMP, 4, "cmp", AddressingMode::AbsoluteIndexedByX, 3}, // DD {&CPU::DEC, 7, "dec", AddressingMode::AbsoluteIndexedByX, 3}, // DE diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp index bb06b87..59eddbc 100644 --- a/sources/CPU/Instructions/InternalInstruction.cpp +++ b/sources/CPU/Instructions/InternalInstruction.cpp @@ -320,4 +320,10 @@ namespace ComSquare::CPU this->_registers.dbr = this->_pop(); return 0; } + + int CPU::STP(uint24_t, AddressingMode) + { + this->_isStopped = true; + return 0; + } } \ No newline at end of file diff --git a/sources/CPU/Instructions/Interrupts.cpp b/sources/CPU/Instructions/Interrupts.cpp index 2e09647..8f8d515 100644 --- a/sources/CPU/Instructions/Interrupts.cpp +++ b/sources/CPU/Instructions/Interrupts.cpp @@ -18,6 +18,7 @@ namespace ComSquare::CPU this->_registers.d = 0x0000; this->_registers.sh = 0x01; // the low bit of the stack pointer is undefined on reset. this->_registers.pc = this->_cartridgeHeader.emulationInterrupts.reset; + this->_isStopped = false; return 0; } From 838c33b1cfb1fddbcc8370c98a813e6b5e0d35a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Wed, 13 May 2020 19:43:50 +0200 Subject: [PATCH 45/59] refactoring bgrendering --- sources/PPU/PPU.cpp | 59 ++++++++++++++++++++++++++++++--------------- sources/PPU/PPU.hpp | 6 +++-- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 54e8542..7b412da 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -260,7 +260,7 @@ namespace ComSquare::PPU this->_renderer.putPixel(x, y, pixelTmp); } } - renderBackground(1, {0, 0}, 4, false); + renderBackground(1, {8, 8}, 4, false); this->_renderer.drawScreen(); } @@ -420,23 +420,27 @@ namespace ComSquare::PPU return this->cgram->read_internal(addr); } - void PPU::renderBackground(int bgNumber, std::vector characterSize, int bpp, bool priority) + void PPU::renderBackground(int bgNumber, Vector2 characterSize, int bpp, bool priority) { - int nbCharactersHeight = (this->_registers._bgsc[bgNumber - 1].tilemapVerticalMirroring) ? 64 : 32; - int nbCharactersWidth = (this->_registers._bgsc[bgNumber - 1].tilemapHorizontalMirroring) ? 64 : 32; + int nbCharactersHeight = (this->_registers._bgsc[bgNumber - 1].tilemapVerticalMirroring) ? 2 : 1; + int nbCharactersWidth = (this->_registers._bgsc[bgNumber - 1].tilemapHorizontalMirroring) ? 2 : 1; uint16_t vramAddress = this->_registers._bgsc[bgNumber - 1].tilemapAddress << 1U; - int size = 8; - uint16_t tileMapValue; + Vector2 offset(0, 0); + // find an efficient way to render tilemap in order with correct offset and vramaddresses: + for (int i = 0; i < nbCharactersWidth ; i++) { + drawBasicTileMap(vramAddress, bgNumber, bpp, characterSize, offset); + vramAddress += 0x800; + offset.x += 32 * characterSize.x; + } + if (nbCharactersWidth == 1 && nbCharactersHeight == 2) { + vramAddress += 0x800; + nbCharactersHeight = 1; + offset.x = 0; + } + for (int i = 0; i < nbCharactersHeight ; i++) { + drawBasicTileMap(vramAddress, bgNumber, bpp, characterSize, offset); + vramAddress += 0x800; - if (this->_registers._bgmode.raw & (1U << (bgNumber + 3U))) - size = 16; - for (int i = 0; i < nbCharactersHeight; i++) { - for (int j = 0; j < nbCharactersWidth; j++) { - tileMapValue = this->vram->read_internal(vramAddress); - tileMapValue += this->vram->read_internal(vramAddress + 1) << 8U; - vramAddress += 2; - drawBgTile(tileMapValue, {i * size, j * size}, bgNumber, bpp, size); - } } } @@ -450,7 +454,7 @@ namespace ComSquare::PPU return baseAddress + (x * 16 * step) + (y * step); } - void PPU::drawBgTile(uint16_t data, Vector2 pos, int bg, int bpp, int size) + void PPU::drawBgTile(uint16_t data, Vector2 pos, int bg, int bpp, Vector2 characterSize) { uint16_t graphicAddress; union TileMapData tileData; @@ -463,8 +467,8 @@ namespace ComSquare::PPU tileData.raw = data; graphicAddress = this->getGraphicVramAddress(tileData.posX, tileData.posY, bg, bpp); // loop on all pixels of the tile 8x8 6x16 16x8 8x16 - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { + for (int i = 0; i < characterSize.y; i++) { + for (int j = 0; j < characterSize.x; j++) { palette = getPalette(tileData.palette); reference = getTilePixelReference(graphicAddress, bpp, index); color = getRealColor(palette[reference]); @@ -477,7 +481,7 @@ namespace ComSquare::PPU } } index = 0; - pos.x -= size; + pos.x -= characterSize.x; pos.y++; } } @@ -528,4 +532,21 @@ namespace ComSquare::PPU } return 0; } + + void PPU::drawBasicTileMap(uint16_t baseAddress, int bgNumber, int bpp, Vector2 characterSize, Vector2 offset) + { + uint16_t tileMapValue = 0; + Vector2 pos(0,0); + uint16_t vramAddress = baseAddress; + + for (int j = baseAddress; j < (0x800 / 2) + baseAddress; j++) { + tileMapValue = this->vram->read_internal(vramAddress); + tileMapValue += this->vram->read_internal(vramAddress + 1) << 8U; + vramAddress += 2; + drawBgTile(tileMapValue, {((pos.x - pos.y * 32) * characterSize.x) + offset.x, (pos.y * characterSize.y) + offset.x}, bgNumber, bpp, characterSize); + pos.x++; + if (j % 32 == 0) + pos.y++; + } + } } \ No newline at end of file diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index 7c8bd82..13dee70 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -589,17 +589,19 @@ namespace ComSquare::PPU //! @brief Allow others components to read the CGRAM (Debuggers) uint16_t cgramRead(uint16_t addr); //! @brief Render a background on the screen - void renderBackground(int bgNumber, std::vector characterSize, int bpp, bool priority); + void renderBackground(int bgNumber, Vector2 characterSize, int bpp, bool priority); //! @brief Get the correct Vram address for a gien x and y uint16_t getGraphicVramAddress(int x, int y, int bg, int bpp); //! @brief Draw a tile on the screen at x y pos - void drawBgTile(uint16_t data, Vector2 pos, int bg, int bpp, int size); + void drawBgTile(uint16_t data, Vector2 pos, int bg, int bpp, Vector2 characterSize); //! @brief Get a palette from the number of the palette (0 - 7) std::vector getPalette(int nbPalette); //! @brief Transform SNES color code BGR to uint32_t RGB uint32_t getRealColor(uint16_t color); //! @brief Get the color reference of a nb pixel tile uint8_t getTilePixelReference(uint16_t addr, int bpp, int nb); + //! @brief draw a tilemap 32x32 starting at baseAddress + void drawBasicTileMap(uint16_t baseAddress, int bgNumber, int bpp, Vector2 characterSize, Vector2 offset); }; } #endif //COMSQUARE_PPU_HPP From d0e4caf12e35185feaadeded54233025cef1a1e4 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Wed, 13 May 2020 23:12:31 +0200 Subject: [PATCH 46/59] Implementing MVN --- CMakeLists.txt | 2 +- sources/CPU/CPU.hpp | 13 ++++++++++--- .../CPU/Instructions/InternalInstruction.cpp | 5 +++++ .../CPU/Instructions/TransferRegisters.cpp | 18 ++++++++++++++++++ ...ransferRegisters.cpp => testTransfers.cpp} | 19 +++++++++++++++++++ 5 files changed, 53 insertions(+), 4 deletions(-) rename tests/CPU/{TransferRegisters.cpp => testTransfers.cpp} (94%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18c98a8..302d68a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,7 +90,7 @@ add_executable(unit_tests sources/APU/IPL/IPL.cpp tests/CPU/Math/testSBC.cpp sources/CPU/Instructions/TransferRegisters.cpp - tests/CPU/TransferRegisters.cpp + tests/CPU/testTransfers.cpp sources/CPU/AddressingModes.cpp sources/Models/Components.hpp sources/CPU/Instruction.hpp diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 1baa090..39e483f 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -443,6 +443,13 @@ namespace ComSquare::CPU int PEA(uint24_t, AddressingMode); //! @brief Stop the processor int STP(uint24_t, AddressingMode); + //! @brief WDM Reserved for Future Expansion (used as a code breakpoint) + int WDM(uint24_t, AddressingMode); + //! @brief Block Move Next. This instruction is special: it takes parameter in the registers + //! @param X_register Source address + //! @param Y_register Destination address + //! @param C_register (16 bits accumulator) Length -1 + int MVN(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -513,7 +520,7 @@ namespace ComSquare::CPU {&CPU::AND, 5, "and", AddressingMode::AbsoluteIndexedByXLong, 4}, // 3F {&CPU::RTI, 6, "rti", AddressingMode::Implied, 1}, // 40 {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 41 - {&CPU::BRK, 7, "wdm #-#", AddressingMode::Implied, 2}, // 42 + {&CPU::WDM, 2, "wdm", AddressingMode::Immediate8bits, 2}, // 42 {&CPU::EOR, 4, "eor", AddressingMode::StackRelative, 2}, // 43 {&CPU::BRK, 7, "mvp #-#", AddressingMode::Implied, 2}, // 44 {&CPU::EOR, 3, "eor", AddressingMode::DirectPage, 2}, // 45 @@ -531,7 +538,7 @@ namespace ComSquare::CPU {&CPU::EOR, 5, "eor", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 51 {&CPU::EOR, 5, "eor", AddressingMode::DirectPageIndirect, 2}, // 52 {&CPU::EOR, 4, "eor", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 53 - {&CPU::BRK, 7, "mvn #-#", AddressingMode::Implied, 2}, // 54 + {&CPU::MVN, 0, "mvn", AddressingMode::Immediate16bits, 2}, // 54 {&CPU::EOR, 4, "eor", AddressingMode::DirectPageIndexedByX, 2}, // 55 {&CPU::LSR, 6, "lsr", AddressingMode::DirectPageIndexedByX, 2}, // 56 {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 57 @@ -618,7 +625,7 @@ namespace ComSquare::CPU {&CPU::TAY, 2, "tay", AddressingMode::Implied, 1}, // A8 {&CPU::LDA, 2, "lda", AddressingMode::ImmediateForA, 2}, // A9 {&CPU::TAX, 2, "tax", AddressingMode::Implied, 1}, // AA - {&CPU::BRK, 7, "plb #-#", AddressingMode::Implied, 2}, // AB + {&CPU::PLB, 4, "plb", AddressingMode::Implied, 1}, // AB {&CPU::LDY, 4, "ldy", AddressingMode::Absolute, 4}, // AC {&CPU::LDA, 4, "lda", AddressingMode::Absolute, 3}, // AD {&CPU::LDX, 4, "ldx", AddressingMode::Absolute, 3}, // AE diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp index 59eddbc..8430522 100644 --- a/sources/CPU/Instructions/InternalInstruction.cpp +++ b/sources/CPU/Instructions/InternalInstruction.cpp @@ -326,4 +326,9 @@ namespace ComSquare::CPU this->_isStopped = true; return 0; } + + int CPU::WDM(uint24_t, AddressingMode) + { + return 0; + } } \ No newline at end of file diff --git a/sources/CPU/Instructions/TransferRegisters.cpp b/sources/CPU/Instructions/TransferRegisters.cpp index 18efae8..64821e3 100644 --- a/sources/CPU/Instructions/TransferRegisters.cpp +++ b/sources/CPU/Instructions/TransferRegisters.cpp @@ -2,6 +2,7 @@ // Created by anonymus-raccoon on 2/28/20. // +#include #include "../CPU.hpp" namespace ComSquare::CPU @@ -150,4 +151,21 @@ namespace ComSquare::CPU this->_registers.p.z = this->_registers.y == 0; return 0; } + + int CPU::MVN(uint24_t params, AddressingMode) + { + uint8_t srcBank = params; + uint8_t destBank = params >> 8u; + int length = this->_registers.a + 1; + + this->_registers.dbr = destBank; + while (this->_registers.a != 0xFFFF) { + uint8_t data = this->_bus->read(srcBank << 24u | this->_registers.x); + this->_bus->write(destBank << 24u | this->_registers.y, data); + this->_registers.x++; + this->_registers.y++; + this->_registers.a--; + } + return 7 * length; + } } \ No newline at end of file diff --git a/tests/CPU/TransferRegisters.cpp b/tests/CPU/testTransfers.cpp similarity index 94% rename from tests/CPU/TransferRegisters.cpp rename to tests/CPU/testTransfers.cpp index 91ab304..6550cc5 100644 --- a/tests/CPU/TransferRegisters.cpp +++ b/tests/CPU/testTransfers.cpp @@ -435,4 +435,23 @@ Test(TYX, nativeMode) cr_assert_eq(snes.cpu->_registers.x, 0xAB0D, "The x index should be 0xAB0D but it was %x", snes.cpu->_registers.x); cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set."); cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should be not set."); +} + +Test(MVN, hardCase) +{ + Init() + snes.cpu->_registers.a = 0x10; + snes.cpu->_registers.x = 0x0000; + snes.cpu->_registers.y = 0x1000; + for (int i = 0; i <= snes.cpu->_registers.a; i++) + snes.wram->_data[i] = i; + + int cycles = snes.cpu->MVN(0x2010, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(cycles, 0x77, "The MVN should take 0x77 cycles but it took %x.", cycles); + cr_assert_eq(snes.cpu->_registers.dbr, 0x20, "The data bank register should be 0x20 but it was %x", snes.cpu->_registers.dbr); + cr_assert_eq(snes.cpu->_registers.a, 0xFFFF, "The c accumulator should be 0xFFFF but it was %x", snes.cpu->_registers.a); + cr_assert_eq(snes.cpu->_registers.x, 0x0011, "The x index should be 0x0011 but it was %x", snes.cpu->_registers.x); + cr_assert_eq(snes.cpu->_registers.y, 0x1011, "The y index should be 0x1011 but it was %x", snes.cpu->_registers.y); + for (int i = 0; i < 0x11; i++) + cr_assert_eq(snes.wram->_data[i + 0x1000], i, "The data in ram should be %x but it was %x", i, snes.wram->_data[i + 0x1000]); } \ No newline at end of file From c8f7af7ea32393ac385ad050d920e56e25a1c357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Thu, 14 May 2020 01:05:27 +0200 Subject: [PATCH 47/59] rendering a background is done tested with red.smc --- sources/PPU/PPU.cpp | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 7b412da..d12e94d 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -422,25 +422,21 @@ namespace ComSquare::PPU void PPU::renderBackground(int bgNumber, Vector2 characterSize, int bpp, bool priority) { - int nbCharactersHeight = (this->_registers._bgsc[bgNumber - 1].tilemapVerticalMirroring) ? 2 : 1; - int nbCharactersWidth = (this->_registers._bgsc[bgNumber - 1].tilemapHorizontalMirroring) ? 2 : 1; + int nbBgHeight = (this->_registers._bgsc[bgNumber - 1].tilemapVerticalMirroring) ? 2 : 1; + int nbBgWidth = (this->_registers._bgsc[bgNumber - 1].tilemapHorizontalMirroring) ? 2 : 1; uint16_t vramAddress = this->_registers._bgsc[bgNumber - 1].tilemapAddress << 1U; Vector2 offset(0, 0); - // find an efficient way to render tilemap in order with correct offset and vramaddresses: - for (int i = 0; i < nbCharactersWidth ; i++) { - drawBasicTileMap(vramAddress, bgNumber, bpp, characterSize, offset); - vramAddress += 0x800; - offset.x += 32 * characterSize.x; - } - if (nbCharactersWidth == 1 && nbCharactersHeight == 2) { - vramAddress += 0x800; - nbCharactersHeight = 1; - offset.x = 0; - } - for (int i = 0; i < nbCharactersHeight ; i++) { - drawBasicTileMap(vramAddress, bgNumber, bpp, characterSize, offset); - vramAddress += 0x800; + for (int i = 0; i < 4; i++) { + if (!(i == 1 && nbBgWidth == 1) && !(i > 1 && nbBgHeight == 1)) { + drawBasicTileMap(vramAddress, bgNumber, bpp, characterSize, offset); + } + vramAddress+= 0x800; + offset.x += 32 * characterSize.x; + if (i == 2) { + offset.x = 0; + offset.y += 32 * characterSize.y; + } } } @@ -466,7 +462,6 @@ namespace ComSquare::PPU tileData.raw = data; graphicAddress = this->getGraphicVramAddress(tileData.posX, tileData.posY, bg, bpp); - // loop on all pixels of the tile 8x8 6x16 16x8 8x16 for (int i = 0; i < characterSize.y; i++) { for (int j = 0; j < characterSize.x; j++) { palette = getPalette(tileData.palette); @@ -475,7 +470,7 @@ namespace ComSquare::PPU this->_renderer.putPixel(pos.x, pos.y, color); index++; pos.x++; - if (index == 8 / bpp - 1) { + if (index == (8 / bpp) - 1) { index = 0; graphicAddress++; } @@ -539,14 +534,18 @@ namespace ComSquare::PPU Vector2 pos(0,0); uint16_t vramAddress = baseAddress; - for (int j = baseAddress; j < (0x800 / 2) + baseAddress; j++) { + while (vramAddress < 0x800 + baseAddress) { tileMapValue = this->vram->read_internal(vramAddress); tileMapValue += this->vram->read_internal(vramAddress + 1) << 8U; vramAddress += 2; - drawBgTile(tileMapValue, {((pos.x - pos.y * 32) * characterSize.x) + offset.x, (pos.y * characterSize.y) + offset.x}, bgNumber, bpp, characterSize); - pos.x++; - if (j % 32 == 0) + drawBgTile(tileMapValue, {(pos.x * characterSize.x) + offset.x, (pos.y * characterSize.y) + offset.y}, bgNumber, bpp, characterSize); + //pos.x++; + if (pos.x % 31 == 0 && pos.x) { pos.y++; + pos.x = 0; + } + else + pos.x++; } } } \ No newline at end of file From 8240fbd54c4808393a6b4272acbae822962d2c2d Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 14 May 2020 01:06:29 +0200 Subject: [PATCH 48/59] Implementing MVP --- sources/CPU/CPU.hpp | 7 ++++++- .../CPU/Instructions/TransferRegisters.cpp | 17 +++++++++++++++++ tests/CPU/testTransfers.cpp | 19 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 39e483f..2b95861 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -450,6 +450,11 @@ namespace ComSquare::CPU //! @param Y_register Destination address //! @param C_register (16 bits accumulator) Length -1 int MVN(uint24_t, AddressingMode); + //! @brief Block Move Previous. This instruction is special: it takes parameter in the registers + //! @param X_register Source address (last byte) + //! @param Y_register Destination address (last byte) + //! @param C_register (16 bits accumulator) Length -1 + int MVP(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -522,7 +527,7 @@ namespace ComSquare::CPU {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 41 {&CPU::WDM, 2, "wdm", AddressingMode::Immediate8bits, 2}, // 42 {&CPU::EOR, 4, "eor", AddressingMode::StackRelative, 2}, // 43 - {&CPU::BRK, 7, "mvp #-#", AddressingMode::Implied, 2}, // 44 + {&CPU::MVP, 0, "mvp", AddressingMode::Immediate16bits, 3}, // 44 {&CPU::EOR, 3, "eor", AddressingMode::DirectPage, 2}, // 45 {&CPU::LSR, 5, "lsr", AddressingMode::DirectPage, 2}, // 46 {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectLong, 2}, // 47 diff --git a/sources/CPU/Instructions/TransferRegisters.cpp b/sources/CPU/Instructions/TransferRegisters.cpp index 64821e3..496a5d6 100644 --- a/sources/CPU/Instructions/TransferRegisters.cpp +++ b/sources/CPU/Instructions/TransferRegisters.cpp @@ -168,4 +168,21 @@ namespace ComSquare::CPU } return 7 * length; } + + int CPU::MVP(uint24_t params, AddressingMode) + { + uint8_t srcBank = params; + uint8_t destBank = params >> 8u; + int length = this->_registers.a + 1; + + this->_registers.dbr = destBank; + while (this->_registers.a != 0xFFFF) { + uint8_t data = this->_bus->read(srcBank << 24u | this->_registers.x); + this->_bus->write(destBank << 24u | this->_registers.y, data); + this->_registers.x--; + this->_registers.y--; + this->_registers.a--; + } + return 7 * length; + } } \ No newline at end of file diff --git a/tests/CPU/testTransfers.cpp b/tests/CPU/testTransfers.cpp index 6550cc5..87497b6 100644 --- a/tests/CPU/testTransfers.cpp +++ b/tests/CPU/testTransfers.cpp @@ -454,4 +454,23 @@ Test(MVN, hardCase) cr_assert_eq(snes.cpu->_registers.y, 0x1011, "The y index should be 0x1011 but it was %x", snes.cpu->_registers.y); for (int i = 0; i < 0x11; i++) cr_assert_eq(snes.wram->_data[i + 0x1000], i, "The data in ram should be %x but it was %x", i, snes.wram->_data[i + 0x1000]); +} + +Test(MVP, hardCase) +{ + Init() + snes.cpu->_registers.a = 0x10; + snes.cpu->_registers.x = 0x0010; + snes.cpu->_registers.y = 0x1010; + for (int i = 0; i <= snes.cpu->_registers.a; i++) + snes.wram->_data[i] = i; + + int cycles = snes.cpu->MVP(0x2010, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(cycles, 0x77, "The MVN should take 0x77 cycles but it took %x.", cycles); + cr_assert_eq(snes.cpu->_registers.dbr, 0x20, "The data bank register should be 0x20 but it was %x", snes.cpu->_registers.dbr); + cr_assert_eq(snes.cpu->_registers.a, 0xFFFF, "The c accumulator should be 0xFFFF but it was %x", snes.cpu->_registers.a); + cr_assert_eq(snes.cpu->_registers.x, 0xFFFF, "The x index should be 0xFFFF but it was %x", snes.cpu->_registers.x); + cr_assert_eq(snes.cpu->_registers.y, 0x0FFF, "The y index should be 0x0FFF but it was %x", snes.cpu->_registers.y); + for (int i = 0; i < 0x11; i++) + cr_assert_eq(snes.wram->_data[i + 0x1000], i, "The data in ram should be %x but it was %x", i, snes.wram->_data[i + 0x1000]); } \ No newline at end of file From 2033bd56e62c0fe8dcbbd8c0e0feb8791c056583 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 14 May 2020 01:21:52 +0200 Subject: [PATCH 49/59] Fixing warning/compilation --- sources/Models/Vector2.hpp | 11 +++-------- ui/cartridgeView.ui | 8 ++++---- ui/ui_cpu.h | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/sources/Models/Vector2.hpp b/sources/Models/Vector2.hpp index 0d58acd..5908d2d 100644 --- a/sources/Models/Vector2.hpp +++ b/sources/Models/Vector2.hpp @@ -6,12 +6,7 @@ #define COMSQUARE_VECTOR2_HPP #include -#include -#include -#include -#include -#include -#include +#include namespace ComSquare { @@ -25,8 +20,8 @@ namespace ComSquare Vector2() : x(0), y(0) {} - Vector2(T x, T y) - : x(x), y(y) {} + Vector2(T _x, T _y) + : x(_x), y(_y) {} Vector2(sf::Vector2 v) : x(v.x), y(v.y) {} diff --git a/ui/cartridgeView.ui b/ui/cartridgeView.ui index fcccf42..2e4aea9 100644 --- a/ui/cartridgeView.ui +++ b/ui/cartridgeView.ui @@ -22,7 +22,7 @@ - 0 + 1 @@ -180,7 +180,7 @@ 351 - + @@ -272,7 +272,7 @@ Native - + 0 @@ -281,7 +281,7 @@ 351 - + diff --git a/ui/ui_cpu.h b/ui/ui_cpu.h index 5bb8f98..b7aafd0 100644 --- a/ui/ui_cpu.h +++ b/ui/ui_cpu.h @@ -1,7 +1,7 @@ /******************************************************************************** ** Form generated from reading UI file 'cpu.ui' ** -** Created by: Qt User Interface Compiler version 5.13.2 +** Created by: Qt User Interface Compiler version 5.14.2 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ From e021f193fa90dcb18a72a5293d46273d066b81e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Thu, 14 May 2020 01:25:59 +0200 Subject: [PATCH 50/59] removing unused variable --- sources/PPU/PPU.cpp | 1 - ui/ui_cpu.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index d12e94d..b5e4031 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -456,7 +456,6 @@ namespace ComSquare::PPU union TileMapData tileData; std::vector palette; int index = 0; - uint16_t tmp; uint8_t reference = 0; uint32_t color = 0; diff --git a/ui/ui_cpu.h b/ui/ui_cpu.h index b7aafd0..5bb8f98 100644 --- a/ui/ui_cpu.h +++ b/ui/ui_cpu.h @@ -1,7 +1,7 @@ /******************************************************************************** ** Form generated from reading UI file 'cpu.ui' ** -** Created by: Qt User Interface Compiler version 5.14.2 +** Created by: Qt User Interface Compiler version 5.13.2 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ From 92e0d41f748e1f65393fe89a18e1d031ab05b88e Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 14 May 2020 14:52:50 +0200 Subject: [PATCH 51/59] Fixing an open bus issue with the bus's debugger --- sources/Debugger/MemoryBusDebug.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sources/Debugger/MemoryBusDebug.cpp b/sources/Debugger/MemoryBusDebug.cpp index a02533c..670f484 100644 --- a/sources/Debugger/MemoryBusDebug.cpp +++ b/sources/Debugger/MemoryBusDebug.cpp @@ -165,9 +165,10 @@ namespace ComSquare::Debugger void MemoryBusDebug::write(uint24_t addr, uint8_t data) { auto accessor = this->getAccessor(addr); - uint8_t value; + uint8_t value = 0; try { - value = accessor->read(addr - accessor->getStart()); + if (accessor) + value = accessor->read(addr - accessor->getStart()); } catch (InvalidAddress &) { value = 0; } From 166a55ec04db2766ea30adcb9c0a85574f2a5dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Thu, 14 May 2020 14:53:46 +0200 Subject: [PATCH 52/59] moving background related founctions in backgrounds.c --- CMakeLists.txt | 2 +- sources/PPU/Backgrounds.cpp | 142 ++++++++++++++++++++++++++++++++++++ sources/PPU/PPU.cpp | 128 -------------------------------- 3 files changed, 143 insertions(+), 129 deletions(-) create mode 100644 sources/PPU/Backgrounds.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f8e1a63..fbb74d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -212,7 +212,7 @@ add_executable(ComSquare sources/Models/Components.hpp sources/Debugger/CGramDebug.cpp sources/Debugger/CGramDebug.hpp - sources/Models/Vector2.hpp) + sources/Models/Vector2.hpp sources/PPU/Backgrounds.cpp) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) diff --git a/sources/PPU/Backgrounds.cpp b/sources/PPU/Backgrounds.cpp new file mode 100644 index 0000000..d498476 --- /dev/null +++ b/sources/PPU/Backgrounds.cpp @@ -0,0 +1,142 @@ +// +// Created by cbihan on 5/14/20. +// + +#include +#include +#include "PPU.hpp" +#include "PPUUtils.hpp" +#include "../Exceptions/NotImplementedException.hpp" +#include "../Exceptions/InvalidAddress.hpp" +#include "../Ram/Ram.hpp" +#include "../Models/Vector2.hpp" + +namespace ComSquare::PPU +{ + void PPU::renderBackground(int bgNumber, Vector2 characterSize, int bpp, bool priority) + { + int nbBgHeight = (this->_registers._bgsc[bgNumber - 1].tilemapVerticalMirroring) ? 2 : 1; + int nbBgWidth = (this->_registers._bgsc[bgNumber - 1].tilemapHorizontalMirroring) ? 2 : 1; + uint16_t vramAddress = this->_registers._bgsc[bgNumber - 1].tilemapAddress << 1U; + Vector2 offset(0, 0); + + for (int i = 0; i < 4; i++) { + if (!(i == 1 && nbBgWidth == 1) && !(i > 1 && nbBgHeight == 1)) { + drawBasicTileMap(vramAddress, bgNumber, bpp, characterSize, offset); + } + vramAddress+= 0x800; + offset.x += 32 * characterSize.x; + if (i == 2) { + offset.x = 0; + offset.y += 32 * characterSize.y; + } + } + } + + uint16_t PPU::getGraphicVramAddress(int x, int y, int bg, int bpp) + { + uint16_t baseAddress = this->_registers._bgnba[bg > 2].raw; + int step = bpp * 8; + + baseAddress = (bg % 2) ? baseAddress & 0xFU : (baseAddress & 0xFU) >> 4U; + baseAddress = baseAddress << 12U; + return baseAddress + (x * 16 * step) + (y * step); + } + + void PPU::drawBgTile(uint16_t data, Vector2 pos, int bg, int bpp, Vector2 characterSize) + { + uint16_t graphicAddress; + union TileMapData tileData; + std::vector palette; + int index = 0; + uint8_t reference = 0; + uint32_t color = 0; + + tileData.raw = data; + graphicAddress = this->getGraphicVramAddress(tileData.posX, tileData.posY, bg, bpp); + for (int i = 0; i < characterSize.y; i++) { + for (int j = 0; j < characterSize.x; j++) { + palette = getPalette(tileData.palette); + reference = getTilePixelReference(graphicAddress, bpp, index); + color = getRealColor(palette[reference]); + this->_renderer.putPixel(pos.x, pos.y, color); + index++; + pos.x++; + if (index == (8 / bpp) - 1) { + index = 0; + graphicAddress++; + } + } + index = 0; + pos.x -= characterSize.x; + pos.y++; + } + } + + std::vector PPU::getPalette(int nbPalette) + { + std::vector palette(0xF); + + uint16_t addr = nbPalette * 0x10; + for (int i = 0; i < 0xF; i++) { + palette[i] = this->cgramRead(addr); + palette[i] += this->cgramRead(addr + 1) << 8U; + } + return palette; + } + + uint32_t PPU::getRealColor(uint16_t color) + { + uint8_t blue; + uint8_t red; + uint8_t green; + uint32_t pixelTmp; + + blue = (color & 0x7D00U) >> 10U; + green = (color & 0x03E0U) >> 5U; + red = (color & 0x001FU); + + pixelTmp = this->_registers._inidisp.brightness * 255U / 15U; + pixelTmp += (red * 255U / 31U) << 24U; + pixelTmp += (green * 255U / 31U) << 16U; + pixelTmp += (blue * 255U / 31U) << 8U; + return pixelTmp; + } + + uint8_t PPU::getTilePixelReference(uint16_t addr, int bpp, int nb) + { + uint8_t reference = this->vram->read_internal(addr); + + switch (bpp) { + case 8: + return reference; + case 4: + return (reference & (0xFU << ((1 - nb) * 4U))) >> (1 - nb) * 4U; + case 2: + return (reference & (0x3U << ((3 - nb) * 2U))) >> (3 - nb) * 2U; + default: + break; + } + return 0; + } + + void PPU::drawBasicTileMap(uint16_t baseAddress, int bgNumber, int bpp, Vector2 characterSize, Vector2 offset) + { + uint16_t tileMapValue = 0; + Vector2 pos(0,0); + uint16_t vramAddress = baseAddress; + + while (vramAddress < 0x800 + baseAddress) { + tileMapValue = this->vram->read_internal(vramAddress); + tileMapValue += this->vram->read_internal(vramAddress + 1) << 8U; + vramAddress += 2; + drawBgTile(tileMapValue, {(pos.x * characterSize.x) + offset.x, (pos.y * characterSize.y) + offset.y}, bgNumber, bpp, characterSize); + if (pos.x % 31 == 0 && pos.x) { + pos.y++; + pos.x = 0; + } + else + pos.x++; + } + } +} \ No newline at end of file diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index b5e4031..15263c4 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -419,132 +419,4 @@ namespace ComSquare::PPU { return this->cgram->read_internal(addr); } - - void PPU::renderBackground(int bgNumber, Vector2 characterSize, int bpp, bool priority) - { - int nbBgHeight = (this->_registers._bgsc[bgNumber - 1].tilemapVerticalMirroring) ? 2 : 1; - int nbBgWidth = (this->_registers._bgsc[bgNumber - 1].tilemapHorizontalMirroring) ? 2 : 1; - uint16_t vramAddress = this->_registers._bgsc[bgNumber - 1].tilemapAddress << 1U; - Vector2 offset(0, 0); - - for (int i = 0; i < 4; i++) { - if (!(i == 1 && nbBgWidth == 1) && !(i > 1 && nbBgHeight == 1)) { - drawBasicTileMap(vramAddress, bgNumber, bpp, characterSize, offset); - } - vramAddress+= 0x800; - offset.x += 32 * characterSize.x; - if (i == 2) { - offset.x = 0; - offset.y += 32 * characterSize.y; - } - } - } - - uint16_t PPU::getGraphicVramAddress(int x, int y, int bg, int bpp) - { - uint16_t baseAddress = this->_registers._bgnba[bg > 2].raw; - int step = bpp * 8; - - baseAddress = (bg % 2) ? baseAddress & 0xFU : (baseAddress & 0xFU) >> 4U; - baseAddress = baseAddress << 12U; - return baseAddress + (x * 16 * step) + (y * step); - } - - void PPU::drawBgTile(uint16_t data, Vector2 pos, int bg, int bpp, Vector2 characterSize) - { - uint16_t graphicAddress; - union TileMapData tileData; - std::vector palette; - int index = 0; - uint8_t reference = 0; - uint32_t color = 0; - - tileData.raw = data; - graphicAddress = this->getGraphicVramAddress(tileData.posX, tileData.posY, bg, bpp); - for (int i = 0; i < characterSize.y; i++) { - for (int j = 0; j < characterSize.x; j++) { - palette = getPalette(tileData.palette); - reference = getTilePixelReference(graphicAddress, bpp, index); - color = getRealColor(palette[reference]); - this->_renderer.putPixel(pos.x, pos.y, color); - index++; - pos.x++; - if (index == (8 / bpp) - 1) { - index = 0; - graphicAddress++; - } - } - index = 0; - pos.x -= characterSize.x; - pos.y++; - } - } - - std::vector PPU::getPalette(int nbPalette) - { - std::vector palette(0xF); - - uint16_t addr = nbPalette * 0x10; - for (int i = 0; i < 0xF; i++) { - palette[i] = this->cgramRead(addr); - palette[i] += this->cgramRead(addr + 1) << 8U; - } - return palette; - } - - uint32_t PPU::getRealColor(uint16_t color) - { - uint8_t blue; - uint8_t red; - uint8_t green; - uint32_t pixelTmp; - - blue = (color & 0x7D00U) >> 10U; - green = (color & 0x03E0U) >> 5U; - red = (color & 0x001FU); - - pixelTmp = this->_registers._inidisp.brightness * 255U / 15U; - pixelTmp += (red * 255U / 31U) << 24U; - pixelTmp += (green * 255U / 31U) << 16U; - pixelTmp += (blue * 255U / 31U) << 8U; - return pixelTmp; - } - - uint8_t PPU::getTilePixelReference(uint16_t addr, int bpp, int nb) - { - uint8_t reference = this->vram->read_internal(addr); - - switch (bpp) { - case 8: - return reference; - case 4: - return (reference & (0xFU << ((1 - nb) * 4U))) >> (1 - nb) * 4U; - case 2: - return (reference & (0x3U << ((3 - nb) * 2U))) >> (3 - nb) * 2U; - default: - break; - } - return 0; - } - - void PPU::drawBasicTileMap(uint16_t baseAddress, int bgNumber, int bpp, Vector2 characterSize, Vector2 offset) - { - uint16_t tileMapValue = 0; - Vector2 pos(0,0); - uint16_t vramAddress = baseAddress; - - while (vramAddress < 0x800 + baseAddress) { - tileMapValue = this->vram->read_internal(vramAddress); - tileMapValue += this->vram->read_internal(vramAddress + 1) << 8U; - vramAddress += 2; - drawBgTile(tileMapValue, {(pos.x * characterSize.x) + offset.x, (pos.y * characterSize.y) + offset.y}, bgNumber, bpp, characterSize); - //pos.x++; - if (pos.x % 31 == 0 && pos.x) { - pos.y++; - pos.x = 0; - } - else - pos.x++; - } - } } \ No newline at end of file From c6e4cd1702689962a9a3b60100a814ee6565ab9e Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 14 May 2020 15:51:48 +0200 Subject: [PATCH 53/59] Fixing a segfault with the bus & cpu's debugger together --- sources/CPU/CPU.cpp | 2 -- sources/CPU/CPU.hpp | 2 +- sources/Debugger/CPU/CPUDebug.cpp | 19 ++++++++++++++----- sources/Debugger/CPU/CPUDebug.hpp | 10 ++++++++-- ui/ui_cpu.h | 2 +- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index 8116408..cd9ddca 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -6,9 +6,7 @@ #include #include -#include "../Exceptions/NotImplementedException.hpp" #include "../Exceptions/InvalidAddress.hpp" -#include "../Exceptions/InvalidOpcode.hpp" namespace ComSquare::CPU { diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 26dde23..f127d41 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -713,7 +713,7 @@ namespace ComSquare::CPU virtual bool isDebugger(); //! @brief Change the memory bus used by the CPU. - void setMemoryBus(std::shared_ptr bus); + virtual void setMemoryBus(std::shared_ptr bus); }; } diff --git a/sources/Debugger/CPU/CPUDebug.cpp b/sources/Debugger/CPU/CPUDebug.cpp index 5be3734..6bcb800 100644 --- a/sources/Debugger/CPU/CPUDebug.cpp +++ b/sources/Debugger/CPU/CPUDebug.cpp @@ -5,11 +5,9 @@ #include "CPUDebug.hpp" #include "../../Utility/Utility.hpp" #include "../../Exceptions/InvalidOpcode.hpp" -#include "../../CPU/CPU.hpp" #include #include #include -#include using namespace ComSquare::CPU; @@ -21,7 +19,7 @@ namespace ComSquare::Debugger _ui(), _model(*this), _painter(*this), - _stackModel(*this->_bus, *this), + _stackModel(this->_bus, *this), _snes(snes) { this->_window->setContextMenuPolicy(Qt::NoContextMenu); @@ -70,6 +68,12 @@ namespace ComSquare::Debugger this->_snes.disableCPUDebugging(); } + void CPUDebug::setMemoryBus(std::shared_ptr bus) + { + this->_stackModel.setMemoryBus(bus); + CPU::setMemoryBus(bus); + } + unsigned CPUDebug::update() { try { @@ -379,7 +383,12 @@ QSize RowPainter::sizeHint(const QStyleOptionViewItem &, const QModelIndex &) co return QSize(); } -StackModel::StackModel(ComSquare::Memory::MemoryBus &bus, ComSquare::Debugger::CPUDebug &cpu) : _bus(bus), _cpu(cpu) { } +StackModel::StackModel(std::shared_ptr bus, ComSquare::Debugger::CPUDebug &cpu) : _bus(bus), _cpu(cpu) { } + +void StackModel::setMemoryBus(std::shared_ptr bus) +{ + this->_bus = std::move(bus); +} int StackModel::rowCount(const QModelIndex &) const { @@ -405,7 +414,7 @@ QVariant StackModel::data(const QModelIndex &index, int role) const return QVariant(); uint16_t addr = index.row() * 2 + index.column(); try { - uint8_t value = this->_bus.read(addr); + uint8_t value = this->_bus->read(addr); return (ComSquare::Utility::to_hex(value, ComSquare::Utility::NoPrefix).c_str()); } catch (std::exception &) { return "??"; diff --git a/sources/Debugger/CPU/CPUDebug.hpp b/sources/Debugger/CPU/CPUDebug.hpp index ab596d0..db00d37 100644 --- a/sources/Debugger/CPU/CPUDebug.hpp +++ b/sources/Debugger/CPU/CPUDebug.hpp @@ -34,10 +34,10 @@ class StackModel : public QAbstractTableModel { Q_OBJECT private: - ComSquare::Memory::MemoryBus &_bus; + std::shared_ptr _bus; ComSquare::Debugger::CPUDebug &_cpu; public: - explicit StackModel(ComSquare::Memory::MemoryBus &bus, ComSquare::Debugger::CPUDebug &cpu); + explicit StackModel(std::shared_ptr bus, ComSquare::Debugger::CPUDebug &cpu); StackModel(const StackModel &) = delete; const StackModel &operator=(const StackModel &) = delete; ~StackModel() override = default; @@ -50,6 +50,9 @@ public: QVariant data(const QModelIndex &index, int role) const override; //! @brief Override the headers to use hex values. QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + + //! @brief Change the memory bus used by the view. + void setMemoryBus(std::shared_ptr bus); }; //! @brief The qt model that show the history. @@ -285,6 +288,9 @@ namespace ComSquare::Debugger //! @brief Override the basic cpu's update to allow pausing of the CPU only. unsigned update() override; + + //! @brief Change the memory bus used by the CPU. + void setMemoryBus(std::shared_ptr bus) override; }; } diff --git a/ui/ui_cpu.h b/ui/ui_cpu.h index 97769dd..b7aafd0 100644 --- a/ui/ui_cpu.h +++ b/ui/ui_cpu.h @@ -1,7 +1,7 @@ /******************************************************************************** ** Form generated from reading UI file 'cpu.ui' ** -** Created by: Qt User Interface Compiler version 5.14.1 +** Created by: Qt User Interface Compiler version 5.14.2 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ From 5f0ed5f5614f1f36b7552a4317ad19a41ae98253 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 14 May 2020 17:37:06 +0200 Subject: [PATCH 54/59] Adding the WAI and handling NMI & IRQ interrupts --- sources/CPU/CPU.cpp | 35 ++++++++++++++++++++--- sources/CPU/CPU.hpp | 24 ++++++++++++++-- sources/CPU/Instructions/Interrupts.cpp | 38 ++++++++++++------------- 3 files changed, 71 insertions(+), 26 deletions(-) diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index 4f2a727..88ce592 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -205,13 +205,40 @@ namespace ComSquare::CPU { unsigned cycles = 0; - if (this->_isStopped) - return 0xFF; - for (int i = 0; i < 0xFF; i++) - cycles += this->_executeInstruction(this->readPC()); + for (int i = 0; i < 0xFF; i++) { + if (this->_isStopped) { + cycles += 1; + continue; + } + + this->_checkInterrupts(); + + if (!this->_isWaitingForInterrupt) + cycles += this->_executeInstruction(this->readPC()); + } return cycles; } + void CPU::_checkInterrupts() + { + if (!this->IsNMIRequested && !this->IsIRQRequested && !this->IsAbortRequested) + return; + this->_isWaitingForInterrupt = false; + + if (this->IsNMIRequested) { + this->_runInterrupt( + this->_cartridgeHeader.nativeInterrupts.nmi, + this->_cartridgeHeader.emulationInterrupts.nmi); + return; + } + if (this->IsIRQRequested && !this->_registers.p.i) { + this->_runInterrupt( + this->_cartridgeHeader.nativeInterrupts.irq, + this->_cartridgeHeader.emulationInterrupts.irq); + return; + } + } + uint24_t CPU::_getValueAddr(Instruction &instruction) { switch (instruction.addressingMode) { diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 2b95861..808796b 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -186,12 +186,16 @@ namespace ComSquare::CPU protected: //! @brief All the registers of the CPU Registers _registers{}; + //! @brief Internal registers of the CPU (accessible from the bus via addr $4200 to $421F). + InternalRegisters _internalRegisters{}; + //! @brief Is the CPU running in emulation mode (in 8bits) bool _isEmulationMode = true; //! @brief If the processor is stopped (using an STP instruction), the clock is stopped and no instruction will be run until a manual reset. bool _isStopped = false; - //! @brief Internal registers of the CPU (accessible from the bus via addr $4200 to $421F). - InternalRegisters _internalRegisters{}; + //! @brief Is the processor waiting for an interrupt (if true, instructions are not run until an interrupt is requested). + bool _isWaitingForInterrupt = false; + //! @brief The memory bus to use for read/write. std::shared_ptr _bus; //! @brief The cartridge header (stored for interrupt vectors.. @@ -258,6 +262,11 @@ namespace ComSquare::CPU //! @brief Return the data at the program bank concatenated with the program counter. It also increment the program counter (the program bank is not incremented on overflows). uint8_t readPC(); + //! @brief Check if an interrupt is requested and handle it. + void _checkInterrupts(); + //! @brief Run an interrupt (save state of the processor and jump to the interrupt handler) + void _runInterrupt(uint24_t nativeHandler, uint24_t emulationHandler); + //! @brief Execute a single instruction. //! @return The number of CPU cycles that the instruction took. virtual unsigned _executeInstruction(uint8_t opcode); @@ -443,6 +452,8 @@ namespace ComSquare::CPU int PEA(uint24_t, AddressingMode); //! @brief Stop the processor int STP(uint24_t, AddressingMode); + //! @brief Wait for Interrupt + int WAI(uint24_t, AddressingMode); //! @brief WDM Reserved for Future Expansion (used as a code breakpoint) int WDM(uint24_t, AddressingMode); //! @brief Block Move Next. This instruction is special: it takes parameter in the registers @@ -662,7 +673,7 @@ namespace ComSquare::CPU {&CPU::INY, 2, "iny", AddressingMode::Implied, 1}, // C8 {&CPU::CMP, 2, "cmp", AddressingMode::ImmediateForA, 2}, // C9 {&CPU::DEX, 2, "dex", AddressingMode::Implied, 1}, // CA - {&CPU::BRK, 7, "wai #-#", AddressingMode::Implied, 2}, // CB + {&CPU::WAI, 3, "wai", AddressingMode::Implied, 1}, // CB {&CPU::CPY, 4, "cpy", AddressingMode::Absolute, 3}, // CC {&CPU::CMP, 4, "cmp", AddressingMode::Absolute, 3}, // CD {&CPU::DEC, 6, "dec", AddressingMode::Absolute, 3}, // CE @@ -744,6 +755,13 @@ namespace ComSquare::CPU //! @brief Reset interrupt - Called on boot and when the reset button is pressed. virtual int RESB(); + //! @brief Is an NMI (non-maskable interrupt) requested. + bool IsNMIRequested = false; + //! @brief Is an interrupt (maskable) requested. + bool IsIRQRequested = false; + //! @brief Is an abort requested + bool IsAbortRequested = false; + //! @brief Return true if the CPU is overloaded with debugging features. virtual bool isDebugger(); diff --git a/sources/CPU/Instructions/Interrupts.cpp b/sources/CPU/Instructions/Interrupts.cpp index 8f8d515..f084ce0 100644 --- a/sources/CPU/Instructions/Interrupts.cpp +++ b/sources/CPU/Instructions/Interrupts.cpp @@ -22,7 +22,7 @@ namespace ComSquare::CPU return 0; } - int CPU::BRK(uint24_t, AddressingMode) + void CPU::_runInterrupt(uint24_t nativeHandler, uint24_t emulationHandler) { if (this->_isEmulationMode) { this->_push(this->_registers.pc); @@ -30,7 +30,7 @@ namespace ComSquare::CPU this->_registers.p.i = true; this->_registers.p.d = false; this->_registers.pbr = 0x0; - this->_registers.pc = this->_cartridgeHeader.emulationInterrupts.brk; + this->_registers.pc = emulationHandler; } else { this->_push(this->_registers.pbr); this->_push(this->_registers.pc); @@ -38,29 +38,23 @@ namespace ComSquare::CPU this->_registers.p.i = true; this->_registers.p.d = false; this->_registers.pbr = 0x0; - this->_registers.pc = this->_cartridgeHeader.nativeInterrupts.brk; + this->_registers.pc = nativeHandler; } + } + + int CPU::BRK(uint24_t, AddressingMode) + { + this->_runInterrupt( + this->_cartridgeHeader.nativeInterrupts.brk, + this->_cartridgeHeader.emulationInterrupts.brk); return !this->_isEmulationMode; } int CPU::COP(uint24_t, AddressingMode) { - if (this->_isEmulationMode) { - this->_push(this->_registers.pc); - this->_push(this->_registers.p.flags); - this->_registers.p.i = true; - this->_registers.p.d = false; - this->_registers.pbr = 0x0; - this->_registers.pc = this->_cartridgeHeader.emulationInterrupts.cop; - } else { - this->_push(this->_registers.pbr); - this->_push(this->_registers.pc); - this->_push(this->_registers.p.flags); - this->_registers.p.i = true; - this->_registers.p.d = false; - this->_registers.pbr = 0x0; - this->_registers.pc = this->_cartridgeHeader.nativeInterrupts.cop; - } + this->_runInterrupt( + this->_cartridgeHeader.nativeInterrupts.cop, + this->_cartridgeHeader.emulationInterrupts.cop); return !this->_isEmulationMode; } @@ -73,4 +67,10 @@ namespace ComSquare::CPU this->_registers.pbr = this->_pop16(); return !this->_isEmulationMode; } + + int CPU::WAI(uint24_t, AddressingMode) + { + this->_isWaitingForInterrupt = true; + return 0; + } } \ No newline at end of file From efbf009f218b1366d29733d35b00fbca3fc177dd Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 14 May 2020 17:58:47 +0200 Subject: [PATCH 55/59] Oups --- sources/CPU/CPU.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp index 3c4c248..88ce592 100644 --- a/sources/CPU/CPU.cpp +++ b/sources/CPU/CPU.cpp @@ -7,6 +7,7 @@ #include #include #include "../Exceptions/InvalidAddress.hpp" +#include "../Exceptions/InvalidOpcode.hpp" namespace ComSquare::CPU { From 24bcafeea3896022704904815d263f69f22e5096 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 14 May 2020 18:12:29 +0200 Subject: [PATCH 56/59] Removing unintended logs to the bus's debugger --- sources/Debugger/CPU/CPUDebug.cpp | 2 +- sources/Debugger/CPU/Disassembly.cpp | 10 +++++----- sources/Debugger/MemoryBusDebug.cpp | 2 +- sources/SNES.cpp | 1 - 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/sources/Debugger/CPU/CPUDebug.cpp b/sources/Debugger/CPU/CPUDebug.cpp index 6bcb800..d677158 100644 --- a/sources/Debugger/CPU/CPUDebug.cpp +++ b/sources/Debugger/CPU/CPUDebug.cpp @@ -414,7 +414,7 @@ QVariant StackModel::data(const QModelIndex &index, int role) const return QVariant(); uint16_t addr = index.row() * 2 + index.column(); try { - uint8_t value = this->_bus->read(addr); + uint8_t value = this->_bus->read(addr, true); return (ComSquare::Utility::to_hex(value, ComSquare::Utility::NoPrefix).c_str()); } catch (std::exception &) { return "??"; diff --git a/sources/Debugger/CPU/Disassembly.cpp b/sources/Debugger/CPU/Disassembly.cpp index 7541dd7..75aefd2 100644 --- a/sources/Debugger/CPU/Disassembly.cpp +++ b/sources/Debugger/CPU/Disassembly.cpp @@ -42,13 +42,13 @@ namespace ComSquare::Debugger ctx.mFlag = true; ctx.xFlag = true; } else { - uint8_t m = this->_bus->read(pc - 1); + uint8_t m = this->_bus->read(pc - 1, true); ctx.mFlag &= ~m & 0b00100000u; ctx.xFlag &= ~m & 0b00010000u; } } if (instruction.opcode == 0xE2) { // SEP - uint8_t m = this->_bus->read(pc - 1); + uint8_t m = this->_bus->read(pc - 1, true); ctx.mFlag |= m & 0b00100000u; ctx.xFlag |= m & 0b00010000u; } @@ -150,7 +150,7 @@ namespace ComSquare::Debugger std::string CPUDebug::_getAbsoluteValue(uint24_t pc) { - uint24_t value = this->_bus->read(pc) + (this->_bus->read(pc + 1, true) << 8u); + uint24_t value = this->_bus->read(pc, true) + (this->_bus->read(pc + 1, true) << 8u); return Utility::to_hex(value, Utility::HexString::AsmPrefix); } @@ -193,13 +193,13 @@ namespace ComSquare::Debugger std::string CPUDebug::_getAbsoluteIndexByXValue(uint24_t pc) { - uint24_t value = this->_bus->read(pc) + (this->_bus->read(pc + 1, true) << 8u); + uint24_t value = this->_bus->read(pc, true) + (this->_bus->read(pc + 1, true) << 8u); return Utility::to_hex(value, Utility::HexString::AsmPrefix) + ", x"; } std::string CPUDebug::_getAbsoluteIndexByYValue(uint24_t pc) { - uint24_t value = this->_bus->read(pc) + (this->_bus->read(pc + 1, true) << 8u); + uint24_t value = this->_bus->read(pc, true) + (this->_bus->read(pc + 1, true) << 8u); return Utility::to_hex(value, Utility::HexString::AsmPrefix) + ", y"; } diff --git a/sources/Debugger/MemoryBusDebug.cpp b/sources/Debugger/MemoryBusDebug.cpp index 670f484..51bbc4c 100644 --- a/sources/Debugger/MemoryBusDebug.cpp +++ b/sources/Debugger/MemoryBusDebug.cpp @@ -150,7 +150,7 @@ namespace ComSquare::Debugger uint8_t MemoryBusDebug::read(uint24_t addr, bool silence) { - if (!silence && !forceSilence) { + if (!silence && !this->forceSilence) { auto accessor = this->getAccessor(addr); if (!accessor) { this->_model.log(BusLog(true, addr, accessor, this->_openBus, this->_openBus)); diff --git a/sources/SNES.cpp b/sources/SNES.cpp index a57cd5a..bb6d7aa 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -3,7 +3,6 @@ // #include -#include #include "SNES.hpp" #ifdef DEBUGGER_ENABLED #include "Debugger/CPU/CPUDebug.hpp" From c3a24f023848e6d688ce6d3c06f4a383f80f5934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Thu, 14 May 2020 18:21:21 +0200 Subject: [PATCH 57/59] fixing compilation --- CMakeLists.txt | 7 +++++-- sources/PPU/Background.cpp | 28 ++++++++++++++++++++++++++++ sources/PPU/Background.hpp | 22 ++++++++++++++++++++++ sources/PPU/Backgrounds.cpp | 1 + sources/PPU/PPU.cpp | 2 +- sources/PPU/PPU.hpp | 3 --- 6 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 sources/PPU/Background.cpp create mode 100644 sources/PPU/Background.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fbb74d9..0624057 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,8 @@ add_executable(unit_tests tests/CPU/Math/testOthersMath.cpp tests/testRectangleMemory.cpp tests/CPU/Math/testCMP.cpp -) + sources/PPU/Backgrounds.cpp + sources/PPU/Background.cpp sources/PPU/Background.hpp) # include criterion & coverage target_link_libraries(unit_tests criterion -lgcov) @@ -212,7 +213,9 @@ add_executable(ComSquare sources/Models/Components.hpp sources/Debugger/CGramDebug.cpp sources/Debugger/CGramDebug.hpp - sources/Models/Vector2.hpp sources/PPU/Backgrounds.cpp) + sources/Models/Vector2.hpp + sources/PPU/Backgrounds.cpp + sources/PPU/Background.cpp sources/PPU/Background.hpp) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) diff --git a/sources/PPU/Background.cpp b/sources/PPU/Background.cpp new file mode 100644 index 0000000..b4afa83 --- /dev/null +++ b/sources/PPU/Background.cpp @@ -0,0 +1,28 @@ +// +// Created by cbihan on 5/14/20. +// + +#include "Background.hpp" + +namespace PPU +{ + /*void PPU::renderBackground(int bgNumber, Vector2 characterSize, int bpp, bool priority) + { + int nbBgHeight = (this->_registers._bgsc[bgNumber - 1].tilemapVerticalMirroring) ? 2 : 1; + int nbBgWidth = (this->_registers._bgsc[bgNumber - 1].tilemapHorizontalMirroring) ? 2 : 1; + uint16_t vramAddress = this->_registers._bgsc[bgNumber - 1].tilemapAddress << 1U; + Vector2 offset(0, 0); + + for (int i = 0; i < 4; i++) { + if (!(i == 1 && nbBgWidth == 1) && !(i > 1 && nbBgHeight == 1)) { + drawBasicTileMap(vramAddress, bgNumber, bpp, characterSize, offset); + } + vramAddress+= 0x800; + offset.x += 32 * characterSize.x; + if (i == 2) { + offset.x = 0; + offset.y += 32 * characterSize.y; + } + } + }*/ +} \ No newline at end of file diff --git a/sources/PPU/Background.hpp b/sources/PPU/Background.hpp new file mode 100644 index 0000000..bee5559 --- /dev/null +++ b/sources/PPU/Background.hpp @@ -0,0 +1,22 @@ +// +// Created by cbihan on 5/14/20. +// + +#ifndef COMSQUARE_BACKGROUND_HPP +#define COMSQUARE_BACKGROUND_HPP + +#include +#include +#include "../Models/Vector2.hpp" + +class Background { + int width; + int height; + int bpp; + bool directColor; + bool highRes; + std::array, 1024> buffer; +}; + + +#endif //COMSQUARE_BACKGROUND_HPP diff --git a/sources/PPU/Backgrounds.cpp b/sources/PPU/Backgrounds.cpp index d498476..c7d01dc 100644 --- a/sources/PPU/Backgrounds.cpp +++ b/sources/PPU/Backgrounds.cpp @@ -15,6 +15,7 @@ namespace ComSquare::PPU { void PPU::renderBackground(int bgNumber, Vector2 characterSize, int bpp, bool priority) { + (void)priority; int nbBgHeight = (this->_registers._bgsc[bgNumber - 1].tilemapVerticalMirroring) ? 2 : 1; int nbBgWidth = (this->_registers._bgsc[bgNumber - 1].tilemapHorizontalMirroring) ? 2 : 1; uint16_t vramAddress = this->_registers._bgsc[bgNumber - 1].tilemapAddress << 1U; diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 15263c4..c0a5661 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -260,7 +260,7 @@ namespace ComSquare::PPU this->_renderer.putPixel(x, y, pixelTmp); } } - renderBackground(1, {8, 8}, 4, false); + this->renderBackground(1, {8, 8}, 4, false); this->_renderer.drawScreen(); } diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index 13dee70..38aceaf 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -17,11 +17,8 @@ //#define max4BitTiles 2048 //#define max8BitTiles 1024 - - namespace ComSquare::PPU { - enum ppuRegisters { //! @brief INIDISP Register (F-blank and Brightness) inidisp = 0x00, From 703afbf77fc90e18174a7cd9bc76bb4acdd2b2ec Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 14 May 2020 18:25:17 +0200 Subject: [PATCH 58/59] Oups --- sources/SNES.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/sources/SNES.cpp b/sources/SNES.cpp index bb6d7aa..a57cd5a 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -3,6 +3,7 @@ // #include +#include #include "SNES.hpp" #ifdef DEBUGGER_ENABLED #include "Debugger/CPU/CPUDebug.hpp" From 996758c41f11c5608cc264884a2b09e551fa5934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Thu, 14 May 2020 18:28:51 +0200 Subject: [PATCH 59/59] refixing compilation --- sources/SNES.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sources/SNES.cpp b/sources/SNES.cpp index 5487ef3..1ae1b61 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -3,6 +3,7 @@ // #include +#include #include "SNES.hpp" #ifdef DEBUGGER_ENABLED #include "Debugger/CPU/CPUDebug.hpp" @@ -10,6 +11,7 @@ #include "Debugger/MemoryBusDebug.hpp" #include "Debugger/CGramDebug.hpp" + #endif namespace ComSquare