diff --git a/Makefile b/Makefile index 50dd084..b77a699 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,8 @@ O_FILES := $(foreach file,$(C_FILES),$(BUILD_DIR)/$(file:.c=.c.o)) \ $(foreach file,$(DATA_FILES),$(BUILD_DIR)/$(file:.bin=.bin.o)) \ DECOMP_C_OBJS := $(filter %.c.o,$(filter-out $(BUILD_DIR)/src/libultra%,$(O_FILES))) +DECOMP_POKE_STADIUM := $(filter %.c.o,$(filter-out $(BUILD_DIR)/src/libleo%,$(DECOMP_C_OBJS))) +DECOMP_LIBLEO := $(filter $(BUILD_DIR)/src/libleo/%.c.o,$(O_FILES)) DEP_FILES := $(O_FILES:.o=.d) $(DECOMP_C_OBJS:.o=.asmproc.d) @@ -249,7 +251,8 @@ build/src/libultra/io/gbpakreadwrite.c.o: CC := $(CC_OLD) build/src/libultra/io/gbpakselectbank.c.o: CC := $(CC_OLD) # run ASM-processor on non-libultra source files -$(DECOMP_C_OBJS): CC := $(ASMPROC) $(ASMPROC_FLAGS) $(CC) -- $(AS) $(ASFLAGS) -- +$(DECOMP_POKE_STADIUM): CC := $(ASMPROC) $(ASMPROC_FLAGS) $(CC) -- $(AS) $(ASFLAGS) -- +$(DECOMP_LIBLEO): CC := $(ASMPROC) $(ASMPROC_FLAGS) $(CC_OLD) -- $(AS) $(ASFLAGS) -- # turn off syntax checking errors for libultra build/src/libultra/al/%.c.o: CHECK_WARNINGS := -w diff --git a/include/PR/leo.h b/include/PR/leo.h index 96f2edd..2a3c487 100644 --- a/include/PR/leo.h +++ b/include/PR/leo.h @@ -32,8 +32,8 @@ typedef u8 LEOStatus; typedef struct { - u8 drive; /* version of hw */ - u8 driver; /* version of sw */ + u8 driver; /* version of hw */ + u8 drive; /* version of sw */ u8 deviceType; /* dev type, always 00 */ u8 ndevices; /* # of devices, always 01 */ } LEOVersion; diff --git a/include/libleo/internal.h b/include/libleo/internal.h index a61aaa9..9dc04d0 100644 --- a/include/libleo/internal.h +++ b/include/libleo/internal.h @@ -15,6 +15,31 @@ typedef struct { /* 0xA */ u8 start_block; } tgt_param_form; // size = 0xC +typedef union { + /* 0x00 */ struct { + /* 0x00 */ u32 country; + /* 0x04 */ u8 fmt_type; + /* 0x05 */ u8 disk_type; + /* 0x06 */ u16 ipl_load_len; + /* 0x08 */ u8 defect_num[20]; + /* 0x1C */ void* loadptr; + /* 0x20 */ u8 defect_data[192]; + /* 0xE0 */ u16 rom_end_lba; + /* 0xE2 */ u16 ram_start_lba; + /* 0xE4 */ u16 ram_end_lba; + } param; + /* 0x00 */ u64 u64_data[29]; +} leo_sys_form; // size = 0xE8 + +typedef struct { + /* 0x0 */ u8 year; + /* 0x1 */ u8 month; + /* 0x2 */ u8 day; + /* 0x3 */ u8 hour; + /* 0x4 */ u8 minute; + /* 0x5 */ u8 second; +} __LOCTime; // size = 0x6 + /* libleo conversion tables */ extern const u8 LEOBYTE_TBL1[]; extern const u16 LEOBYTE_TBL2[]; @@ -73,6 +98,26 @@ extern const s32 LEORAM_BYTE[]; #define LEO_STATUS_MECHANIC_ERROR 0x00020000 #define LEO_STATUS_DISK_CHANGE 0x00010000 +#define LEO_CUR_TK_INDEX_LOCK 0x60000000 + +#define LEO_BM_STATUS_RUNNING 0x80000000 //Running +#define LEO_BM_STATUS_ERROR 0x04000000 //Error +#define LEO_BM_STATUS_MICRO 0x02000000 //Micro Status? +#define LEO_BM_STATUS_BLOCK 0x01000000 //Block Transfer +#define LEO_BM_STATUS_C1CORRECTION 0x00800000 //C1 Correction +#define LEO_BM_STATUS_C1DOUBLE 0x00400000 //C1 Double +#define LEO_BM_STATUS_C1SINGLE 0x00200000 //C1 Single +#define LEO_BM_STATUS_C1ERROR 0x00010000 //C1 Error + +#define LEO_BM_CTL_START 0x80000000 //Start Buffer Manager +#define LEO_BM_CTL_MODE 0x40000000 //Buffer Manager Mode +#define LEO_BM_CTL_IMASK 0x20000000 //BM Interrupt Mask +#define LEO_BM_CTL_RESET 0x10000000 //Buffer Manager Reset +#define LEO_BM_CTL_DISABLE_OR 0x08000000 //Disable OR Check? +#define LEO_BM_CTL_DISABLE_C1 0x04000000 //Disable C1 Correction +#define LEO_BM_CTL_BLOCK 0x02000000 //Block Transfer +#define LEO_BM_CTL_CLR_MECHANIC_INTR 0x01000000 //Mechanic Interrupt Reset + /* ASIC commands */ #define ASIC_NO_OPERATION 0x00000000 #define ASIC_RD_SEEK 0x00010001 @@ -95,7 +140,11 @@ extern const s32 LEORAM_BYTE[]; #define ASIC_READ_TIMER_YEAR 0x00120000 #define ASIC_READ_TIMER_DATE 0x00130000 #define ASIC_READ_TIMER_MINUTE 0x00140000 +#define ASIC_SET_LED_TIMER 0x00150000 +#define ASIC_READ_PROGRAM_VERSION 0x001B0000 #define ASIC_NEED_DISK_IN 0x00000001 +#define ASIC_SOFT_RESET_CODE 0x000a0000 +#define ASIC_HARD_RESET_CODE 0xaaaa0000 // Functions extern u8 leoAnalize_asic_status(void); @@ -120,24 +169,56 @@ extern void leoClrUA_RESET(void); extern void leoClrUA_MEDIUM_CHANGED(void); extern void leoSetUA_MEDIUM_CHANGED(void); extern void leoInitUnit_atten(void); +extern void leoClr_queue(void); +extern void leointerrupt(void*); +extern void leomain(void*); +extern void leoRead_common(u32 offset); +extern void leoClrUA_MEDIUM_CHANGED(void); +extern void leoSetUA_MEDIUM_CHANGED(void); extern int leoC2_Correction(void); extern s32 leoVerifyRTC(u8 yearhi, u8 yearlo); +extern u8 __locReadTimer(__LOCTime* time); extern s32 __leoSetReset(void); extern s32 __osLeoInterrupt(void); +extern u16 leoLba_to_vzone(u32 lba); +extern u16 leoLba_to_phys(u32 lba); extern s32 __leoActive; +extern s32 __leoResetCalled; +extern s32 __leoQueuesCreated; extern s32 LEO_country_code; -extern u8 leoDiskStack[]; +extern u32 LEOasic_bm_ctl_shadow; +extern u32 LEOasic_seq_ctl_shadow; extern u8 LEOdisk_type; extern u8 LEOdrive_flag; +extern u8 leoDiskStack[]; +extern u8 LEOcommandThreadStack[0x400]; +extern u8 LEOinterruptThreadStack[0x400]; +extern u8* LEOwrite_pointer; +extern u8* LEOc2ctrl_que_buf; extern LEOVersion __leoVersion; extern LEOCmd* LEOcur_command; +extern OSMesgQueue LEOblock_que; extern OSMesgQueue LEOevent_que; extern OSMesgQueue LEOc2ctrl_que; extern OSMesgQueue LEOcontrol_que; +extern OSMesgQueue LEOpost_que; +extern OSMesgQueue LEOcommand_que; +extern OSMesgQueue LEOdma_que; +extern OSMesg LEOevent_que_buf[1]; +extern OSMesg LEOcontrol_que_buf[1]; +extern OSMesg LEOdma_que_buf[2]; +extern OSMesg LEOblock_que_buf[1]; +extern OSMesg LEOpost_que_buf[1]; +extern OSIoMesg LEOPiDmaParam; extern OSPiHandle* LEOPiInfo; +extern OSThread LEOcommandThread; extern OSThread LEOinterruptThread; extern tgt_param_form LEOtgt_param; -extern vu16 LEOrw_flags; +extern leo_sys_form LEO_sys_data; + +extern vu8 LEOclr_que_flag; +// needs to not be volatile in some files +// extern vu16 LEOrw_flags; #endif diff --git a/splat.yaml b/splat.yaml index 6dc89ca..ce5276d 100644 --- a/splat.yaml +++ b/splat.yaml @@ -127,38 +127,38 @@ segments: - [0x518A0, asm] - [0x51B20, asm] - [0x51BC0, c, libleo/readwrite] - - [0x51C50, asm, libleo/leofunc] - - [0x520C0, asm, libleo/leoint] - - [0x52AC0, asm, libleo/leocmdex] + - [0x51C50, c, libleo/leofunc] + - [0x520C0, c, libleo/leoint] + - [0x52AC0, c, libleo/leocmdex] - [0x53150, c, libleo/leoread] - - [0x53310, asm, libleo/lbatobyte] - - [0x53460, asm, libleo/driverominit] - - [0x535C0, asm, libleo/inquiry] + - [0x53310, c, libleo/lbatobyte] + - [0x53460, c, libleo/driverominit] + - [0x535C0, c, libleo/leoinquiry] - [0x53670, c, libleo/leodiskinit] - [0x53710, c, libleo/readdiskid] - - [0x53770, asm, libleo/leord_diskid] + - [0x53770, c, libleo/leord_diskid] - [0x53900, c, libleo/leomecha] - - [0x54250, asm, libleo/spdlmotor] + - [0x54250, c, libleo/spdlmotor] - [0x54310, c, libleo/leoc2ecc] - [0x55400, c, libleo/setrtc] - - [0x55570, asm, libleo/leomseq_tbl] - - [0x55720, asm, libleo/leomotor] - - [0x55810, asm, libleo/leomode_sel] + - [0x55570, c, libleo/leomseq_tbl] + - [0x55720, c, libleo/leomotor] + - [0x55810, c, libleo/leomode_sel] - [0x558C0, c, libleo/leord_capa] - - [0x55960, asm, libleo/leoutil] - - [0x55BB0, asm, libleo/leorezero] - - [0x55C50, asm, libleo/bytetolba] - - [0x55DB0, asm, libleo/leoreset] - - [0x55ED0, asm, libleo/leotranslat] - - [0x56170, asm, libleo/leotimer] - - [0x56680, asm, libleo/leowrite] + - [0x55960, c, libleo/leoutil] + - [0x55BB0, c, libleo/leorezero] + - [0x55C50, c, libleo/bytetolba] + - [0x55DB0, c, libleo/leoreset] + - [0x55ED0, c, libleo/leotranslat] + - [0x56170, c, libleo/leotimer] + - [0x56680, c, libleo/leowrite] - [0x567B0, c, libleo/cjcreateleomanager] - [0x569F0, c, libleo/leointerrupt] - [0x570C0, c, libleo/driveexist] - [0x57190, c, libleo/testunitready] - [0x57230, c, libleo/leotestunit] - [0x57270, c, libleo/readrtc] - - [0x572D0, asm, libleo/leoseek] + - [0x572D0, c, libleo/leoseek] - [0x57390, c, libleo/seek] - [0x573F0, c, libultra/io/piacs] - [0x574B0, hasm, libultra/os/setcause] diff --git a/src/libleo/bytetolba.c b/src/libleo/bytetolba.c new file mode 100644 index 0000000..684b1f1 --- /dev/null +++ b/src/libleo/bytetolba.c @@ -0,0 +1,41 @@ +#include +#include "libleo/internal.h" + +s32 LeoByteToLBA(s32 startlba, u32 nbytes, s32* lba) { + u32 reslba; + u32 byte_p_blk; + u16 zone; + u16 vzone; + u8 flag; + + if (!__leoActive) { + return -1; + } + reslba = 0; + flag = vzone = 1; + startlba += 0x18; + while (nbytes != 0) { + if ((flag != 0) || (LEOVZONE_TBL[LEOdisk_type][vzone] == startlba)) { + vzone = leoLba_to_vzone(startlba); + zone = LEOVZONE_PZONEHD_TBL[LEOdisk_type][vzone]; + if (zone >= 8) { + zone += -7; + } + byte_p_blk = LEOBYTE_TBL2[zone]; + } + if (nbytes < byte_p_blk) { + nbytes = 0; + } else { + nbytes -= byte_p_blk; + } + reslba++; + startlba++; + if ((nbytes != 0) && ((u32) startlba >= NUM_LBAS+0x18)) { + return LEO_ERROR_LBA_OUT_OF_RANGE; + } + flag = 0; + } + + *lba = reslba; + return 0; +} diff --git a/src/libleo/cjcreateleomanager.c b/src/libleo/cjcreateleomanager.c index 10deae9..0cf9ae1 100644 --- a/src/libleo/cjcreateleomanager.c +++ b/src/libleo/cjcreateleomanager.c @@ -1,13 +1,14 @@ #include #include "libleo/internal.h" -#ifdef NON_MATCHING -// https://decomp.me/scratch/OYMx2 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" + s32 LeoCJCreateLeoManager(OSPri comPri, OSPri intPri, OSMesg *cmdBuf, s32 cmdMsgCnt) { OSPiHandle* driveRomHandle; OSPiHandle* leoDiskHandle; - volatile LEOCmdInquiry cmdBlockInq; - volatile LEOCmd cmdBlockID; + UNUSED volatile LEOCmdInquiry cmdBlockInq; + UNUSED volatile LEOCmd cmdBlockID; LEODiskID thisID; u32 stat; u32 data; @@ -24,7 +25,7 @@ s32 LeoCJCreateLeoManager(OSPri comPri, OSPri intPri, OSMesg *cmdBuf, s32 cmdMsg driveRomHandle = osDriveRomInit(); __leoActive = 1; - __osSetHWIntrRoutine(1, __osLeoInterrupt, leoDiskStack + 0xFF0); + __osSetHWIntrRoutine(1, __osLeoInterrupt, leoDiskStack); leoInitialize(comPri, intPri, cmdBuf, cmdMsgCnt); if (osResetType == 1) { @@ -78,6 +79,3 @@ s32 LeoCJCreateLeoManager(OSPri comPri, OSPri intPri, OSMesg *cmdBuf, s32 cmdMsg return LEO_ERROR_GOOD; } -#else -#pragma GLOBAL_ASM("asm/nonmatchings/libleo/cjcreateleomanager/LeoCJCreateLeoManager.s") -#endif diff --git a/src/libleo/driverominit.c b/src/libleo/driverominit.c new file mode 100644 index 0000000..42924ec --- /dev/null +++ b/src/libleo/driverominit.c @@ -0,0 +1,57 @@ +#include +#include "libleo/internal.h" + +void __osPiRelAccess(void); +void __osPiGetAccess(void); + +extern OSPiHandle* __osCurrentHandle[]; +extern OSPiHandle __DriveRomHandle; + +#ifdef NON_MATCHING +// https://decomp.me/scratch/uNZ73 +OSPiHandle* osDriveRomInit(void) { + register s32 saveMask; + register u32 value; + register s32 status; + static s32 first = 1; // D_80079580 + + __osPiGetAccess(); + if (!first) { + __osPiRelAccess(); + return &__DriveRomHandle; + } + first = 0; + __DriveRomHandle.type = DEVICE_TYPE_BULK; + __DriveRomHandle.baseAddress = PHYS_TO_K1(PI_DOM1_ADDR1); + __DriveRomHandle.domain = PI_DOMAIN1; + __DriveRomHandle.speed = 0; + bzero(&__DriveRomHandle.transferInfo, sizeof(__OSTranxInfo)); + + while (status = HW_REG(PI_STATUS_REG, u32), status & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY)) {} + + 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; + + value = HW_REG(__DriveRomHandle.baseAddress, u32); + __DriveRomHandle.latency = value & 0xFF; + __DriveRomHandle.pulse = (value >> 8) & 0xFF; + __DriveRomHandle.pageSize = (value >> 0x10) & 0xF; + __DriveRomHandle.relDuration = (value >> 0x14) & 0xF; + + HW_REG(PI_BSD_DOM1_LAT_REG, u32) = (u8)value; + HW_REG(PI_BSD_DOM1_PGS_REG, u32) = __DriveRomHandle.pageSize; + HW_REG(PI_BSD_DOM1_RLS_REG, u32) = __DriveRomHandle.relDuration; + HW_REG(PI_BSD_DOM1_PWD_REG, u32) = __DriveRomHandle.pulse; + + saveMask = __osDisableInt(); + __DriveRomHandle.next = __osPiTable; + __osPiTable = &__DriveRomHandle; + __osRestoreInt(saveMask); + __osPiRelAccess(); + return &__DriveRomHandle; +} +#else +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/driverominit/osDriveRomInit.s") +#endif diff --git a/src/libleo/lbatobyte.c b/src/libleo/lbatobyte.c new file mode 100644 index 0000000..499b0bd --- /dev/null +++ b/src/libleo/lbatobyte.c @@ -0,0 +1,37 @@ +#include +#include "libleo/internal.h" + +s32 LeoLBAToByte(s32 startlba, u32 nlbas, s32* bytes) { + u32 resbytes; + u32 byte_p_blk; + u16 zone; + u16 vzone; + u8 flag; + + if (!__leoActive) { + return -1; + } + resbytes = 0; + flag = vzone = 1; + startlba += 0x18; + while (nlbas > 0) { + if ((flag != 0) || (LEOVZONE_TBL[LEOdisk_type][vzone] == startlba)) { + vzone = leoLba_to_vzone(startlba); + zone = LEOVZONE_PZONEHD_TBL[LEOdisk_type][vzone]; + if (zone >= 8) { + zone -= 7; + } + byte_p_blk = LEOBYTE_TBL2[zone]; + } + resbytes += byte_p_blk; + nlbas -= 1; + startlba += 1; + if ((nlbas > 0) && ((u32)startlba >= NUM_LBAS+0x18)) { + return LEO_ERROR_LBA_OUT_OF_RANGE; + } + flag = 0; + } + + *bytes = resbytes; + return LEO_ERROR_GOOD; +} diff --git a/src/libleo/leoc2ecc.c b/src/libleo/leoc2ecc.c index e880a5c..d9026ba 100644 --- a/src/libleo/leoc2ecc.c +++ b/src/libleo/leoc2ecc.c @@ -1,5 +1,8 @@ #include "common.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunknown-pragmas" + #pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoC2_Correction.s") #pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoC2_single_ecc.s") diff --git a/src/libleo/leocmdex.c b/src/libleo/leocmdex.c new file mode 100644 index 0000000..8b74dac --- /dev/null +++ b/src/libleo/leocmdex.c @@ -0,0 +1,5 @@ +#include "common.h" + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leocmdex/leomain.s") + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leocmdex/leoRead_system_area.s") diff --git a/src/libleo/leofunc.c b/src/libleo/leofunc.c new file mode 100644 index 0000000..8f0ed0b --- /dev/null +++ b/src/libleo/leofunc.c @@ -0,0 +1,133 @@ +#include +#include "libleo/internal.h" +#include "PR/os_message.h" + +const u8 LEO_ZERO_MESG[] = { 0 }; + +#ifdef NON_MATCHING +// https://decomp.me/scratch/dB2K5 +void leoInitialize(OSPri compri, OSPri intpri, OSMesg* command_que_buf, u32 cmd_buff_size) { + u32 savedMask; + OSPri oldPri; + OSPri myPri; + OSPri pri; + + if (intpri < compri) { + pri = compri; + } else { + pri = intpri; + } + + oldPri = -1; + + myPri = osGetThreadPri(NULL); + if (myPri < pri) { + oldPri = myPri; + osSetThreadPri(NULL, pri); + } + + savedMask = __osDisableInt(); + + __leoQueuesCreated = true; + osCreateMesgQueue(&LEOcommand_que, command_que_buf, cmd_buff_size); + osCreateMesgQueue(&LEOcontrol_que, LEOcontrol_que_buf, ARRAY_COUNT(LEOcontrol_que_buf)); + osCreateMesgQueue(&LEOevent_que, LEOevent_que_buf, ARRAY_COUNT(LEOevent_que_buf)); + osCreateMesgQueue(&LEOdma_que, LEOdma_que_buf, ARRAY_COUNT(LEOdma_que_buf)); + osCreateMesgQueue(&LEOblock_que, LEOblock_que_buf, ARRAY_COUNT(LEOblock_que_buf)); + osCreateMesgQueue(&LEOpost_que, LEOpost_que_buf, ARRAY_COUNT(LEOpost_que_buf)); + osCreateThread(&LEOcommandThread, 1, leomain, NULL, LEOcommandThreadStack + sizeof(LEOcommandThreadStack), compri); + osStartThread(&LEOcommandThread); + // LEOinterruptThreadStack reused the same memory address (D_80100638) as LEOcommand_que + // This won't compile + osCreateThread(&LEOinterruptThread, 1, leointerrupt, NULL, LEOinterruptThreadStack + sizeof(LEOinterruptThreadStack), intpri); + osStartThread(&LEOinterruptThread); + osSetEventMesg(OS_EVENT_CART, &LEOevent_que, (OSMesg)0x30000); + osSendMesg(&LEOblock_que, NULL, 0); + __osRestoreInt(savedMask); + + if (oldPri != -1) { + osSetThreadPri(NULL, oldPri); + } +} +#else +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leofunc/leoInitialize.s") +#endif + +void leoCommand(void* cmd_blk_addr) { + if (__leoResetCalled != 0) { + ((LEOCmd*)cmd_blk_addr)->header.status = LEO_STATUS_CHECK_CONDITION; + ((LEOCmd*)cmd_blk_addr)->header.sense = LEO_SENSE_WAITING_NMI; + if ((((LEOCmd*)cmd_blk_addr)->header.control & LEO_CONTROL_POST) != 0) { + osSendMesg(((LEOCmd*)cmd_blk_addr)->header.post, (OSMesg)LEO_SENSE_WAITING_NMI, 1); // Presumably + } + return; + } + osRecvMesg(&LEOblock_que, NULL, 1); + ((LEOCmd*)cmd_blk_addr)->header.status = LEO_STATUS_BUSY; + ((LEOCmd*)cmd_blk_addr)->header.sense = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + + switch (((LEOCmd*)cmd_blk_addr)->header.command) { + case 1: + LEOclr_que_flag = 0xFF; + leoClr_queue(); + LEOclr_que_flag = 0; + ((LEOCmd*)cmd_blk_addr)->header.status = LEO_STATUS_GOOD; + if (((LEOCmd*)cmd_blk_addr)->header.control & LEO_CONTROL_POST) { + osSendMesg(((LEOCmd*)cmd_blk_addr)->header.post, (OSMesg)0, 1); + } + break; + + case 5: + case 6: + ((LEOCmd*)cmd_blk_addr)->data.readwrite.rw_bytes = 0; + goto cmd_queing; + + default: + if ((u32)(((LEOCmd*)cmd_blk_addr)->header.command - 1) >= 0xE) { + ((LEOCmd*)cmd_blk_addr)->header.sense = LEO_SENSE_INVALID_COMMAND_OPERATION_CODE; + ((LEOCmd*)cmd_blk_addr)->header.status = LEO_STATUS_CHECK_CONDITION; + break; + } + + cmd_queing: + if (osSendMesg(&LEOcommand_que, (OSMesg)cmd_blk_addr, 0) != 0) { + ((LEOCmd*)cmd_blk_addr)->header.sense = LEO_SENSE_QUEUE_FULL; + ((LEOCmd*)cmd_blk_addr)->header.status = LEO_STATUS_CHECK_CONDITION; + } + } + osSendMesg(&LEOblock_que, (OSMesg)0, 1); +} + +void LeoReset(void) { + __leoResetCalled = true; + if (__leoQueuesCreated) { + LEOclr_que_flag = 0xFF; + leoClr_queue(); + LEOclr_que_flag = 0; + osRecvMesg(&LEOevent_que, NULL, 0); + osSendMesg(&LEOevent_que, (OSMesg)ASIC_SOFT_RESET_CODE, 1); + osSendMesg(&LEOcommand_que, (OSMesg)LEO_ZERO_MESG, 1); + } +} + +s32 __leoSetReset(void) { + leoDrive_reset(); + return 0; +} + +s32 LeoResetClear(void) { + LEOCmdHeader resetclear; + + resetclear.command = 0xF; + resetclear.control = LEO_CONTROL_POST; + resetclear.status = 0; + resetclear.post = &LEOpost_que; + if (osSendMesg(&LEOcommand_que, &resetclear.command, 0) != 0) { + return LEO_SENSE_QUEUE_FULL; + } + osRecvMesg(&LEOpost_que, NULL, 1); + if (resetclear.status == LEO_STATUS_GOOD) { + return LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + } + return resetclear.sense; +} diff --git a/src/libleo/leoinquiry.c b/src/libleo/leoinquiry.c new file mode 100644 index 0000000..40dab40 --- /dev/null +++ b/src/libleo/leoinquiry.c @@ -0,0 +1,22 @@ +#include +#include "libleo/internal.h" + +void leoInquiry(void) { + u32 asic_id; + + osEPiReadIo(LEOPiInfo, LEO_ID_REG, &asic_id); + if (leoSend_asic_cmd_w(ASIC_READ_PROGRAM_VERSION, 0) == 0) { + u32 asic_data; + + osEPiReadIo(LEOPiInfo, LEO_DATA, &asic_data); + if (asic_data & LEO_STATUS_DISK_CHANGE) { + asic_id |= LEO_STATUS_MOTOR_NOT_SPINNING; + } + } + + ((LEOCmdInquiry*)LEOcur_command)->dev_type = 0; + ((LEOCmdInquiry*)LEOcur_command)->version = asic_id >> 0x10; + ((LEOCmdInquiry*)LEOcur_command)->dev_num = 1; + ((LEOCmdInquiry*)LEOcur_command)->leo_bios_ver = 0; + LEOcur_command->header.status = LEO_STATUS_GOOD; +} diff --git a/src/libleo/leoint.c b/src/libleo/leoint.c new file mode 100644 index 0000000..70c52dd --- /dev/null +++ b/src/libleo/leoint.c @@ -0,0 +1,115 @@ +#include +#include "libleo/internal.h" + +extern vu16 LEOrw_flags; + +void* read_write_track(); + +void leointerrupt(void* arg) { + u32 result; + u32 tg_blocks; + + osCreateMesgQueue(&LEOc2ctrl_que, (OSMesg)&LEOc2ctrl_que_buf, 1); + + while (true) { + osStopThread(&LEOinterruptThread); + tg_blocks = LEOcur_command->data.readwrite.xfer_blks; + LEOwrite_pointer = LEOcur_command->data.readwrite.buff_ptr; + do { + leoLba_to_phys(LEOtgt_param.lba); + if (LEOrw_flags & 0x8000) { + result = leoSeek_i(1); + } else { + result = leoSeek_i(0); + } + + if (result != 0) { + goto complete; + } + + if (LEOrw_flags & 0x2000) { + LEOtgt_param.rdwr_blocks = 1; + } else if (LEOtgt_param.rdwr_blocks > tg_blocks) { + LEOtgt_param.rdwr_blocks = tg_blocks; + } + LEOtgt_param.lba += LEOtgt_param.rdwr_blocks; + tg_blocks -= LEOtgt_param.rdwr_blocks; + result = read_write_track(); + if (result != 0) { + goto complete; + } + + LEOcur_command->data.readwrite.rw_bytes = LEOwrite_pointer - (u8*)LEOcur_command->data.readwrite.buff_ptr; + } while (tg_blocks != 0); + result = 0x90000; // Inaccessible? + + complete:; + + osSendMesg(&LEOcontrol_que, result, 1); + } +} + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoint/read_write_track.s") + +u32 leoChk_mecha_int(void) { + u32 stat = leoWait_mecha_cmd_done(ASIC_RD_SEEK); + u32 index_stat; + + if (stat == 0) { + osEPiReadIo(LEOPiInfo, LEO_CUR_TK, &index_stat); + if ((index_stat & LEO_CUR_TK_INDEX_LOCK) != LEO_CUR_TK_INDEX_LOCK) { + stat = 0x18; + } + } + return stat; +} + +void leosetup_BM(void) { + osEPiWriteIo(LEOPiInfo, 0x05000510U, LEOasic_bm_ctl_shadow | 0x10000000); + osEPiWriteIo(LEOPiInfo, 0x05000510U, LEOasic_bm_ctl_shadow); + if (LEOtgt_param.start_block != 0) { + LEOasic_bm_ctl_shadow = 0x5A0000; + } else { + LEOasic_bm_ctl_shadow = 0; + } + if (!(LEOrw_flags & 0x8000)) { + LEOasic_bm_ctl_shadow |= 0x40000000; + } + if (LEOtgt_param.rdwr_blocks == 2) { + LEOasic_bm_ctl_shadow |= 0x02000000; + } + osEPiWriteIo(LEOPiInfo, 0x05000510U, LEOasic_bm_ctl_shadow); +} + +#ifdef NON_MATCHING +u32 leochk_err_reg(void) { + u32 sense; + u32 index_status; + + osEPiReadIo(LEOPiInfo, 0x05000514U, &sense); + osEPiWriteIo(LEOPiInfo, 0x05000510U, LEOasic_bm_ctl_shadow | 0x10000000); + osEPiWriteIo(LEOPiInfo, 0x05000510U, LEOasic_bm_ctl_shadow); + if (sense & 0x04000000) { + return 0x31; + } + if (sense & 0x10000000) { + return 4; + } + if (sense & 0x42000000) { + if (LEOrw_flags & 0x8000) { + return 0x16; + } + return 0x17; + } + if (sense & 0x80000000) { + return 0x18; + } + osEPiReadIo(LEOPiInfo, 0x0500050CU, &index_status); + if ((index_status & 0x60000000) == 0x60000000) { + return 0x19; + } + return 0x18; +} +#else +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoint/leochk_err_reg.s") +#endif diff --git a/src/libleo/leomecha.c b/src/libleo/leomecha.c index 5de7819..a9ffa55 100644 --- a/src/libleo/leomecha.c +++ b/src/libleo/leomecha.c @@ -215,7 +215,14 @@ u8 leoRecal_w(void) { return leoSend_asic_cmd_w(ASIC_RECAL, 0); } -#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leomecha/leoSeek_i.s") +u8 leoSeek_i(u16 rwmode) { + u32 tgt_tk = ((LEOtgt_param.head << 0xC) + LEOtgt_param.cylinder) << 0x10; + + if (rwmode == 0) { + return leoSend_asic_cmd_i(0x10001, tgt_tk); + } + return leoSend_asic_cmd_i(0x20001, tgt_tk); +} u8 leoSeek_w(void) { u8 sksense = leoSeek_i(0); @@ -231,7 +238,7 @@ s32 leoRecv_event_mesg(s32 control) { u32 done_mesg; if (osRecvMesg(&LEOevent_que, (OSMesg*)&done_mesg, control) == 0) { - if (done_mesg == 0xA0000) { + if (done_mesg == ASIC_SOFT_RESET_CODE) { leoDrive_reset(); return 0xFF; } @@ -239,12 +246,63 @@ s32 leoRecv_event_mesg(s32 control) { return 0; } -#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leomecha/leoChk_err_retry.s") +#ifdef NON_MATCHING +// https://decomp.me/scratch/BFO8S +u32 leoChk_err_retry(u32 sense) { + if ((currentCommand == LEO_COMMAND_READ_DISK_ID) || (currentCommand == LEO_COMMAND_START_STOP)) { + switch (sense) { + case LEO_SENSE_POWERONRESET_DEVICERESET_OCCURED: + unit_atten |= 2; + case LEO_SENSE_DIAGNOSTIC_FAILURE: + case LEO_SENSE_COMMAND_PHASE_ERROR: + case LEO_SENSE_WAITING_NMI: + case LEO_SENSE_DEVICE_COMMUNICATION_FAILURE: + case LEO_SENSE_MEDIUM_NOT_PRESENT: + case LEO_SENSE_EJECTED_ILLEGALLY_RESUME: + LEOdrive_flag = 0; + return -1; + } + } else { + switch (sense) { + case LEO_SENSE_POWERONRESET_DEVICERESET_OCCURED: + unit_atten |= 2; + break; + case LEO_SENSE_MEDIUM_MAY_HAVE_CHANGED: + unit_atten |= 1; + break; + case LEO_SENSE_DIAGNOSTIC_FAILURE: + case LEO_SENSE_COMMAND_PHASE_ERROR: + case LEO_SENSE_WAITING_NMI: + case LEO_SENSE_DEVICE_COMMUNICATION_FAILURE: + case LEO_SENSE_MEDIUM_NOT_PRESENT: + case LEO_SENSE_EJECTED_ILLEGALLY_RESUME: + LEOdrive_flag = 0; + return -1; + } + } -#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leomecha/leoChk_cur_drvmode.s") + return 0; +} +#else +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leomecha/leoChk_err_retry.s") +#endif + +u8 leoChk_cur_drvmode(void) { + u8 devstat = 0; + if (!(asic_cur_status & 0x1000000)) { + devstat = 1; + } + if (asic_cur_status & 0x80000) { + devstat |= 2; + } + if (asic_cur_status & 0x100000) { + devstat |= 4; + } + return devstat; +} void leoDrive_reset() { - osEPiWriteIo(LEOPiInfo, LEO_HARD_RESET, 0xAAAA0000); + osEPiWriteIo(LEOPiInfo, LEO_HARD_RESET, ASIC_HARD_RESET_CODE); } u32 leoChkUnit_atten(void) { diff --git a/src/libleo/leomode_sel.c b/src/libleo/leomode_sel.c new file mode 100644 index 0000000..ef787cd --- /dev/null +++ b/src/libleo/leomode_sel.c @@ -0,0 +1,25 @@ +#include +#include "libleo/internal.h" + +void leoMode_sel(void) { + u32 sense; + + sense = leoSend_asic_cmd_w_nochkDiskChange(ASIC_SET_STBY, LEOcur_command->data.time.yearlo << 0x10); + if (sense != LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION) { + goto mselerror; + } + sense = leoSend_asic_cmd_w_nochkDiskChange(ASIC_SET_SLEEP, LEOcur_command->data.time.month << 0x10); + if (sense != LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION) { + goto mselerror; + } + sense = leoSend_asic_cmd_w_nochkDiskChange(ASIC_SET_LED_TIMER, LEOcur_command->data.readwrite.xfer_blks); + if (sense != LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION) { + mselerror: + LEOcur_command->header.sense = sense; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + + LEOcur_command->header.sense = sense; + LEOcur_command->header.status = LEO_STATUS_GOOD; +} diff --git a/src/libleo/leomotor.c b/src/libleo/leomotor.c new file mode 100644 index 0000000..cddf6d7 --- /dev/null +++ b/src/libleo/leomotor.c @@ -0,0 +1,35 @@ +#include +#include "libleo/internal.h" + +void leoStart_stop(void) { + u32 send_cmd; + u8 sense_code; + u8 retry_cntr = 8; + u32 send_data; + + do { + send_data = 0; + if ((LEOcur_command->header.control & 1)) { + send_cmd = 0x50001; + } else if ((LEOcur_command->header.control & 2)) { + send_cmd = 0xD0000; + } else { + if ((LEOcur_command->header.control & 4)) { + send_data = 0x10000; + } + send_cmd = 0x40000; + } + sense_code = leoSend_asic_cmd_w_nochkDiskChange(send_cmd, send_data); + if (sense_code == 0) { + LEOcur_command->header.status = 0; + return; + } + if (leoChk_err_retry(sense_code)) { + break; + } + } while (retry_cntr--); + + LEOcur_command->header.sense = sense_code; + LEOcur_command->header.status = 2; + return; +} diff --git a/src/libleo/leomseq_tbl.c b/src/libleo/leomseq_tbl.c new file mode 100644 index 0000000..dbdc0f9 --- /dev/null +++ b/src/libleo/leomseq_tbl.c @@ -0,0 +1,53 @@ +#include +#include "libleo/internal.h" + +extern vu16 LEOrw_flags; + +u32 mseq_tbl[0x10]; + +const u32 rd_mseq_code[0x10] = { + 0x00010000, 0x00020200, 0x80030100, 0x82040000, 0xA8050000, 0xA0060600, 0x31760000, 0x00020300, + 0, 0, 0, 0, 0, 0, 0, 0x4060000, +}; +const u32 wt_mseq_code[0x10] = { + 0x40020000, 0x00020000, 0x40130B00, 0x42140100, 0x68050000, 0x50060600, 0x401702FF, 0x01870000, + 0x40020000, 0, 0, 0, 0, 0, 0, 0x40F0000, +}; + +void leoSet_mseq(u16 rwmode) { + u32* tbl; + u32 sct_byte_x; + u32 sct_byte_u; + u8 i; + LEOasic_seq_ctl_shadow &= 0xBFFFFFFF; + osEPiWriteIo(LEOPiInfo, LEO_SEQ_STATUS, LEOasic_seq_ctl_shadow); + if (rwmode == 1) { + tbl = wt_mseq_code; + } else { + tbl = rd_mseq_code; + } + for (i = 0; i < 0x10; i++, tbl++) { + mseq_tbl[i] = *tbl; + } + + sct_byte_x = sct_byte_u = LEOtgt_param.sec_bytes - 1; + sct_byte_u += 7; + sct_byte_x <<= 8; + mseq_tbl[4] |= sct_byte_x; + + osWritebackDCache(mseq_tbl, 0x40); + LEOPiDmaParam.dramAddr = mseq_tbl; + LEOPiDmaParam.devAddr = LEO_RAM_ADDR; + LEOPiDmaParam.size = 0x40; + LEOPiInfo->transferInfo.cmdType = 2; + osEPiStartDma(LEOPiInfo, &LEOPiDmaParam, 1); + osRecvMesg(&LEOdma_que, NULL, 1); + osEPiWriteIo(LEOPiInfo, LEO_SEC_BYTE, (sct_byte_u | 0x5900) << 0x10); + + if (LEOrw_flags & 0x800) { + sct_byte_x += 0x100; + } + osEPiWriteIo(LEOPiInfo, LEO_HOST_SECBYTE, sct_byte_x << 8); + LEOasic_seq_ctl_shadow |= LEO_STATUS_DATA_REQUEST; + osEPiWriteIo(LEOPiInfo, LEO_SEQ_CTL, LEOasic_seq_ctl_shadow); +} diff --git a/src/libleo/leord_capa.c b/src/libleo/leord_capa.c index 07b2434..a07e72d 100644 --- a/src/libleo/leord_capa.c +++ b/src/libleo/leord_capa.c @@ -22,5 +22,3 @@ void leoRd_capacity(void) { } LEOcur_command->header.status = LEO_STATUS_GOOD; } - -// #pragma GLOBAL_ASM("asm/nonmatchings/libleo/leord_capa/leoRd_capacity.s") diff --git a/src/libleo/leord_diskid.c b/src/libleo/leord_diskid.c new file mode 100644 index 0000000..5606042 --- /dev/null +++ b/src/libleo/leord_diskid.c @@ -0,0 +1,3 @@ +#include "common.h" + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leord_diskid/leoReadDiskId.s") diff --git a/src/libleo/leoread.c b/src/libleo/leoread.c index f5b2e78..14f9302 100644 --- a/src/libleo/leoread.c +++ b/src/libleo/leoread.c @@ -1,7 +1,7 @@ #include #include "libleo/internal.h" -void leoRead_common(u32 offset); +extern vu16 LEOrw_flags; void leoRead(void) { LEOrw_flags = 0; diff --git a/src/libleo/leoreset.c b/src/libleo/leoreset.c new file mode 100644 index 0000000..d3daf09 --- /dev/null +++ b/src/libleo/leoreset.c @@ -0,0 +1,27 @@ +#include +#include "libleo/internal.h" + +void leoClr_queue(void) { + OSMesg clr_cmd; + + while (osRecvMesg(&LEOcommand_que, &clr_cmd, OS_MESG_NOBLOCK) == 0) { + ((LEOCmd*)clr_cmd)->header.sense = LEO_SENSE_COMMAND_TERMINATED; + ((LEOCmd*)clr_cmd)->header.status = LEO_STATUS_CHECK_CONDITION; + if (((LEOCmd*)clr_cmd)->header.control & LEO_CONTROL_POST) { + osSendMesg(((LEOCmd*)clr_cmd)->header.post, (OSMesg)LEO_SENSE_COMMAND_TERMINATED, OS_MESG_BLOCK); + } + } +} + +void leoClr_reset(void) { + u32 code = leoAnalize_asic_status(); + + if ((code == LEO_SENSE_COMMAND_PHASE_ERROR) || (code == LEO_SENSE_DEVICE_COMMUNICATION_FAILURE) || + (code == LEO_SENSE_POWERONRESET_DEVICERESET_OCCURED)) { + LEOcur_command->header.sense = code; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + } else { + LEOcur_command->header.sense = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + LEOcur_command->header.status = LEO_STATUS_GOOD; + } +} diff --git a/src/libleo/leorezero.c b/src/libleo/leorezero.c new file mode 100644 index 0000000..190c008 --- /dev/null +++ b/src/libleo/leorezero.c @@ -0,0 +1,26 @@ +#include +#include "libleo/internal.h" + +void leoRezero(void) { + u8 sense_code; + u8 retry_cntr = 8; + + do { + sense_code = leoRecal_w(); + + if (sense_code == LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION) { + LEOtgt_param.cylinder = 0; + LEOtgt_param.head = 0; + LEOtgt_param.zone = 0; + LEOcur_command->header.status = LEO_STATUS_GOOD; + return; + } + + if (leoChk_err_retry(sense_code) != 0) { + break; + } + } while (retry_cntr--); + + LEOcur_command->header.sense = sense_code; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; +} diff --git a/src/libleo/leoseek.c b/src/libleo/leoseek.c new file mode 100644 index 0000000..aa3702c --- /dev/null +++ b/src/libleo/leoseek.c @@ -0,0 +1,31 @@ +#include +#include "libleo/internal.h" + +void leoSeek(void) { + u8 sense_code; + u8 retry_cntr = 20; + + if (LEOcur_command->data.seek.lba > LEO_LBA_MAX) { + LEOcur_command->header.sense = LEO_SENSE_LBA_OUT_OF_RANGE; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + + leoLba_to_phys(LEOcur_command->data.seek.lba + 0x18); + + do { + sense_code = leoSeek_w(); + if (sense_code == LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION) { + LEOcur_command->header.status = LEO_STATUS_GOOD; + return; + } + + if (leoChk_err_retry(sense_code) != 0) { + break; + } + } while (retry_cntr--); + + LEOcur_command->header.sense = sense_code; + LEOcur_command->header.status = LEO_SENSE_DIAGNOSTIC_FAILURE; + return; +} diff --git a/src/libleo/leotimer.c b/src/libleo/leotimer.c new file mode 100644 index 0000000..ac3c7d0 --- /dev/null +++ b/src/libleo/leotimer.c @@ -0,0 +1,83 @@ +#include +#include "libleo/internal.h" + +void leoReadTimer(void) { + UNUSED u8* filler; + UNUSED u8 padding[4]; + __LOCTime time; + u8 sense_code = __locReadTimer(&time); + LEOcur_command->data.time.yearlo = time.year; + LEOcur_command->data.time.month = time.month; + LEOcur_command->data.time.day = time.day; + LEOcur_command->data.time.hour = time.hour; + LEOcur_command->data.time.minute = time.minute; + LEOcur_command->data.time.second = time.second; + if (sense_code != 0) { + LEOcur_command->header.sense = sense_code; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + if ((u8) LEOcur_command->data.time.yearlo >= 0x96U) { + LEOcur_command->data.time.yearhi = 0x19; + } else { + LEOcur_command->data.time.yearhi = 0x20; + } + LEOcur_command->header.status = 0; +} + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leotimer/leoSetTimer.s") + +u8 __locReadTimer(__LOCTime* time) { + u32 data; + u8 sense_code; + + sense_code = leoSend_asic_cmd_w_nochkDiskChange(ASIC_READ_TIMER_MINUTE, 0U); + if (sense_code != 0) { + return sense_code; + } + osEPiReadIo(LEOPiInfo, LEO_DATA, &data); + time->minute = (u8) ((u32) (data & 0xFF000000) >> 0x18); + time->second = (s8) ((u32) (data & 0xFF0000) >> 0x10); + sense_code = leoSend_asic_cmd_w_nochkDiskChange(ASIC_READ_TIMER_DATE, 0U); + if (sense_code != 0) { + time->minute = (u8) (time->minute & 0xFF7F); + return sense_code; + } + osEPiReadIo(LEOPiInfo, LEO_DATA, &data); + time->day = (s8) ((u32) (data & 0xFF000000) >> 0x18); + time->hour = (s8) ((u32) (data & 0xFF0000) >> 0x10); + sense_code = leoSend_asic_cmd_w_nochkDiskChange(ASIC_READ_TIMER_YEAR, 0U); + if (sense_code != 0) { + time->minute = (u8) (time->minute & 0xFF7F); + return sense_code; + } + osEPiReadIo(LEOPiInfo, LEO_DATA, &data); + sense_code = time->minute; + time->year = (s8) ((u32) (data & 0xFF000000) >> 0x18); + time->month = (s8) ((u32) (data & 0xFF0000) >> 0x10); + if (sense_code & 0x80) { + time->minute = (u8) (sense_code & 0xFF7F); + return 5; + } + return 0; +} + +u8 __locSetTimer(__LOCTime* time) { + u32 yearMonth; + u32 dayHour; + u32 minuteSecond; + u8 temp_v0; + u8 temp_v0_2; + u8 temp_v0_3; + u8 result; + + yearMonth = (time->year << 0x18) + (time->month << 0x10); + dayHour = (time->day << 0x18) + (time->hour << 0x10); + minuteSecond = (time->minute << 0x18) + (time->second << 0x10); + temp_v0 = leoSend_asic_cmd_w_nochkDiskChange(ASIC_SET_TIMER_YEAR, yearMonth); + result = temp_v0; + if ((temp_v0 != 0) || (temp_v0_2 = leoSend_asic_cmd_w_nochkDiskChange(ASIC_SET_TIMER_DATE, dayHour), result = temp_v0_2, (temp_v0_2 != 0)) || (temp_v0_3 = leoSend_asic_cmd_w_nochkDiskChange(ASIC_SET_TIMER_MINUTE, minuteSecond), result = temp_v0_3, (temp_v0_3 != 0))) { + return result; + } + return 0; +} diff --git a/src/libleo/leotranslat.c b/src/libleo/leotranslat.c new file mode 100644 index 0000000..090e737 --- /dev/null +++ b/src/libleo/leotranslat.c @@ -0,0 +1,75 @@ +#include +#include "libleo/internal.h" + +void leoTranslate(void) { + u32 lba; + u32 calc_bytes; + u32 calc_blks; + u32 byte_p_blk; + u16 zone; + u16 vzone; + u8 flag; // boolean + if (LEOcur_command->data.readwrite.lba >= NUM_LBAS) { + + + LEOcur_command->header.sense = LEO_SENSE_LBA_OUT_OF_RANGE; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + lba = LEOcur_command->data.readwrite.lba + 0x18; + calc_blks = 0; + calc_bytes = 0; + flag = vzone = 1; + + if (LEOcur_command->header.control & LEO_CONTROL_TBL) { + calc_bytes = LEOcur_command->data.readwrite.xfer_blks; + + while (calc_bytes != 0) { + if (flag || (LEOVZONE_TBL[LEOdisk_type][vzone] == lba)) { + vzone = leoLba_to_vzone(lba); + zone = LEOVZONE_PZONEHD_TBL[LEOdisk_type][vzone]; + if (zone >= 8) + zone -= 7; + byte_p_blk = LEOBYTE_TBL2[zone]; + } + if (calc_bytes < byte_p_blk) { + calc_bytes = 0; + } else { + calc_bytes -= byte_p_blk; + } + calc_blks++; + lba++; + + if ((calc_bytes != 0) && (lba >= 0x10DC)) { + LEOcur_command->header.sense = LEO_SENSE_LBA_OUT_OF_RANGE; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + flag = false; + } + LEOcur_command->data.readwrite.buff_ptr = calc_blks; + } else { + calc_blks = LEOcur_command->data.readwrite.xfer_blks; + + while (calc_blks != 0) { + if (flag || (LEOVZONE_TBL[LEOdisk_type][vzone] == lba)) { + vzone = leoLba_to_vzone(lba); + zone = LEOVZONE_PZONEHD_TBL[LEOdisk_type][vzone]; + if (zone >= 8) + zone -= 7; + byte_p_blk = LEOBYTE_TBL2[zone]; + } + calc_bytes += byte_p_blk; + calc_blks--; + lba++; + if ((calc_blks != 0) && (lba >= 0x10DC)) { + LEOcur_command->header.sense = LEO_SENSE_LBA_OUT_OF_RANGE; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + flag = false; + } + LEOcur_command->data.readwrite.buff_ptr = calc_bytes; + } + LEOcur_command->header.status = LEO_STATUS_GOOD; +} diff --git a/src/libleo/leoutil.c b/src/libleo/leoutil.c new file mode 100644 index 0000000..af1ae63 --- /dev/null +++ b/src/libleo/leoutil.c @@ -0,0 +1,34 @@ +#include +#include "libleo/internal.h" + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoutil/leoLba_to_phys.s") + +const u16 LEOVZONE_TBL[][0x10] = { + { 0x0124, 0x0248, 0x035A, 0x047E, 0x05A2, 0x06B4, 0x07C6, 0x08D8, 0x09EA, 0x0AB6, 0x0B82, 0x0C94, 0x0DA6, 0x0EB8, + 0x0FCA, 0x10DC }, + { 0x0124, 0x0248, 0x035A, 0x046C, 0x057E, 0x06A2, 0x07C6, 0x08D8, 0x09EA, 0x0AFC, 0x0BC8, 0x0C94, 0x0DA6, 0x0EB8, + 0x0FCA, 0x10DC }, + { 0x0124, 0x0248, 0x035A, 0x046C, 0x057E, 0x0690, 0x07A2, 0x08C6, 0x09EA, 0x0AFC, 0x0C0E, 0x0CDA, 0x0DA6, 0x0EB8, + 0x0FCA, 0x10DC }, + { 0x0124, 0x0248, 0x035A, 0x046C, 0x057E, 0x0690, 0x07A2, 0x08B4, 0x09C6, 0x0AEA, 0x0C0E, 0x0D20, 0x0DEC, 0x0EB8, + 0x0FCA, 0x10DC }, + { 0x0124, 0x0248, 0x035A, 0x046C, 0x057E, 0x0690, 0x07A2, 0x08B4, 0x09C6, 0x0AD8, 0x0BEA, 0x0D0E, 0x0E32, 0x0EFE, + 0x0FCA, 0x10DC }, + { 0x0124, 0x0248, 0x035A, 0x046C, 0x057E, 0x0690, 0x07A2, 0x086E, 0x0980, 0x0A92, 0x0BA4, 0x0CB6, 0x0DC8, 0x0EEC, + 0x1010, 0x10DC }, + { 0x0124, 0x0248, 0x035A, 0x046C, 0x057E, 0x0690, 0x07A2, 0x086E, 0x093A, 0x0A4C, 0x0B5E, 0x0C70, 0x0D82, 0x0E94, + 0x0FB8, 0x10DC }, +}; + +u16 leoLba_to_vzone(u32 lba) { + u16 i; + const u16* ptr = LEOVZONE_TBL[LEOdisk_type]; + + for (i = 0; i < ARRAY_COUNT(LEOVZONE_TBL[LEOdisk_type]); i++, ptr++) { + if (lba < *ptr) { + return i; + } + } + + return 0xFF; +} diff --git a/src/libleo/leowrite.c b/src/libleo/leowrite.c new file mode 100644 index 0000000..54e9e32 --- /dev/null +++ b/src/libleo/leowrite.c @@ -0,0 +1,52 @@ +#include +#include "libleo/internal.h" + +extern u16 LEOrw_flags; // NOT volatile in this file! + +void leoWrite(void) { + u32 message; + u32 start_lba; + u32 xfer_blk; + u32 write_bytes = 0; + u8 retry_count = 0; + + start_lba = LEOcur_command->data.readwrite.lba; + xfer_blk = LEOcur_command->data.readwrite.xfer_blks; + if (((start_lba | xfer_blk) & 0xFFFF0000) != 0) { + goto invalid_lba; + } + + start_lba += 0x18; + if ((start_lba >= 0x10DC) || (start_lba + xfer_blk > 0x10DC)) { + invalid_lba: + LEOcur_command->header.sense = LEO_SENSE_LBA_OUT_OF_RANGE; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + + if (start_lba < LEORAM_START_LBA[LEOdisk_type]) { + LEOcur_command->header.sense = LEO_SENSE_WRITE_PROTECT_ERROR; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + + if (xfer_blk == 0) { + LEOcur_command->header.sense = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + LEOcur_command->header.status = LEO_STATUS_GOOD; + return; + } + + LEOrw_flags = 0x8000; + LEOtgt_param.lba = start_lba; + osStartThread(&LEOinterruptThread); + osRecvMesg(&LEOcontrol_que, (OSMesg*)&message, OS_MESG_BLOCK); + + if (message != 0x90000) { + LEOcur_command->header.sense = message; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + + LEOcur_command->header.sense = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + LEOcur_command->header.status = LEO_STATUS_GOOD; +} diff --git a/src/libleo/setrtc.c b/src/libleo/setrtc.c index 55c532f..280c33b 100644 --- a/src/libleo/setrtc.c +++ b/src/libleo/setrtc.c @@ -22,13 +22,11 @@ s32 LeoSetRTC(LEOCmd* cmdBlock, LEODiskTime* RTCdata, OSMesgQueue* mq) { 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; if (((yearlo & 0xF) >= 0xA) || ((yearlo & 0xF0) >= 0x91) || ((yearhi & 0xF) >= 0xA) || ((yearhi & 0xF0) >= 0x91)) { @@ -40,6 +38,3 @@ s32 leoVerifyRTC(u8 yearhi, u8 yearlo) { } return 0; } -#else -#pragma GLOBAL_ASM("asm/nonmatchings/libleo/setrtc/leoVerifyRTC.s") -#endif diff --git a/src/libleo/spdlmotor.c b/src/libleo/spdlmotor.c new file mode 100644 index 0000000..a32190e --- /dev/null +++ b/src/libleo/spdlmotor.c @@ -0,0 +1,34 @@ +#include +#include "libleo/internal.h" + +s32 LeoSpdlMotor(LEOCmd* cmdBlock, u8 mode, OSMesgQueue* mq) { + if (!__leoActive) { + return -1; + } + cmdBlock->header.command = LEO_COMMAND_START_STOP; + cmdBlock->header.reserve1 = 0; + + switch (mode) { + case LEO_MOTOR_ACTIVE: + cmdBlock->header.control = LEO_CONTROL_START; + break; + case LEO_MOTOR_STANDBY: + cmdBlock->header.control = LEO_CONTROL_STBY; + break; + case LEO_MOTOR_SLEEP: + cmdBlock->header.control = 0; + break; + case LEO_MOTOR_BRAKE: + cmdBlock->header.control = LEO_CONTROL_BRAKE; + break; + } + cmdBlock->header.reserve3 = 0; + + if (mq != NULL) { + cmdBlock->header.post = mq; + cmdBlock->header.control |= LEO_CONTROL_POST; + } + + leoCommand(cmdBlock); + return 0; +} diff --git a/tools/symbol_addrs.txt b/tools/symbol_addrs.txt index 1cb3779..72e1635 100644 --- a/tools/symbol_addrs.txt +++ b/tools/symbol_addrs.txt @@ -16,6 +16,7 @@ _Litob = 0x80064CA0; _Printf = 0x8005D850; _Putfld = 0x8005D1E0; __leoSetReset = 0x80051414; +__leoResetCalled = 0x80079510; __ll_div = 0x8005751C; __ll_lshift = 0x800574B4; __ll_mod = 0x80057608; @@ -76,6 +77,8 @@ __ull_div = 0x80057478; __ull_divremi = 0x800575A8; __ull_rem = 0x8005743C; __ull_rshift = 0x80057410; +__locReadTimer = 0x80055864; +__locSetTimer = 0x800559D4; guLookAtReflect = 0x8005AECC; guLookAtReflectF = 0x8005AAC0; guMtxF2L = 0x8005AF50; @@ -92,16 +95,37 @@ guTranslateF = 0x8005E5A0; ldiv = 0x80064C10; LEOcur_command = 0x801006C8; LEOPiInfo = 0x80100710; +LEOPiDmaParam = 0x80100718; +mseq_tbl = 0x80101090; +rd_mseq_code = 0x8007E170; +wt_mseq_code = 0x8007E1B0; unit_atten = 0x80100844; asic_cur_status = 0x80100840; currentCommand = 0x80100730; -LEOinterruptThread = 0x800FFC88; LEOc2ctrl_que = 0x801006F8; +LEOcommand_que = 0x80100638; LEOcontrol_que = 0x80100668; +LEOcontrol_que_buf = 0x801006B4; +LEOevent_que = 0x80100650; +LEOevent_que_buf = 0x801006B0; +LEOdma_que = 0x80100680; +LEOdma_que_buf = 0x801006B8; +LEOpost_que = 0x800FF9D0; +LEOpost_que_buf = 0x800FF9E8; +LEOblock_que = 0x80100698; +LEOblock_que_buf = 0x801006C0; +LEOcommandThread = 0x800FFAD8; +LEOcommandThreadStack = 0x80100238; +LEOinterruptThread = 0x800FFC88; +LEOinterruptThreadStack = 0x80100638; +LEOclr_que_flag = 0x801006D5; +LEO_ZERO_MESG = 0X8007DA30; LEORAM_START_LBA = 0x8007DD18; LEORAM_BYTE = 0x8007DD28; +LEOVZONE_TBL = 0x8007DB98; +LEOVZONE_PZONEHD_TBL = 0x8007DC98; +LEOBYTE_TBL2 = 0x8007DB84; LEOdrive_flag = 0x801006D4; -LEOevent_que = 0x80100650; LEOtgt_param = 0x801006E0; leoDiskStack = 0x801020D0; LEOdisk_type = 0x801006D8; @@ -156,6 +180,14 @@ leoTest_unit_rdy = 0x80056630; leoTranslate = 0x800552D0; leoWait_mecha_cmd_done = 0x80053150; leointerrupt = 0x800514C0; +read_write_track = 0x80051650; +leoChk_mecha_int = 0x80051C4C; +leosetup_BM = 0x80051CB4; +leochk_err_reg = 0x80051D9C; +LEOwrite_pointer = 0x801006C4; +LEOc2ctrl_que_buf = 0x801006F0; +LEOasic_bm_ctl_shadow = 0x801006CC; +LEOasic_seq_ctl_shadow = 0x801006D0; leomain = 0x80051EC0; lldiv = 0x80064B10; main_func = 0x80000530; @@ -415,7 +447,7 @@ __CartRomHandle = 0x801038D0; __DriveRomHandle = 0x80100740; __osPfsLastChannel = 0x8007AE50; __osViDevMgr = 0x8007AE90; -__osLeoDevMgr = 0x80079514; +__leoQueuesCreated = 0x80079514; __leoActive = 0x800795B0; __leoVersion = 0x801010D0; __additional_scanline = 0x8007AEAC;