// // Created by Selim Mustafaev on 24.09.2023. // #ifndef NES_OAM_H #define NES_OAM_H #include "Shifter.h" #include #include #include namespace nes { class Ppu; struct SpriteInfo { uint8_t y = 0xFF; uint8_t id = 0x00; uint8_t attr = 0x00; uint8_t x = 0xFF; }; struct SpritePixelInfo { uint8_t pattern = 0; uint8_t palette = 0; uint8_t priority = 0; }; class Oam { public: static constexpr size_t OAM_SIZE = 64; static constexpr size_t MAX_SPRITES_PER_SCANLINE = 8; static constexpr uint8_t SPRITE_PALETTE_OFFSET = 4; public: explicit Oam(Ppu* ppu); void setAddress(uint8_t address); [[nodiscard]] uint8_t read() const; void write(uint8_t value); void dmaTick(uint64_t cycles); void dmaStart(uint8_t page); bool dmaActive() const; uint8_t address() const; public: bool detectVisibleSprites(int16_t scanline, bool bigSprite); void loadShifters(int16_t scanline, bool bigSprite, bool patternSprite); void updateShifters(); [[nodiscard]] SpritePixelInfo getPixel(); [[nodiscard]] bool spriteZeroBeingRendered() const; private: [[nodiscard]] uint8_t flipByte(uint8_t byte) const; private: Ppu* _ppu; uint8_t _address = 0x00; SpriteInfo _data[OAM_SIZE]; SpriteInfo _visibleSprites[MAX_SPRITES_PER_SCANLINE]; Shifter _spriteShifters[MAX_SPRITES_PER_SCANLINE]; uint8_t _visibleSpriteCount = 0; bool _spriteZeroVisible = false; bool _firstVisibleSpriteBeingRendered = false; private: uint8_t _dmaPage = 0; uint8_t _dmaAddress = 0; uint8_t _dmaData = 0; bool _dmaActive = false; bool _dmaDummy = true; }; } #endif //NES_OAM_H