diff --git a/CMakeLists.txt b/CMakeLists.txt index 74174d5..e4a6865 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,9 @@ add_executable(unit_tests sources/CPU/Instructions/Interrupts.cpp sources/CPU/Instructions/MathematicalOperations.cpp tests/CPU/testAddressingMode.cpp - tests/tests.cpp) + tests/tests.cpp + tests/PPU/testPpuWrite.cpp +) # include criterion & coverage target_link_libraries(unit_tests criterion -lgcov) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index ce5f625..a5db727 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -26,55 +26,47 @@ namespace ComSquare::PPU { switch (addr) { case 0x00: //! @brief $2100 INIDISP Register (F-blank and Brightness) - //! @brief Take the first bit to set the bool. - this->_fBlank = data >> 7U; - //! @brief Take the 4 last bits representing the brightness. - this->_brightness = data & 0xFU; + this->_inidisp.raw = data; break; case 0x01: //! @brief $2101 OBSEL Register (Object Size and Character Address) - //! @brief The first 3 bits. - this->_objectSize = (data & 0xE0U) >> 5U; - //! @brief The last 3 bits; - this->_baseSelect = data & 0x07U; - //! @brief th 2 center bits. - this->_nameSelect = (data & 0x18U) >> 3U; + this->_obsel.raw = data; break; case 0x02: //! @brief $2102 OAMADDL (OAM Address low byte). + this->_oamadd.oamaddl = data; //! @brief we recreate the oamAddress with the previous oamAddress because there is one bit missing (given by the register $2103) - this->_oamAddress = (this->_oamAddress & 0x100U) | data; break; case 0x03: //! @brief $2103 OAMADDH (OAM Address high bit and Obj Priority) + this->_oamadd.oamaddh = data; //! @brief Same as $2102 we recreate the oamAddress with the previous oamAddress because there are 8 bits missing (given by the register $2102) - this->_oamAddress = (this->_oamAddress & 0xFFU) | ((data & 0x01U) << 8U); - //! @brief The objPriority is given by the first bit of the data - this->_objPriority = (data & 0x80U) >> 7U; break; - case 0x04: - this->oamdata = data; + case 0x04: //! @brief $2104 OAMDATA (Data for OAM write). + //! @brief not implemented yet. + // throw InvalidAddress("PPU Internal Registers write", addr); + this->_oamdata = data; break; - case 0x05: - this->bgmode.raw = data; + case 0x05: //! @brief $2105 BGMODE (BG Mode and Character Size). + this->_bgmode.raw = data; break; case 0x06: - this->mosaic.raw = data; + this->_mosaic.raw = data; break; case 0x07: - this->bg1sc.raw = data; + this->_bg1sc.raw = data; break; case 0x08: - this->bg2sc.raw = data; + this->_bg2sc.raw = data; break; case 0x09: - this->bg3sc.raw = data; + this->_bg3sc.raw = data; break; case 0x0A: - this->bg4sc.raw = data; + this->_bg4sc.raw = data; break; case 0x0B: - this->bg12nba.raw = data; + this->_bg12nba.raw = data; break; case 0x0C: - this->bg34nba.raw = data; + this->_bg34nba.raw = data; break; //TODO adding the rest of the registers. oaf ! default: diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index a512dc7..375b5af 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -17,6 +17,10 @@ namespace ComSquare::PPU //! @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; @@ -28,6 +32,7 @@ namespace ComSquare::PPU unsigned char characterHeight; unsigned char characterWidth; } _BG[4]; + struct object { bool verticalMirroring; bool horizontalMirroring; @@ -36,25 +41,34 @@ namespace ComSquare::PPU }; //! @brief INIDISP variables (F-blank and Brightness) - bool _fBlank; - unsigned short _brightness; //! @brief F=max, 0="off". + struct { + bool _fBlank; + //! @brief F=max, 0="off". + unsigned short _brightness; + } _inidisp; //! @brief OBSEL variables (Object Size and Character Address) - unsigned char _objectSize; //! @brief "OamMode" this contains the size of the Objects (ex: 8x8 and 16x16) - unsigned char _baseSelect; //! @brief "OamBaseAddress" - unsigned char _nameSelect; //! @brief "OamAddressOffset" + 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) - uint16_t _oamAddress; - bool _objPriority; + struct { + uint16_t _oamAddress; + bool _objPriority; + } _oamadd; - - - - - - - /// OLD to stuff to refactor + //! @brief BGMODE (BG Mode and Character Size) + struct { + unsigned char _bgMode; + bool _mode1Bg3Priority; + _layerInfo layers[4]; + } _bgmode;*/ @@ -62,48 +76,48 @@ namespace ComSquare::PPU //! @brief INIDISP Register (F-blank and Brightness) union { struct { - bool fblank: 1; - bool _: 3; uint8_t brightness: 4; + bool _: 3; + bool fblank: 1; }; uint8_t raw; - } inidisp; + } _inidisp; //! @brief OBSEL Register (Object Size and Character Address) union { struct { - uint8_t objectSize: 3; - bool nameSelect: 2; uint8_t baseSelect: 3; + bool nameSelect: 2; + uint8_t objectSize: 3; }; uint8_t raw; - } obsel; + } _obsel; //! @brief OAMADD Register (OAM Address and Obj Priority) union { struct { - bool objPriorityActivationBit: 1; - uint8_t _: 6; uint32_t oamAddress: 9; + uint8_t _: 6; + bool objPriorityActivationBit: 1; }; struct { - uint8_t oamaddh; uint8_t oamaddl; + uint8_t oamaddh; }; uint32_t raw; - } oamadd; + } _oamadd; //! @brief OAMDATA Register (Data for OAM write) - uint8_t oamdata; + uint8_t _oamdata; //! @brief BGMODE Register (OAM Address and Obj Priority) union { struct { - bool characterSizeBg4: 1; - bool characterSizeBg3: 1; - bool characterSizeBg2: 1; - bool characterSizeBg1: 1; - bool mode1Bg3PriorityBit: 1; uint8_t bgMode: 3; + bool mode1Bg3PriorityBit: 1; + bool characterSizeBg1: 1; + bool characterSizeBg2: 1; + bool characterSizeBg3: 1; + bool characterSizeBg4: 1; }; uint8_t raw; - } bgmode; + } _bgmode; //! @brief MOSAIC Register (Screen Pixelation) union { struct { @@ -114,7 +128,7 @@ namespace ComSquare::PPU bool affectBg1: 1; }; uint8_t raw; - } mosaic; + } _mosaic; //! @brief BG1SC Register (BG1 Tilemap Address and Size) union { struct { @@ -123,7 +137,7 @@ namespace ComSquare::PPU bool tilemapVerticalMirroring: 1; }; uint8_t raw; - } bg1sc; + } _bg1sc; //! @brief BG2SC Register (BG2 Tilemap Address and Size) union { struct { @@ -132,7 +146,7 @@ namespace ComSquare::PPU bool tilemapVerticalMirroring: 1; }; uint8_t raw; - } bg2sc; + } _bg2sc; //! @brief BG3SC Register (BG3 Tilemap Address and Size) union { struct { @@ -141,7 +155,7 @@ namespace ComSquare::PPU bool tilemapVerticalMirroring: 1; }; uint8_t raw; - } bg3sc; + } _bg3sc; //! @brief BG4SC Register (BG4 Tilemap Address and Size) union { struct { @@ -150,7 +164,7 @@ namespace ComSquare::PPU bool tilemapVerticalMirroring: 1; }; uint8_t raw; - } bg4sc; + } _bg4sc; //! @brief BG12NBA Register (BG1 and 2 Chr Address) union { struct { @@ -158,7 +172,7 @@ namespace ComSquare::PPU uint8_t baseAddressBg1a3: 4; }; uint8_t raw; - } bg12nba; + } _bg12nba; //! @brief BG34NBA Register (BG3 and 4 Chr Address) union { struct { @@ -166,7 +180,7 @@ namespace ComSquare::PPU uint8_t baseAddressBg1a3: 4; }; uint8_t raw; - } bg34nba; + } _bg34nba; //! @brief BG1HOFS Register (BG1 Horizontal Scroll) //! @brief BG1VOFS Register (BG1 Vertical Scroll) union { @@ -175,7 +189,7 @@ namespace ComSquare::PPU uint32_t offsetBg: 10; }; uint16_t raw; - } bg1ofs; + } _bg1ofs; //! @brief M7HOFS Register (Mode 7 _BG Horizontal Scroll) //! @brief M7VOFS Register (Mode 7 _BG Vertical Scroll) union { @@ -184,7 +198,7 @@ namespace ComSquare::PPU uint32_t offsetBg : 13; }; uint8_t raw; - } m7ofs; + } _m7ofs; //! @brief BG2HOFS Register (BG2 Horizontal Scroll) //! @brief BG2VOFS Register (BG2 Vertical Scroll) union { @@ -193,7 +207,7 @@ namespace ComSquare::PPU uint32_t offsetBg: 10; }; uint8_t raw; - } bg2ofs; + } _bg2ofs; //! @brief BG3HOFS Register (BG3 Horizontal Scroll) //! @brief BG3VOFS Register (BG3 Vertical Scroll) union { @@ -202,7 +216,7 @@ namespace ComSquare::PPU uint32_t offsetBg: 10; }; uint8_t raw; - } bg3ofs; + } _bg3ofs; //! @brief BG4HOFS Register (BG4 Horizontal Scroll) //! @brief BG4VOFS Register (BG4 Vertical Scroll) union { @@ -211,7 +225,7 @@ namespace ComSquare::PPU uint32_t offsetBg: 10; }; uint8_t raw; - } bg4ofs; + } _bg4ofs; //! @brief VMAIN Register (Video Port Control) union { struct { @@ -221,7 +235,7 @@ namespace ComSquare::PPU uint8_t incrementCount: 2; }; uint8_t raw; - } vmain; + } _vmain; //! @brief VMADD Register (VRAM Address) union { struct { @@ -229,7 +243,7 @@ namespace ComSquare::PPU uint8_t vmaddl; }; uint32_t vmadd; - } vmadd; + } _vmadd; //! @brief VMDATA Register (VRAM Data Write) union { struct { @@ -237,7 +251,7 @@ namespace ComSquare::PPU uint8_t vmdatal; }; uint32_t vmdata; - } vmdata; + } _vmdata; //! @brief M7SEL Register (Mode 7 Settings) union { struct { @@ -248,7 +262,7 @@ namespace ComSquare::PPU bool verticalMirroring: 1; }; uint8_t raw; - } m7sel; + } _m7sel; //! M7A M7B M7C M7D i didn't understand how they works so they will be added later. //! @brief M7X Register (Mode 7 Center X) union { @@ -257,7 +271,7 @@ namespace ComSquare::PPU uint8_t value; }; uint32_t center; - } m7x; + } _m7x; //! @brief M7Y Register (Mode 7 Center Y) union { struct { @@ -265,9 +279,9 @@ namespace ComSquare::PPU uint8_t value; }; uint32_t center; - } m7y; + } _m7y; //! @brief CGADD Register (CGRAM Address) - uint8_t cgadd; + uint8_t _cgadd; //! @brief CGDATA Register (CGRAM Data write) union { struct { @@ -277,7 +291,7 @@ namespace ComSquare::PPU uint8_t red: 5; }; uint16_t raw; - } cgdata; + } _cgdata; //! @brief W12SEL - W34SEL Registers (Window Mask Settings for BGs) and WOBJSEL Register (Window Mask Settings for OBJ and Color Window) union { struct { @@ -291,7 +305,7 @@ namespace ComSquare::PPU bool window1InversionForBg1Bg2Obj: 1; }; uint8_t raw; - } wsel; + } _wsel; //! @brief WH0 Register (CWindow 1 Left Position) uint8_t wh0; //! @brief WH1 Register (CWindow 1 Right Position) diff --git a/tests/PPU/testPpuWrite.cpp b/tests/PPU/testPpuWrite.cpp new file mode 100644 index 0000000..bde5f52 --- /dev/null +++ b/tests/PPU/testPpuWrite.cpp @@ -0,0 +1,130 @@ +// +// Created by cbihan on 2/10/20. +// + +#include +#include +#include +#include "../tests.hpp" +#include "../../sources/SNES.hpp" +#include "../../sources/Memory/MemoryBus.hpp" +#include "../../sources/PPU/PPU.hpp" +using namespace ComSquare; + +Test(PPU_write, inidisp_data_full_ones) +{ + auto pair = Init(); + pair.first.write(0x2100, 0b11111111); + cr_assert_eq(pair.second.ppu->_inidisp.fblank, true); + cr_assert_eq(pair.second.ppu->_inidisp.brightness, 0xF); +} + +Test(PPU_write, inidisp_data_full_zeros) +{ + auto pair = Init(); + pair.first.write(0x2100, 0b00000000); + cr_assert_eq(pair.second.ppu->_inidisp.fblank, false); + cr_assert_eq(pair.second.ppu->_inidisp.brightness, 0x0); +} + +Test(PPU_write, inidisp_data_fBlank_on_brghtness_off) +{ + auto pair = Init(); + pair.first.write(0x2100, 0b10000000); + cr_assert_eq(pair.second.ppu->_inidisp.fblank, true); + cr_assert_eq(pair.second.ppu->_inidisp.brightness, 0x0); +} + +Test(PPU_write, inidisp_data_fBlank_off_brghtness_max) +{ + auto pair = Init(); + pair.first.write(0x2100, 0b00001111); + cr_assert_eq(pair.second.ppu->_inidisp.fblank, false); + cr_assert_eq(pair.second.ppu->_inidisp.brightness, 0xF); +} + +Test(PPU_write, inidisp_data_fBlank_off_brghtness_half) +{ + auto pair = Init(); + pair.first.write(0x2100, 0b00000101); + cr_assert_eq(pair.second.ppu->_inidisp.fblank, false); + cr_assert_eq(pair.second.ppu->_inidisp.brightness, 0x5); +} + +Test(PPU_write, obsel_111_object_size_and_all_null) +{ + auto pair = Init(); + pair.first.write(0x2101, 0b11100000); + cr_assert_eq(pair.second.ppu->_obsel.objectSize, 0b111); + cr_assert_eq(pair.second.ppu->_obsel.nameSelect, 0b00); + cr_assert_eq(pair.second.ppu->_obsel.baseSelect, 0b000); +} + +Test(PPU_write, obsel_data_full) +{ + auto pair = Init(); + pair.first.write(0x2101, 0b11111111); + cr_assert_eq(pair.second.ppu->_obsel.objectSize, 0b111); + cr_assert_eq(pair.second.ppu->_obsel.nameSelect, 0b11); + cr_assert_eq(pair.second.ppu->_obsel.baseSelect, 0b111); +} + +Test(PPU_write, obsel_data_full_nameselect) +{ + auto pair = Init(); + pair.first.write(0x2101, 0b00011000); + cr_assert_eq(pair.second.ppu->_obsel.objectSize, 0b000); + cr_assert_eq(pair.second.ppu->_obsel.nameSelect, 0b11); + cr_assert_eq(pair.second.ppu->_obsel.baseSelect, 0b000); +} + +Test(PPU_write, obsel_data_full_baseselect) +{ + auto pair = Init(); + pair.first.write(0x2101, 0b00000111); + cr_assert_eq(pair.second.ppu->_obsel.objectSize, 0b000); + cr_assert_eq(pair.second.ppu->_obsel.nameSelect, 0b00); + cr_assert_eq(pair.second.ppu->_obsel.baseSelect, 0b111); +} + +Test(PPU_write, oamaddl_data_full) +{ + auto pair = Init(); + pair.first.write(0x2102, 0b11111111); + cr_assert_eq(pair.second.ppu->_oamadd.oamAddress, 0b011111111); +} + +Test(PPU_write, oamaddh_data_full) +{ + auto pair = Init(); + pair.first.write(0x2103, 0b11111111); + cr_assert_eq(pair.second.ppu->_oamadd.objPriorityActivationBit, true); + cr_assert_eq(pair.second.ppu->_oamadd.oamAddress, 0b100000000); +} + +Test(PPU_write, oamaddlh_data_full) +{ + auto pair = Init(); + pair.first.write(0x2102, 0b11111111); + pair.first.write(0x2103, 0b11111111); + cr_assert_eq(pair.second.ppu->_oamadd.objPriorityActivationBit, true); + cr_assert_eq(pair.second.ppu->_oamadd.oamAddress, 0b111111111); +} + +Test(PPU_write, oamaddlh_data_full_priorityBit_off) +{ + auto pair = Init(); + pair.first.write(0x2102, 0b11111111); + pair.first.write(0x2103, 0b01111111); + cr_assert_eq(pair.second.ppu->_oamadd.objPriorityActivationBit, false); + cr_assert_eq(pair.second.ppu->_oamadd.oamAddress, 0b111111111); +} + +Test(PPU_write, oamaddlh_oamAdress_11_priorityBit_on) +{ + auto pair = Init(); + pair.first.write(0x2102, 0b00001011); + pair.first.write(0x2103, 0b10011100); + cr_assert_eq(pair.second.ppu->_oamadd.objPriorityActivationBit, true); + cr_assert_eq(pair.second.ppu->_oamadd.oamAddress, 11); +} \ No newline at end of file diff --git a/tests/testMemoryBus.cpp b/tests/testMemoryBus.cpp index 49805be..bbc0ebe 100644 --- a/tests/testMemoryBus.cpp +++ b/tests/testMemoryBus.cpp @@ -356,7 +356,7 @@ Test(BusWrite, WritePPU) auto pair = Init(); pair.first.write(0x002106, 123); - cr_assert_eq(pair.second.ppu->mosaic.raw, 123); + cr_assert_eq(pair.second.ppu->_mosaic.raw, 123); } Test(BusWrite, WriteCPU)