GameBoy Emulator 1
Game Boy emulator core and tooling
Loading...
Searching...
No Matches
ppu.hpp
1#pragma once
2
3#include "ProcessingUnit.hpp"
4#include "mmu.hpp"
5#include "common.hpp"
6#include "interrupt_controller.hpp"
7#include <SFML/Graphics.hpp>
8#include <array>
9#include <deque>
10#include <string>
11#include <vector>
12#include <memory>
13
14class MMU;
15
16class PPU {
17public:
18 struct RomInfo {
19 std::string title;
20 u8 type{};
21 u8 rom_size{};
22 u8 ram_size{};
23 std::string mbc_name;
24 std::vector<u8> rom_bytes;
25 };
26
27 struct OpcodeTrace {
28 u16 pc{};
29 u8 opcode{};
30 };
31
32 PPU();
33 explicit PPU(InterruptController& ic);
34
35 void set_mmu(MMU* m) { mmu = m; }
36 void set_cpu(ProcessingUnit* c) { cpu = c; }
37 void set_rom_info(const RomInfo& info) { romInfo = info; }
38 void step(int cycles);
39 u8 read(u16 address) const;
40 void write(u16 address, u8 value);
41
42 const u32* get_framebuffer() const { return framebuffer.data(); }
43 bool is_frame_ready() const { return frame_ready; }
44 void clear_frame_ready() { frame_ready = false; }
45
46 // Debug / Feature functions
47 void init_window(bool debug, const std::string& rom_title, bool fullscreen = false);
48 bool isOpen() const;
49 bool isPaused() const { return paused; }
50 void handleEvents(JoypadState& joypad);
51 void update(float dtSeconds, u64 cyclesExecuted);
52 void render();
53
54 void recordOpcode(u16 pc, u8 opcode);
55 void checkBreakpoint(u16 pc);
56
57 bool isStepRequested() const { return stepRequested; }
58 void clearStepRequest() { stepRequested = false; }
59
60 bool isTurbo() const { return turbo; }
61 void setTurbo(bool val) { turbo = val; }
62 int getActiveSlot() const { return activeSlot; }
63 void setActiveSlot(int slot) { activeSlot = slot; }
64 void reset();
65 bool isResetRequested() const { return resetRequested; }
66 void clearResetRequest() { resetRequested = false; }
67
68private:
69 bool saveStateSlot(int slot);
70 bool loadStateSlot(int slot);
71 bool saveStatePath(const std::string& filepath);
72 bool loadStatePath(const std::string& filepath);
73
74 void drawPanels();
75 void drawText(const sf::Vector2f& pos, const std::string& text, unsigned size, const sf::Color& color);
76 std::string toHex(u32 value, int width) const;
77
78 // Emulation components
79 std::unique_ptr<InterruptController> dummy_ic;
80 InterruptController& ic;
81 ProcessingUnit* cpu = nullptr;
82 MMU* mmu = nullptr;
83 RomInfo romInfo;
84
85 // Rendering / SFML Window components
86 sf::RenderWindow window;
87 sf::Font font;
88 bool fontLoaded{false};
89 bool debugMode{false};
90
91 sf::Texture screenTexture;
92 sf::Sprite screenSprite;
93
94 // Emulation state
95 std::array<u8, 0x2000> vram{};
96 std::array<u8, 160> oam{};
97
98 u8 lcdc = 0x00;
99 u8 stat = 0x00;
100 u8 scy = 0x00;
101 u8 scx = 0x00;
102 u8 ly = 0x00;
103 u8 lyc = 0x00;
104 u8 dma = 0x00;
105 u8 bgp = 0x00;
106 u8 obp0 = 0x00;
107 u8 obp1 = 0x00;
108 u8 wy = 0x00;
109 u8 wx = 0x00;
110
111 int mode_clock = 0;
112 u8 window_line_counter = 0;
113 bool frame_ready = false;
114 std::array<u32, 160 * 144> framebuffer{};
115
116 enum class Mode {
117 HBlank = 0,
118 VBlank = 1,
119 OAMSearch = 2,
120 PixelTransfer = 3
121 };
122
123 Mode get_mode() const { return static_cast<Mode>(stat & 0x03); }
124 void set_mode(Mode mode);
125 void update_stat();
126
127 void render_scanline();
128 void render_sprites();
129 u32 get_color(u8 color_id, u16 palette_address) const;
130
131 // Debugging state
132 std::deque<OpcodeTrace> opcodeLog;
133 std::vector<u16> breakpoints;
134 bool paused{false};
135 bool stepRequested{false};
136 bool turbo{false};
137 int activeSlot{0};
138 bool resetRequested{false};
139 std::string externalStatePath;
140 JoypadState clickableJoypad{};
141 JoypadState physicalJoypad{};
142 JoypadState currentJoypadState{};
143
144 float timeAccumulator{0.0f};
145 u64 lastCycles{0};
146 u64 lastReads{0};
147 u64 lastWrites{0};
148
149 std::string statusMessage;
150 float statusTimer{0.0f};
151 u32 frameCounter{0};
152};
Definition mmu.hpp:12