mega-drive.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. struct MegaDrive : Cartridge {
  2. auto name() -> string override { return "Mega Drive"; }
  3. auto extensions() -> vector<string> override { return {"md", "smd", "gen", "bin"}; }
  4. auto export(string location) -> vector<uint8_t> override;
  5. auto heuristics(vector<uint8_t>& data, string location) -> string override;
  6. };
  7. auto MegaDrive::export(string location) -> vector<uint8_t> {
  8. vector<uint8_t> data;
  9. append(data, {location, "program.rom"});
  10. return data;
  11. }
  12. auto MegaDrive::heuristics(vector<uint8_t>& data, string location) -> string {
  13. if(data.size() < 0x200) return {};
  14. string ramMode = "none";
  15. uint32_t ramFrom = 0;
  16. ramFrom |= data[0x01b4] << 24;
  17. ramFrom |= data[0x01b5] << 16;
  18. ramFrom |= data[0x01b6] << 8;
  19. ramFrom |= data[0x01b7] << 0;
  20. uint32_t ramTo = 0;
  21. ramTo |= data[0x01b8] << 24;
  22. ramTo |= data[0x01b9] << 16;
  23. ramTo |= data[0x01ba] << 8;
  24. ramTo |= data[0x01bb] << 0;
  25. if(!(ramFrom & 1) && !(ramTo & 1)) ramMode = "hi";
  26. if( (ramFrom & 1) && (ramTo & 1)) ramMode = "lo";
  27. if(!(ramFrom & 1) && (ramTo & 1)) ramMode = "word";
  28. if(data[0x01b0] != 'R' || data[0x01b1] != 'A') ramMode = "none";
  29. uint32_t ramSize = ramTo - ramFrom + 1;
  30. if(ramMode == "hi") ramSize = (ramTo >> 1) - (ramFrom >> 1) + 1;
  31. if(ramMode == "lo") ramSize = (ramTo >> 1) - (ramFrom >> 1) + 1;
  32. if(ramMode == "word") ramSize = ramTo - ramFrom + 1;
  33. if(ramMode != "none") ramSize = bit::round(min(0x20000, ramSize));
  34. if(ramMode == "none") ramSize = 0;
  35. vector<string> regions;
  36. string region = slice((const char*)&data[0x1f0], 0, 16).trimRight(" ");
  37. if(!regions) {
  38. if(region == "JAPAN" ) regions.append("NTSC-J");
  39. if(region == "EUROPE") regions.append("PAL");
  40. }
  41. if(!regions) {
  42. if(region.find("J")) regions.append("NTSC-J");
  43. if(region.find("U")) regions.append("NTSC-U");
  44. if(region.find("E")) regions.append("PAL");
  45. if(region.find("W")) regions.append("NTSC-J", "NTSC-U", "PAL");
  46. }
  47. if(!regions && region.size() == 1) {
  48. uint8_t field = region.hex();
  49. if(field & 0x01) regions.append("NTSC-J");
  50. if(field & 0x04) regions.append("NTSC-U");
  51. if(field & 0x08) regions.append("PAL");
  52. }
  53. if(!regions) {
  54. regions.append("NTSC-J");
  55. }
  56. string domesticName;
  57. domesticName.resize(48);
  58. memory::copy(domesticName.get(), &data[0x0120], domesticName.size());
  59. for(auto& c : domesticName) if(c < 0x20 || c > 0x7e) c = ' ';
  60. while(domesticName.find(" ")) domesticName.replace(" ", " ");
  61. domesticName.strip();
  62. string internationalName;
  63. internationalName.resize(48);
  64. memory::copy(internationalName.get(), &data[0x0150], internationalName.size());
  65. for(auto& c : internationalName) if(c < 0x20 || c > 0x7e) c = ' ';
  66. while(internationalName.find(" ")) internationalName.replace(" ", " ");
  67. internationalName.strip();
  68. string s;
  69. s += "game\n";
  70. s +={" name: ", Media::name(location), "\n"};
  71. s +={" label: ", Media::name(location), "\n"};
  72. s +={" title: ", domesticName, "\n"};
  73. s +={" region: ", regions.merge(", "), "\n"};
  74. s += " board\n";
  75. if(domesticName == "Game Genie") {
  76. s += " memory\n";
  77. s += " type: ROM\n";
  78. s +={" size: 0x", hex(data.size()), "\n"};
  79. s += " content: Program\n";
  80. s += " slot\n";
  81. s += " type: Mega Drive\n";
  82. } else if(domesticName == "SONIC & KNUCKLES") {
  83. s += " memory\n";
  84. s += " type: ROM\n";
  85. s += " size: 0x200000\n";
  86. s += " content: Program\n";
  87. s += " memory\n";
  88. s += " type: ROM\n";
  89. s += " size: 0x40000\n";
  90. s += " content: Patch\n";
  91. s += " slot\n";
  92. s += " type: Mega Drive\n";
  93. } else {
  94. s += " memory\n";
  95. s += " type: ROM\n";
  96. s +={" size: 0x", hex(data.size()), "\n"};
  97. s += " content: Program\n";
  98. }
  99. if(ramSize && ramMode != "none") {
  100. s += " memory\n";
  101. s += " type: RAM\n";
  102. s +={" size: 0x", hex(ramSize), "\n"};
  103. s += " content: Save\n";
  104. s +={" mode: ", ramMode, "\n"};
  105. s +={" offset: 0x", hex(ramFrom), "\n"};
  106. }
  107. s += " bootable\n";
  108. return s;
  109. }