diff --git a/LR35902/inc/Display.h b/LR35902/inc/Display.h index 49335b5..4b9b296 100644 --- a/LR35902/inc/Display.h +++ b/LR35902/inc/Display.h @@ -6,6 +6,7 @@ #include "GameBoyBus.h" #include "AbstractColourPalette.h" +#include "ObjectAttribute.h" namespace EightBit { namespace GameBoy { @@ -29,11 +30,13 @@ namespace EightBit { void initialise(); void render(); + void loadObjectAttributes(); private: std::vector m_pixels; Bus& m_bus; const AbstractColourPalette* m_colours; + std::array m_objectAttributes; std::array createPalette(int address); diff --git a/LR35902/inc/GameBoyBus.h b/LR35902/inc/GameBoyBus.h index 109ac18..9e64d39 100644 --- a/LR35902/inc/GameBoyBus.h +++ b/LR35902/inc/GameBoyBus.h @@ -123,6 +123,7 @@ namespace EightBit { Bus(); Signal InterruptGenerated; + Signal DisplayStatusModeUpdated; void reset(); @@ -209,6 +210,7 @@ namespace EightBit { void updateLcdStatusMode(int mode) { const auto current = m_ioPorts.peek(STAT) & ~Processor::Mask2; m_ioPorts.poke(STAT, current | mode); + DisplayStatusModeUpdated.fire(mode); } void disableBootRom() { m_disableBootRom = true; } diff --git a/LR35902/src/Display.cpp b/LR35902/src/Display.cpp index 43066a3..5e6f190 100644 --- a/LR35902/src/Display.cpp +++ b/LR35902/src/Display.cpp @@ -48,6 +48,18 @@ void EightBit::GameBoy::Display::renderObjects() { renderObjects(objBlockHeight); } +void EightBit::GameBoy::Display::loadObjectAttributes() { + + auto oamAddress = 0xfe00; + + const auto control = m_bus.peekRegister(Bus::LCDC); + const auto objBlockHeight = (control & Bus::ObjectBlockCompositionSelection) ? 16 : 8; + + for (int i = 0; i < 40; ++i) { + m_objectAttributes[i] = ObjectAttribute(m_bus, oamAddress + 4 * i, objBlockHeight); + } +} + void EightBit::GameBoy::Display::renderObjects(int objBlockHeight) { std::vector> palettes(2); @@ -59,21 +71,28 @@ void EightBit::GameBoy::Display::renderObjects(int objBlockHeight) { for (int i = 0; i < 40; ++i) { - const auto current = ObjectAttribute(m_bus, oamAddress + 4 * i, objBlockHeight); + const auto& current = m_objectAttributes[i]; + const auto sprite = current.pattern(); - 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()]; - const auto flipX = current.flipX(); - const auto flipY = current.flipY(); - renderTile( - objBlockHeight, - spriteX, spriteY, -8, -16, - flipX, flipY, true, - palette, - definition); + const auto hidden = (spriteX == 0) && (spriteY == 0); + + if (!hidden) { + + const auto definition = CharacterDefinition(m_bus, objDefinitionAddress + 16 * sprite, objBlockHeight); + const auto& palette = palettes[current.palette()]; + const auto flipX = current.flipX(); + const auto flipY = current.flipY(); + + renderTile( + objBlockHeight, + spriteX, spriteY, -8, -16, + flipX, flipY, true, + palette, + definition); + } } } diff --git a/LR35902/src/LR35902.cpp b/LR35902/src/LR35902.cpp index 1857e44..b9b5a3d 100644 --- a/LR35902/src/LR35902.cpp +++ b/LR35902/src/LR35902.cpp @@ -373,14 +373,17 @@ int EightBit::GameBoy::LR35902::runRasterLine(int limit) { if ((m_bus.peekRegister(Bus::STAT) & Bit6) && (m_bus.peekRegister(Bus::LYC) == m_bus.peekRegister(Bus::LY))) m_bus.triggerInterrupt(Bus::Interrupts::DisplayControlStatus); + // Mode 2, OAM unavailable m_bus.updateLcdStatusMode(Bus::LcdStatusMode::SearchingOamRam); if (m_bus.peekRegister(Bus::STAT) & Bit5) m_bus.triggerInterrupt(Bus::Interrupts::DisplayControlStatus); count += run(80); // ~19us + // Mode 3, OAM/VRAM unavailable m_bus.updateLcdStatusMode(Bus::LcdStatusMode::TransferringDataToLcd); count += run(170); // ~41us + // Mode 0 m_bus.updateLcdStatusMode(Bus::LcdStatusMode::HBlank); if (m_bus.peekRegister(Bus::STAT) & Bit3) m_bus.triggerInterrupt(Bus::Interrupts::DisplayControlStatus); @@ -392,10 +395,6 @@ int EightBit::GameBoy::LR35902::runRasterLine(int limit) { count += run(Bus::CyclesPerLine); } - assert(count > 0); - assert(count >= Bus::CyclesPerLine); - assert((count - Bus::CyclesPerLine) - 16); - return count; }