From 871260cfcf562688204f5fea09ced0e7078600af Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Wed, 26 Jun 2019 19:06:30 +0200 Subject: [PATCH] naomi: better error handling when loading a gdrom x64 and arm64 dynarecs: Support 64-bit immediate readm (ninjaslt) --- core/hw/naomi/gdcartridge.cpp | 13 +++++- core/hw/naomi/naomi_cart.cpp | 8 +++- core/hw/naomi/naomi_cart.h | 8 ++++ core/rec-ARM64/rec_arm64.cpp | 82 +++++++++++++++++++++++------------ core/rec-x64/rec_x64.cpp | 75 ++++++++++++++++++++++---------- 5 files changed, 134 insertions(+), 52 deletions(-) diff --git a/core/hw/naomi/gdcartridge.cpp b/core/hw/naomi/gdcartridge.cpp index faa81768f..a4fd4c25f 100644 --- a/core/hw/naomi/gdcartridge.cpp +++ b/core/hw/naomi/gdcartridge.cpp @@ -507,7 +507,8 @@ void GDCartridge::device_start() if (gdrom == NULL) gdrom = OpenDisc((gdrom_path + ".gdi").c_str()); if (gdrom == NULL) - return; + throw NaomiCartException("Naomi GDROM: Cannot open " + gdrom_path + ".chd or " + gdrom_path + ".gdi"); + // primary volume descriptor // read frame 0xb06e (frame=sector+150) // dimm board firmware starts straight from this frame @@ -564,6 +565,7 @@ void GDCartridge::device_start() u32 file_rounded_size = (file_size + 2047) & -2048; for (dimm_data_size = 4096; dimm_data_size < file_rounded_size; dimm_data_size <<= 1); dimm_data = (u8 *)malloc(dimm_data_size); + verify(dimm_data != NULL); if (dimm_data_size != file_rounded_size) memset(dimm_data + file_rounded_size, 0, dimm_data_size - file_rounded_size); @@ -583,7 +585,7 @@ void GDCartridge::device_start() delete gdrom; if (!dimm_data) - printf("Naomi GDROM: Could not find the file to decrypt.\n"); + throw NaomiCartException("Naomi GDROM: Could not find the file to decrypt."); } } @@ -593,6 +595,8 @@ void GDCartridge::device_reset() } void *GDCartridge::GetDmaPtr(u32 &size) { + if (dimm_data == NULL) + return NULL; dimm_cur_address = DmaOffset & (dimm_data_size-1); size = min(size, dimm_data_size - dimm_cur_address); return dimm_data + dimm_cur_address; @@ -607,6 +611,11 @@ void GDCartridge::AdvancePtr(u32 size) bool GDCartridge::Read(u32 offset, u32 size, void *dst) { + if (dimm_data == NULL) + { + *(u32 *)dst = 0; + return true; + } u32 addr = offset & (dimm_data_size-1); memcpy(dst, &dimm_data[addr], min(size, dimm_data_size - addr)); return true; diff --git a/core/hw/naomi/naomi_cart.cpp b/core/hw/naomi/naomi_cart.cpp index 55bfdd5c1..30bfe5c84 100644 --- a/core/hw/naomi/naomi_cart.cpp +++ b/core/hw/naomi/naomi_cart.cpp @@ -331,7 +331,12 @@ static bool naomi_cart_LoadZip(char *filename) if (parent_archive != NULL) delete parent_archive; - CurrentCartridge->Init(); + try { + CurrentCartridge->Init(); + } catch (NaomiCartException& e) { + printf("%s\n", e.reason.c_str()); + return false; + } strcpy(naomi_game_id, CurrentCartridge->GetGameId().c_str()); printf("NAOMI GAME ID [%s]\n", naomi_game_id); @@ -604,6 +609,7 @@ void naomi_cart_Close() delete[] RomCacheMap; RomCacheMap = NULL; } + bios_loaded = false; } bool naomi_cart_SelectFile() diff --git a/core/hw/naomi/naomi_cart.h b/core/hw/naomi/naomi_cart.h index 85758fb28..e189bb107 100644 --- a/core/hw/naomi/naomi_cart.h +++ b/core/hw/naomi/naomi_cart.h @@ -78,6 +78,14 @@ private: u8 naomi_cart_ram[64 * 1024]; }; +class NaomiCartException +{ +public: + NaomiCartException(std::string reason) : reason(reason) {} + + std::string reason; +}; + bool naomi_cart_SelectFile(); void naomi_cart_Close(); diff --git a/core/rec-ARM64/rec_arm64.cpp b/core/rec-ARM64/rec_arm64.cpp index dd3fbbe1b..4ce70f8d7 100644 --- a/core/rec-ARM64/rec_arm64.cpp +++ b/core/rec-ARM64/rec_arm64.cpp @@ -1639,18 +1639,28 @@ private: return false; u32 paddr; u32 rv; - if (size == 2) + switch (size) + { + case 1: + rv = mmu_data_translation(addr, paddr); + break; + case 2: rv = mmu_data_translation(addr, paddr); - else if (size == 4) + break; + case 4: + case 8: rv = mmu_data_translation(addr, paddr); - else + break; + default: die("Invalid immediate size"); + break; + } if (rv != MMU_ERROR_NONE) return false; addr = paddr; } bool isram = false; - void* ptr = _vmem_read_const(addr, isram, size); + void* ptr = _vmem_read_const(addr, isram, size > 4 ? 4 : size); if (isram) { @@ -1712,35 +1722,50 @@ private: else { // Not RAM - Mov(w0, addr); - - switch(size) + if (size == 8) { - case 1: + verify(!regalloc.IsAllocAny(op.rd)); + // Need to call the handler twice + Mov(w0, addr); GenCallRuntime((void (*)())ptr); - Sxtb(w0, w0); - break; + Str(w0, sh4_context_mem_operand(op.rd.reg_ptr())); - case 2: + Mov(w0, addr + 4); GenCallRuntime((void (*)())ptr); - Sxth(w0, w0); - break; - - case 4: - GenCallRuntime((void (*)())ptr); - break; - - case 8: - die("SZ_64F not supported"); - break; + Str(w0, sh4_context_mem_operand((u8*)op.rd.reg_ptr() + 4)); } - - if (regalloc.IsAllocg(op.rd)) - Mov(regalloc.MapRegister(op.rd), w0); else { - verify(regalloc.IsAllocf(op.rd)); - Fmov(regalloc.MapVRegister(op.rd), w0); + Mov(w0, addr); + + switch(size) + { + case 1: + GenCallRuntime((void (*)())ptr); + Sxtb(w0, w0); + break; + + case 2: + GenCallRuntime((void (*)())ptr); + Sxth(w0, w0); + break; + + case 4: + GenCallRuntime((void (*)())ptr); + break; + + default: + die("Invalid size"); + break; + } + + if (regalloc.IsAllocg(op.rd)) + Mov(regalloc.MapRegister(op.rd), w0); + else + { + verify(regalloc.IsAllocf(op.rd)); + Fmov(regalloc.MapVRegister(op.rd), w0); + } } } @@ -1848,13 +1873,16 @@ private: case 8: rv = mmu_data_translation(addr, paddr); break; + default: + die("Invalid immediate size"); + break; } if (rv != MMU_ERROR_NONE) return false; addr = paddr; } bool isram = false; - void* ptr = _vmem_write_const(addr, isram, size); + void* ptr = _vmem_write_const(addr, isram, size > 4 ? 4 : size); Register reg2; if (op.rs2.is_imm()) diff --git a/core/rec-x64/rec_x64.cpp b/core/rec-x64/rec_x64.cpp index b315d18ff..1bb975fe2 100644 --- a/core/rec-x64/rec_x64.cpp +++ b/core/rec-x64/rec_x64.cpp @@ -1517,19 +1517,29 @@ private: u32 paddr; u32 rv; - if (size == 2) + switch (size) + { + case 1: + rv = mmu_data_translation(addr, paddr); + break; + case 2: rv = mmu_data_translation(addr, paddr); - else if (size == 4) + break; + case 4: + case 8: rv = mmu_data_translation(addr, paddr); - else + break; + default: die("Invalid immediate size"); + break; + } if (rv != MMU_ERROR_NONE) return false; addr = paddr; } bool isram = false; - void* ptr = _vmem_read_const(addr, isram, size); + void* ptr = _vmem_read_const(addr, isram, size > 4 ? 4 : size); if (isram) { @@ -1597,29 +1607,47 @@ private: else { // Not RAM: the returned pointer is a memory handler - mov(call_regs[0], addr); - - switch(size) + if (size == 8) { - case 1: - GenCall((void (*)())ptr); - movsx(eax, al); - break; + verify(!regalloc.IsAllocAny(op.rd)); - case 2: + // Need to call the handler twice + mov(call_regs[0], addr); GenCall((void (*)())ptr); - movsx(eax, ax); - break; + mov(rcx, (size_t)op.rd.reg_ptr()); + mov(dword[rcx], eax); - case 4: + mov(call_regs[0], addr + 4); GenCall((void (*)())ptr); - break; - - default: - die("Invalid immediate size"); - break; + mov(rcx, (size_t)op.rd.reg_ptr() + 4); + mov(dword[rcx], eax); + } + else + { + mov(call_regs[0], addr); + + switch(size) + { + case 1: + GenCall((void (*)())ptr); + movsx(eax, al); + break; + + case 2: + GenCall((void (*)())ptr); + movsx(eax, ax); + break; + + case 4: + GenCall((void (*)())ptr); + break; + + default: + die("Invalid immediate size"); + break; + } + host_reg_to_shil_param(op.rd, eax); } - host_reg_to_shil_param(op.rd, eax); } return true; @@ -1651,6 +1679,9 @@ private: case 8: rv = mmu_data_translation(addr, paddr); break; + default: + die("Invalid immediate size"); + break; } if (rv != MMU_ERROR_NONE) return false; @@ -1658,7 +1689,7 @@ private: addr = paddr; } bool isram = false; - void* ptr = _vmem_write_const(addr, isram, size); + void* ptr = _vmem_write_const(addr, isram, size > 4 ? 4 : size); if (isram) {