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.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

156 lignes
3.9KB

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