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.

138 line
3.4KB

  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;
  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 (hdr->flags_6 & ines_Flag_Horizontal) {
  47. cart->flags |= Cart_Flag_Horizontal;
  48. } else {
  49. cart->flags &= ~Cart_Flag_Horizontal;
  50. }
  51. if (hdr->flags_6 & ines_Flag_Battery) {
  52. cart->flags |= Cart_Flag_Battery;
  53. }
  54. // Don't initialize the mapper until all flags are set!
  55. status = nes_map_init(cart->mapper, cart);
  56. }
  57. return status;
  58. }
  59. void nes_cart_done(nes_cart* cart) {
  60. if (NULL != cart->ines_mem) {
  61. unmap_file(cart->ines_mem, cart->ines_size);
  62. cart->ines_mem = NULL;
  63. }
  64. }
  65. int nes_cart_init_file(nes_cart* cart, FILE* file) {
  66. int status = 0;
  67. int size = -1;
  68. void* mem = NULL;
  69. // Get file size
  70. status = fseek(file, 0, SEEK_END);
  71. if (0 != status) {
  72. INES_ERR("Failed to check file size");
  73. } else {
  74. size = ftell(file);
  75. }
  76. // Map file
  77. if (0 == status) {
  78. mem = map_file(file, size, Filemap_Mode_Read);
  79. if (NULL == mem) {
  80. INES_ERR("Failed to map file (%d bytes)", size);
  81. status = -1;
  82. }
  83. }
  84. // Check in memory; unmap on failure
  85. if (0 == status) {
  86. status = nes_cart_init_mem(cart, mem, size);
  87. if (0 != status) {
  88. unmap_file(file, size);
  89. }
  90. }
  91. return status;
  92. }
  93. FILE* nes_load_cart(nes_cart* cart, const char* cart_filename) {
  94. int status = 0;
  95. FILE* cart_file = fopen(cart_filename, "rb");
  96. if (NULL == cart_file) {
  97. status = -1;
  98. fprintf(stderr, "Could not open %s\n", cart_filename);
  99. }
  100. if (status == 0) {
  101. status = nes_cart_init_file(cart, cart_file);
  102. }
  103. if (status == 0) {
  104. // Failure might mean there's nothing to load
  105. load_sram(cart, cart_filename);
  106. }
  107. if (status != 0 && NULL != cart_file) {
  108. fclose(cart_file);
  109. cart_file = NULL;
  110. }
  111. return cart_file;
  112. }