Add support for different CIC chips

This commit is contained in:
CocoSimone
2022-10-01 14:45:43 +02:00
parent 38b5b4d430
commit b79c869415
11 changed files with 317 additions and 27 deletions

View File

@@ -148,10 +148,10 @@ ImDrawData* Window::Present(n64::Core& core) {
void Window::LoadROM(n64::Core& core, const std::string &path) {
if(!path.empty()) {
u32 crc = core.LoadROM(path);
n64::CartInfo cartInfo = core.LoadROM(path);
std::ifstream gameDbFile("resources/game_db.json");
json gameDb = json::parse(gameDbFile);
auto entry = gameDb[fmt::format("{:08x}", crc)]["name"];
auto entry = gameDb[fmt::format("{:08x}", cartInfo.crc)]["name"];
std::string name{};
if(!entry.empty()) {
name = entry.get<std::string>();

View File

@@ -16,13 +16,17 @@ void Core::Stop() {
romLoaded = false;
}
u32 Core::LoadROM(const std::string& rom_) {
CartInfo Core::LoadROM(const std::string& rom_) {
rom = rom_;
cpu.Reset();
mem.Reset();
pause = false;
romLoaded = true;
return mem.LoadROM(rom);
CartInfo cartInfo = mem.LoadROM(rom);
DoPIFHLE(mem, cpu.regs, cartInfo);
return cartInfo;
}
void Core::Run(Window& window, float volumeL, float volumeR) {

View File

@@ -5,12 +5,13 @@
#include <string>
struct Window;
namespace n64 {
struct Core {
~Core() { Stop(); }
Core();
void Stop();
u32 LoadROM(const std::string&);
CartInfo LoadROM(const std::string&);
void Run(Window&, float volumeL, float volumeR);
void UpdateController(const u8*);
void TogglePause() { pause = !pause; }

View File

@@ -16,7 +16,7 @@ void Mem::Reset() {
mmio.Reset();
}
u32 Mem::LoadROM(const std::string& filename) {
CartInfo Mem::LoadROM(const std::string& filename) {
std::ifstream file(filename, std::ios::binary);
file.unsetf(std::ios::skipws);
@@ -36,14 +36,16 @@ u32 Mem::LoadROM(const std::string& filename) {
file.close();
u32 crc = 0;
util::SwapN64Rom(crc, sizeAdjusted, cart.data());
CartInfo result{};
u32 cicChecksum;
util::SwapN64Rom(sizeAdjusted, cart.data(), result.crc, cicChecksum);
memcpy(mmio.rsp.dmem, cart.data(), 0x1000);
u32 rdram_size = RDRAM_SIZE;
memcpy(&mmio.rdp.dram[0x318], &rdram_size, sizeof(u32));
SetCICType(result.cicType, cicChecksum);
result.isPAL = IsROMPAL();
return crc;
return result;
}
template <bool tlb>

View File

@@ -7,11 +7,18 @@
namespace n64 {
struct Registers;
struct CartInfo {
bool isPAL;
u32 cicType;
u32 crc;
};
struct Mem {
~Mem() = default;
Mem();
void Reset();
u32 LoadROM(const std::string&);
CartInfo LoadROM(const std::string&);
[[nodiscard]] auto GetRDRAM() -> u8* {
return mmio.rdp.dram.data();
}
@@ -46,6 +53,47 @@ private:
u8 pifBootrom[PIF_BOOTROM_SIZE]{};
u8 isviewer[ISVIEWER_SIZE]{};
size_t romMask;
void SetCICType(u32& cicType, u32 checksum) {
switch(checksum) {
case 0xEC8B1325: // 7102
cicType = CIC_NUS_7102;
case 0x1DEB51A9: // 6101
cicType = CIC_NUS_6101;
break;
case 0xC08E5BD6:
cicType = CIC_NUS_6102_7101;
break;
case 0x03B8376A:
cicType = CIC_NUS_6103_7103;
break;
case 0xCF7F41DC:
cicType = CIC_NUS_6105_7105;
break;
case 0xD1059C6A:
cicType = CIC_NUS_6106_7106;
break;
default:
util::warn("Could not determine CIC TYPE! Checksum: {:08X} is unknown!\n", checksum);
cicType = UNKNOWN_CIC_TYPE;
break;
}
}
bool IsROMPAL() {
static const char pal_codes[] = {'D', 'F', 'I', 'P', 'S', 'U', 'X', 'Y'};
for (int i = 0; i < 8; i++) {
if (cart[0x3e] == pal_codes[i]) {
return true;
}
}
return false;
}
};
template <bool tlb = true>

View File

@@ -12,14 +12,6 @@ void Registers::Reset() {
oldPC = (s64)0xFFFFFFFFA4000040;
pc = oldPC;
nextPC = pc + 4;
lo = 0;
hi = 0;
gpr[11] = (s64)0xFFFFFFFFA4000040;
gpr[20] = 0x0000000000000001;
gpr[22] = 0x000000000000003F;
gpr[29] = (s64)0xFFFFFFFFA4001FF0;
cop0.Reset();
cop1.Reset();
}
void Registers::SetPC(s64 val) {

View File

@@ -3,7 +3,7 @@
#include <util.hpp>
#include <n64/core/mmio/Interrupt.hpp>
#define MI_VERSION_REG 0x02020102
#define MI_VERSION_REG 0x01010101
namespace n64 {
MI::MI() {

View File

@@ -1,5 +1,6 @@
#include <n64/core/mmio/PIF.hpp>
#include <n64/core/Mem.hpp>
#include <n64/core/cpu/Registers.hpp>
#include <util.hpp>
namespace n64 {
@@ -65,4 +66,208 @@ void ProcessPIFCommands(u8* pifRam, Controller& controller, Mem& mem) {
}
}
void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
u32 cicType = cartInfo.cicType;
bool pal = cartInfo.isPAL;
mem.Write32<false>(regs, 0x1FC007E4, cicSeeds[cicType], regs.pc);
switch(cicType) {
case CIC_NUS_6101:
mem.Write32<false>(regs, 0x318, RDRAM_SIZE, regs.pc);
regs.gpr[2] = (s64)0xFFFFFFFFDF6445CC;
regs.gpr[3] = (s64)0xFFFFFFFFDF6445CC;
regs.gpr[4] = 0x45CC;
regs.gpr[5] = 0x73EE317A;
regs.gpr[6] = (s64)0xFFFFFFFFA4001F0C;
regs.gpr[7] = (s64)0xFFFFFFFFA4001F08;
regs.gpr[8] = 0xC0;
regs.gpr[10] = 0x40;
regs.gpr[11] = (s64)0xFFFFFFFFA4000040;
regs.gpr[12] = (s64)0xFFFFFFFFC7601FAC;
regs.gpr[13] = (s64)0xFFFFFFFFC7601FAC;
regs.gpr[14] = (s64)0xFFFFFFFFB48E2ED6;
regs.gpr[15] = (s64)0xFFFFFFFFBA1A7D4B;
regs.gpr[20] = 0x0000000000000001;
regs.gpr[22] = 0x000000000000003F;
regs.gpr[23] = 0x0000000000000001;
regs.gpr[24] = 0x0000000000000002;
regs.gpr[25] = (s64)0xFFFFFFFF905F4718;
regs.gpr[29] = (s64)0xFFFFFFFFA4001FF0;
regs.gpr[31] = (s64)0xFFFFFFFFA4001550;
regs.lo = (s64)0xFFFFFFFFBA1A7D4B;
regs.hi = (s64)0xFFFFFFFF997EC317;
break;
case CIC_NUS_7102:
mem.Write32<false>(regs, 0x318, RDRAM_SIZE, regs.pc);
regs.gpr[1] = 0x0000000000000001;
regs.gpr[2] = 0x000000001E324416;
regs.gpr[3] = 0x000000001E324416;
regs.gpr[4] = 0x0000000000004416;
regs.gpr[5] = 0x000000000EC5D9AF;
regs.gpr[6] = (s64)0xFFFFFFFFA4001F0C;
regs.gpr[7] = (s64)0xFFFFFFFFA4001F08;
regs.gpr[8] = 0x00000000000000C0;
regs.gpr[10] = 0x0000000000000040;
regs.gpr[11] = (s64)0xFFFFFFFFA4000040;
regs.gpr[12] = 0x00000000495D3D7B;
regs.gpr[13] = (s64)0xFFFFFFFF8B3DFA1E;
regs.gpr[14] = 0x000000004798E4D4;
regs.gpr[15] = (s64)0xFFFFFFFFF1D30682;
regs.gpr[22] = 0x000000000000003F;
regs.gpr[23] = 0x0000000000000007;
regs.gpr[25] = 0x0000000013D05CAB;
regs.gpr[29] = (s64)0xFFFFFFFFA4001FF0;
regs.gpr[31] = (s64)0xFFFFFFFFA4001554;
regs.lo = (s64)0xFFFFFFFFF1D30682;
regs.hi = 0x0000000010054A98;
break;
case CIC_NUS_6102_7101:
mem.Write32<false>(regs, 0x318, RDRAM_SIZE, regs.pc);
regs.gpr[1] = 0x0000000000000001;
regs.gpr[2] = 0x000000000EBDA536;
regs.gpr[3] = 0x000000000EBDA536;
regs.gpr[4] = 0x000000000000A536;
regs.gpr[5] = (s64)0xFFFFFFFFC0F1D859;
regs.gpr[6] = (s64)0xFFFFFFFFA4001F0C;
regs.gpr[7] = (s64)0xFFFFFFFFA4001F08;
regs.gpr[8] = 0x00000000000000C0;
regs.gpr[10] = 0x0000000000000040;
regs.gpr[11] = (s64)0xFFFFFFFFA4000040;
regs.gpr[12] = (s64)0xFFFFFFFFED10D0B3;
regs.gpr[13] = 0x000000001402A4CC;
regs.gpr[14] = 0x000000002DE108EA;
regs.gpr[15] = 0x000000003103E121;
regs.gpr[20] = 0x0000000000000001;
regs.gpr[25] = (s64)0xFFFFFFFF9DEBB54F;
regs.gpr[29] = (s64)0xFFFFFFFFA4001FF0;
regs.gpr[31] = (s64)0xFFFFFFFFA4001550;
regs.hi = 0x000000003FC18657;
regs.lo = 0x000000003103E121;
if (pal) {
regs.gpr[20] = 0x0000000000000000;
regs.gpr[23] = 0x0000000000000006;
regs.gpr[31] = (s64)0xFFFFFFFFA4001554;
}
break;
case CIC_NUS_6103_7103:
mem.Write32<false>(regs, 0x318, RDRAM_SIZE, regs.pc);
regs.gpr[0] = 0x0000000000000000;
regs.gpr[1] = 0x0000000000000001;
regs.gpr[2] = 0x0000000049A5EE96;
regs.gpr[3] = 0x0000000049A5EE96;
regs.gpr[4] = 0x000000000000EE96;
regs.gpr[5] = (s64)0xFFFFFFFFD4646273;
regs.gpr[6] = (s64)0xFFFFFFFFA4001F0C;
regs.gpr[7] = (s64)0xFFFFFFFFA4001F08;
regs.gpr[8] = 0x00000000000000C0;
regs.gpr[9] = 0x0000000000000000;
regs.gpr[10] = 0x0000000000000040;
regs.gpr[11] = (s64)0xFFFFFFFFA4000040;
regs.gpr[12] = (s64)0xFFFFFFFFCE9DFBF7;
regs.gpr[13] = (s64)0xFFFFFFFFCE9DFBF7;
regs.gpr[14] = 0x000000001AF99984;
regs.gpr[15] = 0x0000000018B63D28;
regs.gpr[16] = 0x0000000000000000;
regs.gpr[17] = 0x0000000000000000;
regs.gpr[18] = 0x0000000000000000;
regs.gpr[19] = 0x0000000000000000;
regs.gpr[20] = 0x0000000000000001;
regs.gpr[21] = 0x0000000000000000;
regs.gpr[23] = 0x0000000000000000;
regs.gpr[24] = 0x0000000000000000;
regs.gpr[25] = (s64)0xFFFFFFFF825B21C9;
regs.gpr[26] = 0x0000000000000000;
regs.gpr[27] = 0x0000000000000000;
regs.gpr[28] = 0x0000000000000000;
regs.gpr[29] = (s64)0xFFFFFFFFA4001FF0;
regs.gpr[30] = 0x0000000000000000;
regs.gpr[31] = (s64)0xFFFFFFFFA4001550;
regs.lo = 0x0000000018B63D28;
regs.hi = 0x00000000625C2BBE;
if (pal) {
regs.gpr[20] = 0x0000000000000000;
regs.gpr[23] = 0x0000000000000006;
regs.gpr[31] = (s64)0xFFFFFFFFA4001554;
}
break;
case CIC_NUS_6105_7105:
mem.Write32<false>(regs, 0x3F0, RDRAM_SIZE, regs.pc);
regs.gpr[2] = (s64)0xFFFFFFFFF58B0FBF;
regs.gpr[3] = (s64)0xFFFFFFFFF58B0FBF;
regs.gpr[4] = 0x0000000000000FBF;
regs.gpr[5] = (s64)0xFFFFFFFFDECAAAD1;
regs.gpr[6] = (s64)0xFFFFFFFFA4001F0C;
regs.gpr[7] = (s64)0xFFFFFFFFA4001F08;
regs.gpr[8] = 0x00000000000000C0;
regs.gpr[10] = 0x0000000000000040;
regs.gpr[11] = (s64)0xFFFFFFFFA4000040;
regs.gpr[12] = (s64)0xFFFFFFFF9651F81E;
regs.gpr[13] = 0x000000002D42AAC5;
regs.gpr[14] = 0x00000000489B52CF;
regs.gpr[15] = 0x0000000056584D60;
regs.gpr[20] = 0x0000000000000001;
regs.gpr[24] = 0x0000000000000002;
regs.gpr[25] = (s64)0xFFFFFFFFCDCE565F;
regs.gpr[29] = (s64)0xFFFFFFFFA4001FF0;
regs.gpr[31] = (s64)0xFFFFFFFFA4001550;
regs.lo = 0x0000000056584D60;
regs.hi = 0x000000004BE35D1F;
if (pal) {
regs.gpr[20] = 0x0000000000000000;
regs.gpr[23] = 0x0000000000000006;
regs.gpr[31] = (s64)0xFFFFFFFFA4001554;
}
mem.Write32<false>(regs, 0x04001000, 0x3C0DBFC0, regs.pc);
mem.Write32<false>(regs, 0x04001004, 0x8DA807FC, regs.pc);
mem.Write32<false>(regs, 0x04001008, 0x25AD07C0, regs.pc);
mem.Write32<false>(regs, 0x0400100C, 0x31080080, regs.pc);
mem.Write32<false>(regs, 0x04001000, 0x5500FFFC, regs.pc);
mem.Write32<false>(regs, 0x04001004, 0x3C0DBFC0, regs.pc);
mem.Write32<false>(regs, 0x04001008, 0x8DA80024, regs.pc);
mem.Write32<false>(regs, 0x0400100C, 0x3C0BB000, regs.pc);
break;
case CIC_NUS_6106_7106:
regs.gpr[2] = (s64)0xFFFFFFFFA95930A4;
regs.gpr[3] = (s64)0xFFFFFFFFA95930A4;
regs.gpr[4] = 0x00000000000030A4;
regs.gpr[5] = (s64)0xFFFFFFFFB04DC903;
regs.gpr[6] = (s64)0xFFFFFFFFA4001F0C;
regs.gpr[7] = (s64)0xFFFFFFFFA4001F08;
regs.gpr[8] = 0x00000000000000C0;
regs.gpr[10] = 0x0000000000000040;
regs.gpr[11] = (s64)0xFFFFFFFFA4000040;
regs.gpr[12] = (s64)0xFFFFFFFFBCB59510;
regs.gpr[13] = (s64)0xFFFFFFFFBCB59510;
regs.gpr[14] = 0x000000000CF85C13;
regs.gpr[15] = 0x000000007A3C07F4;
regs.gpr[20] = 0x0000000000000001;
regs.gpr[24] = 0x0000000000000002;
regs.gpr[25] = 0x00000000465E3F72;
regs.gpr[29] = (s64)0xFFFFFFFFA4001FF0;
regs.gpr[30] = 0x0000000000000000;
regs.gpr[31] = (s64)0xFFFFFFFFA4001550;
regs.lo = 0x000000007A3C07F4;
regs.hi = 0x0000000023953898;
if (pal) {
regs.gpr[20] = 0x0000000000000000;
regs.gpr[23] = 0x0000000000000006;
regs.gpr[31] = (s64)0xFFFFFFFFA4001554;
}
break;
}
regs.gpr[22] = (cicSeeds[cicType] >> 8) & 0xFF;
regs.cop0.Reset();
}
}

View File

@@ -14,6 +14,30 @@ union Controller {
static_assert(sizeof(Controller) == 4);
struct Mem;
struct Registers;
const u32 cicSeeds[] = {
0x0,
0x00043F3F, // CIC_NUS_6101
0x00043F3F, // CIC_NUS_7102
0x00003F3F, // CIC_NUS_6102_7101
0x0000783F, // CIC_NUS_6103_7103
0x0000913F, // CIC_NUS_6105_7105
0x0000853F, // CIC_NUS_6106_7106
};
enum CICType {
UNKNOWN_CIC_TYPE,
CIC_NUS_6101,
CIC_NUS_7102,
CIC_NUS_6102_7101,
CIC_NUS_6103_7103,
CIC_NUS_6105_7105,
CIC_NUS_6106_7106
};
struct CartInfo;
void ProcessPIFCommands(u8*, Controller&, Mem&);
void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo);
}

View File

@@ -103,9 +103,9 @@ inline VPR GetVTE(VPR vt, u8 e) {
vte = Broadcast(vt, e - 4, e - 4, e - 4, e - 4, e, e, e, e);
break;
case 8 ... 15: {
int index = e - 8;
for (u16& i : vte.element) {
i = vt.element[index];
int index = ELEMENT_INDEX(e - 8);
for (u16& vteE : vte.element) {
vteE = vt.element[index];
}
} break;
}
@@ -407,7 +407,19 @@ void RSP::vabs(u32 instr) {
}
void RSP::vadd(u32 instr) {
util::panic("VADD!\n");
VPR& vs = vpr[VS(instr)];
VPR& vd = vpr[VD(instr)];
VPR vte = GetVTE(vpr[VT(instr)], E2(instr));
for(int i = 0; i < 8; i++) {
s16 vsE = vs.selement[i];
s16 vteE = vte.selement[i];
s32 result = vsE + vteE + (vco.l.element[i] != 0);
acc.l.element[i] = result;
vd.element[i] = clamp_signed(result);
vco.l.element[i] = 0;
vco.h.element[i] = 0;
}
}
void RSP::vmov(u32 instr) {

View File

@@ -169,7 +169,7 @@ enum RomTypes {
V64 = 0x37804012
};
inline void SwapN64Rom(u32& crc, size_t size, u8* rom) {
inline void SwapN64Rom(size_t size, u8* rom, u32& crc, u32& cicChecksum) {
RomTypes endianness;
memcpy(&endianness, rom, 4);
endianness = static_cast<RomTypes>(be32toh(endianness));
@@ -180,8 +180,8 @@ inline void SwapN64Rom(u32& crc, size_t size, u8* rom) {
memcpy(temp, rom, size);
SwapBuffer16(size, temp);
crc = crc32(0, temp, size);
cicChecksum = crc32(0, &temp[0x40], 0x9c0);
free(temp);
SwapBuffer32(size, rom);
SwapBuffer16(size, rom);
} break;
@@ -190,10 +190,12 @@ inline void SwapN64Rom(u32& crc, size_t size, u8* rom) {
memcpy(temp, rom, size);
SwapBuffer32(size, temp);
crc = crc32(0, temp, size);
cicChecksum = crc32(0, &temp[0x40], 0x9c0);
free(temp);
} break;
case RomTypes::Z64:
crc = crc32(0, rom, size);
cicChecksum = crc32(0, &rom[0x40], 0x9c0);
SwapBuffer32(size, rom);
break;
default: