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.

149 line
3.7KB

  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include "map.h"
  4. typedef struct {
  5. uint8_t* prg_rom;
  6. int prg_rom_banks;
  7. uint8_t mirror;
  8. uint8_t bank;
  9. uint8_t vram[nes_vram_page_size * 2];
  10. uint8_t chr_ram[8 * 1024];
  11. uint8_t* prg_bank_lo;
  12. uint8_t* prg_bank_hi;
  13. } uxrom_mapper;
  14. static void uxrom_set_bank(uxrom_mapper* map, uint8_t bank) {
  15. map->bank = (bank % map->prg_rom_banks);
  16. map->prg_bank_lo = &map->prg_rom[
  17. map->bank * nes_prg_rom_page_size
  18. ];
  19. }
  20. static void uxrom_reset(void* data) {
  21. uxrom_mapper* map = (uxrom_mapper*)data;
  22. uxrom_set_bank(map, 0);
  23. map->prg_bank_lo = map->prg_rom;
  24. }
  25. static void* uxrom_init(nes_mapper* nes_map, nes_cart* cart) {
  26. uxrom_mapper* map = calloc(1, sizeof(uxrom_mapper));
  27. if (NULL != map) {
  28. map->prg_rom = cart->prg_rom;
  29. map->prg_rom_banks = cart->prg_rom_banks;
  30. map->mirror = (cart->flags & Cart_Flag_Horizontal) ? 0 : 1;
  31. map->prg_bank_hi = &map->prg_rom[(map->prg_rom_banks - 1) *
  32. nes_prg_rom_page_size];
  33. uxrom_reset(map);
  34. }
  35. return map;
  36. }
  37. static void uxrom_done(void* data) {
  38. free(data);
  39. }
  40. static inline uint8_t* uxrom_prg_addr(uxrom_mapper* map,
  41. uint16_t addr) {
  42. uint8_t* bank = ( addr < 0xC000U ?
  43. map->prg_bank_lo : map->prg_bank_hi );
  44. return &(bank[addr & 0x3FFF]);
  45. }
  46. static uint8_t uxrom_read(void* _map, uint16_t addr) {
  47. uint8_t val = 0;
  48. if (addr >= nes_mem_rom_start) {
  49. val = *(uxrom_prg_addr((uxrom_mapper*)_map, addr));
  50. }
  51. return val;
  52. }
  53. static void uxrom_write(void* _map, uint16_t addr, uint8_t val) {
  54. uxrom_mapper* map = (uxrom_mapper*)_map;
  55. if (addr >= nes_mem_rom_start) {
  56. uxrom_set_bank(map, val);
  57. }
  58. }
  59. static uint8_t* uxrom_chr_addr(void* data, uint16_t addr) {
  60. return &((uxrom_mapper*)data)->chr_ram[addr];
  61. }
  62. static uint8_t* uxrom_vram_addr(void* data, uint16_t addr) {
  63. uxrom_mapper* map = (uxrom_mapper*)data;
  64. int page = addr >> 10U;
  65. page >>= map->mirror;
  66. addr = ((page & 1) << 10U) | (addr & 0x3FFU);
  67. return &map->vram[addr];
  68. }
  69. static void uxrom_chr_write(void* data,
  70. uint16_t addr, uint8_t val) {
  71. ((uxrom_mapper*)data)->chr_ram[addr] = val;
  72. }
  73. /* Save State */
  74. int uxrom_state_size(const void* _map) {
  75. uxrom_mapper* map = (uxrom_mapper*)_map;
  76. return ( sizeof(uint32_t) +
  77. sizeof(map->vram) +
  78. sizeof(map->chr_ram));
  79. }
  80. int uxrom_state_read(void* _map, const void* data) {
  81. uxrom_mapper* map = (uxrom_mapper*)_map;
  82. const void* ptr = data;
  83. map->bank = *(uint32_t*)ptr;
  84. ptr += sizeof(uint32_t);
  85. memcpy(map->vram, ptr, sizeof(map->vram));
  86. ptr += sizeof(map->vram);
  87. memcpy(map->chr_ram, ptr, sizeof(map->chr_ram));
  88. ptr += sizeof(map->chr_ram);
  89. return (ptr - data);
  90. }
  91. int uxrom_state_write(const void* _map, void* data) {
  92. uxrom_mapper* map = (uxrom_mapper*)_map;
  93. void* ptr = data;
  94. uint32_t bank = map->bank;
  95. memcpy(ptr, &bank, sizeof(bank));
  96. ptr += sizeof(bank);
  97. memcpy(ptr, map->vram, sizeof(map->vram));
  98. ptr += sizeof(map->vram);
  99. memcpy(ptr, map->chr_ram, sizeof(map->chr_ram));
  100. ptr += sizeof(map->chr_ram);
  101. return (ptr - data);
  102. }
  103. nes_mapper mapper_uxrom = {
  104. .name = "UxROM",
  105. .init = uxrom_init,
  106. .reset = uxrom_reset,
  107. .done = uxrom_done,
  108. .read = uxrom_read,
  109. .write = uxrom_write,
  110. .chr_addr = uxrom_chr_addr,
  111. .vram_addr = uxrom_vram_addr,
  112. .chr_write = uxrom_chr_write,
  113. .state_size = uxrom_state_size,
  114. .state_read = uxrom_state_read,
  115. .state_write = uxrom_state_write,
  116. };