From ea3f15498995dc6481a2d5f03b8a4a5e1e90dec4 Mon Sep 17 00:00:00 2001 From: "Adrian.Conlon" Date: Sun, 17 Sep 2017 09:46:28 +0100 Subject: [PATCH] Preliminary support for 16 row high sprites. Don't think it's working! Signed-off-by: Adrian.Conlon --- LR35902/inc/CharacterDefinition.h | 18 +++++++++++------- LR35902/inc/Display.h | 1 + LR35902/src/Display.cpp | 28 +++++++++++++++------------- LR35902/src/LR35902.cpp | 16 ++++++++++------ 4 files changed, 37 insertions(+), 26 deletions(-) diff --git a/LR35902/inc/CharacterDefinition.h b/LR35902/inc/CharacterDefinition.h index da227a7..ed558a2 100644 --- a/LR35902/inc/CharacterDefinition.h +++ b/LR35902/inc/CharacterDefinition.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include @@ -11,16 +11,20 @@ namespace EightBit { public: CharacterDefinition() {} - CharacterDefinition(Bus& bus, uint16_t address) { + CharacterDefinition(Bus& bus, uint16_t address, int height) { - for (auto row = 0; row < 8; ++row) { + const int width = 8; + + m_definition.resize(width * height); + + for (auto row = 0; row < height; ++row) { auto planeAddress = address + row * 2; auto planeLow = bus.peek(planeAddress); auto planeHigh = bus.peek(planeAddress + 1); - for (int bit = 0; bit < 8; ++bit) { + for (int bit = 0; bit < width; ++bit) { auto mask = 1 << bit; @@ -29,15 +33,15 @@ namespace EightBit { auto colour = bitHigh | bitLow; - m_definition[row * 8 + (7 - bit)] = colour; + m_definition[row * width + ((width - 1) - bit)] = colour; } } } - const std::array& get() const { return m_definition; } + const std::vector& get() const { return m_definition; } private: - std::array m_definition; + std::vector m_definition; }; } } \ No newline at end of file diff --git a/LR35902/inc/Display.h b/LR35902/inc/Display.h index b9467d4..49335b5 100644 --- a/LR35902/inc/Display.h +++ b/LR35902/inc/Display.h @@ -48,6 +48,7 @@ namespace EightBit { void renderObjects(int objBlockHeight); void renderTile( + int height, int drawX, int drawY, int offsetX, int offsetY, bool flipX, bool flipY, bool allowTransparencies, const std::array& palette, diff --git a/LR35902/src/Display.cpp b/LR35902/src/Display.cpp index 3862530..43066a3 100644 --- a/LR35902/src/Display.cpp +++ b/LR35902/src/Display.cpp @@ -22,15 +22,12 @@ void EightBit::GameBoy::Display::initialise() { void EightBit::GameBoy::Display::render() { auto control = m_bus.peekRegister(Bus::LCDC); - auto on = control & Bus::LcdEnable; - if (on) { + if (control & Bus::LcdEnable) { - const auto bgDisplay = (control & Bus::DisplayBackground) != 0; - if (bgDisplay) + if (control & Bus::DisplayBackground) renderBackground(); - const auto objEnable = (control & Bus::ObjectEnable) != 0; - if (objEnable) + if (control & Bus::ObjectEnable) renderObjects(); } } @@ -64,7 +61,7 @@ void EightBit::GameBoy::Display::renderObjects(int objBlockHeight) { const auto current = ObjectAttribute(m_bus, oamAddress + 4 * i, objBlockHeight); const auto sprite = current.pattern(); - const auto definition = CharacterDefinition(m_bus, objDefinitionAddress + 16 * sprite); + const auto definition = CharacterDefinition(m_bus, objDefinitionAddress + 16 * sprite, objBlockHeight); const auto spriteX = current.positionX(); const auto spriteY = current.positionY(); const auto& palette = palettes[current.palette()]; @@ -72,6 +69,7 @@ void EightBit::GameBoy::Display::renderObjects(int objBlockHeight) { const auto flipY = current.flipY(); renderTile( + objBlockHeight, spriteX, spriteY, -8, -16, flipX, flipY, true, palette, @@ -118,13 +116,14 @@ void EightBit::GameBoy::Display::renderBackground( auto definitionPair = definitions.find(character); if (definitionPair == definitions.end()) { - definitions[character] = CharacterDefinition(m_bus, bgCharacters + 16 * character); + definitions[character] = CharacterDefinition(m_bus, bgCharacters + 16 * character, 8); definitionPair = definitions.find(character); } auto definition = definitionPair->second; renderTile( + 8, column * 8, row * 8, offsetX - scrollX, offsetY - scrollY, false, false, false, palette, @@ -134,26 +133,29 @@ void EightBit::GameBoy::Display::renderBackground( } void EightBit::GameBoy::Display::renderTile( + int height, int drawX, int drawY, int offsetX, int offsetY, bool flipX, bool flipY, bool allowTransparencies, const std::array& palette, const CharacterDefinition& definition) { - for (int cy = 0; cy < 8; ++cy) { + const auto width = 8; - for (int cx = 0; cx < 8; ++cx) { + for (int cy = 0; cy < height; ++cy) { - uint8_t y = drawY + (flipY ? 7 - cy : cy) + offsetY; + for (int cx = 0; cx < width; ++cx) { + + uint8_t y = drawY + (flipY ? (height - 1) - cy : cy) + offsetY; if (y >= RasterHeight) break; - uint8_t x = drawX + (flipX ? 7 - cx : cx) + offsetX; + uint8_t x = drawX + (flipX ? (width - 1) - cx : cx) + offsetX; if (x >= RasterWidth) break; auto outputPixel = y * RasterWidth + x; - auto colour = definition.get()[cy * 8 + cx]; + auto colour = definition.get()[cy * width + cx]; if (!allowTransparencies || (allowTransparencies && (colour > 0))) m_pixels[outputPixel] = m_colours->getColour(palette[colour]); } diff --git a/LR35902/src/LR35902.cpp b/LR35902/src/LR35902.cpp index 7628443..8103606 100644 --- a/LR35902/src/LR35902.cpp +++ b/LR35902/src/LR35902.cpp @@ -337,16 +337,20 @@ int EightBit::GameBoy::LR35902::runRasterLines(int limit) { int EightBit::GameBoy::LR35902::runRasterLine() { const auto count = run(cyclesPerLine()); - m_bus.updateLcdStatusMode(Bus::LcdStatusMode::HBlank); - m_bus.incrementLY(); - if ((m_bus.peekRegister(Bus::STAT) & Bit6) && (m_bus.peekRegister(Bus::LYC) == m_bus.peekRegister(Bus::LY))) - m_bus.triggerInterrupt(Bus::Interrupts::DisplayControlStatus); + if (m_bus.peekRegister(Bus::LCDC) & Bus::LcdEnable) { + m_bus.updateLcdStatusMode(Bus::LcdStatusMode::HBlank); + m_bus.incrementLY(); + if ((m_bus.peekRegister(Bus::STAT) & Bit6) && (m_bus.peekRegister(Bus::LYC) == m_bus.peekRegister(Bus::LY))) + m_bus.triggerInterrupt(Bus::Interrupts::DisplayControlStatus); + } return count; } int EightBit::GameBoy::LR35902::runVerticalBlankLines() { - m_bus.updateLcdStatusMode(Bus::LcdStatusMode::VBlank); - m_bus.triggerInterrupt(Bus::Interrupts::VerticalBlank); + if (m_bus.peekRegister(Bus::LCDC) & Bus::LcdEnable) { + m_bus.updateLcdStatusMode(Bus::LcdStatusMode::VBlank); + m_bus.triggerInterrupt(Bus::Interrupts::VerticalBlank); + } return runRasterLines(Bus::TotalLineCount - Display::RasterHeight); }