From 0d8676aa93e7fab69cfe2f1e43fe3ffaf3bc2d43 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Thu, 13 Jul 2023 07:32:03 -0500 Subject: [PATCH] decompile Libleo main api decomp ReadDiskID decomp ReadWrite add symbol addresses decompile LeoSetRTC decompile LeoReadRTC decompile LeoSeek decompile LeoTestUnitReady decompile LeoDriveExist decomp LBA <-> Byte decompile LeoSetRTC --- .gitignore | 3 +++ diff.py | 2 +- include/functions.h | 6 ++--- include/libleo/internal.h | 17 +++++++++++++ splat.yaml | 16 ++++++------- src/libleo/driveexist.c | 45 ++++++++++++++++++++++++++++++++++ src/libleo/readdiskid.c | 19 +++++++++++++++ src/libleo/readrtc.c | 18 ++++++++++++++ src/libleo/readwrite.c | 26 ++++++++++++++++++++ src/libleo/seek.c | 19 +++++++++++++++ src/libleo/setrtc.c | 49 ++++++++++++++++++++++++++++++++++++++ src/libleo/testunitready.c | 23 ++++++++++++++++++ src/rsp.c | 4 ++-- tools/symbol_addrs.txt | 9 ++++++- 14 files changed, 241 insertions(+), 15 deletions(-) create mode 100644 include/libleo/internal.h create mode 100644 src/libleo/driveexist.c create mode 100644 src/libleo/readdiskid.c create mode 100644 src/libleo/readrtc.c create mode 100644 src/libleo/readwrite.c create mode 100644 src/libleo/seek.c create mode 100644 src/libleo/setrtc.c create mode 100644 src/libleo/testunitready.c diff --git a/.gitignore b/.gitignore index 7415e30..909e221 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,6 @@ tools/ido7.1_compiler/ # diffing directory expected/ + +# misc +.DS_Store diff --git a/diff.py b/diff.py index 0e1da09..e5e87aa 100644 --- a/diff.py +++ b/diff.py @@ -273,7 +273,7 @@ if args.source: fail(MISSING_PREREQUISITES.format(e.name)) if objdump_executable is None: - for objdump_cand in ["mips-linux-gnu-objdump", "mips64-elf-objdump"]: + for objdump_cand in ["mips-linux-gnu-objdump", "mips64-elf-objdump", "mips-elf-objdump"]: try: subprocess.check_call( [objdump_cand, "--version"], diff --git a/include/functions.h b/include/functions.h index 852532f..2cc83af 100644 --- a/include/functions.h +++ b/include/functions.h @@ -6,6 +6,9 @@ extern void func_80057FD0(void *, int); extern s32 func_8005A990(OSPiHandle *); +// bcopy.s +extern void _bcopy(void *, void *, u32); + // 3A80.s extern void func_80002F58(void); extern void *func_80002FDC(s32); @@ -51,7 +54,4 @@ extern void func_8002B274(s32, s32); // exception_set.s extern void set_watch_lohi(s32); -// readwrite.s -extern void func_80050FC0(void *, s32, s32, void *, s32, OSMesgQueue *); - #endif diff --git a/include/libleo/internal.h b/include/libleo/internal.h new file mode 100644 index 0000000..d7eca79 --- /dev/null +++ b/include/libleo/internal.h @@ -0,0 +1,17 @@ +#ifndef LIBLEO_INTERNAL_H +#define LIBLEO_INTERNAL_H + +/* libleo conversion tables */ +extern const u8 LEOBYTE_TBL1[]; +extern const u16 LEOBYTE_TBL2[]; +extern const u16 LEOVZONE_TBL[][0x10]; +extern const u16 LEOZONE_SCYL_TBL[]; +extern const u8 LEOVZONE_PZONEHD_TBL[][0x10]; +extern const u16 LEOZONE_OUTERCYL_TBL[]; +extern const u16 LEORAM_START_LBA[]; +extern const s32 LEORAM_BYTE[]; + +extern s32 __leoActive; +extern s32 leoVerifyRTC(u8 yearhi, u8 yearlo); + +#endif diff --git a/splat.yaml b/splat.yaml index 2e9834c..de214c1 100644 --- a/splat.yaml +++ b/splat.yaml @@ -126,7 +126,7 @@ segments: - [0x517A0, asm] # yay0 audio decoder - [0x518A0, asm] - [0x51B20, asm] - - [0x51BC0, asm, libleo/readwrite] + - [0x51BC0, c, libleo/readwrite] - [0x51C50, asm, libleo/leofunc] - [0x520C0, asm, libleo/leoint] - [0x52AC0, asm, libleo/leocmdex] @@ -134,18 +134,18 @@ segments: - [0x53310, asm, libleo/lbatobyte] - [0x53460, asm, libleo/driverominit] - [0x535C0, asm, libleo/inquiry] - - [0x53710, asm, libleo/readdiskid] + - [0x53710, c, libleo/readdiskid] - [0x53770, asm, libleo/leord_diskid] - [0x53900, asm, libleo/leomecha] - [0x54250, asm, libleo/spdlmotor] - [0x54310, asm, libleo/leoc2ecc] - - [0x55400, asm, libleo/setrtc] + - [0x55400, c, libleo/setrtc] - [0x55570, asm, libleo/leomseq_tbl] - [0x55720, asm, libleo/leomotor] - [0x55810, asm, libleo/leomode_sel] - [0x558C0, asm, libleo/leord_capa] - [0x55960, asm, libleo/leoutil] - - [0x55BB0, asm, libleo/rezero] + - [0x55BB0, asm, libleo/leorezero] - [0x55C50, asm, libleo/bytetolba] - [0x55DB0, asm, libleo/leoreset] - [0x55ED0, asm, libleo/leotranslat] @@ -153,12 +153,12 @@ segments: - [0x56680, asm, libleo/leowrite] - [0x567B0, asm, libleo/cjcreateleomanager] - [0x569F0, asm, libleo/leointerrupt] - - [0x570C0, asm, libleo/driveexist] - - [0x57190, asm, libleo/testunitready] + - [0x570C0, c, libleo/driveexist] + - [0x57190, c, libleo/testunitready] - [0x57230, asm, libleo/leotestunit] - - [0x57270, asm, libleo/readrtc] + - [0x57270, c, libleo/readrtc] - [0x572D0, asm, libleo/leoseek] - - [0x57390, asm, libleo/seek] + - [0x57390, c, libleo/seek] - [0x573F0, c, libultra/io/piacs] - [0x574B0, hasm, libultra/os/setcause] - [0x574C0, c, libultra/os/sendmesg] diff --git a/src/libleo/driveexist.c b/src/libleo/driveexist.c new file mode 100644 index 0000000..e69e5bd --- /dev/null +++ b/src/libleo/driveexist.c @@ -0,0 +1,45 @@ +#include +#include "libleo/internal.h" + +void __osPiRelAccess(void); +void __osPiGetAccess(void); + +#define CONNECTED 0x2129FFF8 +#define DDROM_STATUS_REG 0x06001010 + +// https://github.com/LuigiBlood/64dd/wiki/64DD-IPL +u32 LeoDriveExist(void) { + register u32 ddromStatus; + register s32 status; + register u32 lastLatency; + register u32 lastPageSize; + register u32 lastRelDuration; + register u32 lastPulse; + + __osPiGetAccess(); + + while ((status = HW_REG(PI_STATUS_REG, u32)) & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) {} + + lastLatency = HW_REG(PI_BSD_DOM1_LAT_REG, u32); + lastPageSize = HW_REG(PI_BSD_DOM1_PGS_REG, u32); + lastRelDuration = HW_REG(PI_BSD_DOM1_RLS_REG, u32); + lastPulse = HW_REG(PI_BSD_DOM1_PWD_REG, u32); + + HW_REG(PI_BSD_DOM1_LAT_REG, u32) = 0xFF; + HW_REG(PI_BSD_DOM1_PGS_REG, u32) = 0; + HW_REG(PI_BSD_DOM1_RLS_REG, u32) = 3; + HW_REG(PI_BSD_DOM1_PWD_REG, u32) = 0xFF; + + ddromStatus = HW_REG(DDROM_STATUS_REG, u32); + + HW_REG(PI_BSD_DOM1_LAT_REG, u32) = lastLatency; + HW_REG(PI_BSD_DOM1_PGS_REG, u32) = lastPageSize; + HW_REG(PI_BSD_DOM1_RLS_REG, u32) = lastRelDuration; + HW_REG(PI_BSD_DOM1_PWD_REG, u32) = lastPulse; + + __osPiRelAccess(); + if (ddromStatus == CONNECTED) { + return 1; + } + return 0; +} diff --git a/src/libleo/readdiskid.c b/src/libleo/readdiskid.c new file mode 100644 index 0000000..733bd7f --- /dev/null +++ b/src/libleo/readdiskid.c @@ -0,0 +1,19 @@ +#include +#include "libleo/internal.h" + +s32 LeoReadDiskID(LEOCmd *cmdBlock, LEODiskID *vaddr, OSMesgQueue *mq) { + if (!__leoActive) { + return -1; + } + cmdBlock->header.command = LEO_COMMAND_READ_DISK_ID; + cmdBlock->header.reserve1 = 0; + cmdBlock->header.control = 0; + cmdBlock->header.reserve3 = 0; + cmdBlock->data.readdiskid.buffer_pointer = vaddr; + if (mq != NULL) { + cmdBlock->header.control |= LEO_CONTROL_POST; + cmdBlock->header.post = mq; + } + leoCommand(cmdBlock); + return 0; +} diff --git a/src/libleo/readrtc.c b/src/libleo/readrtc.c new file mode 100644 index 0000000..ffbeaca --- /dev/null +++ b/src/libleo/readrtc.c @@ -0,0 +1,18 @@ +#include +#include "libleo/internal.h" + +s32 LeoReadRTC(LEOCmd* cmdBlock, OSMesgQueue* mq) { + if (!__leoActive) { + return -1; + } + cmdBlock->header.command = LEO_COMMAND_READ_TIMER; + cmdBlock->header.reserve1 = 0; + cmdBlock->header.control = 0; + cmdBlock->header.reserve3 = 0; + if (mq != NULL) { + cmdBlock->header.control |= LEO_CONTROL_POST; + cmdBlock->header.post = mq; + } + leoCommand(cmdBlock); + return 0; +} diff --git a/src/libleo/readwrite.c b/src/libleo/readwrite.c new file mode 100644 index 0000000..1c4a3b6 --- /dev/null +++ b/src/libleo/readwrite.c @@ -0,0 +1,26 @@ +#include +#include "libleo/internal.h" + +s32 LeoReadWrite(LEOCmd* cmdBlock, s32 direction, u32 LBA, void* vAddr, u32 nLBAs, OSMesgQueue* mq) { + if (!__leoActive) { + return -1; + } + if (direction == OS_READ) { + cmdBlock->header.command = LEO_COMMAND_READ; + } else { + cmdBlock->header.command = LEO_COMMAND_WRITE; + } + cmdBlock->header.reserve1 = 0; + if (mq != NULL) { + cmdBlock->header.control = LEO_CONTROL_POST; + } else { + cmdBlock->header.control = 0; + } + cmdBlock->header.reserve3 = 0; + cmdBlock->header.post = mq; + cmdBlock->data.readwrite.lba = LBA; + cmdBlock->data.readwrite.xfer_blks = nLBAs; + cmdBlock->data.readwrite.buff_ptr = vAddr; + leoCommand(cmdBlock); + return 0; +} diff --git a/src/libleo/seek.c b/src/libleo/seek.c new file mode 100644 index 0000000..b279b19 --- /dev/null +++ b/src/libleo/seek.c @@ -0,0 +1,19 @@ +#include +#include "libleo/internal.h" + +s32 LeoSeek(LEOCmd* cmdBlock, u32 lba, OSMesgQueue* mq) { + if (!__leoActive) { + return -1; + } + cmdBlock->header.command = LEO_COMMAND_SEEK; + cmdBlock->header.reserve1 = 0; + cmdBlock->header.control = 0; + cmdBlock->header.reserve3 = 0; + cmdBlock->data.readwrite.lba = lba; + if (mq != NULL) { + cmdBlock->header.control |= LEO_CONTROL_POST; + cmdBlock->header.post = mq; + } + leoCommand(cmdBlock); + return 0; +} diff --git a/src/libleo/setrtc.c b/src/libleo/setrtc.c new file mode 100644 index 0000000..d21074b --- /dev/null +++ b/src/libleo/setrtc.c @@ -0,0 +1,49 @@ +#include +#include "libleo/internal.h" + +s32 LeoSetRTC(LEOCmd* cmdBlock, LEODiskTime* RTCdata, OSMesgQueue* mq) { + if (!__leoActive) { + return -1; + } + if (leoVerifyRTC(RTCdata->yearhi, RTCdata->yearlo) != 0) { + osSendMesg(mq, (void *)LEO_SENSE_ILLEGAL_TIMER_VALUE, 1); + return 0; + } + cmdBlock->header.command = LEO_COMMAND_SET_TIMER; + cmdBlock->header.reserve1 = 0; + cmdBlock->header.control = 0; + cmdBlock->header.reserve3 = 0; + _bcopy(RTCdata, &cmdBlock->data.time, 8); + if (mq != NULL) { + cmdBlock->header.control |= LEO_CONTROL_POST; + cmdBlock->header.post = mq; + } + leoCommand(cmdBlock); + return 0; +} + +#ifdef NON_MATCHING +/* + * The "year" is expressed in 4 digits with the high 2 digits being yearhi and low 2 digits being yearlo. 2023 = 0x20, 0x23 + * The "hour" member uses the 24-hour clock. + * Return 0 if year is between ranges from 1996 to 2095 + */ +// https://decomp.me/scratch/NUHIy +s32 leoVerifyRTC(u8 yearhi, u8 yearlo) { + u32 year; + s32 hiMask; + u32 loMask; + hiMask = yearhi & 0xFF; + loMask = yearlo & 0xFF; + if (((loMask & 0xF) >= 0xA) || ((loMask & 0xF0) >= 0x91) || ((hiMask & 0xF) >= 0xA) || ((hiMask & 0xF0) >= 0x91)) { + return 1; + } + year = (((hiMask - ((hiMask >> 4) * 6)) * 0x64) + loMask) - ((loMask >> 4) * 6); + if ((year < 0x7CCU) || (year >= 0x830U)) { + return 1; + } + return 0; +} +#else +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/setrtc/leoVerifyRTC.s") +#endif diff --git a/src/libleo/testunitready.c b/src/libleo/testunitready.c new file mode 100644 index 0000000..3c8d3c6 --- /dev/null +++ b/src/libleo/testunitready.c @@ -0,0 +1,23 @@ +#include +#include "libleo/internal.h" + +s32 LeoTestUnitReady(u8* status) { + volatile LEOCmdTestUnitReady cmdBlock; + + if (!__leoActive) { + return -1; + } + if (HW_REG(PI_STATUS_REG, u32) & 1) { + return LEO_STATUS_BUSY; + } + cmdBlock.header.command = 3; + cmdBlock.header.reserve1 = 0; + cmdBlock.header.control = 0; + cmdBlock.header.reserve3 = 0; + leoCommand((void *)&cmdBlock); + + while (cmdBlock.header.status == LEO_STATUS_BUSY) {} + + *status = cmdBlock.test; + return cmdBlock.header.sense; +} \ No newline at end of file diff --git a/src/rsp.c b/src/rsp.c index 33771c2..f7e3ca1 100644 --- a/src/rsp.c +++ b/src/rsp.c @@ -156,12 +156,12 @@ void* func_800009C8(void) { } void *func_800009F8(struct UnkStruct800006C4_2* arg0) { - func_80050FC0(arg0, 0, arg0->unk1C, arg0->vaddr, arg0->size, &D_80083BD0.queue2); + LeoReadWrite(arg0, 0, arg0->unk1C, arg0->vaddr, arg0->size, &D_80083BD0.queue2); return func_800009C8(); } void *func_80000A3C(struct UnkStruct800006C4_2* arg0) { - func_80050FC0(arg0, 1, arg0->unk1C, arg0->vaddr, arg0->size, &D_80083BD0.queue2); + LeoReadWrite(arg0, 1, arg0->unk1C, arg0->vaddr, arg0->size, &D_80083BD0.queue2); return func_800009C8(); } diff --git a/tools/symbol_addrs.txt b/tools/symbol_addrs.txt index bffca2b..ddcbd36 100644 --- a/tools/symbol_addrs.txt +++ b/tools/symbol_addrs.txt @@ -2,12 +2,16 @@ LeoByteToLBA = 0x80055050; LeoCJCreateLeoManager = 0x80055BB0; LeoDriveExist = 0x800564C0; LeoLBAToByte = 0x80052710; +LeoReadDiskID = 0x80052B10; +LeoReadWrite = 0x80050FC0; LeoReadRTC = 0x80056670; LeoReset = 0x80051384; LeoResetClear = 0x80051438; LeoSeek = 0x80056790; LeoSetRTC = 0x80054800; LeoSpdlMotor = 0x80053650; +LeoTestUnitReady = 0x80056590; +leoVerifyRTC = 0x800548C0; _Litob = 0x80064CA0; _Printf = 0x8005D850; _Putfld = 0x8005D1E0; @@ -107,6 +111,7 @@ leoReadTimer = 0x80055570; leoRead_common = 0x8005257C; leoRead_system_area = 0x8005233C; leoRecal_i = 0x800532EC; +leoRecal_w = 0x80053314; leoRecv_event_mesg = 0x800533DC; leoRetUnit_atten = 0x800535BC; leoRezero = 0x80054FB0; @@ -185,7 +190,6 @@ sprintf = 0x8005E044; strchr = 0x8005E2A4; strlen = 0x8005E27C; viMgrMain = 0x80065140; -LeoReadDiskID = 0x80052B10; leoRd_capacity = 0x80054CC0; leoWrite = 0x80055A80; leoSeek = 0x800566D0; @@ -378,8 +382,11 @@ osViModeNtscLan1 = 0x8007AD50; g_OsGbNintendoData = 0x8007ADF0; g_OsGbCartVersions = 0x8007AE20; __CartRomHandle = 0x801038D0; +__DriveRomHandle = 0x80100740; __osPfsLastChannel = 0x8007AE50; __osViDevMgr = 0x8007AE90; +__osLeoDevMgr = 0x80079514; +__leoActive = 0x800795B0; __additional_scanline = 0x8007AEAC; viThread = 0x80103950; viThreadStack = 0x80103B00;