yaze 0.2.0
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
ppu.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EMU_PPU_H
2#define YAZE_APP_EMU_PPU_H
3
4#include <array>
5#include <cstdint>
6#include <vector>
7
8#include "app/emu/cpu/clock.h"
11#include "app/rom.h"
12
13namespace yaze {
14namespace app {
15namespace emu {
16namespace video {
17
18using namespace PpuRegisters;
19using namespace memory;
20
22 public:
23 virtual ~PpuInterface() = default;
24
25 // Memory Interactions
26 virtual void Write(uint16_t address, uint8_t data) = 0;
27 virtual uint8_t Read(uint16_t address) const = 0;
28};
29
30// Enum representing different background modes
31enum class BackgroundMode {
32 Mode0, // 4 layers, each 2bpp (4 colors)
33 Mode1, // 2 layers, 4bpp (16 colors), 1 layer, 2bpp (4 colors)
34 Mode2, // 2 layers, 4bpp (16 colors), 1 layer for offset-per-tile
35 Mode3, // 1 layer, 8bpp (256 colors), 1 layer, 4bpp (16 colors)
36 Mode4, // 1 layer, 8bpp (256 colors), 1 layer, 2bpp (4 colors)
37 // 1 layer for offset-per-tile
38 Mode5, // 1 layer, 4bpp (16 colors), 1 layer, 2bpp (4 colors) hi-res
39 Mode6, // 1 layer, 4bpp (16 colors), 1 layer for offset-per-tile, hi-res
40 Mode7, // 1 layer, 8bpp (256 colors), rotation/scaling
41};
42
43// Enum representing sprite sizes
45
46// Struct representing a sprite's attributes
48 uint8_t x; // X position of the sprite
49 uint8_t y; // Y position of the sprite
50 uint16_t tile; // Tile number for the sprite
51 uint8_t palette; // Palette number for the sprite
52 uint8_t priority; // Priority for the sprite
53 bool hFlip; // Horizontal flip flag
54 bool vFlip; // Vertical flip flag
55};
56
57// Struct representing a tilemap entry
59 uint16_t tileNumber; // Tile number for the tile
60 uint8_t palette; // Palette number for the tile
61 uint8_t priority; // Priority for the tile
62 bool hFlip; // Horizontal flip flag
63 bool vFlip; // Vertical flip flag
64};
65
66// Struct representing a tilemap
67struct Tilemap {
68 std::vector<TilemapEntry> entries; // Entries for the tilemap
69};
70
71// Struct representing a color
72struct Color {
73 uint8_t r; // Red component
74 uint8_t g; // Green component
75 uint8_t b; // Blue component
76};
77
78// Registers
79struct OAMSize {
80 uint8_t base_selection : 3;
81 uint8_t name_selection : 2;
82 uint8_t object_size : 3;
83};
84
85struct OAMAddress {
86 uint8_t oam_address_low : 8;
87 uint8_t oam_address_msb : 1;
89 uint8_t unused : 6;
90};
91
93 uint8_t SC_size : 2;
94 uint8_t tile_map_address : 5;
95 uint8_t unused : 1;
96};
97
99 uint8_t BG1_address : 4;
100 uint8_t BG2_address : 4;
101 uint8_t BG3_address : 4;
102 uint8_t BG4_address : 4;
103};
104
106 uint8_t increment_rate : 2;
107 uint8_t full_graphic : 2;
108 uint8_t increment_mode : 1;
109 uint8_t unused : 3;
110};
111
113 uint8_t brightness : 4;
114 uint8_t disable_screen : 1;
115 uint8_t unused : 3;
116};
117
120 uint8_t priority : 1;
121 uint8_t BG1_tile_size : 1;
122 uint8_t BG2_tile_size : 1;
123 uint8_t BG3_tile_size : 1;
124 uint8_t BG4_tile_size : 1;
125};
126
128 uint8_t offset : 8;
129 uint8_t mode7_bits : 3;
130 uint8_t unused : 5;
131};
132
134 uint8_t BG1_enable : 1;
135 uint8_t BG2_enable : 1;
136 uint8_t BG3_enable : 1;
137 uint8_t BG4_enable : 1;
138 uint8_t sprites_enable : 1;
139 uint8_t unused : 3;
140};
141
143 uint8_t BG1_clip_in_out : 1;
144 uint8_t BG1_enable : 1;
145 uint8_t BG2_clip_in_out : 1;
146 uint8_t BG2_enable : 1;
147 uint8_t BG3_clip_in_out : 1;
148 uint8_t BG3_enable : 1;
149 uint8_t BG4_clip_in_out : 1;
150 uint8_t BG4_enable : 1;
151};
152
155 uint8_t sprites_enable : 1;
158 uint8_t unused : 4;
159};
160
162 uint8_t position : 8;
163};
164
166 uint8_t BG1_mask_logic : 2;
167 uint8_t BG2_mask_logic : 2;
168 uint8_t BG3_mask_logic : 2;
169 uint8_t BG4_mask_logic : 2;
170};
171
172// Counter/IRQ/NMI Registers
174 uint8_t softwareLatchHvCounter; // Register $2137
175 uint16_t horizontalScanLocation; // Register $213C
176 uint16_t verticalScanLocation; // Register $213D
177 uint8_t counterEnable; // Register $4200
178 uint16_t horizontalIrqTrigger; // Register $4207/$4208
179 uint16_t verticalIrqTrigger; // Register $4209/$420A
180 uint8_t nmiRegister; // Register $4210
181 uint8_t irqRegister; // Register $4211
182 uint8_t statusRegisterIrq; // Register $4212
183};
184
185// Joypad Registers
187 uint16_t joypadData[4]; // Register $4218 to $421F
188 uint8_t oldStyleJoypadRegisters[2]; // Registers $4016/$4217
189};
190
191// DMA Registers
193 uint8_t startDmaTransfer; // Register $420B
194 uint8_t enableHDmaTransfer; // Register $420C
195 uint8_t dmacontrol_register_ister[8]; // Register $43?0
196 uint8_t dmaDestinationAddress[8]; // Register $43?1
197 uint32_t dmaSourceAddress[8]; // Register $43?2/$43?3/$43?4
198 uint16_t bytesToTransfer[8]; // Register $43?5/$43?6/$43?7
199 uint16_t hdmaCountPointer[8]; // Register $43?8/$43?9
200 uint8_t scanlinesLeft[8]; // Register $43?A
201};
202
203// WRAM access Registers
205 uint8_t dataByte; // Register $2180
206 uint32_t address; // Register $2181/$2182/$2183
207};
208
209struct Tile {
210 uint16_t index; // Index of the tile in VRAM
211 uint8_t palette; // Palette number used for this tile
212 bool flip_x; // Horizontal flip flag
213 bool flip_y; // Vertical flip flag
214 uint8_t priority; // Priority of this tile
215};
216
223
224typedef struct BgLayer {
225 uint16_t hScroll;
226 uint16_t vScroll;
229 uint16_t tilemapAdr;
230 uint16_t tileAdr;
234
242
245
246 enum class ColorDepth { BPP_2, BPP_4, BPP_8 };
247
248 Size size; // Size of the background layer
249 ColorDepth color_depth; // Color depth of the background layer
250 std::vector<Tile> tilemap; // Tilemap data
251 std::vector<uint8_t> tile_data; // Tile data in VRAM
252 uint16_t tilemap_base_address; // Base address of the tilemap in VRAM
253 uint16_t tile_data_base_address; // Base address of the tile data in VRAM
254 uint8_t scroll_x; // Horizontal scroll offset
255 uint8_t scroll_y; // Vertical scroll offset
256 bool enabled; // Whether the background layer is enabled
257};
258
259class Ppu : public SharedRom {
260 public:
261 // Initializes the PPU with the necessary resources and dependencies
262 Ppu(memory::Memory& memory, Clock& clock) : memory_(memory), clock_(clock) {}
263
264 // Initialize the frame buffer
265 void Init() {
266 frame_buffer_.resize(256 * 240, 0);
268 }
269
270 // Resets the PPU to its initial state
271 void Reset();
272
273 // Runs the PPU for one frame.
274 void Update();
275 void UpdateClock(double delta_time) { clock_.UpdateClock(delta_time); }
276
277 void HandleFrameStart();
278 void RunLine(int line);
279 void HandlePixel(int x, int y);
280
281 void LatchHV() {
282 h_count_ = memory_.h_pos() / 4;
284 counters_latched_ = true;
285 }
286
287 int GetPixel(int x, int y, bool sub, int* r, int* g, int* b);
288
289 void EvaluateSprites(int line);
290
291 void CalculateMode7Starts(int y);
292
293 bool GetWindowState(int layer, int x);
294
295 // if we are overscanning this frame (determined at 0,225)
296 bool frame_overscan_ = false;
297 bool overscan_ = false;
298
299 // settings
301 uint8_t brightness;
302 uint8_t mode;
307 bool frame_interlace; // if we are interlacing this frame (determined at
308 // start vblank)
310
313 return frame_overscan_;
314 }
315
316 void HandleVblank();
317 void HandleOPT(int layer, int* lx, int* ly);
318 uint16_t GetOffsetValue(int col, int row);
319 int GetPixelForBgLayer(int x, int y, int layer, bool priority);
320
321 uint8_t Read(uint8_t adr, bool latch);
322 void Write(uint8_t adr, uint8_t val);
323
324 uint16_t GetVramRemap();
325
326 void PutPixels(uint8_t* pixel_data);
327
328 // Returns the pixel data for the current frame
329 const std::vector<uint8_t>& GetFrameBuffer() const { return frame_buffer_; }
330
331 private:
332 int GetPixelForMode7(int x, int layer, bool priority);
333
334 const int cyclesPerScanline = 341; // SNES PPU has 341 cycles per scanline
335 const int totalScanlines = 262; // SNES PPU has 262 scanlines per frame
336 const int visibleScanlines = 224; // SNES PPU renders 224 visible scanlines
337
339
342
343 // vram access
344 uint16_t vram[0x8000];
345 uint16_t vram_pointer;
350
351 // cgram access
352 uint16_t cgram[0x100];
356
357 // oam access
358 uint16_t oam[0x100];
359 uint8_t high_oam_[0x20];
360 uint8_t oam_adr_;
365 uint8_t oam_buffer_;
366
367 // Objects / Sprites
368 bool time_over_ = false;
369 bool range_over_ = false;
374 uint8_t obj_size_;
375 std::array<uint8_t, 256> obj_pixel_buffer_;
376 std::array<uint8_t, 256> obj_priority_buffer_;
377
378 // Color Math
379 uint8_t clip_mode_ = 0;
381 bool math_enabled_array_[6] = {false, false, false, false, false, false};
382 bool add_subscreen_ = false;
388
389 // layers
391
392 // mode 7
393 int16_t m7matrix[8]; // a, b, c, d, x, y, h, v
394 uint8_t m7prev;
400
401 // mode 7 internal
402 int32_t m7startX;
403 int32_t m7startY;
404
405 // windows
407 uint8_t window1left;
409 uint8_t window2left;
411
412 // Background Layers
413 std::array<BackgroundLayer, 4> bg_layers_;
414 uint8_t mosaic_startline_ = 1;
415
420
421 // pixel buffer (xbgr)
422 // times 2 for even and odd frame
423 uint8_t pixelBuffer[512 * 4 * 239 * 2];
424 uint8_t pixelOutputFormat = 0;
425
426 // latching
427 uint16_t h_count_;
428 uint16_t v_count_;
434
438 uint16_t screen_brightness_ = 0x00;
439
442
445 std::vector<SpriteAttributes> sprites_;
446 std::vector<uint8_t> tile_data_;
447 std::vector<uint8_t> frame_buffer_;
448
449 // PPU registers
453 std::array<BGSC, 4> bgsc_;
454 std::array<BGNBA, 4> bgnba_;
455 std::array<BGHOFS, 4> bghofs_;
456 std::array<BGVOFS, 4> bgvofs_;
457};
458
459} // namespace video
460} // namespace emu
461} // namespace app
462} // namespace yaze
463
464#endif // YAZE_APP_EMU_PPU_H
A class to hold a shared pointer to a Rom object.
Definition rom.h:576
virtual void UpdateClock(double delta)=0
Memory interface.
Definition memory.h:48
virtual auto v_pos() const -> uint16_t=0
virtual auto h_pos() const -> uint16_t=0
virtual void Write(uint16_t address, uint8_t data)=0
virtual uint8_t Read(uint16_t address) const =0
std::array< BackgroundLayer, 4 > bg_layers_
Definition ppu.h:413
std::array< BGHOFS, 4 > bghofs_
Definition ppu.h:455
uint16_t tile_data_size_
Definition ppu.h:435
Ppu(memory::Memory &memory, Clock &clock)
Definition ppu.h:262
int GetPixelForBgLayer(int x, int y, int layer, bool priority)
Definition ppu.cc:405
const int totalScanlines
Definition ppu.h:335
BackgroundMode bg_mode_
Definition ppu.h:444
const int cyclesPerScanline
Definition ppu.h:334
WindowLayer windowLayer[6]
Definition ppu.h:406
uint8_t pixelBuffer[512 *4 *239 *2]
Definition ppu.h:423
std::vector< uint8_t > tile_data_
Definition ppu.h:446
uint8_t prevent_math_mode_
Definition ppu.h:380
void HandlePixel(int x, int y)
Definition ppu.cc:163
uint16_t obj_tile_adr1_
Definition ppu.h:372
std::vector< uint8_t > frame_buffer_
Definition ppu.h:447
void EvaluateSprites(int line)
Definition ppu.cc:472
bool math_enabled_array_[6]
Definition ppu.h:381
uint8_t mosaic_startline_
Definition ppu.h:414
uint8_t Read(uint8_t adr, bool latch)
Definition ppu.cc:598
uint16_t tilemap_base_address_
Definition ppu.h:437
uint16_t screen_brightness_
Definition ppu.h:438
std::array< uint8_t, 256 > obj_priority_buffer_
Definition ppu.h:376
void Write(uint8_t adr, uint8_t val)
Definition ppu.cc:733
void HandleOPT(int layer, int *lx, int *ly)
Definition ppu.cc:356
uint16_t GetVramRemap()
Definition ppu.cc:1023
void CalculateMode7Starts(int y)
Definition ppu.cc:567
uint16_t cgram[0x100]
Definition ppu.h:352
uint16_t obj_tile_adr2_
Definition ppu.h:373
std::vector< SpriteAttributes > sprites_
Definition ppu.h:445
uint8_t pixelOutputFormat
Definition ppu.h:424
void UpdateClock(double delta_time)
Definition ppu.h:275
int GetPixel(int x, int y, bool sub, int *r, int *g, int *b)
Definition ppu.cc:230
OAMAddress oam_address_
Definition ppu.h:451
uint16_t vram_read_buffer_
Definition ppu.h:349
uint16_t vram_increment_
Definition ppu.h:347
void RunLine(int line)
Definition ppu.cc:151
uint16_t oam[0x100]
Definition ppu.h:358
BgLayer bg_layer_[4]
Definition ppu.h:416
bool GetWindowState(int layer, int x)
Definition ppu.cc:326
const int visibleScanlines
Definition ppu.h:336
uint16_t vram_base_address_
Definition ppu.h:436
void PutPixels(uint8_t *pixel_data)
Definition ppu.cc:1038
int GetPixelForMode7(int x, int layer, bool priority)
Definition ppu.cc:307
std::array< uint8_t, 256 > obj_pixel_buffer_
Definition ppu.h:375
std::array< BGNBA, 4 > bgnba_
Definition ppu.h:454
int16_t m7matrix[8]
Definition ppu.h:393
std::array< BGSC, 4 > bgsc_
Definition ppu.h:453
uint16_t GetOffsetValue(int col, int row)
Definition ppu.cc:391
std::array< BGVOFS, 4 > bgvofs_
Definition ppu.h:456
uint8_t high_oam_[0x20]
Definition ppu.h:359
uint16_t vram[0x8000]
Definition ppu.h:344
const std::vector< uint8_t > & GetFrameBuffer() const
Definition ppu.h:329
struct yaze::app::emu::video::Layer Layer
struct yaze::app::emu::video::BgLayer BgLayer
struct yaze::app::emu::video::WindowLayer WindowLayer
Definition common.cc:22
std::vector< uint8_t > tile_data
Definition ppu.h:251
std::vector< Tile > tilemap
Definition ppu.h:250
std::vector< TilemapEntry > entries
Definition ppu.h:68