cartridge.cpp 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #include "bs-memory.cpp"
  2. #include "colecovision.cpp"
  3. #include "famicom.cpp"
  4. #include "game-boy.cpp"
  5. #include "game-boy-advance.cpp"
  6. #include "game-boy-color.cpp"
  7. #include "master-system.cpp"
  8. #include "mega-drive.cpp"
  9. #include "game-gear.cpp"
  10. #include "msx.cpp"
  11. #include "msx2.cpp"
  12. #include "neo-geo-pocket.cpp"
  13. #include "neo-geo-pocket-color.cpp"
  14. #include "nintendo-64.cpp"
  15. #include "pc-engine.cpp"
  16. #include "sg-1000.cpp"
  17. #include "sc-3000.cpp"
  18. #include "sufami-turbo.cpp"
  19. #include "super-famicom.cpp"
  20. #include "supergrafx.cpp"
  21. #include "wonderswan.cpp"
  22. #include "wonderswan-color.cpp"
  23. #include "pocket-challenge-v2.cpp"
  24. auto Cartridge::construct() -> void {
  25. Media::construct();
  26. }
  27. auto Cartridge::append(vector<uint8_t>& output, string filename) -> bool {
  28. if(!file::exists(filename)) return false;
  29. auto input = file::read(filename);
  30. auto size = output.size();
  31. output.resize(size + input.size());
  32. memory::copy(output.data() + size, input.data(), input.size());
  33. return true;
  34. }
  35. auto Cartridge::import(string location) -> string {
  36. auto data = Media::read(location);
  37. auto manifest = this->manifest(data, location);
  38. if(!manifest) return "failed to parse ROM";
  39. auto document = BML::unserialize(manifest);
  40. location = {pathname, Location::prefix(location), "/"};
  41. if(!directory::create(location)) return "output directory not writable";
  42. if(settings.createManifests) {
  43. file::write({location, "manifest.bml"}, manifest);
  44. }
  45. auto buffer = array_view<uint8_t>{data};
  46. for(auto memory : document.find("game/board/memory")) {
  47. auto type = memory["type"].text();
  48. auto size = memory["size"].natural();
  49. auto content = memory["content"].text();
  50. auto architecture = memory["architecture"].text();
  51. auto identifier = memory["identifier"].text();
  52. bool write = false;
  53. if(type == "ROM") write = true;
  54. if(type == "Flash" && content != "Save") write = true;
  55. if(!write) continue;
  56. string filename{content, ".", type};
  57. if(architecture) filename.prepend(architecture, ".");
  58. filename.downcase();
  59. if(size > buffer.size()) return {"missing ", filename};
  60. file::write({location, filename}, {buffer, size});
  61. buffer += size;
  62. }
  63. return {};
  64. }
  65. auto Cartridge::manifest(string location) -> string {
  66. vector<uint8_t> data;
  67. if(directory::exists(location)) {
  68. data = export(location);
  69. } else if(file::exists(location)) {
  70. data = file::read(location);
  71. }
  72. return manifest(data, location);
  73. }
  74. auto Cartridge::manifest(vector<uint8_t>& data, string location) -> string {
  75. string digest = Hash::SHA256(data).digest();
  76. for(auto game : database.find("game")) {
  77. if(game["sha256"].text() == digest) return BML::serialize(game);
  78. }
  79. return heuristics(data, location);
  80. }