fuck this shit

This commit is contained in:
2026-06-11 14:37:02 +02:00
parent 2b59e5f461
commit bad1691ee2
13 changed files with 414 additions and 317 deletions
+15 -13
View File
@@ -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;
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -45,7 +45,7 @@ void Scheduler::HandleEvents() {
break;
case STOP:
core.Stop();
core.rom = {};
core.romPath = {};
break;
case RESET:
core.Reset();
+10 -6
View File
@@ -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;
+4 -4
View File
@@ -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
+2 -2
View File
@@ -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);
}
+2 -2
View File
@@ -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);
}
+4 -4
View File
@@ -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
View File
@@ -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");
+6
View File
@@ -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
View File
@@ -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