#include #include #include #include namespace n64 { Core::Core() { auto cpuType = Options::GetInstance().GetValue("cpu", "type"); if (cpuType == "interpreter") { cpu = std::make_unique(parallel); } else if(cpuType == "jit") { #ifndef __aarch64__ cpu = std::make_unique(parallel); #else panic("JIT currently unsupported on aarch64"); #endif } else { panic("Unimplemented CPU type"); } } void Core::Stop() { pause = true; romLoaded = false; cpu->Reset(); } bool Core::LoadTAS(const fs::path &path) const { return cpu->GetMem().mmio.si.pif.movie.Load(path); } void Core::LoadROM(const std::string &rom_) { Stop(); rom = rom_; std::string archive_types[] = {".zip", ".7z", ".rar", ".tar"}; auto extension = fs::path(rom).extension().string(); const bool isArchive = std::ranges::any_of(archive_types, [&extension](const auto &e) { return e == extension; }); cpu->GetMem().LoadROM(isArchive, rom); GameDB::match(); if (cpu->GetMem().rom.gameNameDB.empty()) { cpu->GetMem().rom.gameNameDB = fs::path(rom).stem().string(); } cpu->GetMem().mmio.vi.isPal = cpu->GetMem().IsROMPAL(); cpu->GetMem().mmio.si.pif.InitDevices(cpu->GetMem().saveType); cpu->GetMem().mmio.si.pif.mempakPath = rom; cpu->GetMem().mmio.si.pif.LoadEeprom(cpu->GetMem().saveType, rom); cpu->GetMem().flash.Load(cpu->GetMem().saveType, rom); cpu->GetMem().LoadSRAM(cpu->GetMem().saveType, rom); cpu->GetMem().mmio.si.pif.Execute(); pause = false; romLoaded = true; } void Core::Run(float volumeL, float volumeR) { Mem &mem = cpu->GetMem(); MMIO &mmio = mem.mmio; Registers ®s = cpu->GetRegs(); for (int field = 0; field < mmio.vi.numFields; field++) { u32 frameCycles = 0; for (int i = 0; i < mmio.vi.numHalflines; i++) { mmio.vi.current = (i << 1) + field; if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) { mmio.mi.InterruptRaise(MI::Interrupt::VI); } for (; cycles < mem.mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) { u32 taken = cpu->Step(); taken += regs.PopStalledCycles(); regs.steps += taken; if (mmio.rsp.spStatus.halt) { regs.steps = 0; mmio.rsp.steps = 0; } else { while (regs.steps > 2) { mmio.rsp.steps += 2; regs.steps -= 3; } while (mmio.rsp.steps > 0) { mmio.rsp.steps--; mmio.rsp.Step(); } } cycles += taken; frameCycles += taken; Scheduler::GetInstance().Tick(taken); } cycles -= mmio.vi.cyclesPerHalfline; } if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) { mmio.mi.InterruptRaise(MI::Interrupt::VI); } mmio.ai.Step(frameCycles, volumeL, volumeR); Scheduler::GetInstance().Tick(frameCycles); } } } // namespace n64