From de0c145dd04c18d54ccfa0f1d6690ad5fb259a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Bihan?= Date: Wed, 12 Feb 2020 17:38:23 +0100 Subject: [PATCH] added registers (BGXXOFS) --- sources/PPU/PPU.cpp | 75 ++++++++++++++++++++++++++++++++++++++++----- sources/PPU/PPU.hpp | 59 ++++++++++++----------------------- sources/SNES.cpp | 2 +- 3 files changed, 87 insertions(+), 49 deletions(-) diff --git a/sources/PPU/PPU.cpp b/sources/PPU/PPU.cpp index 37f2ce8..c3b0fa3 100644 --- a/sources/PPU/PPU.cpp +++ b/sources/PPU/PPU.cpp @@ -2,6 +2,7 @@ // Created by cbihan on 1/27/20. // +#include #include "PPU.hpp" #include "../Exceptions/NotImplementedException.hpp" #include "../Exceptions/InvalidAddress.hpp" @@ -58,8 +59,17 @@ namespace ComSquare::PPU this->_bgnba[addr - 0x0B].raw = data; break; case ppuRegisters::bg1hofs: - // Work in progress ! Non functional ! - this->_bgofs[0].raw = data; + case ppuRegisters::bg1vofs: + case ppuRegisters::bg2hofs: + case ppuRegisters::bg2vofs: + case ppuRegisters::bg3hofs: + case ppuRegisters::bg3vofs: + case ppuRegisters::bg4hofs: + 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; break; case ppuRegisters::vmain: this->_vmain.raw = data; @@ -72,10 +82,36 @@ namespace ComSquare::PPU break; //! @info should must be in vblank for the write (and write it to the screen )? and increment vram address after; case ppuRegisters::vmdatal: - this->_vmdata.vmdatal = data; + if (!this->_inidisp.fblank) { + this->_vmdata.vmdatal = data; + this->_vram[getVramAddress()] = this->_vmdata.vmdata; + } + if (!this->_vmain.incrementMode) + this->_vmadd.vmadd += this->_vmain.incrementAmount; break; case ppuRegisters::vmdatah: - this->_vmdata.vmdatah = data; + if (!this->_inidisp.fblank) { + this->_vmdata.vmdatah = data; + this->_vram[getVramAddress()] = this->_vmdata.vmdata; + } + if (this->_vmain.incrementMode) + this->_vmadd.vmadd += this->_vmain.incrementAmount; + break; + case ppuRegisters::cgadd: + this->_cgadd = data; + this->_isLowByte = true; + break; + case ppuRegisters::cgdata: + if (this->_isLowByte) { + this->_cgdata.cgdatal = data; + this->_bus->write(this->_cgadd, this->_cgdata.cgdatal); + } + else { + this->_cgdata.cgdatah = data; + this->_bus->write(this->_cgadd, this->_cgdata.cgdatah); + } + this->_isLowByte = !this->_isLowByte; + this->_cgadd++; break; //TODO adding the rest of the registers. oaf ! default: @@ -83,13 +119,35 @@ namespace ComSquare::PPU } } + uint8_t PPU::getVramAddress() + { + uint16_t vanillaAddress = this->_vmadd.vmadd; + + switch (this->_vmain.addressRemapping) { + case 0b00: + return vanillaAddress; + case 0b01: + return (vanillaAddress & 0xFF00U) | (vanillaAddress & 0x00E0U) >> 5U | (vanillaAddress & 0x001FU) << 3U; + case 0b10: + return (vanillaAddress & 0xFE00U) | (vanillaAddress & 0x01C0U) >> 6U | (vanillaAddress & 0x3FU) << 3U; + case 0b11: + return (vanillaAddress & 0xFC00U) | (vanillaAddress & 0x0380U) >> 7U | (vanillaAddress & 0x7FU) << 3U; + } + } + void PPU::update(unsigned cycles) { (void)cycles; - uint32_t pixelTmp = 0xFFFFFF00; - pixelTmp |= this->_inidisp.brightness; - if (!this->_inidisp.fblank) - this->_renderer.putPixel(0, 0,pixelTmp); + int inc = 0; + uint32_t pixelTmp = 0xFFFFFFFF; + //pixelTmp |= this->_inidisp.brightness; + if (!this->_inidisp.fblank) { + for (int x = 0; x < 448; x++) { + for (int y = 0; y < 512; y++) { + this->_renderer.putPixel(x, y, (uint32_t)_vram[inc++] << 8U + 0xFFU); + } + } + } this->_renderer.drawScreen(); } @@ -97,5 +155,6 @@ namespace ComSquare::PPU _bus(std::move(bus)), _renderer(renderer) { + //_vram = new uint16_t[32000]; } } \ No newline at end of file diff --git a/sources/PPU/PPU.hpp b/sources/PPU/PPU.hpp index e5b6cde..836d017 100644 --- a/sources/PPU/PPU.hpp +++ b/sources/PPU/PPU.hpp @@ -286,54 +286,23 @@ namespace ComSquare::PPU }; uint8_t raw; } _bgnba[2]; - //! @brief BG1HOFS Register (BG1 Horizontal Scroll) - //! @brief BG1VOFS Register (BG1 Vertical Scroll) + //! @brief BGXXOFS Register (BG1/2/3/4 Horizontal and Vertical Scroll) union { struct { uint16_t offsetBg: 10; uint8_t _ : 6; }; uint16_t raw; - } _bgofs[4]; - //! @brief M7HOFS Register (Mode 7 _BG Horizontal Scroll) - //! @brief M7VOFS Register (Mode 7 _BG Vertical Scroll) + } _bgofs[8]; + //! @brief M7HOFS Register (Mode 7 BG Horizontal Scroll) + //! @brief M7VOFS Register (Mode 7 BG Vertical Scroll) union { struct { uint16_t offsetBg : 13; uint8_t _ : 3; }; uint8_t raw; - } _m7ofs; - /* //! @brief BG2HOFS Register (BG2 Horizontal Scroll) - //! @brief BG2VOFS Register (BG2 Vertical Scroll) - union { - struct { - uint8_t _ : 6; - uint32_t offsetBg: 10; - }; - uint8_t raw; - } _bg2ofs; - //! @brief BG3HOFS Register (BG3 Horizontal Scroll) - //! @brief BG3VOFS Register (BG3 Vertical Scroll) - union { - struct { - uint8_t _ : 6; - uint32_t offsetBg: 10; - }; - uint8_t raw; - } _bg3ofs; - //! @brief BG4HOFS Register (BG4 Horizontal Scroll) - //! @brief BG4VOFS Register (BG4 Vertical Scroll) - union { - struct { - uint8_t _ : 3; - uint32_t offsetBg: 10; - }; - uint8_t raw; - } _bg4ofs;*/ - - // - + } _m7ofs[2]; //! @brief VMAIN Register (Video Port Control) union { struct { @@ -360,7 +329,7 @@ namespace ComSquare::PPU }; uint16_t vmdata; } _vmdata; - //! @brief M7SEL Register (Mode 7 Settings) + //! @brief TODO M7SEL Register (Mode 7 Settings) union { struct { bool playingFieldSize: 1; @@ -393,13 +362,20 @@ namespace ComSquare::PPU //! @brief CGDATA Register (CGRAM Data write) union { struct { - bool _: 1; - uint8_t blue: 5; - uint8_t green: 5; uint8_t red: 5; + uint8_t green: 5; + uint8_t blue: 5; + bool _: 1; + }; + struct { + uint8_t cgdatal; + uint8_t cgdatah; }; uint16_t raw; } _cgdata; + //! @brief This bool is used for writing either the low byte of the data (first call) or the high byte of the data (second call) + //! @info This bool is set to True when writing to $2121 (CGADD) + bool _isLowByte; //! @brief W12SEL - W34SEL Registers (Window Mask Settings for BGs) and WOBJSEL Register (Window Mask Settings for OBJ and Color Window) union { struct { @@ -548,6 +524,7 @@ namespace ComSquare::PPU } mpy; Renderer::IRenderer &_renderer; std::shared_ptr _bus; + uint16_t *_vram; public: PPU(const std::shared_ptr &bus, Renderer::IRenderer &renderer); //! @brief Read data from the component. @@ -563,6 +540,8 @@ namespace ComSquare::PPU //! @brief Update the PPU of n cycles. //! @param The number of cycles to update. void update(unsigned cycles); + //! @brief Give the Vram Address with the right Address remapping + uint8_t getVramAddress(); }; } #endif //COMSQUARE_PPU_HPP diff --git a/sources/SNES.cpp b/sources/SNES.cpp index e1a793c..20646a2 100644 --- a/sources/SNES.cpp +++ b/sources/SNES.cpp @@ -11,7 +11,7 @@ namespace ComSquare SNES::SNES(const std::shared_ptr &bus, const std::string &romPath, Renderer::IRenderer &renderer) : cartridge(new Cartridge::Cartridge(romPath)), cpu(new CPU::CPU(bus, cartridge->header)), - ppu(new PPU::PPU(renderer, bus)), + ppu(new PPU::PPU(bus, renderer)), apu(new APU::APU()), wram(new Ram::Ram(16384)), sram(new Ram::Ram(this->cartridge->header.sramSize))