fuck this shit
This commit is contained in:
+15
-13
@@ -22,26 +22,28 @@ void Core::Reset() {
|
||||
|
||||
void Core::LoadTAS(const fs::path &path) const { mem->mmio.si.pif.movie.Load(path); }
|
||||
|
||||
void Core::LoadROM(const std::string &rom_) {
|
||||
void Core::LoadROM(const std::string &romFilename) {
|
||||
Stop();
|
||||
rom = rom_;
|
||||
romPath = romFilename;
|
||||
|
||||
std::string archive_types[] = {".zip", ".7z", ".rar", ".tar"};
|
||||
|
||||
auto extension = fs::path(rom).extension().string();
|
||||
auto extension = fs::path(romPath).extension().string();
|
||||
const bool isArchive = std::ranges::any_of(archive_types, [&extension](const auto &e) { return e == extension; });
|
||||
|
||||
mem->LoadROM(isArchive, rom);
|
||||
GameDB::match();
|
||||
if (mem->rom.gameNameDB.empty()) {
|
||||
mem->rom.gameNameDB = fs::path(rom).stem().string();
|
||||
auto rom = Mem::LoadROM(isArchive, romPath);
|
||||
GameDB::match(rom);
|
||||
mem->rom = rom;
|
||||
if (rom.gameNameDB.empty()) {
|
||||
rom.gameNameDB = fs::path(romPath).stem().string();
|
||||
mem->rom.gameNameDB = rom.gameNameDB;
|
||||
}
|
||||
mem->mmio.vi.isPal = mem->IsROMPAL();
|
||||
mem->mmio.si.pif.InitDevices(mem->saveType);
|
||||
mem->mmio.si.pif.mempakPath = rom;
|
||||
mem->mmio.si.pif.LoadEeprom(mem->saveType, rom);
|
||||
mem->flash.Load(mem->saveType, rom);
|
||||
mem->LoadSRAM(mem->saveType, rom);
|
||||
mem->mmio.vi.isPal = Mem::IsROMPAL(rom);
|
||||
mem->mmio.si.pif.InitDevices(mem->rom.saveType);
|
||||
mem->mmio.si.pif.mempakPath = romPath;
|
||||
mem->mmio.si.pif.LoadEeprom(mem->rom.saveType, romPath);
|
||||
mem->flash.Load(mem->rom.saveType, romPath);
|
||||
mem->LoadSRAM(mem->rom.saveType, romPath);
|
||||
mem->mmio.si.pif.Execute();
|
||||
pause = false;
|
||||
romLoaded = true;
|
||||
|
||||
@@ -47,7 +47,7 @@ struct Core {
|
||||
int slot = 0;
|
||||
size_t memSize{}, cpuSize{}, verSize{};
|
||||
CPUType cpuType;
|
||||
std::string rom;
|
||||
std::string romPath;
|
||||
std::set<s64> breakpoints{};
|
||||
std::unique_ptr<Mem> mem = std::make_unique<Mem>();
|
||||
Registers regs;
|
||||
|
||||
+79
-29
@@ -2,38 +2,88 @@
|
||||
#include <Core.hpp>
|
||||
|
||||
namespace n64 {
|
||||
void GameDB::match() {
|
||||
n64::Mem& mem = n64::Core::GetMem();
|
||||
const ROM &rom = mem.rom;
|
||||
for (const auto &[code, regions, saveType, name] : gamedb) {
|
||||
const bool matches_code = code == rom.code;
|
||||
bool matches_region = false;
|
||||
const char *regionCodeToReadable(char r) {
|
||||
switch (r) {
|
||||
case 0:
|
||||
return "Region-free";
|
||||
case 'A':
|
||||
return "All regions";
|
||||
case 'B':
|
||||
return "Brazil";
|
||||
case 'C':
|
||||
return "China";
|
||||
case 'D':
|
||||
return "Germany";
|
||||
case 'E':
|
||||
return "North America";
|
||||
case 'F':
|
||||
return "France";
|
||||
case 'G':
|
||||
return "Gateway 64 (NTSC)";
|
||||
case 'H':
|
||||
return "Netherlands";
|
||||
case 'I':
|
||||
return "Italy";
|
||||
case 'J':
|
||||
return "Japan";
|
||||
case 'K':
|
||||
return "Korea";
|
||||
case 'L':
|
||||
return "Gateway 64 (PAL)";
|
||||
case 'N':
|
||||
return "Canada";
|
||||
case 'S':
|
||||
return "Spain";
|
||||
case 'U':
|
||||
return "Australia";
|
||||
case 'W':
|
||||
return "Scandinavia";
|
||||
case 'P':
|
||||
case 'X':
|
||||
case 'Y':
|
||||
case 'Z':
|
||||
return "Europe";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < regions.size() && !matches_region; j++) {
|
||||
if (regions[j] == rom.header.countryCode[0]) {
|
||||
matches_region = true;
|
||||
}
|
||||
std::string GameDB::match(ROM &rom) {
|
||||
std::string result = "";
|
||||
|
||||
for (const auto &[code, regions, saveType, name] : gamedb) {
|
||||
bool matches_region = false;
|
||||
|
||||
if (code == rom.code) {
|
||||
for (int j = 0; j < regions.size(); j++) {
|
||||
if (j == regions.size() - 1)
|
||||
result += regionCodeToReadable(regions[j]);
|
||||
else
|
||||
result += std::string(regionCodeToReadable(regions[j])) + ", ";
|
||||
|
||||
if (regions[j] == rom.header.countryCode[0])
|
||||
matches_region = true;
|
||||
}
|
||||
|
||||
if (matches_region) {
|
||||
rom.saveType = saveType;
|
||||
rom.gameNameDB = name;
|
||||
return result;
|
||||
}
|
||||
|
||||
info("Matched code for {}, but not region! Game supposedly exists in regions [{}] but this image has "
|
||||
"region {}",
|
||||
name, regions, rom.header.countryCode[0]);
|
||||
rom.saveType = saveType;
|
||||
rom.gameNameDB = name;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (matches_code) {
|
||||
if (matches_region) {
|
||||
mem.saveType = saveType;
|
||||
mem.rom.gameNameDB = name;
|
||||
return;
|
||||
}
|
||||
info("Did not match any Game DB entries. Code: {} Region: {}", rom.code, rom.header.countryCode[0]);
|
||||
|
||||
warn(
|
||||
"Matched code for {}, but not region! Game supposedly exists in regions [{}] but this image has region {}",
|
||||
name, regions, rom.header.countryCode[0]);
|
||||
mem.saveType = saveType;
|
||||
mem.rom.gameNameDB = name;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
warn("Did not match any Game DB entries. Code: {} Region: {}", mem.rom.code, mem.rom.header.countryCode[0]);
|
||||
|
||||
mem.rom.gameNameDB = "";
|
||||
mem.saveType = SAVE_NONE;
|
||||
rom.gameNameDB = "";
|
||||
rom.saveType = SAVE_NONE;
|
||||
return "Unknown";
|
||||
}
|
||||
} // namespace n64
|
||||
|
||||
+190
-189
@@ -3,201 +3,202 @@
|
||||
|
||||
namespace n64 {
|
||||
enum SaveType { SAVE_NONE, SAVE_EEPROM_4k, SAVE_EEPROM_16k, SAVE_FLASH_1m, SAVE_SRAM_256k };
|
||||
struct ROM;
|
||||
|
||||
struct GameDBEntry {
|
||||
std::string code;
|
||||
std::string regions;
|
||||
SaveType saveType;
|
||||
const char *name;
|
||||
std::string code;
|
||||
std::string regions;
|
||||
SaveType saveType;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
namespace GameDB {
|
||||
void match();
|
||||
std::string match(ROM &);
|
||||
}
|
||||
|
||||
static const GameDBEntry gamedb[] = {
|
||||
{"NNM", "E", SAVE_NONE, "Namco Museum 64"},
|
||||
{"NDM", "E", SAVE_NONE, "Doom 64"},
|
||||
{"NGN", "E", SAVE_EEPROM_4k, "GoldenEye 007"},
|
||||
// Copied from CEN64 with small edits: https://github.com/n64dev/cen64/blob/master/device/cart_db.c
|
||||
{"CFZ", "EJ", SAVE_SRAM_256k, "F-Zero X (NTSC)"},
|
||||
{"CLB", "EJ", SAVE_EEPROM_4k, "Mario Party (NTSC)"},
|
||||
{"CP2", "J", SAVE_FLASH_1m, "Pokémon Stadium 2 (Japan)"},
|
||||
{"CPS", "J", SAVE_SRAM_256k, "Pokémon Stadium (Japan)"},
|
||||
{"CZL", "EJ", SAVE_SRAM_256k, "Legend of Zelda: Ocarina of Time (NTSC)"},
|
||||
{"N3D", "J", SAVE_EEPROM_16k, "Doraemon 3: Nobita no Machi SOS!"},
|
||||
{"N3H", "J", SAVE_SRAM_256k, "Ganbare! Nippon! Olympics 2000"},
|
||||
{"NA2", "J", SAVE_SRAM_256k, "Virtual Pro Wrestling 2"},
|
||||
{"NAB", "JP", SAVE_EEPROM_4k, "Air Boarder 64"},
|
||||
{"NAD", "E", SAVE_EEPROM_4k, "Worms Armageddon (USA)"},
|
||||
{"NAF", "J", SAVE_FLASH_1m, "Doubutsu no Mori"},
|
||||
{"NAG", "EJP", SAVE_EEPROM_4k, "AeroGauge"},
|
||||
{"NAL", "EJPU", SAVE_SRAM_256k, "Super Smash Bros"},
|
||||
{"NB5", "J", SAVE_SRAM_256k, "Biohazard 2"},
|
||||
{"NB6", "J", SAVE_EEPROM_4k, "Super B-Daman: Battle Phoenix 64"},
|
||||
{"NB7", "EJPU", SAVE_EEPROM_16k, "Banjo-Tooie"},
|
||||
{"NBC", "EJP", SAVE_EEPROM_4k, "Blast Corps"},
|
||||
{"NBD", "EJP", SAVE_EEPROM_4k, "Bomberman Hero"},
|
||||
{"NBH", "EP", SAVE_EEPROM_4k, "Body Harvest"},
|
||||
{"NBK", "EJP", SAVE_EEPROM_4k, "Banjo-Kazooie"},
|
||||
{"NBM", "EJP", SAVE_EEPROM_4k, "Bomberman 64"},
|
||||
{"NBN", "J", SAVE_EEPROM_4k, "Bakuretsu Muteki Bangaioh"},
|
||||
{"NBV", "EJ", SAVE_EEPROM_4k, "Bomberman 64: The Second Attack!"},
|
||||
{"NCC", "DEP", SAVE_FLASH_1m, "Command & Conquer"},
|
||||
{"NCG", "J", SAVE_EEPROM_4k, "Choro Q 64 2: Hacha-Mecha Grand Prix Race"},
|
||||
{"NCH", "EP", SAVE_EEPROM_4k, "Chopper Attack"},
|
||||
{"NCK", "E", SAVE_FLASH_1m, "NBA Courtside 2"},
|
||||
{"NCR", "EJP", SAVE_EEPROM_4k, "Penny Racers"},
|
||||
{"NCT", "EJP", SAVE_EEPROM_4k, "Chameleon Twist"},
|
||||
{"NCU", "EP", SAVE_EEPROM_4k, "Cruis'n USA"},
|
||||
{"NCW", "EP", SAVE_EEPROM_16k, "Cruis'n World"},
|
||||
{"NCX", "J", SAVE_EEPROM_4k, "Custom Robo"},
|
||||
{"NCZ", "J", SAVE_EEPROM_16k, "Custom Robo V2"},
|
||||
{"ND2", "J", SAVE_EEPROM_16k, "Doraemon 2: Nobita to Hikari no Shinden"},
|
||||
{"ND3", "J", SAVE_EEPROM_16k, "Akumajou Dracula Mokushiroku"},
|
||||
{"ND4", "J", SAVE_EEPROM_16k, "Akumajou Dracula Mokushiroku Gaiden: Legend of Cornell"},
|
||||
{"ND6", "J", SAVE_EEPROM_16k, "Densha de Go! 64"},
|
||||
{"NDA", "J", SAVE_FLASH_1m, "Derby Stallion 64"},
|
||||
{"NDK", "J", SAVE_EEPROM_4k, "Space Dynamites"},
|
||||
{"NDO", "EJP", SAVE_EEPROM_16k, "Donkey Kong 64"},
|
||||
{"NDP", "E", SAVE_FLASH_1m, "Dinosaur Planet"},
|
||||
{"NDR", "J", SAVE_EEPROM_4k, "Doraemon: Nobita to 3tsu no Seireiseki"},
|
||||
{"NDU", "EP", SAVE_EEPROM_4k, "Duck Dodgers"},
|
||||
{"NDY", "EJP", SAVE_EEPROM_4k, "Diddy Kong Racing"},
|
||||
{"NEA", "EP", SAVE_EEPROM_4k, "PGA European Tour"},
|
||||
{"NEP", "EJP", SAVE_EEPROM_16k, "Star Wars Episode I: Racer"},
|
||||
{"NER", "E", SAVE_EEPROM_4k, "AeroFighters Assault (USA)"},
|
||||
{"NEV", "J", SAVE_EEPROM_16k, "Neon Genesis Evangelion"},
|
||||
{"NF2", "P", SAVE_EEPROM_4k, "F-1 World Grand Prix II"},
|
||||
{"NFG", "E", SAVE_EEPROM_4k, "Fighter Destiny 2"},
|
||||
{"NFH", "EP", SAVE_EEPROM_4k, "Bass Hunter 64"},
|
||||
{"NFU", "EP", SAVE_EEPROM_16k, "Conker's Bad Fur Day"},
|
||||
{"NFW", "DEFJP", SAVE_EEPROM_4k, "F-1 World Grand Prix"},
|
||||
{"NFX", "EJPU", SAVE_EEPROM_4k, "Star Fox 64"},
|
||||
{"NFY", "J", SAVE_EEPROM_4k, "Kakutou Denshou: F-Cup Maniax"},
|
||||
{"NFZ", "P", SAVE_SRAM_256k, "F-Zero X (PAL)"},
|
||||
{"NG6", "J", SAVE_SRAM_256k, "Ganbare Goemon: Dero Dero Douchuu Obake Tenkomori"},
|
||||
{"NGC", "EP", SAVE_EEPROM_16k, "GT 64: Championship Edition"},
|
||||
{"NGE", "EJP", SAVE_EEPROM_4k, "GoldenEye 007"},
|
||||
{"NGL", "J", SAVE_EEPROM_4k, "Getter Love!!"},
|
||||
{"NGP", "J", SAVE_SRAM_256k, "Goemon: Mononoke Sugoroku"},
|
||||
{"NGT", "J", SAVE_EEPROM_16k, "City-Tour GP: Zen-Nihon GT Senshuken"},
|
||||
{"NGU", "J", SAVE_EEPROM_4k, "Tsumi to Batsu: Hoshi no Keishousha"},
|
||||
{"NGV", "EP", SAVE_EEPROM_4k, "Glover"},
|
||||
{"NHA", "J", SAVE_EEPROM_4k, "Bomber Man 64 (Japan)"},
|
||||
{"NHF", "J", SAVE_EEPROM_4k, "64 Hanafuda: Tenshi no Yakusoku"},
|
||||
{"NHP", "J", SAVE_EEPROM_4k, "Heiwa Pachinko World 64"},
|
||||
{"NHY", "J", SAVE_SRAM_256k, "Hybrid Heaven (Japan)"},
|
||||
{"NIB", "J", SAVE_SRAM_256k, "Itoi Shigesato no Bass Tsuri No. 1 Kettei Ban!"},
|
||||
{"NIC", "E", SAVE_EEPROM_4k, "Indy Racing 2000"},
|
||||
{"NIJ", "EP", SAVE_EEPROM_4k, "Indiana Jones and the Infernal Machine"},
|
||||
{"NIM", "J", SAVE_EEPROM_16k, "Ide Yosuke no Mahjong Juku"},
|
||||
{"NIR", "J", SAVE_EEPROM_4k, "Utchan Nanchan no Hono no Challenger: Denryuu Ira Ira Bou"},
|
||||
{"NJ5", "J", SAVE_SRAM_256k, "Jikkyou Powerful Pro Yakyuu 5"},
|
||||
{"NJD", "E", SAVE_FLASH_1m, "Jet Force Gemini (Kiosk Demo)"},
|
||||
{"NJF", "EJP", SAVE_FLASH_1m, "Jet Force Gemini"},
|
||||
{"NJG", "J", SAVE_SRAM_256k, "Jinsei Game 64"},
|
||||
{"NJM", "EP", SAVE_EEPROM_4k, "Earthworm Jim 3D"},
|
||||
{"NK2", "EJP", SAVE_EEPROM_4k, "Snowboard Kids 2"},
|
||||
{"NK4", "EJP", SAVE_EEPROM_16k, "Kirby 64: The Crystal Shards"},
|
||||
{"NKA", "DEFJP", SAVE_EEPROM_4k, "Fighters Destiny"},
|
||||
{"NKG", "EP", SAVE_SRAM_256k, "MLB featuring Ken Griffey Jr."},
|
||||
{"NKI", "EP", SAVE_EEPROM_4k, "Killer Instinct Gold"},
|
||||
{"NKJ", "E", SAVE_FLASH_1m, "Ken Griffey Jr.'s Slugfest"},
|
||||
{"NKT", "EJP", SAVE_EEPROM_4k, "Mario Kart 64"},
|
||||
{"NLB", "P", SAVE_EEPROM_4k, "Mario Party (PAL)"},
|
||||
{"NLL", "J", SAVE_EEPROM_4k, "Last Legion UX"},
|
||||
{"NLR", "EJP", SAVE_EEPROM_4k, "Lode Runner 3D"},
|
||||
{"NM6", "E", SAVE_FLASH_1m, "Mega Man 64"},
|
||||
{"NM8", "EJP", SAVE_EEPROM_16k, "Mario Tennis"},
|
||||
{"NMF", "EJP", SAVE_SRAM_256k, "Mario Golf"},
|
||||
{"NMG", "DEP", SAVE_EEPROM_4k, "Monaco Grand Prix"},
|
||||
{"NMI", "DEFIPS", SAVE_EEPROM_4k, "Mission: Impossible"},
|
||||
{"NML", "EJP", SAVE_EEPROM_4k, "Mickey's Speedway USA"},
|
||||
{"NMO", "E", SAVE_EEPROM_4k, "Monopoly"},
|
||||
{"NMQ", "EJP", SAVE_FLASH_1m, "Paper Mario"},
|
||||
{"NMR", "EJP", SAVE_EEPROM_4k, "Multi Racing Championship"},
|
||||
{"NMS", "J", SAVE_EEPROM_4k, "Morita Shougi 64"},
|
||||
{"NMU", "E", SAVE_EEPROM_4k, "Big Mountain 2000"},
|
||||
{"NMV", "EJP", SAVE_EEPROM_16k, "Mario Party 3"},
|
||||
{"NMW", "EJP", SAVE_EEPROM_4k, "Mario Party 2"},
|
||||
{"NMX", "EJP", SAVE_EEPROM_16k, "Excitebike 64"},
|
||||
{"NN6", "E", SAVE_EEPROM_4k, "Dr. Mario 64"},
|
||||
{"NNA", "EP", SAVE_EEPROM_4k, "Star Wars Episode I: Battle for Naboo"},
|
||||
{"NNB", "EP", SAVE_EEPROM_16k, "Kobe Bryant in NBA Courtside"},
|
||||
{"NOB", "EJ", SAVE_SRAM_256k, "Ogre Battle 64: Person of Lordly Caliber"},
|
||||
{"NOS", "J", SAVE_EEPROM_4k, "64 Oozumou"},
|
||||
{"NP2", "J", SAVE_EEPROM_4k, "Chou Kuukan Nighter Pro Yakyuu King 2"},
|
||||
{"NP3", "DEFIJPS", SAVE_FLASH_1m, "Pokémon Stadium 2"},
|
||||
{"NP6", "J", SAVE_SRAM_256k, "Jikkyou Powerful Pro Yakyuu 6"},
|
||||
{"NPA", "J", SAVE_SRAM_256k, "Jikkyou Powerful Pro Yakyuu 2000"},
|
||||
{"NPD", "EJP", SAVE_EEPROM_16k, "Perfect Dark"},
|
||||
{"NPE", "J", SAVE_SRAM_256k, "Jikkyou Powerful Pro Yakyuu Basic Ban 2001"},
|
||||
{"NPF", "DEFIJPSU", SAVE_FLASH_1m, "Pokémon Snap"},
|
||||
{"NPG", "EJ", SAVE_EEPROM_4k, "Hey You, Pikachu!"},
|
||||
{"NPH", "E", SAVE_FLASH_1m, "Pokémon Snap Station (Kiosk Demo)"},
|
||||
{"NPM", "P", SAVE_SRAM_256k, "Premier Manager 64"},
|
||||
{"NPN", "DEFP", SAVE_FLASH_1m, "Pokémon Puzzle League"},
|
||||
{"NPO", "DEFIPS", SAVE_FLASH_1m, "Pokémon Stadium (USA, PAL)"},
|
||||
{"NPP", "J", SAVE_EEPROM_16k, "Parlor! Pro 64: Pachinko Jikki Simulation Game"},
|
||||
{"NPS", "J", SAVE_SRAM_256k, "Jikkyou J.League 1999: Perfect Striker 2"},
|
||||
{"NPT", "J", SAVE_EEPROM_4k, "Puyo Puyon Party"},
|
||||
{"NPW", "EJP", SAVE_EEPROM_4k, "Pilotwings 64"},
|
||||
{"NPY", "J", SAVE_EEPROM_4k, "Puyo Puyo Sun 64"},
|
||||
{"NR7", "J", SAVE_EEPROM_16k, "Robot Poncots 64: 7tsu no Umi no Caramel"},
|
||||
{"NRA", "J", SAVE_EEPROM_4k, "Rally '99"},
|
||||
{"NRC", "EJP", SAVE_EEPROM_4k, "Top Gear Overdrive"},
|
||||
{"NRE", "EP", SAVE_SRAM_256k, "Resident Evil 2"},
|
||||
{"NRH", "J", SAVE_FLASH_1m, "Rockman Dash"},
|
||||
{"NRI", "EP", SAVE_SRAM_256k, "The New Tetris"},
|
||||
{"NRS", "EJP", SAVE_EEPROM_4k, "Star Wars: Rogue Squadron"},
|
||||
{"NRZ", "EP", SAVE_EEPROM_16k, "Ridge Racer 64"},
|
||||
{"NS4", "J", SAVE_SRAM_256k, "Super Robot Taisen 64"},
|
||||
{"NS6", "EJ", SAVE_EEPROM_4k, "Star Soldier: Vanishing Earth"},
|
||||
{"NSA", "JP", SAVE_EEPROM_4k, "AeroFighters Assault (PAL, Japan)"},
|
||||
{"NSC", "EP", SAVE_EEPROM_4k, "Starshot: Space Circus Fever"},
|
||||
{"NSI", "J", SAVE_SRAM_256k, "Fushigi no Dungeon: Fuurai no Shiren 2"},
|
||||
{"NSM", "EJP", SAVE_EEPROM_4k, "Super Mario 64"},
|
||||
{"NSN", "J", SAVE_EEPROM_4k, "Snow Speeder"},
|
||||
{"NSQ", "EP", SAVE_FLASH_1m, "StarCraft 64"},
|
||||
{"NSS", "J", SAVE_EEPROM_4k, "Super Robot Spirits"},
|
||||
{"NSU", "EP", SAVE_EEPROM_4k, "Rocket: Robot on Wheels"},
|
||||
{"NSV", "EP", SAVE_EEPROM_4k, "SpaceStation Silicon Valley"},
|
||||
{"NSW", "EJP", SAVE_EEPROM_4k, "Star Wars: Shadows of the Empire"},
|
||||
{"NT3", "J", SAVE_SRAM_256k, "Toukon Road 2"},
|
||||
{"NT6", "J", SAVE_EEPROM_4k, "Tetris 64"},
|
||||
{"NT9", "EP", SAVE_FLASH_1m, "Tigger's Honey Hunt"},
|
||||
{"NTB", "J", SAVE_EEPROM_4k, "Transformers: Beast Wars Metals 64"},
|
||||
{"NTC", "J", SAVE_EEPROM_4k, "64 Trump Collection"},
|
||||
{"NTE", "AP", SAVE_SRAM_256k, "1080 Snowboarding"},
|
||||
{"NTJ", "EP", SAVE_EEPROM_4k, "Tom and Jerry in Fists of Furry"},
|
||||
{"NTM", "EJP", SAVE_EEPROM_4k, "Mischief Makers"},
|
||||
{"NTN", "EP", SAVE_EEPROM_4k, "All-Star Tennis 99"},
|
||||
{"NTP", "EP", SAVE_EEPROM_4k, "Tetrisphere"},
|
||||
{"NTR", "JP", SAVE_EEPROM_4k, "Top Gear Rally (PAL, Japan)"},
|
||||
{"NTW", "J", SAVE_EEPROM_4k, "64 de Hakken!! Tamagotchi"},
|
||||
{"NTX", "EP", SAVE_EEPROM_4k, "Taz Express"},
|
||||
{"NUB", "J", SAVE_EEPROM_16k, "PD Ultraman Battle Collection 64"},
|
||||
{"NUM", "J", SAVE_SRAM_256k, "Nushi Zuri 64: Shiokaze ni Notte"},
|
||||
{"NUT", "J", SAVE_SRAM_256k, "Nushi Zuri 64"},
|
||||
{"NVB", "J", SAVE_SRAM_256k, "Bass Rush: ECOGEAR PowerWorm Championship"},
|
||||
{"NVL", "EP", SAVE_EEPROM_4k, "V-Rally 99 (USA, PAL)"},
|
||||
{"NVP", "J", SAVE_SRAM_256k, "Virtual Pro Wrestling 64"},
|
||||
{"NVY", "J", SAVE_EEPROM_4k, "V-Rally 99 (Japan)"},
|
||||
{"NW2", "EP", SAVE_SRAM_256k, "WCW/nWo Revenge"},
|
||||
{"NW4", "EP", SAVE_FLASH_1m, "WWF No Mercy"},
|
||||
{"NWC", "J", SAVE_EEPROM_4k, "Wild Choppers"},
|
||||
{"NWL", "EP", SAVE_SRAM_256k, "Waialae Country Club: True Golf Classics"},
|
||||
{"NWQ", "E", SAVE_EEPROM_4k, "Rally Challenge 2000"},
|
||||
{"NWR", "EJP", SAVE_EEPROM_4k, "Wave Race 64"},
|
||||
{"NWT", "J", SAVE_EEPROM_4k, "Wetrix (Japan)"},
|
||||
{"NWU", "P", SAVE_EEPROM_4k, "Worms Armageddon (PAL)"},
|
||||
{"NWX", "EJP", SAVE_SRAM_256k, "WWF WrestleMania 2000"},
|
||||
{"NXO", "E", SAVE_EEPROM_4k, "Cruis'n Exotica"},
|
||||
{"NYK", "J", SAVE_EEPROM_4k, "Yakouchuu II: Satsujin Kouro"},
|
||||
{"NYS", "EJP", SAVE_EEPROM_16k, "Yoshi's Story"},
|
||||
{"NYW", "EJ", SAVE_SRAM_256k, "Harvest Moon 64"},
|
||||
{"NZL", "P", SAVE_SRAM_256k, "Legend of Zelda: Ocarina of Time (PAL)"},
|
||||
{"NZS", "EJP", SAVE_FLASH_1m, "Legend of Zelda: Majora's Mask"},
|
||||
{"NNM", "E", SAVE_NONE, "Namco Museum 64"},
|
||||
{"NDM", "E", SAVE_NONE, "Doom 64"},
|
||||
{"NGN", "E", SAVE_EEPROM_4k, "GoldenEye 007"},
|
||||
// Copied from CEN64 with small edits: https://github.com/n64dev/cen64/blob/master/device/cart_db.c
|
||||
{"CFZ", "EJ", SAVE_SRAM_256k, "F-Zero X (NTSC)"},
|
||||
{"CLB", "EJ", SAVE_EEPROM_4k, "Mario Party (NTSC)"},
|
||||
{"CP2", "J", SAVE_FLASH_1m, "Pokémon Stadium 2 (Japan)"},
|
||||
{"CPS", "J", SAVE_SRAM_256k, "Pokémon Stadium (Japan)"},
|
||||
{"CZL", "EJ", SAVE_SRAM_256k, "Legend of Zelda: Ocarina of Time (NTSC)"},
|
||||
{"N3D", "J", SAVE_EEPROM_16k, "Doraemon 3: Nobita no Machi SOS!"},
|
||||
{"N3H", "J", SAVE_SRAM_256k, "Ganbare! Nippon! Olympics 2000"},
|
||||
{"NA2", "J", SAVE_SRAM_256k, "Virtual Pro Wrestling 2"},
|
||||
{"NAB", "JP", SAVE_EEPROM_4k, "Air Boarder 64"},
|
||||
{"NAD", "E", SAVE_EEPROM_4k, "Worms Armageddon (USA)"},
|
||||
{"NAF", "J", SAVE_FLASH_1m, "Doubutsu no Mori"},
|
||||
{"NAG", "EJP", SAVE_EEPROM_4k, "AeroGauge"},
|
||||
{"NAL", "EJPU", SAVE_SRAM_256k, "Super Smash Bros"},
|
||||
{"NB5", "J", SAVE_SRAM_256k, "Biohazard 2"},
|
||||
{"NB6", "J", SAVE_EEPROM_4k, "Super B-Daman: Battle Phoenix 64"},
|
||||
{"NB7", "EJPU", SAVE_EEPROM_16k, "Banjo-Tooie"},
|
||||
{"NBC", "EJP", SAVE_EEPROM_4k, "Blast Corps"},
|
||||
{"NBD", "EJP", SAVE_EEPROM_4k, "Bomberman Hero"},
|
||||
{"NBH", "EP", SAVE_EEPROM_4k, "Body Harvest"},
|
||||
{"NBK", "EJP", SAVE_EEPROM_4k, "Banjo-Kazooie"},
|
||||
{"NBM", "EJP", SAVE_EEPROM_4k, "Bomberman 64"},
|
||||
{"NBN", "J", SAVE_EEPROM_4k, "Bakuretsu Muteki Bangaioh"},
|
||||
{"NBV", "EJ", SAVE_EEPROM_4k, "Bomberman 64: The Second Attack!"},
|
||||
{"NCC", "DEP", SAVE_FLASH_1m, "Command & Conquer"},
|
||||
{"NCG", "J", SAVE_EEPROM_4k, "Choro Q 64 2: Hacha-Mecha Grand Prix Race"},
|
||||
{"NCH", "EP", SAVE_EEPROM_4k, "Chopper Attack"},
|
||||
{"NCK", "E", SAVE_FLASH_1m, "NBA Courtside 2"},
|
||||
{"NCR", "EJP", SAVE_EEPROM_4k, "Penny Racers"},
|
||||
{"NCT", "EJP", SAVE_EEPROM_4k, "Chameleon Twist"},
|
||||
{"NCU", "EP", SAVE_EEPROM_4k, "Cruis'n USA"},
|
||||
{"NCW", "EP", SAVE_EEPROM_16k, "Cruis'n World"},
|
||||
{"NCX", "J", SAVE_EEPROM_4k, "Custom Robo"},
|
||||
{"NCZ", "J", SAVE_EEPROM_16k, "Custom Robo V2"},
|
||||
{"ND2", "J", SAVE_EEPROM_16k, "Doraemon 2: Nobita to Hikari no Shinden"},
|
||||
{"ND3", "J", SAVE_EEPROM_16k, "Akumajou Dracula Mokushiroku"},
|
||||
{"ND4", "J", SAVE_EEPROM_16k, "Akumajou Dracula Mokushiroku Gaiden: Legend of Cornell"},
|
||||
{"ND6", "J", SAVE_EEPROM_16k, "Densha de Go! 64"},
|
||||
{"NDA", "J", SAVE_FLASH_1m, "Derby Stallion 64"},
|
||||
{"NDK", "J", SAVE_EEPROM_4k, "Space Dynamites"},
|
||||
{"NDO", "EJP", SAVE_EEPROM_16k, "Donkey Kong 64"},
|
||||
{"NDP", "E", SAVE_FLASH_1m, "Dinosaur Planet"},
|
||||
{"NDR", "J", SAVE_EEPROM_4k, "Doraemon: Nobita to 3tsu no Seireiseki"},
|
||||
{"NDU", "EP", SAVE_EEPROM_4k, "Duck Dodgers"},
|
||||
{"NDY", "EJP", SAVE_EEPROM_4k, "Diddy Kong Racing"},
|
||||
{"NEA", "EP", SAVE_EEPROM_4k, "PGA European Tour"},
|
||||
{"NEP", "EJP", SAVE_EEPROM_16k, "Star Wars Episode I: Racer"},
|
||||
{"NER", "E", SAVE_EEPROM_4k, "AeroFighters Assault (USA)"},
|
||||
{"NEV", "J", SAVE_EEPROM_16k, "Neon Genesis Evangelion"},
|
||||
{"NF2", "P", SAVE_EEPROM_4k, "F-1 World Grand Prix II"},
|
||||
{"NFG", "E", SAVE_EEPROM_4k, "Fighter Destiny 2"},
|
||||
{"NFH", "EP", SAVE_EEPROM_4k, "Bass Hunter 64"},
|
||||
{"NFU", "EP", SAVE_EEPROM_16k, "Conker's Bad Fur Day"},
|
||||
{"NFW", "DEFJP", SAVE_EEPROM_4k, "F-1 World Grand Prix"},
|
||||
{"NFX", "EJPU", SAVE_EEPROM_4k, "Star Fox 64"},
|
||||
{"NFY", "J", SAVE_EEPROM_4k, "Kakutou Denshou: F-Cup Maniax"},
|
||||
{"NFZ", "P", SAVE_SRAM_256k, "F-Zero X (PAL)"},
|
||||
{"NG6", "J", SAVE_SRAM_256k, "Ganbare Goemon: Dero Dero Douchuu Obake Tenkomori"},
|
||||
{"NGC", "EP", SAVE_EEPROM_16k, "GT 64: Championship Edition"},
|
||||
{"NGE", "EJP", SAVE_EEPROM_4k, "GoldenEye 007"},
|
||||
{"NGL", "J", SAVE_EEPROM_4k, "Getter Love!!"},
|
||||
{"NGP", "J", SAVE_SRAM_256k, "Goemon: Mononoke Sugoroku"},
|
||||
{"NGT", "J", SAVE_EEPROM_16k, "City-Tour GP: Zen-Nihon GT Senshuken"},
|
||||
{"NGU", "J", SAVE_EEPROM_4k, "Tsumi to Batsu: Hoshi no Keishousha"},
|
||||
{"NGV", "EP", SAVE_EEPROM_4k, "Glover"},
|
||||
{"NHA", "J", SAVE_EEPROM_4k, "Bomber Man 64 (Japan)"},
|
||||
{"NHF", "J", SAVE_EEPROM_4k, "64 Hanafuda: Tenshi no Yakusoku"},
|
||||
{"NHP", "J", SAVE_EEPROM_4k, "Heiwa Pachinko World 64"},
|
||||
{"NHY", "J", SAVE_SRAM_256k, "Hybrid Heaven (Japan)"},
|
||||
{"NIB", "J", SAVE_SRAM_256k, "Itoi Shigesato no Bass Tsuri No. 1 Kettei Ban!"},
|
||||
{"NIC", "E", SAVE_EEPROM_4k, "Indy Racing 2000"},
|
||||
{"NIJ", "EP", SAVE_EEPROM_4k, "Indiana Jones and the Infernal Machine"},
|
||||
{"NIM", "J", SAVE_EEPROM_16k, "Ide Yosuke no Mahjong Juku"},
|
||||
{"NIR", "J", SAVE_EEPROM_4k, "Utchan Nanchan no Hono no Challenger: Denryuu Ira Ira Bou"},
|
||||
{"NJ5", "J", SAVE_SRAM_256k, "Jikkyou Powerful Pro Yakyuu 5"},
|
||||
{"NJD", "E", SAVE_FLASH_1m, "Jet Force Gemini (Kiosk Demo)"},
|
||||
{"NJF", "EJP", SAVE_FLASH_1m, "Jet Force Gemini"},
|
||||
{"NJG", "J", SAVE_SRAM_256k, "Jinsei Game 64"},
|
||||
{"NJM", "EP", SAVE_EEPROM_4k, "Earthworm Jim 3D"},
|
||||
{"NK2", "EJP", SAVE_EEPROM_4k, "Snowboard Kids 2"},
|
||||
{"NK4", "EJP", SAVE_EEPROM_16k, "Kirby 64: The Crystal Shards"},
|
||||
{"NKA", "DEFJP", SAVE_EEPROM_4k, "Fighters Destiny"},
|
||||
{"NKG", "EP", SAVE_SRAM_256k, "MLB featuring Ken Griffey Jr."},
|
||||
{"NKI", "EP", SAVE_EEPROM_4k, "Killer Instinct Gold"},
|
||||
{"NKJ", "E", SAVE_FLASH_1m, "Ken Griffey Jr.'s Slugfest"},
|
||||
{"NKT", "EJP", SAVE_EEPROM_4k, "Mario Kart 64"},
|
||||
{"NLB", "P", SAVE_EEPROM_4k, "Mario Party (PAL)"},
|
||||
{"NLL", "J", SAVE_EEPROM_4k, "Last Legion UX"},
|
||||
{"NLR", "EJP", SAVE_EEPROM_4k, "Lode Runner 3D"},
|
||||
{"NM6", "E", SAVE_FLASH_1m, "Mega Man 64"},
|
||||
{"NM8", "EJP", SAVE_EEPROM_16k, "Mario Tennis"},
|
||||
{"NMF", "EJP", SAVE_SRAM_256k, "Mario Golf"},
|
||||
{"NMG", "DEP", SAVE_EEPROM_4k, "Monaco Grand Prix"},
|
||||
{"NMI", "DEFIPS", SAVE_EEPROM_4k, "Mission: Impossible"},
|
||||
{"NML", "EJP", SAVE_EEPROM_4k, "Mickey's Speedway USA"},
|
||||
{"NMO", "E", SAVE_EEPROM_4k, "Monopoly"},
|
||||
{"NMQ", "EJP", SAVE_FLASH_1m, "Paper Mario"},
|
||||
{"NMR", "EJP", SAVE_EEPROM_4k, "Multi Racing Championship"},
|
||||
{"NMS", "J", SAVE_EEPROM_4k, "Morita Shougi 64"},
|
||||
{"NMU", "E", SAVE_EEPROM_4k, "Big Mountain 2000"},
|
||||
{"NMV", "EJP", SAVE_EEPROM_16k, "Mario Party 3"},
|
||||
{"NMW", "EJP", SAVE_EEPROM_4k, "Mario Party 2"},
|
||||
{"NMX", "EJP", SAVE_EEPROM_16k, "Excitebike 64"},
|
||||
{"NN6", "E", SAVE_EEPROM_4k, "Dr. Mario 64"},
|
||||
{"NNA", "EP", SAVE_EEPROM_4k, "Star Wars Episode I: Battle for Naboo"},
|
||||
{"NNB", "EP", SAVE_EEPROM_16k, "Kobe Bryant in NBA Courtside"},
|
||||
{"NOB", "EJ", SAVE_SRAM_256k, "Ogre Battle 64: Person of Lordly Caliber"},
|
||||
{"NOS", "J", SAVE_EEPROM_4k, "64 Oozumou"},
|
||||
{"NP2", "J", SAVE_EEPROM_4k, "Chou Kuukan Nighter Pro Yakyuu King 2"},
|
||||
{"NP3", "DEFIJPS", SAVE_FLASH_1m, "Pokémon Stadium 2"},
|
||||
{"NP6", "J", SAVE_SRAM_256k, "Jikkyou Powerful Pro Yakyuu 6"},
|
||||
{"NPA", "J", SAVE_SRAM_256k, "Jikkyou Powerful Pro Yakyuu 2000"},
|
||||
{"NPD", "EJP", SAVE_EEPROM_16k, "Perfect Dark"},
|
||||
{"NPE", "J", SAVE_SRAM_256k, "Jikkyou Powerful Pro Yakyuu Basic Ban 2001"},
|
||||
{"NPF", "DEFIJPSU", SAVE_FLASH_1m, "Pokémon Snap"},
|
||||
{"NPG", "EJ", SAVE_EEPROM_4k, "Hey You, Pikachu!"},
|
||||
{"NPH", "E", SAVE_FLASH_1m, "Pokémon Snap Station (Kiosk Demo)"},
|
||||
{"NPM", "P", SAVE_SRAM_256k, "Premier Manager 64"},
|
||||
{"NPN", "DEFP", SAVE_FLASH_1m, "Pokémon Puzzle League"},
|
||||
{"NPO", "DEFIPS", SAVE_FLASH_1m, "Pokémon Stadium (USA, PAL)"},
|
||||
{"NPP", "J", SAVE_EEPROM_16k, "Parlor! Pro 64: Pachinko Jikki Simulation Game"},
|
||||
{"NPS", "J", SAVE_SRAM_256k, "Jikkyou J.League 1999: Perfect Striker 2"},
|
||||
{"NPT", "J", SAVE_EEPROM_4k, "Puyo Puyon Party"},
|
||||
{"NPW", "EJP", SAVE_EEPROM_4k, "Pilotwings 64"},
|
||||
{"NPY", "J", SAVE_EEPROM_4k, "Puyo Puyo Sun 64"},
|
||||
{"NR7", "J", SAVE_EEPROM_16k, "Robot Poncots 64: 7tsu no Umi no Caramel"},
|
||||
{"NRA", "J", SAVE_EEPROM_4k, "Rally '99"},
|
||||
{"NRC", "EJP", SAVE_EEPROM_4k, "Top Gear Overdrive"},
|
||||
{"NRE", "EP", SAVE_SRAM_256k, "Resident Evil 2"},
|
||||
{"NRH", "J", SAVE_FLASH_1m, "Rockman Dash"},
|
||||
{"NRI", "EP", SAVE_SRAM_256k, "The New Tetris"},
|
||||
{"NRS", "EJP", SAVE_EEPROM_4k, "Star Wars: Rogue Squadron"},
|
||||
{"NRZ", "EP", SAVE_EEPROM_16k, "Ridge Racer 64"},
|
||||
{"NS4", "J", SAVE_SRAM_256k, "Super Robot Taisen 64"},
|
||||
{"NS6", "EJ", SAVE_EEPROM_4k, "Star Soldier: Vanishing Earth"},
|
||||
{"NSA", "JP", SAVE_EEPROM_4k, "AeroFighters Assault (PAL, Japan)"},
|
||||
{"NSC", "EP", SAVE_EEPROM_4k, "Starshot: Space Circus Fever"},
|
||||
{"NSI", "J", SAVE_SRAM_256k, "Fushigi no Dungeon: Fuurai no Shiren 2"},
|
||||
{"NSM", "EJP", SAVE_EEPROM_4k, "Super Mario 64"},
|
||||
{"NSN", "J", SAVE_EEPROM_4k, "Snow Speeder"},
|
||||
{"NSQ", "EP", SAVE_FLASH_1m, "StarCraft 64"},
|
||||
{"NSS", "J", SAVE_EEPROM_4k, "Super Robot Spirits"},
|
||||
{"NSU", "EP", SAVE_EEPROM_4k, "Rocket: Robot on Wheels"},
|
||||
{"NSV", "EP", SAVE_EEPROM_4k, "SpaceStation Silicon Valley"},
|
||||
{"NSW", "EJP", SAVE_EEPROM_4k, "Star Wars: Shadows of the Empire"},
|
||||
{"NT3", "J", SAVE_SRAM_256k, "Toukon Road 2"},
|
||||
{"NT6", "J", SAVE_EEPROM_4k, "Tetris 64"},
|
||||
{"NT9", "EP", SAVE_FLASH_1m, "Tigger's Honey Hunt"},
|
||||
{"NTB", "J", SAVE_EEPROM_4k, "Transformers: Beast Wars Metals 64"},
|
||||
{"NTC", "J", SAVE_EEPROM_4k, "64 Trump Collection"},
|
||||
{"NTE", "AP", SAVE_SRAM_256k, "1080 Snowboarding"},
|
||||
{"NTJ", "EP", SAVE_EEPROM_4k, "Tom and Jerry in Fists of Furry"},
|
||||
{"NTM", "EJP", SAVE_EEPROM_4k, "Mischief Makers"},
|
||||
{"NTN", "EP", SAVE_EEPROM_4k, "All-Star Tennis 99"},
|
||||
{"NTP", "EP", SAVE_EEPROM_4k, "Tetrisphere"},
|
||||
{"NTR", "JP", SAVE_EEPROM_4k, "Top Gear Rally (PAL, Japan)"},
|
||||
{"NTW", "J", SAVE_EEPROM_4k, "64 de Hakken!! Tamagotchi"},
|
||||
{"NTX", "EP", SAVE_EEPROM_4k, "Taz Express"},
|
||||
{"NUB", "J", SAVE_EEPROM_16k, "PD Ultraman Battle Collection 64"},
|
||||
{"NUM", "J", SAVE_SRAM_256k, "Nushi Zuri 64: Shiokaze ni Notte"},
|
||||
{"NUT", "J", SAVE_SRAM_256k, "Nushi Zuri 64"},
|
||||
{"NVB", "J", SAVE_SRAM_256k, "Bass Rush: ECOGEAR PowerWorm Championship"},
|
||||
{"NVL", "EP", SAVE_EEPROM_4k, "V-Rally 99 (USA, PAL)"},
|
||||
{"NVP", "J", SAVE_SRAM_256k, "Virtual Pro Wrestling 64"},
|
||||
{"NVY", "J", SAVE_EEPROM_4k, "V-Rally 99 (Japan)"},
|
||||
{"NW2", "EP", SAVE_SRAM_256k, "WCW/nWo Revenge"},
|
||||
{"NW4", "EP", SAVE_FLASH_1m, "WWF No Mercy"},
|
||||
{"NWC", "J", SAVE_EEPROM_4k, "Wild Choppers"},
|
||||
{"NWL", "EP", SAVE_SRAM_256k, "Waialae Country Club: True Golf Classics"},
|
||||
{"NWQ", "E", SAVE_EEPROM_4k, "Rally Challenge 2000"},
|
||||
{"NWR", "EJP", SAVE_EEPROM_4k, "Wave Race 64"},
|
||||
{"NWT", "J", SAVE_EEPROM_4k, "Wetrix (Japan)"},
|
||||
{"NWU", "P", SAVE_EEPROM_4k, "Worms Armageddon (PAL)"},
|
||||
{"NWX", "EJP", SAVE_SRAM_256k, "WWF WrestleMania 2000"},
|
||||
{"NXO", "E", SAVE_EEPROM_4k, "Cruis'n Exotica"},
|
||||
{"NYK", "J", SAVE_EEPROM_4k, "Yakouchuu II: Satsujin Kouro"},
|
||||
{"NYS", "EJP", SAVE_EEPROM_16k, "Yoshi's Story"},
|
||||
{"NYW", "EJ", SAVE_SRAM_256k, "Harvest Moon 64"},
|
||||
{"NZL", "P", SAVE_SRAM_256k, "Legend of Zelda: Ocarina of Time (PAL)"},
|
||||
{"NZS", "EJP", SAVE_FLASH_1m, "Legend of Zelda: Majora's Mask"},
|
||||
};
|
||||
}
|
||||
} // namespace n64
|
||||
|
||||
@@ -45,7 +45,7 @@ void Scheduler::HandleEvents() {
|
||||
break;
|
||||
case STOP:
|
||||
core.Stop();
|
||||
core.rom = {};
|
||||
core.romPath = {};
|
||||
break;
|
||||
case RESET:
|
||||
core.Reset();
|
||||
|
||||
@@ -90,7 +90,10 @@ FORCE_INLINE void SetROMCIC(u32 checksum, ROM &rom) {
|
||||
}
|
||||
}
|
||||
|
||||
void Mem::LoadROM(const bool isArchive, const std::string &filename) {
|
||||
ROM Mem::LoadROM(const bool isArchive, const std::string &filename) {
|
||||
ROM rom;
|
||||
rom.cart.resize(CART_SIZE);
|
||||
std::ranges::fill(rom.cart, 0);
|
||||
u32 endianness;
|
||||
{
|
||||
size_t sizeAdjusted;
|
||||
@@ -133,7 +136,8 @@ void Mem::LoadROM(const bool isArchive, const std::string &filename) {
|
||||
SetROMCIC(checksum, rom);
|
||||
endianness = std::byteswap(ircolib::ReadAccess<u32>(rom.cart, 0));
|
||||
Util::SwapN64Rom(rom.cart, endianness);
|
||||
rom.pal = IsROMPAL();
|
||||
rom.pal = IsROMPAL(rom);
|
||||
return rom;
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -451,7 +455,7 @@ void Mem::Write(const u32 paddr, u64 val) {
|
||||
|
||||
template <>
|
||||
u32 Mem::BackupRead<u32>(const u32 addr) {
|
||||
switch (saveType) {
|
||||
switch (rom.saveType) {
|
||||
case SAVE_NONE:
|
||||
return 0;
|
||||
case SAVE_EEPROM_4k:
|
||||
@@ -469,7 +473,7 @@ u32 Mem::BackupRead<u32>(const u32 addr) {
|
||||
|
||||
template <>
|
||||
u8 Mem::BackupRead<u8>(const u32 addr) {
|
||||
switch (saveType) {
|
||||
switch (rom.saveType) {
|
||||
case SAVE_NONE:
|
||||
return 0;
|
||||
case SAVE_EEPROM_4k:
|
||||
@@ -492,7 +496,7 @@ u8 Mem::BackupRead<u8>(const u32 addr) {
|
||||
|
||||
template <>
|
||||
void Mem::BackupWrite<u32>(const u32 addr, const u32 val) {
|
||||
switch (saveType) {
|
||||
switch (rom.saveType) {
|
||||
case SAVE_NONE:
|
||||
warn("Accessing cartridge with save type SAVE_NONE in write word");
|
||||
break;
|
||||
@@ -511,7 +515,7 @@ void Mem::BackupWrite<u32>(const u32 addr, const u32 val) {
|
||||
|
||||
template <>
|
||||
void Mem::BackupWrite<u8>(const u32 addr, const u8 val) {
|
||||
switch (saveType) {
|
||||
switch (rom.saveType) {
|
||||
case SAVE_NONE:
|
||||
warn("Accessing cartridge with save type SAVE_NONE in write word");
|
||||
break;
|
||||
|
||||
@@ -29,6 +29,7 @@ struct ROM {
|
||||
char gameNameCart[20];
|
||||
char code[4];
|
||||
ROMHeader header;
|
||||
SaveType saveType = SAVE_NONE;
|
||||
size_t mask;
|
||||
CICType cicType;
|
||||
std::vector<u8> cart;
|
||||
@@ -78,7 +79,7 @@ struct Mem {
|
||||
~Mem() = default;
|
||||
void Reset();
|
||||
void LoadSRAM(SaveType, fs::path);
|
||||
void LoadROM(bool, const std::string &);
|
||||
static ROM LoadROM(bool, const std::string &);
|
||||
|
||||
[[nodiscard]] auto GetRDRAMPtr() -> u8 * { return mmio.rdp.rdram.data(); }
|
||||
|
||||
@@ -119,7 +120,6 @@ struct Mem {
|
||||
|
||||
MMIO mmio;
|
||||
ROM rom;
|
||||
SaveType saveType = SAVE_NONE;
|
||||
Flash flash;
|
||||
|
||||
private:
|
||||
@@ -135,9 +135,9 @@ struct Mem {
|
||||
std::string sramPath{};
|
||||
mio::mmap_sink saveData{};
|
||||
|
||||
[[nodiscard]] FORCE_INLINE bool IsROMPAL() const {
|
||||
[[nodiscard]] static FORCE_INLINE bool IsROMPAL(ROM &rom) {
|
||||
static constexpr char pal_codes[] = {'D', 'F', 'I', 'P', 'S', 'U', 'X', 'Y'};
|
||||
return std::ranges::any_of(pal_codes, [this](char a) { return rom.cart[0x3d] == a; });
|
||||
return std::ranges::any_of(pal_codes, [&rom](char a) { return rom.cart[0x3d] == a; });
|
||||
}
|
||||
};
|
||||
} // namespace n64
|
||||
|
||||
@@ -64,8 +64,8 @@ void AI::Write(const u32 addr, const u32 val) {
|
||||
{
|
||||
const u32 oldDacFreq = dac.freq;
|
||||
dacRate = val & 0x3FFF;
|
||||
dac.freq = std::max(1.f, (float)GetVideoFrequency(mem.IsROMPAL()) / (dacRate + 1)) * 1.037;
|
||||
dac.period = GetVideoFrequency(mem.IsROMPAL()) / dac.freq;
|
||||
dac.freq = std::max(1.f, (float)GetVideoFrequency(mem.rom.pal) / (dacRate + 1)) * 1.037;
|
||||
dac.period = GetVideoFrequency(mem.rom.pal) / dac.freq;
|
||||
if (oldDacFreq != dac.freq) {
|
||||
device.AdjustSampleRate(dac.freq);
|
||||
}
|
||||
|
||||
@@ -507,7 +507,7 @@ void PI::DMA<false>() {
|
||||
n64::Mem &mem = n64::Core::GetMem();
|
||||
const s32 len = rdLen + 1;
|
||||
trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
|
||||
if (mem.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < (CART_REGION_START_2_2 + 1_mb)) {
|
||||
if (mem.rom.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < (CART_REGION_START_2_2 + 1_mb)) {
|
||||
cartAddr = SREGION_PI_SRAM | ((cartAddr & (1_mb - 1)) << 1);
|
||||
}
|
||||
|
||||
@@ -535,7 +535,7 @@ void PI::DMA<true>() {
|
||||
const s32 len = wrLen + 1;
|
||||
trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);
|
||||
|
||||
if (mem.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < (CART_REGION_START_2_2 + 1_mb)) {
|
||||
if (mem.rom.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < (CART_REGION_START_2_2 + 1_mb)) {
|
||||
cartAddr = SREGION_PI_SRAM | ((cartAddr & (1_mb - 1)) << 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -347,10 +347,10 @@ void PIF::MempakWrite(u8 *cmd, u8 *res) {
|
||||
|
||||
void PIF::EepromRead(const u8 *cmd, u8 *res) const {
|
||||
n64::Mem &mem = n64::Core::GetMem();
|
||||
assert(mem.saveType == SAVE_EEPROM_4k || mem.saveType == SAVE_EEPROM_16k);
|
||||
assert(mem.rom.saveType == SAVE_EEPROM_4k || mem.rom.saveType == SAVE_EEPROM_16k);
|
||||
if (channel == 4) {
|
||||
const u8 offset = cmd[3];
|
||||
if ((offset * 8) >= GetSaveSize(mem.saveType)) {
|
||||
if ((offset * 8) >= GetSaveSize(mem.rom.saveType)) {
|
||||
panic("Out of range EEPROM read! offset: {:02X}", offset);
|
||||
}
|
||||
|
||||
@@ -362,10 +362,10 @@ void PIF::EepromRead(const u8 *cmd, u8 *res) const {
|
||||
|
||||
void PIF::EepromWrite(const u8 *cmd, u8 *res) {
|
||||
n64::Mem &mem = n64::Core::GetMem();
|
||||
assert(mem.saveType == SAVE_EEPROM_4k || mem.saveType == SAVE_EEPROM_16k);
|
||||
assert(mem.rom.saveType == SAVE_EEPROM_4k || mem.rom.saveType == SAVE_EEPROM_16k);
|
||||
if (channel == 4) {
|
||||
const u8 offset = cmd[3];
|
||||
if ((offset * 8) >= GetSaveSize(mem.saveType)) {
|
||||
if ((offset * 8) >= GetSaveSize(mem.rom.saveType)) {
|
||||
panic("Out of range EEPROM write! offset: {:02X}", offset);
|
||||
}
|
||||
|
||||
|
||||
+56
-51
@@ -11,43 +11,71 @@
|
||||
#include <Options.hpp>
|
||||
#include <Scheduler.hpp>
|
||||
|
||||
void KaizenGui::populateRomsList(const std::string &romsPath) {
|
||||
centralWidget->setCurrentWidget(romPathNotSet);
|
||||
if (!romsPath.empty()) {
|
||||
int i = 0;
|
||||
centralWidget->setCurrentWidget(romsList);
|
||||
|
||||
for (const auto &file : fs::recursive_directory_iterator{romsPath}) {
|
||||
if (!file.is_regular_file())
|
||||
continue;
|
||||
|
||||
auto filename = file.path().lexically_normal().string();
|
||||
|
||||
bool isPlain = std::ranges::any_of(std::array{".n64", ".z64", ".v64"},
|
||||
[&](const std::string &ext) { return file.path().extension() == ext; });
|
||||
|
||||
bool isArchive =
|
||||
std::ranges::any_of(std::array{".zip", ".7z", ".rar", ".tar"},
|
||||
[&](const std::string &ext) { return file.path().extension() == ext; });
|
||||
|
||||
if (!isArchive && !isPlain)
|
||||
continue;
|
||||
|
||||
auto rom = n64::Mem::LoadROM(isArchive, filename);
|
||||
auto regions = n64::GameDB::match(rom);
|
||||
|
||||
romsListPaths.push_back(filename);
|
||||
romsList->insertRow(i);
|
||||
romsList->setItem(i, 0, new QTableWidgetItem(core.mem->rom.gameNameDB.c_str()));
|
||||
romsList->setItem(i, 1, new QTableWidgetItem(regions.c_str()));
|
||||
romsList->setItem(i, 2, new QTableWidgetItem("Never"));
|
||||
romsList->setItem(i, 3, new QTableWidgetItem("0h 0m 0s"));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
currentHomeWidget = centralWidget->currentWidget();
|
||||
}
|
||||
|
||||
KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::UserScope) {
|
||||
SDL_InitSubSystem(SDL_INIT_GAMEPAD);
|
||||
|
||||
hide();
|
||||
|
||||
auto romsNotFoundLabel = new QLabel(R"(Kaizen could not find any ROMs. Set the path in "Settings -> General")");
|
||||
|
||||
romsList->verticalHeader()->hide();
|
||||
romsList->setSizePolicy({QSizePolicy::Maximum, QSizePolicy::Maximum});
|
||||
romsList->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
romsList->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
romsList->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
romsList->setSortingEnabled(true);
|
||||
romsList->setColumnCount(3);
|
||||
romsList->setColumnCount(4);
|
||||
romsList->setHorizontalHeaderItem(0, romName);
|
||||
romsList->setHorizontalHeaderItem(1, romLastPlayed);
|
||||
romsList->setHorizontalHeaderItem(2, romTimePlayed);
|
||||
romsList->setHorizontalHeaderItem(1, romRegions);
|
||||
romsList->setHorizontalHeaderItem(2, romLastPlayed);
|
||||
romsList->setHorizontalHeaderItem(3, romTimePlayed);
|
||||
|
||||
auto romsPath = Options::GetRomsPath();
|
||||
if (!romsPath.empty()) {
|
||||
int i = 0;
|
||||
centralWidget->addWidget(romsList);
|
||||
for (const auto &file : fs::recursive_directory_iterator{romsPath}) {
|
||||
if (file.is_regular_file() &&
|
||||
std::ranges::any_of(std::array{".n64", ".z64", ".v64"},
|
||||
[&](const std::string &ext) { return file.path().extension() == ext; })) {
|
||||
romsList->insertRow(i);
|
||||
romsList->setItem(i, 0, new QTableWidgetItem(file.path().stem().string().c_str()));
|
||||
romsList->setItem(i, 1, new QTableWidgetItem("Never"));
|
||||
romsList->setItem(i, 2, new QTableWidgetItem("0h 0m 0s"));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
centralWidget->addWidget(romsNotFoundLabel);
|
||||
}
|
||||
vulkanWidget = new RenderWidget();
|
||||
vulkanWidget->hide();
|
||||
|
||||
centralWidget->addWidget(vulkanWidget);
|
||||
centralWidget->addWidget(romsList);
|
||||
centralWidget->addWidget(romPathNotSet);
|
||||
|
||||
populateRomsList(Options::GetRomsPath());
|
||||
|
||||
connect(romsList, &QTableWidget::cellDoubleClicked, this, [&](int row, int) {
|
||||
auto fileToLoad = fs::path(romsPath) / romsList->item(row, 0)->text().toStdString();
|
||||
auto fileToLoad = fs::path(Options::GetRomsPath()) / romsListPaths[row];
|
||||
std::println("{}", fileToLoad.string());
|
||||
LoadROM(fileToLoad.string());
|
||||
});
|
||||
@@ -57,11 +85,6 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
|
||||
restoreGeometry(settings.value("geometry").toByteArray());
|
||||
restoreState(settings.value("windowState").toByteArray());
|
||||
|
||||
vulkanWidget = new RenderWidget();
|
||||
vulkanWidget->hide();
|
||||
|
||||
centralWidget->addWidget(vulkanWidget);
|
||||
|
||||
cpuTypeLabel = new QLabel("Interpreter");
|
||||
if (Options::GetCpuType() == n64::CachedInterpreter)
|
||||
cpuTypeLabel->setText("Cached Interpreter");
|
||||
@@ -108,7 +131,7 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
|
||||
auto open = fileMenu->addAction("Open");
|
||||
open->setShortcut(QKeyCombination(Qt::CTRL, Qt::Key_O));
|
||||
connect(open, &QAction::triggered, this, [&] {
|
||||
auto originPath = romsPath.empty() ? QDir::currentPath() : romsPath.c_str();
|
||||
auto originPath = Options::GetRomsPath().empty() ? QDir::currentPath() : Options::GetRomsPath().c_str();
|
||||
auto fileToLoad =
|
||||
QFileDialog::getOpenFileName(this, "Select a Nintendo 64 ROM", originPath, "N64 ROM (*.z64 *.n64 *.v64)")
|
||||
.toStdString();
|
||||
@@ -123,26 +146,8 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
|
||||
auto settingsMenu = emulationMenu->addAction("Settings");
|
||||
settingsWindow = new SettingsWindow();
|
||||
connect(settingsMenu, &QAction::triggered, settingsWindow, &SettingsWindow::show);
|
||||
connect(settingsWindow->general, &GeneralSettings::romFolderSelected, this, [&] {
|
||||
romsPath = Options::GetRomsPath();
|
||||
if (!romsPath.empty()) {
|
||||
int i = 0;
|
||||
centralWidget->addWidget(romsList);
|
||||
for (const auto &file : fs::recursive_directory_iterator{romsPath}) {
|
||||
if (file.is_regular_file() &&
|
||||
std::ranges::any_of(std::array{".n64", ".z64", ".v64"},
|
||||
[&](const std::string &ext) { return file.path().extension() == ext; })) {
|
||||
romsList->insertRow(i);
|
||||
romsList->setItem(i, 0, new QTableWidgetItem(file.path().stem().string().c_str()));
|
||||
romsList->setItem(i, 1, new QTableWidgetItem("Never"));
|
||||
romsList->setItem(i, 2, new QTableWidgetItem("0h 0m 0s"));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
centralWidget->addWidget(romsNotFoundLabel);
|
||||
}
|
||||
});
|
||||
connect(settingsWindow->general, &GeneralSettings::romFolderSelected, this,
|
||||
[&] { populateRomsList(Options::GetRomsPath()); });
|
||||
|
||||
connect(settingsWindow->cpu, &CPUSettings::cpuTypeChanged, this, [&] {
|
||||
core.cpuType = Options::GetCpuType();
|
||||
@@ -185,7 +190,7 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
|
||||
emulationMenu->addAction(stop);
|
||||
connect(stop, &QAction::triggered, this, [&] {
|
||||
Scheduler::GetInstance().EnqueueRelative(0, STOP);
|
||||
centralWidget->setCurrentWidget(romsList);
|
||||
centralWidget->setCurrentWidget(currentHomeWidget);
|
||||
});
|
||||
|
||||
auto helpMenu = menuBar()->addMenu("Help");
|
||||
|
||||
@@ -18,6 +18,7 @@ class KaizenGui final : QMainWindow {
|
||||
void updateKeys();
|
||||
void updateAxis();
|
||||
bool eventFilter(QObject *, QEvent *) override;
|
||||
void populateRomsList(const std::string &);
|
||||
|
||||
public:
|
||||
explicit KaizenGui() noexcept;
|
||||
@@ -32,8 +33,13 @@ class KaizenGui final : QMainWindow {
|
||||
bool fastForward = false;
|
||||
bool minimized = false;
|
||||
|
||||
std::vector<std::string> romsListPaths{};
|
||||
|
||||
QWidget *currentHomeWidget;
|
||||
QLabel *romPathNotSet = new QLabel(R"(Kaizen could not find any ROMs. Set the path in "Settings -> General")");
|
||||
QTableWidget *romsList = new QTableWidget();
|
||||
QTableWidgetItem *romName = new QTableWidgetItem("Name");
|
||||
QTableWidgetItem *romRegions = new QTableWidgetItem("Regions");
|
||||
QTableWidgetItem *romLastPlayed = new QTableWidgetItem("Last played");
|
||||
QTableWidgetItem *romTimePlayed = new QTableWidgetItem("Time played");
|
||||
QStackedWidget *centralWidget = new QStackedWidget();
|
||||
|
||||
+44
-15
@@ -7,32 +7,61 @@
|
||||
#endif
|
||||
|
||||
namespace Util {
|
||||
enum LogLevel : u8 { Trace, Debug, Warn, Info, Error, Always };
|
||||
enum LogLevel : u8 { Trace, Debug, Info, Warn, Error, Always };
|
||||
|
||||
#ifndef NDEBUG
|
||||
static constexpr auto globalLogLevel = Debug;
|
||||
#else
|
||||
static constexpr auto globalLogLevel = Info;
|
||||
static constexpr auto globalLogLevel = Warn;
|
||||
#endif
|
||||
|
||||
template <LogLevel messageType = Info, class... Args>
|
||||
void print(const std::format_string<Args...> fmt, Args... args) {
|
||||
if (messageType >= globalLogLevel) {
|
||||
if (messageType <= Debug) {
|
||||
if (messageType >= globalLogLevel) {
|
||||
if (messageType <= Debug) {
|
||||
#ifndef NDEBUG
|
||||
std::println(fmt, std::forward<Args>(args)...);
|
||||
std::println(fmt, std::forward<Args>(args)...);
|
||||
#endif
|
||||
} else {
|
||||
std::println(fmt, std::forward<Args>(args)...);
|
||||
} else {
|
||||
std::println(fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define panic(fmt, ...) do { Util::print<Util::Error>("[FATAL] " fmt __VA_OPT__(,) __VA_ARGS__); exit(-1); } while(0)
|
||||
#define error(fmt, ...) do { Util::print<Util::Error>("[ERROR] " fmt __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define warn(fmt, ...) do { Util::print<Util::Warn>("[WARN] " fmt __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define info(fmt, ...) do { Util::print<Util::Info>("[INFO] " fmt __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define debug(fmt, ...) do { Util::print<Util::Debug>("[DEBUG] " fmt __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define trace(fmt, ...) do { Util::print<Util::Trace>("[TRACE] " fmt __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define always(fmt, ...) do { Util::print<Util::Always>(fmt __VA_OPT__(,) __VA_ARGS__); } while(0)
|
||||
#define panic(fmt, ...) \
|
||||
do { \
|
||||
Util::print<Util::Error>("[FATAL] " fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
exit(-1); \
|
||||
} \
|
||||
while (0)
|
||||
#define error(fmt, ...) \
|
||||
do { \
|
||||
Util::print<Util::Error>("[ERROR] " fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
while (0)
|
||||
#define warn(fmt, ...) \
|
||||
do { \
|
||||
Util::print<Util::Warn>("[WARN] " fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
while (0)
|
||||
#define info(fmt, ...) \
|
||||
do { \
|
||||
Util::print<Util::Info>("[INFO] " fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
while (0)
|
||||
#define debug(fmt, ...) \
|
||||
do { \
|
||||
Util::print<Util::Debug>("[DEBUG] " fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
while (0)
|
||||
#define trace(fmt, ...) \
|
||||
do { \
|
||||
Util::print<Util::Trace>("[TRACE] " fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
while (0)
|
||||
#define always(fmt, ...) \
|
||||
do { \
|
||||
Util::print<Util::Always>(fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
while (0)
|
||||
} // namespace Util
|
||||
|
||||
Reference in New Issue
Block a user