nes_rom.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * MIT License
  3. *
  4. * Copyright (c) 2022 Dozingfiretruck
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in all
  14. * copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE.
  23. */
  24. #include "nes.h"
  25. #if (NES_USE_SRAM == 1)
  26. #define SRAM_SIZE (0x2000)
  27. #endif
  28. #if (NES_USE_FS == 1)
  29. nes_t* nes_load_file(const char* file_path ){
  30. nes_header_info_t nes_header_info = {0};
  31. nes_t* nes = NULL;
  32. FILE* nes_file = nes_fopen(file_path, "rb");
  33. if (!nes_file){
  34. goto error;
  35. }
  36. nes = (nes_t *)nes_malloc(sizeof(nes_t));
  37. if (nes == NULL) {
  38. goto error;
  39. }
  40. memset(nes, 0, sizeof(nes_t));
  41. #if (NES_USE_SRAM == 1)
  42. nes->nes_rom.sram = (uint8_t*)nes_malloc(SRAM_SIZE);
  43. #endif
  44. if (nes_fread(&nes_header_info, sizeof(nes_header_info), 1, nes_file)) {
  45. if ( nes_memcmp( nes_header_info.identification, "NES\x1a", 4 )){
  46. goto error;
  47. }
  48. if (nes_header_info.trainer){
  49. #if (NES_USE_SRAM == 1)
  50. if (nes_fread(nes->nes_rom.sram, TRAINER_SIZE, 1, nes_file)==0){
  51. goto error;
  52. }
  53. #else
  54. nes_fseek(nes_file, TRAINER_SIZE, SEEK_CUR);
  55. #endif
  56. }
  57. nes->nes_rom.prg_rom_size = ((nes_header_info.prg_rom_size_m << 8) & 0xF00) | nes_header_info.prg_rom_size_l;
  58. nes->nes_rom.chr_rom_size = ((nes_header_info.prg_rom_size_m << 8) & 0xF00) | nes_header_info.chr_rom_size_l;
  59. nes->nes_rom.mapper_number = ((nes_header_info.mapper_number_h << 8) & 0xF00) | ((nes_header_info.mapper_number_m << 4) & 0xF0) | (nes_header_info.mapper_number_l & 0x0F);
  60. nes->nes_rom.mirroring_type = (nes_header_info.mirroring);
  61. nes->nes_rom.four_screen = (nes_header_info.four_screen);
  62. nes->nes_rom.save_ram = (nes_header_info.save);
  63. nes->nes_rom.prg_rom = (uint8_t*)nes_malloc(PRG_ROM_UNIT_SIZE * nes->nes_rom.prg_rom_size);
  64. if (nes->nes_rom.prg_rom == NULL) {
  65. goto error;
  66. }
  67. if (nes_fread(nes->nes_rom.prg_rom, PRG_ROM_UNIT_SIZE, nes->nes_rom.prg_rom_size, nes_file)==0){
  68. goto error;
  69. }
  70. nes->nes_rom.chr_rom = (uint8_t*)nes_malloc(CHR_ROM_UNIT_SIZE * (nes->nes_rom.chr_rom_size ? nes->nes_rom.chr_rom_size : 1));
  71. if (nes->nes_rom.chr_rom == NULL) {
  72. goto error;
  73. }
  74. if (nes->nes_rom.chr_rom_size){
  75. if (nes_fread(nes->nes_rom.chr_rom, CHR_ROM_UNIT_SIZE, (nes->nes_rom.chr_rom_size), nes_file)==0){
  76. goto error;
  77. }
  78. }
  79. }else{
  80. goto error;
  81. }
  82. nes_fclose(nes_file);
  83. nes_init(nes);
  84. nes_load_mapper(nes);
  85. nes->nes_mapper.mapper_init(nes);
  86. return nes;
  87. error:
  88. if (nes_file){
  89. nes_fclose(nes_file);
  90. }
  91. if (nes){
  92. nes_rom_free(nes);
  93. }
  94. return NULL;
  95. }
  96. #endif
  97. // release
  98. int nes_rom_free(nes_t* nes){
  99. if (nes->nes_rom.prg_rom){
  100. nes_free(nes->nes_rom.prg_rom);
  101. }
  102. if (nes->nes_rom.chr_rom){
  103. nes_free(nes->nes_rom.chr_rom);
  104. }
  105. if (nes->nes_rom.sram){
  106. nes_free(nes->nes_rom.sram);
  107. }
  108. if (nes){
  109. nes_free(nes);
  110. }
  111. return NES_OK;
  112. }
  113. nes_t* nes_load_rom(const uint8_t* nes_rom){
  114. nes_t* nes = (nes_t *)nes_malloc(sizeof(nes_t));
  115. if (nes == NULL) {
  116. goto error;
  117. }
  118. memset(nes, 0, sizeof(nes_t));
  119. nes_header_info_t* nes_header_info = (nes_header_info_t*)nes_rom;
  120. #if (NES_USE_SRAM == 1)
  121. nes->nes_rom.sram = (uint8_t*)nes_malloc(SRAM_SIZE);
  122. #endif
  123. if ( nes_memcmp( nes_header_info->identification, "NES\x1a", 4 )){
  124. goto error;
  125. }
  126. uint8_t* nes_bin = nes_rom + sizeof(nes_header_info_t);
  127. if (nes_header_info->trainer){
  128. #if (NES_USE_SRAM == 1)
  129. #else
  130. #endif
  131. nes_bin += TRAINER_SIZE;
  132. }
  133. nes->nes_rom.prg_rom_size = ((nes_header_info->prg_rom_size_m << 8) & 0xF00) | nes_header_info->prg_rom_size_l;
  134. nes->nes_rom.chr_rom_size = ((nes_header_info->prg_rom_size_m << 8) & 0xF00) | nes_header_info->chr_rom_size_l;
  135. nes->nes_rom.mapper_number = ((nes_header_info->mapper_number_h << 8) & 0xF00) | ((nes_header_info->mapper_number_m << 4) & 0xF0) | (nes_header_info->mapper_number_l & 0x0F);
  136. nes->nes_rom.mirroring_type = (nes_header_info->mirroring);
  137. nes->nes_rom.four_screen = (nes_header_info->four_screen);
  138. nes->nes_rom.save_ram = (nes_header_info->save);
  139. nes->nes_rom.prg_rom = nes_bin;
  140. nes_bin += PRG_ROM_UNIT_SIZE * nes->nes_rom.prg_rom_size;
  141. if (nes->nes_rom.chr_rom_size){
  142. nes->nes_rom.chr_rom = nes_bin;
  143. }
  144. nes_init(nes);
  145. nes_load_mapper(nes);
  146. nes->nes_mapper.mapper_init(nes);
  147. return nes;
  148. error:
  149. if (nes){
  150. nes_rom_free(nes);
  151. }
  152. return NULL;
  153. }