cart.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #include <../base.hpp>
  2. #include <../chip/chip.hpp>
  3. #include <../reader/reader.hpp>
  4. #define CART_CPP
  5. #include <nall/crc32.hpp>
  6. #include <nall/ups.hpp>
  7. #include "cart.hpp"
  8. #include "cart_file.cpp"
  9. #include "cart_header.cpp"
  10. #include "cart_loader.cpp"
  11. namespace memory {
  12. MappedRAM cartrom, cartram, cartrtc;
  13. MappedRAM bscram;
  14. MappedRAM stArom, stAram;
  15. MappedRAM stBrom, stBram;
  16. };
  17. Cartridge cartridge;
  18. void Cartridge::load_begin(Mode cartridge_mode) {
  19. cart.rom = cart.ram = cart.rtc = 0;
  20. bs.ram = 0;
  21. stA.rom = stA.ram = 0;
  22. stB.rom = stB.ram = 0;
  23. cart.rom_size = cart.ram_size = cart.rtc_size = 0;
  24. bs.ram_size = 0;
  25. stA.rom_size = stA.ram_size = 0;
  26. stB.rom_size = stB.ram_size = 0;
  27. set(loaded, false);
  28. set(bsx_flash_loaded, false);
  29. set(patched, false);
  30. set(mode, cartridge_mode);
  31. }
  32. void Cartridge::load_end() {
  33. memory::cartrom.map(cart.rom, cart.rom_size);
  34. memory::cartram.map(cart.ram, cart.ram_size);
  35. memory::cartrtc.map(cart.rtc, cart.rtc_size);
  36. memory::bscram.map(bs.ram, bs.ram_size);
  37. memory::stArom.map(stA.rom, stA.rom_size);
  38. memory::stAram.map(stA.ram, stA.ram_size);
  39. memory::stBrom.map(stB.rom, stB.rom_size);
  40. memory::stBram.map(stB.ram, stB.ram_size);
  41. /* enable rom write */
  42. memory::cartrom.write_protect(false);
  43. memory::cartram.write_protect(false);
  44. memory::bscram.write_protect(true);
  45. memory::stArom.write_protect(true);
  46. memory::stAram.write_protect(false);
  47. memory::stBrom.write_protect(true);
  48. memory::stBram.write_protect(false);
  49. string cheat_file = get_filename(cart.filename, "cht", snes.config.path.cheat);
  50. if(file::exists(cheat_file)) {
  51. cheat.clear();
  52. cheat.load(cheat_file);
  53. }
  54. bus.load_cart();
  55. set(loaded, true);
  56. }
  57. void Cartridge::unload() {
  58. if(loaded() == false) return;
  59. bus.unload_cart();
  60. switch(mode()) {
  61. case ModeNormal: unload_normal(); break;
  62. case ModeBsxSlotted: unload_bsx_slotted(); break;
  63. case ModeBsx: unload_bsx(); break;
  64. case ModeSufamiTurbo: unload_sufami_turbo(); break;
  65. }
  66. if(cart.rom) { delete[] cart.rom; cart.rom = 0; }
  67. if(cart.ram) { delete[] cart.ram; cart.ram = 0; }
  68. if(cart.rtc) { delete[] cart.rtc; cart.rtc = 0; }
  69. if(bs.ram) { delete[] bs.ram; bs.ram = 0; }
  70. if(stA.rom) { delete[] stA.rom; stA.rom = 0; }
  71. if(stA.ram) { delete[] stA.ram; stA.ram = 0; }
  72. if(stB.rom) { delete[] stB.rom; stB.rom = 0; }
  73. if(stB.ram) { delete[] stB.ram; stB.ram = 0; }
  74. string cheat_file = get_filename(cart.filename, "cht", snes.config.path.cheat);
  75. if(cheat.count() > 0 || file::exists(cheat_file)) {
  76. cheat.save(cheat_file);
  77. cheat.clear();
  78. }
  79. set(loaded, false);
  80. }
  81. Cartridge::Cartridge() {
  82. set(loaded, false);
  83. }
  84. Cartridge::~Cartridge() {
  85. if(loaded() == true) unload();
  86. }
  87. void Cartridge::set_cartinfo(const Cartridge::cartinfo_t &source) {
  88. set(region, source.region);
  89. set(mapper, source.mapper);
  90. set(dsp1_mapper, source.dsp1_mapper);
  91. set(has_bsx_slot, source.bsx_slot);
  92. set(has_superfx, source.superfx);
  93. set(has_sa1, source.sa1);
  94. set(has_srtc, source.srtc);
  95. set(has_sdd1, source.sdd1);
  96. set(has_spc7110, source.spc7110);
  97. set(has_spc7110rtc, source.spc7110rtc);
  98. set(has_cx4, source.cx4);
  99. set(has_dsp1, source.dsp1);
  100. set(has_dsp2, source.dsp2);
  101. set(has_dsp3, source.dsp3);
  102. set(has_dsp4, source.dsp4);
  103. set(has_obc1, source.obc1);
  104. set(has_st010, source.st010);
  105. set(has_st011, source.st011);
  106. set(has_st018, source.st018);
  107. }
  108. //==========
  109. //cartinfo_t
  110. //==========
  111. void Cartridge::cartinfo_t::reset() {
  112. type = TypeUnknown;
  113. mapper = LoROM;
  114. dsp1_mapper = DSP1Unmapped;
  115. region = NTSC;
  116. rom_size = 0;
  117. ram_size = 0;
  118. bsx_slot = false;
  119. superfx = false;
  120. sa1 = false;
  121. srtc = false;
  122. sdd1 = false;
  123. spc7110 = false;
  124. spc7110rtc = false;
  125. cx4 = false;
  126. dsp1 = false;
  127. dsp2 = false;
  128. dsp3 = false;
  129. dsp4 = false;
  130. obc1 = false;
  131. st010 = false;
  132. st011 = false;
  133. st018 = false;
  134. }
  135. Cartridge::cartinfo_t::cartinfo_t() {
  136. reset();
  137. }
  138. //=======
  139. //utility
  140. //=======
  141. //ensure file path is absolute (eg resolve relative paths)
  142. string Cartridge::filepath(const char *filename, const char *pathname) {
  143. //if no pathname, return filename as-is
  144. string file(filename);
  145. file.replace("\\", "/");
  146. string path = (!pathname || !*pathname) ? (const char*)snes.config.path.current : pathname;
  147. //ensure path ends with trailing '/'
  148. path.replace("\\", "/");
  149. if(!strend(path, "/")) path.append("/");
  150. //replace relative path with absolute path
  151. if(strbegin(path, "./")) {
  152. ltrim(path, "./");
  153. path = string() << snes.config.path.base << path;
  154. }
  155. //remove folder part of filename
  156. lstring part;
  157. part.split("/", file);
  158. return path << part[part.size() - 1];
  159. }
  160. //remove directory information and file extension ("/foo/bar.ext" -> "bar")
  161. string Cartridge::basename(const char *filename) {
  162. string name(filename);
  163. //remove extension
  164. for(signed i = strlen(name) - 1; i >= 0; i--) {
  165. if(name[i] == '.') {
  166. name[i] = 0;
  167. break;
  168. }
  169. }
  170. //remove directory information
  171. for(signed i = strlen(name) - 1; i >= 0; i--) {
  172. if(name[i] == '/' || name[i] == '\\') {
  173. i++;
  174. char *output = name();
  175. while(true) {
  176. *output++ = name[i];
  177. if(!name[i]) break;
  178. i++;
  179. }
  180. break;
  181. }
  182. }
  183. return name;
  184. }
  185. //remove filename and return path only ("/foo/bar.ext" -> "/foo/bar/")
  186. string Cartridge::basepath(const char *filename) {
  187. string path(filename);
  188. path.replace("\\", "/");
  189. //remove filename
  190. for(signed i = strlen(path) - 1; i >= 0; i--) {
  191. if(path[i] == '/') {
  192. path[i] = 0;
  193. break;
  194. }
  195. }
  196. if(!strend(path, "/")) path.append("/");
  197. return path;
  198. }