NESe (pronounced "Nessie") is a NES emulator based on the e6502 emulator, also written in C with a focus on speed and portability for use on embedded platforms, especially ARM.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 line
3.6KB

  1. #ifndef NESE_PPU_H_
  2. #define NESE_PPU_H_
  3. #include <stdint.h>
  4. #define nes_ppu_render_w (256U)
  5. #define nes_ppu_render_h (240U)
  6. #define nes_ppu_scanline_dots (341U)
  7. #define nes_ppu_prerender_line (0U)
  8. #define nes_ppu_visible_line (1U)
  9. #define nes_ppu_postrender_line (241U)
  10. #define nes_ppu_vblank_line (242U)
  11. #define nes_ppu_frame_end_line (262U)
  12. typedef struct {
  13. uint8_t y;
  14. uint8_t index;
  15. uint8_t attr;
  16. uint8_t x;
  17. } oam_sprite;
  18. typedef enum {
  19. oam_Attr_Pal_Mask = 0b00000011,
  20. oam_Attr_Background = 0b00100000,
  21. oam_Attr_Flip_X = 0b01000000,
  22. oam_Attr_Flip_Y = 0b10000000,
  23. } oam_Attribute;
  24. typedef enum {
  25. ppu_reg_ctrl = 0,
  26. ppu_reg_mask,
  27. ppu_reg_status,
  28. ppu_reg_oam_addr,
  29. ppu_reg_oam_data,
  30. ppu_reg_scroll,
  31. ppu_reg_addr,
  32. ppu_reg_data,
  33. } ppu_reg_offset;
  34. typedef enum {
  35. ppu_Control_Nametable_Mask = 0b00000011,
  36. ppu_Control_Scroll_Page_X = 0b00000001,
  37. ppu_Control_Scroll_Page_Y = 0b00000010,
  38. ppu_Control_VRAM_Inc = 0b00000100,
  39. ppu_Control_Sprite_Bank = 0b00001000,
  40. ppu_Control_Back_Bank = 0b00010000,
  41. ppu_Control_Sprite_Size = 0b00100000,
  42. ppu_Control_Master = 0b01000000,
  43. ppu_Control_VBlank = 0b10000000,
  44. } nes_ppu_Control;
  45. typedef enum {
  46. ppu_Mask_Greyscale = 0b00000001,
  47. ppu_Mask_Left_Back = 0b00000010,
  48. ppu_Mask_Left_Sprite = 0b00000100,
  49. ppu_Mask_Back = 0b00001000,
  50. ppu_Mask_Sprite = 0b00010000,
  51. ppu_Mask_More_Red = 0b00100000,
  52. ppu_Mask_More_Green = 0b01000000,
  53. ppu_Mask_More_Blue = 0b10000000,
  54. } nes_ppu_Mask;
  55. typedef enum {
  56. ppu_Status_Open_Bus_Mask = 0b00011111,
  57. ppu_Status_Overflow = 0b00100000,
  58. ppu_Status_Hit = 0b01000000,
  59. ppu_Status_VBlank = 0b10000000,
  60. } nes_ppu_Status;
  61. #define NES_CHR_ROM_PAGE_SIZE (0x0400U)
  62. #define NES_VRAM_PAGE_SIZE (0x0400U)
  63. #define NES_PPU_CHR_SIZE (0x2000U)
  64. #define NES_PPU_VRAM_SIZE (0x1000U)
  65. #define NES_PPU_RAM_SIZE (0x4000U)
  66. #define NES_PPU_OAM_SIZE (64U * 4U)
  67. #define NES_PPU_PAL_START (0x3F00U)
  68. typedef struct {
  69. // Registers &c.
  70. uint8_t ctrl;
  71. uint8_t mask;
  72. uint8_t status;
  73. uint8_t oam_addr;
  74. uint16_t addr; // aka "v"
  75. uint8_t data;
  76. uint8_t x; // Fine X scroll
  77. uint16_t t; // temp VRAM addr
  78. uint8_t latch; // aka "w" - TODO: Could this be a flag?
  79. uint8_t addr_inc; // Auto-increment (1 or 32)
  80. // Memory banks
  81. uint8_t* chr;
  82. int n_chr_banks;
  83. uint8_t* chr_ram; // TODO: Could this be a flag?
  84. uint8_t* bank[16];
  85. uint8_t vram[NES_PPU_VRAM_SIZE];
  86. uint8_t pal_bank[NES_CHR_ROM_PAGE_SIZE]; // Mirrored in banks 12-15, also pal
  87. uint8_t oam[NES_PPU_OAM_SIZE];
  88. } nes_PPU_Memory;
  89. static inline uint8_t* chr_page(nes_PPU_Memory* mem,
  90. int page) {
  91. return &mem->chr[page * NES_CHR_ROM_PAGE_SIZE];
  92. }
  93. static inline uint8_t* vram_page(nes_PPU_Memory* mem,
  94. int page) {
  95. return &mem->vram[page * NES_VRAM_PAGE_SIZE];
  96. }
  97. #define nes_PPU_Nametable_Bank_Index (8U)
  98. typedef enum {
  99. nes_Mirror_Horizontal = 0,
  100. nes_Mirror_Vertical,
  101. nes_Mirror_Only_0,
  102. nes_Mirror_Only_1,
  103. nes_Mirror_Four,
  104. } nes_Nametable_Mirroring;
  105. void nes_ppu_set_mirroring(nes_PPU_Memory* mem,
  106. nes_Nametable_Mirroring mirror);
  107. typedef struct {
  108. int scanline;
  109. int hit_line;
  110. uint8_t line_data[nes_ppu_render_w];
  111. } nes_PPU;
  112. void nes_ppu_find_hit_line(nes_PPU*, nes_PPU_Memory*);
  113. void nes_ppu_render_line(nes_PPU*, nes_PPU_Memory*);
  114. #endif // NESE_PPU_H_