From b037de4c3d09b29c2bc72c5af01fb4818d396fd9 Mon Sep 17 00:00:00 2001 From: iris Date: Wed, 3 Jun 2026 18:05:35 +0200 Subject: [PATCH] SAZDFsdff --- src/backend/core/Interpreter.cpp | 108 +- src/backend/core/Interpreter.hpp | 3 +- src/backend/core/Mem.cpp | 4 - src/backend/core/RSP.cpp | 3 +- .../core/interpreter/cop1instructions.cpp | 2 + src/backend/core/interpreter/instructions.cpp | 10 + src/backend/core/mmio/PI.cpp | 5 +- src/backend/core/mmio/PIF.cpp | 1104 +++++++++-------- src/backend/core/mmio/SI.cpp | 1 - 9 files changed, 632 insertions(+), 608 deletions(-) diff --git a/src/backend/core/Interpreter.cpp b/src/backend/core/Interpreter.cpp index 2bf674c..332e4f3 100644 --- a/src/backend/core/Interpreter.cpp +++ b/src/backend/core/Interpreter.cpp @@ -96,7 +96,54 @@ u32 Interpreter::Step() { return 1; } -u32 Interpreter::CacheBlock(u32 addr) { +bool Interpreter::DetectIdleLoop(const std::array &code, u32 len, u32 blockAddr) { + if (!Core::GetInstance().idleSkip) + return false; + + u32 lastInstructionIndex = len - 1; + auto delay = code[lastInstructionIndex]; + + if (len == 2) { + // branch or jump to itself + // _nop + + auto branch = code[lastInstructionIndex - 1]; + return ((branch.IsBranch() && branch.offset() == -4) || (branch.target() == ((blockAddr >> 2) & 0x3FFFFFF))) && + delay.instr.raw == 0; + } + + if (len == 3) { + // load reg1, [some location] + // bcond reg2 + // _andi reg2, reg1, immediate + + auto branch = code[lastInstructionIndex - 1]; + auto load = code[lastInstructionIndex - 2]; // load + + return (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) && + delay.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -8 && + load.rt() == delay.rs() && delay.rt() == branch.rs(); + } + + if (len == 4) { + // load reg2, [reg1(offset)] + // andi reg3, reg2, immediate + // bcond reg3, reg4 + // _nop + + auto branch = code[lastInstructionIndex - 1]; + auto andi = code[lastInstructionIndex - 2]; // andi + auto load = code[lastInstructionIndex - 3]; // load + + return (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) && + andi.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -12 && + load.rt() == andi.rs() && andi.rt() == branch.rs(); + } + + return false; +} + +u32 Interpreter::CacheBlock(u64 addr) { u32 blockAddr = addr; CachedLine line; @@ -104,7 +151,9 @@ u32 Interpreter::CacheBlock(u32 addr) { bool fetchDelaySlot = false; for (i = 0; i < MAX_INSTR_PER_BLOCK; i++) { - Instruction instr = mem.Read(addr); + Instruction instr; + if (!Fetch(instr, addr)) + return i + 1; addr += 4; line.code[i] = instr; @@ -127,46 +176,7 @@ u32 Interpreter::CacheBlock(u32 addr) { } } - if (Core::GetInstance().idleSkip) { - auto delay = line.code[i - 1]; - - if (i == 2) { - // branch to itself - // _nop - - auto branch = line.code[i - 2]; - line.idleSkip = branch.IsBranch() && branch.offset() == -4 && delay.instr.raw == 0; - } - - if (i == 3) { - // load reg1, [some location] - // bcond reg2 - // _andi reg2, reg1, immediate - - auto branch = line.code[i - 2]; - auto load = line.code[i - 3]; // load - - line.idleSkip = (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) && - delay.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -8 && - load.rt() == delay.rs() && delay.rt() == branch.rs(); - } - - if (i == 4) { - // load reg2, [reg1(offset)] - // andi reg3, reg2, immediate - // bcond reg3, reg4 - // _nop - - auto branch = line.code[i - 2]; - auto andi = line.code[i - 3]; // andi - auto load = line.code[i - 4]; // load - - line.idleSkip = (load.opcode() == Instruction::LW || load.opcode() == Instruction::LWU) && - andi.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -12 && - load.rt() == andi.rs() && andi.rt() == branch.rs(); - } - } - + line.idleSkip = DetectIdleLoop(line.code, i, blockAddr); line.cycles = i; line.len = i; cachedState.blocks[CACHE_GET_BLOCK(blockAddr)]->lines[CACHE_GET_LINE(blockAddr)] = new CachedLine(line); @@ -175,21 +185,15 @@ u32 Interpreter::CacheBlock(u32 addr) { } u32 Interpreter::ExecuteCached() { - u32 addr; + u64 addr = regs.pc; auto &blocks = cachedState.blocks; - if (!regs.cop0.MapVAddr(Cop0::LOAD, regs.pc, addr)) { - regs.cop0.HandleTLBException(regs.pc); - regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, regs.pc); - return 1; - } - - if (!blocks[CACHE_GET_BLOCK(addr)]) { - blocks[CACHE_GET_BLOCK(addr)] = new CachedBlock(cachedState.MAX_LINES / 4); + if (!blocks[CACHE_GET_BLOCK((u32)addr)]) { + blocks[CACHE_GET_BLOCK((u32)addr)] = new CachedBlock(cachedState.MAX_LINES / 4); return CacheBlock(addr); } - const auto line = blocks[CACHE_GET_BLOCK(addr)]->lines[CACHE_GET_LINE(addr)]; + const auto line = blocks[CACHE_GET_BLOCK((u32)addr)]->lines[CACHE_GET_LINE((u32)addr)]; if (line) { cachedState.exception = false; // i copy the block cycles here in case the block evicts itself when executing which would set the cycles to diff --git a/src/backend/core/Interpreter.hpp b/src/backend/core/Interpreter.hpp index 0ac2f88..e2c87b0 100644 --- a/src/backend/core/Interpreter.hpp +++ b/src/backend/core/Interpreter.hpp @@ -13,7 +13,8 @@ struct Interpreter final { u32 ExecuteCached(); bool FetchThenMaybeAdvance(Instruction &); bool MaybeAdvance(); - u32 CacheBlock(u32 addr); + u32 CacheBlock(u64 addr); + bool DetectIdleLoop(const std::array &, u32, u32); void SignalException(u32 addr) { cachedState.exception = true; } diff --git a/src/backend/core/Mem.cpp b/src/backend/core/Mem.cpp index 40a9296..63a0529 100644 --- a/src/backend/core/Mem.cpp +++ b/src/backend/core/Mem.cpp @@ -278,7 +278,6 @@ void Mem::Write(u32 paddr, u32 val) { if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { mmio.rdp.WriteRDRAM(paddr, val); - Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr); return; } if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { @@ -325,7 +324,6 @@ void Mem::Write(u32 paddr, u32 val) { if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { mmio.rdp.WriteRDRAM(paddr, val); - Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr); return; } if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { @@ -372,7 +370,6 @@ void Mem::Write(const u32 paddr, const u32 val) { if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { mmio.rdp.WriteRDRAM(paddr, val); - Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr); return; } if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { @@ -416,7 +413,6 @@ void Mem::Write(const u32 paddr, u64 val) { if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) { mmio.rdp.WriteRDRAM(paddr, val); - Core::GetInstance().interpreter.cachedState.EvictCachedBlock(paddr); return; } if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) { diff --git a/src/backend/core/RSP.cpp b/src/backend/core/RSP.cpp index 9d8113c..128d746 100644 --- a/src/backend/core/RSP.cpp +++ b/src/backend/core/RSP.cpp @@ -117,8 +117,7 @@ void RSP::DMA() { for (u32 j = 0; j < length; j++) { mem.mmio.rdp.WriteRDRAM(BYTE_ADDRESS(dram_address + j), src[(mem_address + j) & DMEM_DSIZE]); } - Core::GetInstance().interpreter.cachedState.EvictCachedBlocksRange(dram_address, dram_address + length); - + const int skip = i == spDMALen.count ? 0 : spDMALen.skip; dram_address += (length + skip); diff --git a/src/backend/core/interpreter/cop1instructions.cpp b/src/backend/core/interpreter/cop1instructions.cpp index 3f702ac..5e7aac9 100644 --- a/src/backend/core/interpreter/cop1instructions.cpp +++ b/src/backend/core/interpreter/cop1instructions.cpp @@ -1310,6 +1310,7 @@ void Cop1::swc1(const Instruction instr) { regs.cop0.HandleTLBException(addr); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { + Core::GetInstance().interpreter.cachedState.EvictCachedBlock(addr); mem.Write(physical, FGR_T(regs.cop0.status, instr.ft())); } } @@ -1337,6 +1338,7 @@ void Cop1::sdc1(const Instruction instr) { regs.cop0.HandleTLBException(addr); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { + Core::GetInstance().interpreter.cachedState.EvictCachedBlock(addr); mem.Write(physical, FGR_T(regs.cop0.status, instr.ft())); } } diff --git a/src/backend/core/interpreter/instructions.cpp b/src/backend/core/interpreter/instructions.cpp index 984ad63..e4a58f5 100644 --- a/src/backend/core/interpreter/instructions.cpp +++ b/src/backend/core/interpreter/instructions.cpp @@ -409,6 +409,7 @@ void Interpreter::sb(const Instruction instr) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { + cachedState.EvictCachedBlock(address); mem.Write(paddr, regs.Read(instr.rt())); } } @@ -432,6 +433,7 @@ void Interpreter::sc(const Instruction instr) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { + cachedState.EvictCachedBlock(address); mem.Write(paddr, regs.Read(instr.rt())); regs.Write(instr.rt(), 1); } @@ -464,6 +466,7 @@ void Interpreter::scd(const Instruction instr) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { + cachedState.EvictCachedBlock(address); mem.Write(paddr, regs.Read(instr.rt())); regs.Write(instr.rt(), 1); } @@ -480,6 +483,7 @@ void Interpreter::sh(const Instruction instr) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { + cachedState.EvictCachedBlock(address); mem.Write(physical, regs.Read(instr.rt())); } } @@ -498,6 +502,7 @@ void Interpreter::sw(const Instruction instr) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { + cachedState.EvictCachedBlock(address); mem.Write(physical, regs.Read(instr.rt())); } } @@ -515,6 +520,7 @@ void Interpreter::sd(const Instruction instr) { regs.cop0.HandleTLBException(address); regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::STORE), 0, regs.oldPC); } else { + cachedState.EvictCachedBlock(address); mem.Write(physical, regs.Read(instr.rt())); } } @@ -531,6 +537,7 @@ void Interpreter::sdl(const Instruction instr) { const u64 data = mem.Read(paddr & ~7); const u64 rt = regs.Read(instr.rt()); mem.Write(paddr & ~7, (data & ~mask) | (rt >> shift)); + cachedState.EvictCachedBlock(address); } } @@ -546,6 +553,7 @@ void Interpreter::sdr(const Instruction instr) { const u64 data = mem.Read(paddr & ~7); const u64 rt = regs.Read(instr.rt()); mem.Write(paddr & ~7, (data & ~mask) | (rt << shift)); + cachedState.EvictCachedBlock(address); } } @@ -561,6 +569,7 @@ void Interpreter::swl(const Instruction instr) { const u32 data = mem.Read(paddr & ~3); const u32 rt = regs.Read(instr.rt()); mem.Write(paddr & ~3, (data & ~mask) | (rt >> shift)); + cachedState.EvictCachedBlock(address); } } @@ -576,6 +585,7 @@ void Interpreter::swr(const Instruction instr) { const u32 data = mem.Read(paddr & ~3); const u32 rt = regs.Read(instr.rt()); mem.Write(paddr & ~3, (data & ~mask) | (rt << shift)); + cachedState.EvictCachedBlock(address); } } diff --git a/src/backend/core/mmio/PI.cpp b/src/backend/core/mmio/PI.cpp index 68712c5..54f9fd7 100644 --- a/src/backend/core/mmio/PI.cpp +++ b/src/backend/core/mmio/PI.cpp @@ -507,6 +507,9 @@ void PI::DMA() { 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)) { + cartAddr = SREGION_PI_SRAM | ((cartAddr & (1_mb - 1)) << 1); + } for (int i = 0; i < len; i++) { BusWrite(cartAddr + i, mem.mmio.rdp.ReadRDRAM(dramAddr + i)); @@ -539,7 +542,7 @@ void PI::DMA() { for (u32 i = 0; i < len; i++) { mem.mmio.rdp.WriteRDRAM(dramAddr + i, BusRead(cartAddr + i)); } - Core::GetInstance().interpreter.cachedState.EvictCachedBlocksRange(dramAddr, dramAddr + len); + dramAddr += len; dramAddr = (dramAddr + 7) & ~7; cartAddr += len; diff --git a/src/backend/core/mmio/PIF.cpp b/src/backend/core/mmio/PIF.cpp index 925ef01..157537d 100644 --- a/src/backend/core/mmio/PIF.cpp +++ b/src/backend/core/mmio/PIF.cpp @@ -9,646 +9,656 @@ namespace n64 { void PIF::Reset() { - movie.Reset(); - joybusDevices = {}; - bootrom = {}; - ram = {}; - std::error_code error; - if (mempak.is_mapped()) { - mempak.sync(error); - if (error) { - panic("Could not sync {}", mempakPath); + movie.Reset(); + joybusDevices = {}; + bootrom = {}; + ram = {}; + std::error_code error; + if (mempak.is_mapped()) { + mempak.sync(error); + if (error) { + panic("Could not sync {}", mempakPath); + } + mempak.unmap(); } - mempak.unmap(); - } - if (eeprom.is_mapped()) { - eeprom.sync(error); - if (error) { - panic("Could not sync {}", eepromPath); + if (eeprom.is_mapped()) { + eeprom.sync(error); + if (error) { + panic("Could not sync {}", eepromPath); + } + eeprom.unmap(); } - eeprom.unmap(); - } - mempakOpen = false; - channel = 0; + mempakOpen = false; + channel = 0; } void PIF::MaybeLoadMempak() { - if (!mempakOpen) { - fs::path mempakPath_ = mempakPath; - std::string savePath = Options::GetInstance().GetValue("general", "savePath"); - if (!savePath.empty()) { - mempakPath_ = savePath / mempakPath_.filename(); - } - mempakPath = mempakPath_.replace_extension(".mempak").string(); - std::error_code error; - if (mempak.is_mapped()) { - mempak.sync(error); - if (error) { - panic("Could not sync {}", mempakPath); - } - mempak.unmap(); - } + if (!mempakOpen) { + fs::path mempakPath_ = mempakPath; + std::string savePath = Options::GetInstance().GetValue("general", "savePath"); + if (!savePath.empty()) { + mempakPath_ = savePath / mempakPath_.filename(); + } + mempakPath = mempakPath_.replace_extension(".mempak").string(); + std::error_code error; + if (mempak.is_mapped()) { + mempak.sync(error); + if (error) { + panic("Could not sync {}", mempakPath); + } + mempak.unmap(); + } - auto mempakVec = ircolib::ReadFileBinary(mempakPath); - if (mempak.empty()) { - ircolib::WriteFileBinary(std::array{}, mempakPath); - mempakVec = ircolib::ReadFileBinary(mempakPath); - } + auto mempakVec = ircolib::ReadFileBinary(mempakPath); + if (mempak.empty()) { + ircolib::WriteFileBinary(std::array{}, mempakPath); + mempakVec = ircolib::ReadFileBinary(mempakPath); + } - if (mempakVec.size() != MEMPAK_SIZE) { - panic("Corrupt mempak!"); - } + if (mempakVec.size() != MEMPAK_SIZE) { + panic("Corrupt mempak!"); + } - mempak = mio::make_mmap_sink(mempakPath, error); - if (error) { - panic("Could not open {}", mempakPath); + mempak = mio::make_mmap_sink(mempakPath, error); + if (error) { + panic("Could not open {}", mempakPath); + } + mempakOpen = true; } - mempakOpen = true; - } } FORCE_INLINE size_t GetSaveSize(SaveType saveType) { - switch (saveType) { - case SAVE_NONE: - return 0; - case SAVE_EEPROM_4k: - return 512; - case SAVE_EEPROM_16k: - return 2048; - case SAVE_SRAM_256k: - return 32768; - case SAVE_FLASH_1m: - return 131072; - default: - panic("Unknown save type!"); - } + switch (saveType) { + case SAVE_NONE: + return 0; + case SAVE_EEPROM_4k: + return 512; + case SAVE_EEPROM_16k: + return 2048; + case SAVE_SRAM_256k: + return 32768; + case SAVE_FLASH_1m: + return 131072; + default: + panic("Unknown save type!"); + } } void PIF::LoadEeprom(const SaveType saveType, const std::string &path) { - if (saveType == SAVE_EEPROM_16k || saveType == SAVE_EEPROM_4k) { - fs::path eepromPath_ = path; - std::string savePath = Options::GetInstance().GetValue("general", "savePath"); - if (!savePath.empty()) { - eepromPath_ = savePath / eepromPath_.filename(); - } - eepromPath = eepromPath_.replace_extension(".eeprom").string(); - std::error_code error; - if (eeprom.is_mapped()) { - eeprom.sync(error); - if (error) { - panic("Could not sync {}", eepromPath); - } - eeprom.unmap(); - } + if (saveType == SAVE_EEPROM_16k || saveType == SAVE_EEPROM_4k) { + fs::path eepromPath_ = path; + std::string savePath = Options::GetInstance().GetValue("general", "savePath"); + if (!savePath.empty()) { + eepromPath_ = savePath / eepromPath_.filename(); + } + eepromPath = eepromPath_.replace_extension(".eeprom").string(); + std::error_code error; + if (eeprom.is_mapped()) { + eeprom.sync(error); + if (error) { + panic("Could not sync {}", eepromPath); + } + eeprom.unmap(); + } - eepromSize = GetSaveSize(saveType); + eepromSize = GetSaveSize(saveType); - auto eepromVec = ircolib::ReadFileBinary(eepromPath); - if (eepromVec.empty()) { - std::vector dummy{}; - dummy.resize(GetSaveSize(saveType)); - ircolib::WriteFileBinary(dummy, eepromPath); - eepromVec = dummy; - } + auto eepromVec = ircolib::ReadFileBinary(eepromPath); + if (eepromVec.empty()) { + std::vector dummy{}; + dummy.resize(GetSaveSize(saveType)); + ircolib::WriteFileBinary(dummy, eepromPath); + eepromVec = dummy; + } - if (eepromVec.size() != eepromSize) { - panic("Corrupt eeprom!"); - } + if (eepromVec.size() != eepromSize) { + panic("Corrupt eeprom!"); + } - eeprom = mio::make_mmap_sink(eepromPath, error); - if (error) { - panic("Could not open {}. Reason {}", eepromPath, error.message()); + eeprom = mio::make_mmap_sink(eepromPath, error); + if (error) { + panic("Could not open {}. Reason {}", eepromPath, error.message()); + } } - } } enum CommandIndexes { COMMAND_LEN = 0, COMMAND_RESULT_LEN, COMMAND_INDEX, COMMAND_START }; void PIF::CICChallenge() { - u8 challenge[30]; - u8 response[30]; + u8 challenge[30]; + u8 response[30]; - // Split 15 bytes into 30 nibbles - for (int i = 0; i < 15; i++) { - challenge[i * 2 + 0] = (ram[0x30 + i] >> 4) & 0x0F; - challenge[i * 2 + 1] = (ram[0x30 + i] >> 0) & 0x0F; - } + // Split 15 bytes into 30 nibbles + for (int i = 0; i < 15; i++) { + challenge[i * 2 + 0] = (ram[0x30 + i] >> 4) & 0x0F; + challenge[i * 2 + 1] = (ram[0x30 + i] >> 0) & 0x0F; + } - n64_cic_nus_6105(reinterpret_cast(challenge), reinterpret_cast(response), CHL_LEN - 2); + n64_cic_nus_6105(reinterpret_cast(challenge), reinterpret_cast(response), CHL_LEN - 2); - for (int i = 0; i < 15; i++) { - ram[0x30 + i] = (response[i * 2] << 4) + response[i * 2 + 1]; - } + for (int i = 0; i < 15; i++) { + ram[0x30 + i] = (response[i * 2] << 4) + response[i * 2 + 1]; + } } FORCE_INLINE u8 DataCRC(const u8 *data) { - u8 crc = 0; - for (int i = 0; i <= 32; i++) { - for (int j = 7; j >= 0; j--) { - const u8 xorVal = ((crc & 0x80) != 0) ? 0x85 : 0x00; + u8 crc = 0; + for (int i = 0; i <= 32; i++) { + for (int j = 7; j >= 0; j--) { + const u8 xorVal = ((crc & 0x80) != 0) ? 0x85 : 0x00; - crc <<= 1; - if (i < 32) { - if ((data[i] & (1 << j)) != 0) { - crc |= 1; + crc <<= 1; + if (i < 32) { + if ((data[i] & (1 << j)) != 0) { + crc |= 1; + } + } + + crc ^= xorVal; } - } - - crc ^= xorVal; } - } - return crc; + return crc; } #define BCD_ENCODE(x) (((x) / 10) << 4 | ((x) % 10)) #define BCD_DECODE(x) (((x) >> 4) * 10 + ((x) & 15)) void PIF::ConfigureJoyBusFrame() { - n64::Mem& mem = n64::Core::GetMem(); - channel = 0; - int i = 0; - while (i < 63) { - u8 *packet = &ram[i++]; - const u8 commandLength = packet[COMMAND_LEN] & 0x3F; + n64::Mem &mem = n64::Core::GetMem(); + channel = 0; + int i = 0; + while (i < 63) { + u8 *packet = &ram[i++]; + const u8 commandLength = packet[COMMAND_LEN] & 0x3F; - if (commandLength == 0) { - channel++; - } else if (commandLength == 0x3D) { - channel = 0; - channel++; - } else if (commandLength == 0x3E) { - break; - } else if (commandLength == 0x3F) { - continue; - } else { - const u8 r = ram[i++]; - if (r == 0xFE) { - break; - } - const u8 reslen = r & 0x3F; - u8 *res = &ram[i + commandLength]; - const u8 commandIndex = packet[COMMAND_INDEX]; + if (commandLength == 0) { + channel++; + } else if (commandLength == 0x3D) { + channel = 0; + channel++; + } else if (commandLength == 0x3E) { + break; + } else if (commandLength == 0x3F) { + continue; + } else { + const u8 r = ram[i++]; + if (r == 0xFE) { + break; + } + const u8 reslen = r & 0x3F; + u8 *res = &ram[i + commandLength]; + const u8 commandIndex = packet[COMMAND_INDEX]; - switch (commandIndex) { - case 0: - case 0xff: - ControllerID(res); - channel++; - break; - case 1: - if (!ReadButtons(res)) { - packet[COMMAND_RESULT_LEN] |= 0x80; - } - channel++; - break; - case 2: - MempakRead(packet, res); - break; - case 3: - MempakWrite(packet, res); - break; - case 4: - EepromRead(packet, res); - break; - case 5: - EepromWrite(packet, res); - break; - case 6: - res[0] = 0x00; - res[1] = 0x10; - res[2] = 0x80; - break; - case 7: { - const u8 commandStart = packet[COMMAND_START]; - switch (commandStart) { + switch (commandIndex) { case 0: + case 0xff: + ControllerID(res); + channel++; + break; case 1: - case 3: - break; + if (!ReadButtons(res)) { + packet[COMMAND_RESULT_LEN] |= 0x80; + } + channel++; + break; case 2: - { - auto now = std::time(nullptr); - const auto *gmtm = gmtime(&now); - res[0] = BCD_ENCODE(gmtm->tm_sec); - res[1] = BCD_ENCODE(gmtm->tm_min); - res[2] = BCD_ENCODE(gmtm->tm_hour) + 0x80; - res[3] = BCD_ENCODE(gmtm->tm_mday); - res[4] = BCD_ENCODE(gmtm->tm_wday); - res[5] = BCD_ENCODE(gmtm->tm_mon); - res[6] = BCD_ENCODE(gmtm->tm_year); - res[7] = (gmtm->tm_year - 1900) >= 100 ? 1 : 0; - res[8] = 0x80; - } - break; - default: - panic("Invalid read RTC block {}", commandStart); - } - } break; - case 8: - res[0] = 0x00; - break; - default: - panic("Invalid PIF command: {:X}", commandIndex); - } + MempakRead(packet, res); + break; + case 3: + MempakWrite(packet, res); + break; + case 4: + EepromRead(packet, res); + break; + case 5: + EepromWrite(packet, res); + break; + case 6: + res[0] = 0x00; + res[1] = 0x10; + res[2] = 0x00; + break; + case 7: + { + const u8 commandStart = packet[COMMAND_START]; + switch (commandStart) { + case 0: + memset(res, 0, 8); + res[1] = 0x06; + break; + case 1: + memset(res, 0, 8); + break; + case 3: + memset(res, 0, 8); + break; + case 2: + { + auto now = std::time(nullptr); + const auto *gmtm = gmtime(&now); - i += commandLength + reslen; + res[0] = BCD_ENCODE(gmtm->tm_sec); + res[1] = BCD_ENCODE(gmtm->tm_min); + res[2] = BCD_ENCODE(gmtm->tm_hour) + 0x80; + res[3] = BCD_ENCODE(gmtm->tm_mday); + res[4] = BCD_ENCODE(gmtm->tm_wday); + res[5] = BCD_ENCODE(gmtm->tm_mon); + res[6] = BCD_ENCODE(gmtm->tm_year); + res[7] = (gmtm->tm_year - 1900) >= 100 ? 1 : 0; + } + break; + default: + panic("Invalid read RTC block {}", commandStart); + } + } + break; + case 8: + memset(res, 0, 8); + break; + default: + panic("Invalid PIF command: {:X}", commandIndex); + } + + i += commandLength + reslen; + } } - } } void PIF::ProcessCommands() { - const u8 control = ram[63]; - if (control & 1) { - ConfigureJoyBusFrame(); - } + const u8 control = ram[63]; + if (control & 1) { + ConfigureJoyBusFrame(); + } - if (control & 0x02) { - CICChallenge(); - ram[63] &= ~2; - } + if (control & 0x02) { + CICChallenge(); + ram[63] &= ~2; + } - if (control & 0x08) { - ram[63] &= ~8; - } + if (control & 0x08) { + ram[63] &= ~8; + } - if (control & 0x30) { - ram[63] = 0x80; - } + if (control & 0x30) { + ram[63] = 0x80; + } } void PIF::MempakRead(const u8 *cmd, u8 *res) { - MaybeLoadMempak(); - u16 offset = cmd[3] << 8; - offset |= cmd[4]; + MaybeLoadMempak(); + u16 offset = cmd[3] << 8; + offset |= cmd[4]; - // low 5 bits are the CRC - // byte crc = offset & 0x1F; - // offset must be 32-byte aligned - offset &= ~0x1F; + // low 5 bits are the CRC + // byte crc = offset & 0x1F; + // offset must be 32-byte aligned + offset &= ~0x1F; - switch (GetAccessoryType()) { - case ACCESSORY_NONE: - break; - case ACCESSORY_MEMPACK: - if (offset <= MEMPAK_SIZE - 0x20) { - std::copy_n(mempak.begin() + offset, 32, res); + switch (GetAccessoryType()) { + case ACCESSORY_NONE: + break; + case ACCESSORY_MEMPACK: + if (offset <= MEMPAK_SIZE - 0x20) { + std::copy_n(mempak.begin() + offset, 32, res); + } else { + memset(res, 0, 32); + } + break; + case ACCESSORY_RUMBLE_PACK: + memset(res, 0x80, 32); + break; } - break; - case ACCESSORY_RUMBLE_PACK: - memset(res, 0x80, 32); - break; - } - // CRC byte - res[32] = DataCRC(res); + // CRC byte + res[32] = DataCRC(res); } void PIF::MempakWrite(u8 *cmd, u8 *res) { - MaybeLoadMempak(); - // First two bytes in the command are the offset - u16 offset = cmd[3] << 8; - offset |= cmd[4]; + MaybeLoadMempak(); + // First two bytes in the command are the offset + u16 offset = cmd[3] << 8; + offset |= cmd[4]; - // low 5 bits are the CRC - // byte crc = offset & 0x1F; - // offset must be 32-byte aligned - offset &= ~0x1F; + // low 5 bits are the CRC + // byte crc = offset & 0x1F; + // offset must be 32-byte aligned + offset &= ~0x1F; - switch (GetAccessoryType()) { - case ACCESSORY_NONE: - break; - case ACCESSORY_MEMPACK: - if (offset <= MEMPAK_SIZE - 0x20) { - std::copy_n(cmd + 5, 32, mempak.begin() + offset); + switch (GetAccessoryType()) { + case ACCESSORY_NONE: + break; + case ACCESSORY_MEMPACK: + if (offset <= MEMPAK_SIZE - 0x20) { + std::copy_n(cmd + 5, 32, mempak.begin() + offset); + } + break; + case ACCESSORY_RUMBLE_PACK: + break; } - break; - case ACCESSORY_RUMBLE_PACK: - break; - } - // CRC byte - res[0] = DataCRC(&cmd[5]); + // CRC byte + res[0] = DataCRC(&cmd[5]); } 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); - if (channel == 4) { - const u8 offset = cmd[3]; - if ((offset * 8) >= GetSaveSize(mem.saveType)) { - panic("Out of range EEPROM read! offset: {:02X}", offset); - } + n64::Mem &mem = n64::Core::GetMem(); + assert(mem.saveType == SAVE_EEPROM_4k || mem.saveType == SAVE_EEPROM_16k); + if (channel == 4) { + const u8 offset = cmd[3]; + if ((offset * 8) >= GetSaveSize(mem.saveType)) { + panic("Out of range EEPROM read! offset: {:02X}", offset); + } - std::copy_n(eeprom.begin() + offset * 8, 8, res); - } else { - panic("EEPROM read on bad channel {}", channel); - } + std::copy_n(eeprom.begin() + offset * 8, 8, res); + } else { + panic("EEPROM read on bad channel {}", channel); + } } 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); - if (channel == 4) { - const u8 offset = cmd[3]; - if ((offset * 8) >= GetSaveSize(mem.saveType)) { - panic("Out of range EEPROM write! offset: {:02X}", offset); + n64::Mem &mem = n64::Core::GetMem(); + assert(mem.saveType == SAVE_EEPROM_4k || mem.saveType == SAVE_EEPROM_16k); + if (channel == 4) { + const u8 offset = cmd[3]; + if ((offset * 8) >= GetSaveSize(mem.saveType)) { + panic("Out of range EEPROM write! offset: {:02X}", offset); + } + + std::copy_n(cmd + 4, 8, eeprom.begin() + offset * 8); + + res[0] = 0; // Error byte, I guess it always succeeds? + } else { + panic("EEPROM write on bad channel {}", channel); } - - std::copy_n(cmd + 4, 8, eeprom.begin() + offset * 8); - - res[0] = 0; // Error byte, I guess it always succeeds? - } else { - panic("EEPROM write on bad channel {}", channel); - } } void PIF::HLE(const bool pal, const CICType cicType) const { - n64::Mem& mem = n64::Core::GetMem(); - n64::Registers& regs = n64::Core::GetRegs(); - mem.Write(PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]); + n64::Mem &mem = n64::Core::GetMem(); + n64::Registers ®s = n64::Core::GetRegs(); + mem.Write(PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]); - switch (cicType) { - case UNKNOWN_CIC_TYPE: - warn("Unknown CIC type!"); - break; - case CIC_NUS_6101: - regs.Write(0, 0x0000000000000000); - regs.Write(1, 0x0000000000000000); - regs.Write(2, 0xFFFFFFFFDF6445CC); - regs.Write(3, 0xFFFFFFFFDF6445CC); - regs.Write(4, 0x00000000000045CC); - regs.Write(5, 0x0000000073EE317A); - regs.Write(6, 0xFFFFFFFFA4001F0C); - regs.Write(7, 0xFFFFFFFFA4001F08); - regs.Write(8, 0x00000000000000C0); - regs.Write(9, 0x0000000000000000); - regs.Write(10, 0x0000000000000040); - regs.Write(11, 0xFFFFFFFFA4000040); - regs.Write(12, 0xFFFFFFFFC7601FAC); - regs.Write(13, 0xFFFFFFFFC7601FAC); - regs.Write(14, 0xFFFFFFFFB48E2ED6); - regs.Write(15, 0xFFFFFFFFBA1A7D4B); - regs.Write(16, 0x0000000000000000); - regs.Write(17, 0x0000000000000000); - regs.Write(18, 0x0000000000000000); - regs.Write(19, 0x0000000000000000); - regs.Write(20, 0x0000000000000001); - regs.Write(21, 0x0000000000000000); - regs.Write(23, 0x0000000000000001); - regs.Write(24, 0x0000000000000002); - regs.Write(25, 0xFFFFFFFF905F4718); - regs.Write(26, 0x0000000000000000); - regs.Write(27, 0x0000000000000000); - regs.Write(28, 0x0000000000000000); - regs.Write(29, 0xFFFFFFFFA4001FF0); - regs.Write(30, 0x0000000000000000); - regs.Write(31, 0xFFFFFFFFA4001550); + switch (cicType) { + case UNKNOWN_CIC_TYPE: + warn("Unknown CIC type!"); + break; + case CIC_NUS_6101: + regs.Write(0, 0x0000000000000000); + regs.Write(1, 0x0000000000000000); + regs.Write(2, 0xFFFFFFFFDF6445CC); + regs.Write(3, 0xFFFFFFFFDF6445CC); + regs.Write(4, 0x00000000000045CC); + regs.Write(5, 0x0000000073EE317A); + regs.Write(6, 0xFFFFFFFFA4001F0C); + regs.Write(7, 0xFFFFFFFFA4001F08); + regs.Write(8, 0x00000000000000C0); + regs.Write(9, 0x0000000000000000); + regs.Write(10, 0x0000000000000040); + regs.Write(11, 0xFFFFFFFFA4000040); + regs.Write(12, 0xFFFFFFFFC7601FAC); + regs.Write(13, 0xFFFFFFFFC7601FAC); + regs.Write(14, 0xFFFFFFFFB48E2ED6); + regs.Write(15, 0xFFFFFFFFBA1A7D4B); + regs.Write(16, 0x0000000000000000); + regs.Write(17, 0x0000000000000000); + regs.Write(18, 0x0000000000000000); + regs.Write(19, 0x0000000000000000); + regs.Write(20, 0x0000000000000001); + regs.Write(21, 0x0000000000000000); + regs.Write(23, 0x0000000000000001); + regs.Write(24, 0x0000000000000002); + regs.Write(25, 0xFFFFFFFF905F4718); + regs.Write(26, 0x0000000000000000); + regs.Write(27, 0x0000000000000000); + regs.Write(28, 0x0000000000000000); + regs.Write(29, 0xFFFFFFFFA4001FF0); + regs.Write(30, 0x0000000000000000); + regs.Write(31, 0xFFFFFFFFA4001550); - regs.lo = 0xFFFFFFFFBA1A7D4Bll; - regs.hi = 0xFFFFFFFF997EC317ll; - break; - case CIC_NUS_7102: - regs.Write(0, 0x0000000000000000); - regs.Write(1, 0x0000000000000001); - regs.Write(2, 0x000000001E324416); - regs.Write(3, 0x000000001E324416); - regs.Write(4, 0x0000000000004416); - regs.Write(5, 0x000000000EC5D9AF); - regs.Write(6, 0xFFFFFFFFA4001F0C); - regs.Write(7, 0xFFFFFFFFA4001F08); - regs.Write(8, 0x00000000000000C0); - regs.Write(9, 0x0000000000000000); - regs.Write(10, 0x0000000000000040); - regs.Write(11, 0xFFFFFFFFA4000040); - regs.Write(12, 0x00000000495D3D7B); - regs.Write(13, 0xFFFFFFFF8B3DFA1E); - regs.Write(14, 0x000000004798E4D4); - regs.Write(15, 0xFFFFFFFFF1D30682); - regs.Write(16, 0x0000000000000000); - regs.Write(17, 0x0000000000000000); - regs.Write(18, 0x0000000000000000); - regs.Write(19, 0x0000000000000000); - regs.Write(20, 0x0000000000000000); - regs.Write(21, 0x0000000000000000); - regs.Write(22, 0x000000000000003F); - regs.Write(23, 0x0000000000000007); - regs.Write(24, 0x0000000000000000); - regs.Write(25, 0x0000000013D05CAB); - regs.Write(26, 0x0000000000000000); - regs.Write(27, 0x0000000000000000); - regs.Write(28, 0x0000000000000000); - regs.Write(29, 0xFFFFFFFFA4001FF0); - regs.Write(30, 0x0000000000000000); - regs.Write(31, 0xFFFFFFFFA4001554); + regs.lo = 0xFFFFFFFFBA1A7D4Bll; + regs.hi = 0xFFFFFFFF997EC317ll; + break; + case CIC_NUS_7102: + regs.Write(0, 0x0000000000000000); + regs.Write(1, 0x0000000000000001); + regs.Write(2, 0x000000001E324416); + regs.Write(3, 0x000000001E324416); + regs.Write(4, 0x0000000000004416); + regs.Write(5, 0x000000000EC5D9AF); + regs.Write(6, 0xFFFFFFFFA4001F0C); + regs.Write(7, 0xFFFFFFFFA4001F08); + regs.Write(8, 0x00000000000000C0); + regs.Write(9, 0x0000000000000000); + regs.Write(10, 0x0000000000000040); + regs.Write(11, 0xFFFFFFFFA4000040); + regs.Write(12, 0x00000000495D3D7B); + regs.Write(13, 0xFFFFFFFF8B3DFA1E); + regs.Write(14, 0x000000004798E4D4); + regs.Write(15, 0xFFFFFFFFF1D30682); + regs.Write(16, 0x0000000000000000); + regs.Write(17, 0x0000000000000000); + regs.Write(18, 0x0000000000000000); + regs.Write(19, 0x0000000000000000); + regs.Write(20, 0x0000000000000000); + regs.Write(21, 0x0000000000000000); + regs.Write(22, 0x000000000000003F); + regs.Write(23, 0x0000000000000007); + regs.Write(24, 0x0000000000000000); + regs.Write(25, 0x0000000013D05CAB); + regs.Write(26, 0x0000000000000000); + regs.Write(27, 0x0000000000000000); + regs.Write(28, 0x0000000000000000); + regs.Write(29, 0xFFFFFFFFA4001FF0); + regs.Write(30, 0x0000000000000000); + regs.Write(31, 0xFFFFFFFFA4001554); - regs.lo = 0xFFFFFFFFF1D30682ll; - regs.hi = 0x0000000010054A98; - break; - case CIC_NUS_6102_7101: - regs.Write(0, 0x0000000000000000); - regs.Write(1, 0x0000000000000001); - regs.Write(2, 0x000000000EBDA536); - regs.Write(3, 0x000000000EBDA536); - regs.Write(4, 0x000000000000A536); - regs.Write(5, 0xFFFFFFFFC0F1D859); - regs.Write(6, 0xFFFFFFFFA4001F0C); - regs.Write(7, 0xFFFFFFFFA4001F08); - regs.Write(8, 0x00000000000000C0); - regs.Write(9, 0x0000000000000000); - regs.Write(10, 0x0000000000000040); - regs.Write(11, 0xFFFFFFFFA4000040); - regs.Write(12, 0xFFFFFFFFED10D0B3); - regs.Write(13, 0x000000001402A4CC); - regs.Write(14, 0x000000002DE108EA); - regs.Write(15, 0x000000003103E121); - regs.Write(16, 0x0000000000000000); - regs.Write(17, 0x0000000000000000); - regs.Write(18, 0x0000000000000000); - regs.Write(19, 0x0000000000000000); - regs.Write(20, 0x0000000000000001); - regs.Write(21, 0x0000000000000000); - regs.Write(23, 0x0000000000000000); - regs.Write(24, 0x0000000000000000); - regs.Write(25, 0xFFFFFFFF9DEBB54F); - regs.Write(26, 0x0000000000000000); - regs.Write(27, 0x0000000000000000); - regs.Write(28, 0x0000000000000000); - regs.Write(29, 0xFFFFFFFFA4001FF0); - regs.Write(30, 0x0000000000000000); - regs.Write(31, 0xFFFFFFFFA4001550); + regs.lo = 0xFFFFFFFFF1D30682ll; + regs.hi = 0x0000000010054A98; + break; + case CIC_NUS_6102_7101: + regs.Write(0, 0x0000000000000000); + regs.Write(1, 0x0000000000000001); + regs.Write(2, 0x000000000EBDA536); + regs.Write(3, 0x000000000EBDA536); + regs.Write(4, 0x000000000000A536); + regs.Write(5, 0xFFFFFFFFC0F1D859); + regs.Write(6, 0xFFFFFFFFA4001F0C); + regs.Write(7, 0xFFFFFFFFA4001F08); + regs.Write(8, 0x00000000000000C0); + regs.Write(9, 0x0000000000000000); + regs.Write(10, 0x0000000000000040); + regs.Write(11, 0xFFFFFFFFA4000040); + regs.Write(12, 0xFFFFFFFFED10D0B3); + regs.Write(13, 0x000000001402A4CC); + regs.Write(14, 0x000000002DE108EA); + regs.Write(15, 0x000000003103E121); + regs.Write(16, 0x0000000000000000); + regs.Write(17, 0x0000000000000000); + regs.Write(18, 0x0000000000000000); + regs.Write(19, 0x0000000000000000); + regs.Write(20, 0x0000000000000001); + regs.Write(21, 0x0000000000000000); + regs.Write(23, 0x0000000000000000); + regs.Write(24, 0x0000000000000000); + regs.Write(25, 0xFFFFFFFF9DEBB54F); + regs.Write(26, 0x0000000000000000); + regs.Write(27, 0x0000000000000000); + regs.Write(28, 0x0000000000000000); + regs.Write(29, 0xFFFFFFFFA4001FF0); + regs.Write(30, 0x0000000000000000); + regs.Write(31, 0xFFFFFFFFA4001550); - regs.hi = 0x000000003FC18657; - regs.lo = 0x000000003103E121; + regs.hi = 0x000000003FC18657; + regs.lo = 0x000000003103E121; - if (pal) { - regs.Write(20, 0x0000000000000000); - regs.Write(23, 0x0000000000000006); - regs.Write(31, 0xFFFFFFFFA4001554); - } - break; - case CIC_NUS_6103_7103: - regs.Write(0, 0x0000000000000000); - regs.Write(1, 0x0000000000000001); - regs.Write(2, 0x0000000049A5EE96); - regs.Write(3, 0x0000000049A5EE96); - regs.Write(4, 0x000000000000EE96); - regs.Write(5, 0xFFFFFFFFD4646273); - regs.Write(6, 0xFFFFFFFFA4001F0C); - regs.Write(7, 0xFFFFFFFFA4001F08); - regs.Write(8, 0x00000000000000C0); - regs.Write(9, 0x0000000000000000); - regs.Write(10, 0x0000000000000040); - regs.Write(11, 0xFFFFFFFFA4000040); - regs.Write(12, 0xFFFFFFFFCE9DFBF7); - regs.Write(13, 0xFFFFFFFFCE9DFBF7); - regs.Write(14, 0x000000001AF99984); - regs.Write(15, 0x0000000018B63D28); - regs.Write(16, 0x0000000000000000); - regs.Write(17, 0x0000000000000000); - regs.Write(18, 0x0000000000000000); - regs.Write(19, 0x0000000000000000); - regs.Write(20, 0x0000000000000001); - regs.Write(21, 0x0000000000000000); - regs.Write(23, 0x0000000000000000); - regs.Write(24, 0x0000000000000000); - regs.Write(25, 0xFFFFFFFF825B21C9); - regs.Write(26, 0x0000000000000000); - regs.Write(27, 0x0000000000000000); - regs.Write(28, 0x0000000000000000); - regs.Write(29, 0xFFFFFFFFA4001FF0); - regs.Write(30, 0x0000000000000000); - regs.Write(31, 0xFFFFFFFFA4001550); + if (pal) { + regs.Write(20, 0x0000000000000000); + regs.Write(23, 0x0000000000000006); + regs.Write(31, 0xFFFFFFFFA4001554); + } + break; + case CIC_NUS_6103_7103: + regs.Write(0, 0x0000000000000000); + regs.Write(1, 0x0000000000000001); + regs.Write(2, 0x0000000049A5EE96); + regs.Write(3, 0x0000000049A5EE96); + regs.Write(4, 0x000000000000EE96); + regs.Write(5, 0xFFFFFFFFD4646273); + regs.Write(6, 0xFFFFFFFFA4001F0C); + regs.Write(7, 0xFFFFFFFFA4001F08); + regs.Write(8, 0x00000000000000C0); + regs.Write(9, 0x0000000000000000); + regs.Write(10, 0x0000000000000040); + regs.Write(11, 0xFFFFFFFFA4000040); + regs.Write(12, 0xFFFFFFFFCE9DFBF7); + regs.Write(13, 0xFFFFFFFFCE9DFBF7); + regs.Write(14, 0x000000001AF99984); + regs.Write(15, 0x0000000018B63D28); + regs.Write(16, 0x0000000000000000); + regs.Write(17, 0x0000000000000000); + regs.Write(18, 0x0000000000000000); + regs.Write(19, 0x0000000000000000); + regs.Write(20, 0x0000000000000001); + regs.Write(21, 0x0000000000000000); + regs.Write(23, 0x0000000000000000); + regs.Write(24, 0x0000000000000000); + regs.Write(25, 0xFFFFFFFF825B21C9); + regs.Write(26, 0x0000000000000000); + regs.Write(27, 0x0000000000000000); + regs.Write(28, 0x0000000000000000); + regs.Write(29, 0xFFFFFFFFA4001FF0); + regs.Write(30, 0x0000000000000000); + regs.Write(31, 0xFFFFFFFFA4001550); - regs.lo = 0x0000000018B63D28; - regs.hi = 0x00000000625C2BBE; + regs.lo = 0x0000000018B63D28; + regs.hi = 0x00000000625C2BBE; - if (pal) { - regs.Write(20, 0x0000000000000000); - regs.Write(23, 0x0000000000000006); - regs.Write(31, 0xFFFFFFFFA4001554); - } - break; - case CIC_NUS_6105_7105: - regs.Write(0, 0x0000000000000000); - regs.Write(1, 0x0000000000000000); - regs.Write(2, 0xFFFFFFFFF58B0FBF); - regs.Write(3, 0xFFFFFFFFF58B0FBF); - regs.Write(4, 0x0000000000000FBF); - regs.Write(5, 0xFFFFFFFFDECAAAD1); - regs.Write(6, 0xFFFFFFFFA4001F0C); - regs.Write(7, 0xFFFFFFFFA4001F08); - regs.Write(8, 0x00000000000000C0); - regs.Write(9, 0x0000000000000000); - regs.Write(10, 0x0000000000000040); - regs.Write(11, 0xFFFFFFFFA4000040); - regs.Write(12, 0xFFFFFFFF9651F81E); - regs.Write(13, 0x000000002D42AAC5); - regs.Write(14, 0x00000000489B52CF); - regs.Write(15, 0x0000000056584D60); - regs.Write(16, 0x0000000000000000); - regs.Write(17, 0x0000000000000000); - regs.Write(18, 0x0000000000000000); - regs.Write(19, 0x0000000000000000); - regs.Write(20, 0x0000000000000001); - regs.Write(21, 0x0000000000000000); - regs.Write(23, 0x0000000000000000); - regs.Write(24, 0x0000000000000002); - regs.Write(25, 0xFFFFFFFFCDCE565F); - regs.Write(26, 0x0000000000000000); - regs.Write(27, 0x0000000000000000); - regs.Write(28, 0x0000000000000000); - regs.Write(29, 0xFFFFFFFFA4001FF0); - regs.Write(30, 0x0000000000000000); - regs.Write(31, 0xFFFFFFFFA4001550); + if (pal) { + regs.Write(20, 0x0000000000000000); + regs.Write(23, 0x0000000000000006); + regs.Write(31, 0xFFFFFFFFA4001554); + } + break; + case CIC_NUS_6105_7105: + regs.Write(0, 0x0000000000000000); + regs.Write(1, 0x0000000000000000); + regs.Write(2, 0xFFFFFFFFF58B0FBF); + regs.Write(3, 0xFFFFFFFFF58B0FBF); + regs.Write(4, 0x0000000000000FBF); + regs.Write(5, 0xFFFFFFFFDECAAAD1); + regs.Write(6, 0xFFFFFFFFA4001F0C); + regs.Write(7, 0xFFFFFFFFA4001F08); + regs.Write(8, 0x00000000000000C0); + regs.Write(9, 0x0000000000000000); + regs.Write(10, 0x0000000000000040); + regs.Write(11, 0xFFFFFFFFA4000040); + regs.Write(12, 0xFFFFFFFF9651F81E); + regs.Write(13, 0x000000002D42AAC5); + regs.Write(14, 0x00000000489B52CF); + regs.Write(15, 0x0000000056584D60); + regs.Write(16, 0x0000000000000000); + regs.Write(17, 0x0000000000000000); + regs.Write(18, 0x0000000000000000); + regs.Write(19, 0x0000000000000000); + regs.Write(20, 0x0000000000000001); + regs.Write(21, 0x0000000000000000); + regs.Write(23, 0x0000000000000000); + regs.Write(24, 0x0000000000000002); + regs.Write(25, 0xFFFFFFFFCDCE565F); + regs.Write(26, 0x0000000000000000); + regs.Write(27, 0x0000000000000000); + regs.Write(28, 0x0000000000000000); + regs.Write(29, 0xFFFFFFFFA4001FF0); + regs.Write(30, 0x0000000000000000); + regs.Write(31, 0xFFFFFFFFA4001550); - regs.lo = 0x0000000056584D60; - regs.hi = 0x000000004BE35D1F; + regs.lo = 0x0000000056584D60; + regs.hi = 0x000000004BE35D1F; - if (pal) { - regs.Write(20, 0x0000000000000000); - regs.Write(23, 0x0000000000000006); - regs.Write(31, 0xFFFFFFFFA4001554); + if (pal) { + regs.Write(20, 0x0000000000000000); + regs.Write(23, 0x0000000000000006); + regs.Write(31, 0xFFFFFFFFA4001554); + } + + mem.Write(IMEM_REGION_START + 0x00, 0x3C0DBFC0); + mem.Write(IMEM_REGION_START + 0x04, 0x8DA807FC); + mem.Write(IMEM_REGION_START + 0x08, 0x25AD07C0); + mem.Write(IMEM_REGION_START + 0x0C, 0x31080080); + mem.Write(IMEM_REGION_START + 0x10, 0x5500FFFC); + mem.Write(IMEM_REGION_START + 0x14, 0x3C0DBFC0); + mem.Write(IMEM_REGION_START + 0x18, 0x8DA80024); + mem.Write(IMEM_REGION_START + 0x1C, 0x3C0BB000); + break; + case CIC_NUS_6106_7106: + regs.Write(0, 0x0000000000000000); + regs.Write(1, 0x0000000000000000); + regs.Write(2, 0xFFFFFFFFA95930A4); + regs.Write(3, 0xFFFFFFFFA95930A4); + regs.Write(4, 0x00000000000030A4); + regs.Write(5, 0xFFFFFFFFB04DC903); + regs.Write(6, 0xFFFFFFFFA4001F0C); + regs.Write(7, 0xFFFFFFFFA4001F08); + regs.Write(8, 0x00000000000000C0); + regs.Write(9, 0x0000000000000000); + regs.Write(10, 0x0000000000000040); + regs.Write(11, 0xFFFFFFFFA4000040); + regs.Write(12, 0xFFFFFFFFBCB59510); + regs.Write(13, 0xFFFFFFFFBCB59510); + regs.Write(14, 0x000000000CF85C13); + regs.Write(15, 0x000000007A3C07F4); + regs.Write(16, 0x0000000000000000); + regs.Write(17, 0x0000000000000000); + regs.Write(18, 0x0000000000000000); + regs.Write(19, 0x0000000000000000); + regs.Write(20, 0x0000000000000001); + regs.Write(21, 0x0000000000000000); + regs.Write(23, 0x0000000000000000); + regs.Write(24, 0x0000000000000002); + regs.Write(25, 0x00000000465E3F72); + regs.Write(26, 0x0000000000000000); + regs.Write(27, 0x0000000000000000); + regs.Write(28, 0x0000000000000000); + regs.Write(29, 0xFFFFFFFFA4001FF0); + regs.Write(30, 0x0000000000000000); + regs.Write(31, 0xFFFFFFFFA4001550); + regs.lo = 0x000000007A3C07F4; + regs.hi = 0x0000000023953898; + + if (pal) { + regs.Write(20, 0x0000000000000000); + regs.Write(23, 0x0000000000000006); + regs.Write(31, 0xFFFFFFFFA4001554); + } + break; } - mem.Write(IMEM_REGION_START + 0x00, 0x3C0DBFC0); - mem.Write(IMEM_REGION_START + 0x04, 0x8DA807FC); - mem.Write(IMEM_REGION_START + 0x08, 0x25AD07C0); - mem.Write(IMEM_REGION_START + 0x0C, 0x31080080); - mem.Write(IMEM_REGION_START + 0x10, 0x5500FFFC); - mem.Write(IMEM_REGION_START + 0x14, 0x3C0DBFC0); - mem.Write(IMEM_REGION_START + 0x18, 0x8DA80024); - mem.Write(IMEM_REGION_START + 0x1C, 0x3C0BB000); - break; - case CIC_NUS_6106_7106: - regs.Write(0, 0x0000000000000000); - regs.Write(1, 0x0000000000000000); - regs.Write(2, 0xFFFFFFFFA95930A4); - regs.Write(3, 0xFFFFFFFFA95930A4); - regs.Write(4, 0x00000000000030A4); - regs.Write(5, 0xFFFFFFFFB04DC903); - regs.Write(6, 0xFFFFFFFFA4001F0C); - regs.Write(7, 0xFFFFFFFFA4001F08); - regs.Write(8, 0x00000000000000C0); - regs.Write(9, 0x0000000000000000); - regs.Write(10, 0x0000000000000040); - regs.Write(11, 0xFFFFFFFFA4000040); - regs.Write(12, 0xFFFFFFFFBCB59510); - regs.Write(13, 0xFFFFFFFFBCB59510); - regs.Write(14, 0x000000000CF85C13); - regs.Write(15, 0x000000007A3C07F4); - regs.Write(16, 0x0000000000000000); - regs.Write(17, 0x0000000000000000); - regs.Write(18, 0x0000000000000000); - regs.Write(19, 0x0000000000000000); - regs.Write(20, 0x0000000000000001); - regs.Write(21, 0x0000000000000000); - regs.Write(23, 0x0000000000000000); - regs.Write(24, 0x0000000000000002); - regs.Write(25, 0x00000000465E3F72); - regs.Write(26, 0x0000000000000000); - regs.Write(27, 0x0000000000000000); - regs.Write(28, 0x0000000000000000); - regs.Write(29, 0xFFFFFFFFA4001FF0); - regs.Write(30, 0x0000000000000000); - regs.Write(31, 0xFFFFFFFFA4001550); - regs.lo = 0x000000007A3C07F4; - regs.hi = 0x0000000023953898; - - if (pal) { - regs.Write(20, 0x0000000000000000); - regs.Write(23, 0x0000000000000006); - regs.Write(31, 0xFFFFFFFFA4001554); - } - break; - } - - regs.Write(22, (cicSeeds[cicType] >> 8) & 0xFF); - regs.cop0.Reset(); - mem.Write(0x04300004, 0x01010101); - std::copy_n(mem.rom.cart.begin(), 0x1000, mem.mmio.rsp.dmem.begin()); - regs.SetPC32(static_cast(0xA4000040)); + regs.Write(22, (cicSeeds[cicType] >> 8) & 0xFF); + regs.cop0.Reset(); + mem.Write(0x04300004, 0x01010101); + std::copy_n(mem.rom.cart.begin(), 0x1000, mem.mmio.rsp.dmem.begin()); + regs.SetPC32(static_cast(0xA4000040)); } void PIF::Execute() const { - n64::Mem& mem = n64::Core::GetMem(); - const CICType cicType = mem.rom.cicType; - const bool pal = mem.rom.pal; - mem.Write(PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]); - switch (cicType) { - case UNKNOWN_CIC_TYPE: - warn("Unknown CIC type!"); - break; - case CIC_NUS_6101 ... CIC_NUS_6103_7103: - mem.Write(0x318, RDRAM_SIZE); - break; - case CIC_NUS_6105_7105: - mem.Write(0x3F0, RDRAM_SIZE); - break; - case CIC_NUS_6106_7106: - break; - } + n64::Mem &mem = n64::Core::GetMem(); + const CICType cicType = mem.rom.cicType; + const bool pal = mem.rom.pal; + mem.Write(PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]); + switch (cicType) { + case UNKNOWN_CIC_TYPE: + warn("Unknown CIC type!"); + break; + case CIC_NUS_6101 ... CIC_NUS_6103_7103: + mem.Write(0x318, RDRAM_SIZE); + break; + case CIC_NUS_6105_7105: + mem.Write(0x3F0, RDRAM_SIZE); + break; + case CIC_NUS_6106_7106: + break; + } - HLE(pal, cicType); + HLE(pal, cicType); } } // namespace n64 diff --git a/src/backend/core/mmio/SI.cpp b/src/backend/core/mmio/SI.cpp index 539c249..9a35327 100644 --- a/src/backend/core/mmio/SI.cpp +++ b/src/backend/core/mmio/SI.cpp @@ -78,7 +78,6 @@ void SI::Write(u32 addr, u32 val) { status.dmaBusy = true; toDram = true; Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA); - Core::GetInstance().interpreter.cachedState.EvictCachedBlocksRange(dramAddr, dramAddr + 64); break; case 0x04800010: pifAddr = val & 0x1FFFFFFF;