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.

125 lines
3.2KB

  1. #include "cart.h"
  2. #include "filemap.h"
  3. #include "ines.h"
  4. #include "mapper.h"
  5. #include "save.h"
  6. int nes_cart_init_mem(nes_cart* cart, void* mem, int len) {
  7. int status = 0;
  8. ines_Header *hdr = (ines_Header*)mem;
  9. void* ptr = &hdr[1];
  10. cart->ines_mem = mem;
  11. cart->ines_size = len;
  12. status = ines_check_mem(hdr);
  13. if (0 == status && (hdr->flags_6 & ines_Flag_Trainer)) {
  14. // Skip trainer
  15. ptr += ines_trainer_size;
  16. }
  17. if (0 == status) {
  18. int prg_size = nes_prg_rom_page_size * hdr->prg_size_lsb;
  19. if (prg_size <= 0) {
  20. INES_ERR("Bad program ROM size: %#x", prg_size);
  21. status = -1;
  22. } else {
  23. INES_INFO("%d KB PRG ROM", prg_size / 1024);
  24. cart->prg_rom = ptr;
  25. cart->prg_rom_banks = hdr->prg_size_lsb;
  26. }
  27. ptr += prg_size;
  28. }
  29. if (0 == status) {
  30. int chr_size = nes_chr_page_size * hdr->chr_size_lsb * 2;
  31. INES_INFO("%d KB CHR ROM", chr_size / 1024);
  32. cart->chr_rom = ptr;
  33. cart->chr_rom_banks = hdr->chr_size_lsb * 2;
  34. ptr += chr_size;
  35. int index = (hdr->flags_6 & ines_Mapper_Nibble_Lo) >> 4 |
  36. (hdr->flags_7 & ines_Mapper_Nibble_Hi);
  37. cart->mapper = nes_mappers[index];
  38. if (NULL == cart->mapper) {
  39. INES_ERR("No mapper found for type %d", index);
  40. status = -1;
  41. } else if (NULL != cart->mapper->name) {
  42. INES_INFO("Mapper: %s", cart->mapper->name);
  43. }
  44. }
  45. if (0 == status) {
  46. if ((ptr - mem) != len) {
  47. INES_ERR("Bad file size: read %d, expected %d",
  48. (int)(ptr - mem), len);
  49. status = -1;
  50. }
  51. }
  52. if (0 == status) {
  53. if (hdr->flags_6 & ines_Flag_Horizontal) {
  54. cart->flags |= Cart_Flag_Horizontal;
  55. } else {
  56. cart->flags &= ~Cart_Flag_Horizontal;
  57. }
  58. if (hdr->flags_6 & ines_Flag_Battery) {
  59. cart->flags |= Cart_Flag_Battery;
  60. }
  61. // Don't initialize the mapper until all flags are set!
  62. cart->map_data = nes_map_init(cart->mapper, cart);
  63. status = (NULL == cart->map_data ? -1 : 0);
  64. }
  65. return status;
  66. }
  67. void nes_cart_done(nes_cart* cart) {
  68. if (NULL != cart->mapper) {
  69. nes_map_done(cart->mapper, cart->map_data);
  70. cart->mapper = NULL;
  71. cart->map_data = NULL;
  72. }
  73. if (NULL != cart->ines_mem) {
  74. unmap_file(cart->ines_mem, cart->ines_size);
  75. cart->ines_mem = NULL;
  76. }
  77. }
  78. int nes_cart_init_file(nes_cart* cart, FILE* file) {
  79. int status = 0;
  80. int size = -1;
  81. void* mem = NULL;
  82. // Get file size
  83. status = fseek(file, 0, SEEK_END);
  84. if (0 != status) {
  85. INES_ERR("Failed to check file size");
  86. } else {
  87. size = ftell(file);
  88. }
  89. // Map file
  90. if (0 == status) {
  91. mem = map_file(file, size, Filemap_Mode_Read);
  92. if (NULL == mem) {
  93. INES_ERR("Failed to map file (%d bytes)", size);
  94. status = -1;
  95. }
  96. }
  97. // Check in memory; unmap on failure
  98. if (0 == status) {
  99. status = nes_cart_init_mem(cart, mem, size);
  100. if (0 != status) {
  101. unmap_file(file, size);
  102. }
  103. }
  104. return status;
  105. }