From 2152d1df2d38f71f3693d73a764c981e54031924 Mon Sep 17 00:00:00 2001 From: cadmic Date: Tue, 3 Sep 2024 12:30:14 -0700 Subject: [PATCH] [ntsc-1.2] Import libleo from Decompollaborate/n64dd (#2104) * Create stack.h for STACK/STACK_TOP * Import libleo from Decompollaborate/n64dd Co-authored-by: Anghelo Carvajal Co-authored-by: Elliptic Ellipsis * Use (unsigned) int when in mdebug * Apply suggestions from code review Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com> * Use && in leocmdex.c * Use proper names for character tables, revert sNonKanjiIndices * Fix incorrect OSMesg casts * Use LEO_ERROR_GOOD even where docs say 0 Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com> * Remove "Presumably" comment * Whitespace * Remove redundant (debug-only) returns --------- Co-authored-by: Anghelo Carvajal Co-authored-by: Elliptic Ellipsis Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com> --- Makefile | 3 + include/stack.h | 10 + include/ultra64/leo.h | 214 ++++++++++++ include/ultra64/leoappli.h | 198 +++++++++++ include/ultra64/leodrive.h | 147 +++++++++ include/z64.h | 6 - spec | 58 +++- src/boot/boot_main.c | 1 + src/boot/idle.c | 1 + src/boot/z_std_dma.c | 1 + src/code/fault_gc.c | 10 +- src/code/fault_n64.c | 1 + src/code/kanread.s | 2 +- src/code/main.c | 1 + src/libleo/api/bytetolba.c | 44 +++ src/libleo/api/cacreateleomanager.c | 80 +++++ src/libleo/api/cjcreateleomanager.c | 81 +++++ src/libleo/api/clearqueue.c | 20 ++ src/libleo/api/driveexist.c | 41 +++ src/libleo/api/getaadr.s | 332 +++++++++++++++++++ src/libleo/api/getaadr2.s | 33 ++ src/libleo/api/getkadr.s | 229 +++++++++++++ src/libleo/api/lbatobyte.c | 40 +++ src/libleo/api/readwrite.c | 33 ++ src/libleo/api/seek.c | 24 ++ src/libleo/api/spdlmotor.c | 38 +++ src/libleo/api/testunitready.c | 28 ++ src/libleo/leo/leo_tbl.c | 58 ++++ src/libleo/leo/leoc2_syndrome.c | 3 + src/libleo/leo/leoc2ecc.c | 495 ++++++++++++++++++++++++++++ src/libleo/leo/leocmdex.c | 262 +++++++++++++++ src/libleo/leo/leodiskinit.c | 33 ++ src/libleo/leo/leofunc.c | 134 ++++++++ src/libleo/leo/leoglobals.c | 8 + src/libleo/leo/leoinquiry.c | 23 ++ src/libleo/leo/leoint.c | 298 +++++++++++++++++ src/libleo/leo/leointerrupt.c | 208 ++++++++++++ src/libleo/leo/leomecha.c | 344 +++++++++++++++++++ src/libleo/leo/leomode_sel.c | 27 ++ src/libleo/leo/leomotor.c | 36 ++ src/libleo/leo/leomseq_tbl.c | 60 ++++ src/libleo/leo/leoram.c | 41 +++ src/libleo/leo/leord_capa.c | 17 + src/libleo/leo/leord_diskid.c | 54 +++ src/libleo/leo/leoread.c | 70 ++++ src/libleo/leo/leoreset.c | 29 ++ src/libleo/leo/leorezero.c | 28 ++ src/libleo/leo/leoseek.c | 33 ++ src/libleo/leo/leotempbuffer.c | 3 + src/libleo/leo/leotestunit.c | 10 + src/libleo/leo/leotimer.c | 189 +++++++++++ src/libleo/leo/leotranslat.c | 83 +++++ src/libleo/leo/leoutil.c | 107 ++++++ src/libleo/leo/leowrite.c | 54 +++ src/libultra/io/pimgr.c | 1 + src/libultra/io/vimgr.c | 1 + 56 files changed, 4363 insertions(+), 22 deletions(-) create mode 100644 include/stack.h create mode 100644 include/ultra64/leo.h create mode 100644 include/ultra64/leoappli.h create mode 100644 src/libleo/api/bytetolba.c create mode 100644 src/libleo/api/cacreateleomanager.c create mode 100644 src/libleo/api/cjcreateleomanager.c create mode 100644 src/libleo/api/clearqueue.c create mode 100644 src/libleo/api/driveexist.c create mode 100644 src/libleo/api/getaadr.s create mode 100644 src/libleo/api/getaadr2.s create mode 100644 src/libleo/api/getkadr.s create mode 100644 src/libleo/api/lbatobyte.c create mode 100644 src/libleo/api/readwrite.c create mode 100644 src/libleo/api/seek.c create mode 100644 src/libleo/api/spdlmotor.c create mode 100644 src/libleo/api/testunitready.c create mode 100644 src/libleo/leo/leo_tbl.c create mode 100644 src/libleo/leo/leoc2_syndrome.c create mode 100644 src/libleo/leo/leoc2ecc.c create mode 100644 src/libleo/leo/leocmdex.c create mode 100644 src/libleo/leo/leodiskinit.c create mode 100644 src/libleo/leo/leofunc.c create mode 100644 src/libleo/leo/leoglobals.c create mode 100644 src/libleo/leo/leoinquiry.c create mode 100644 src/libleo/leo/leoint.c create mode 100644 src/libleo/leo/leointerrupt.c create mode 100644 src/libleo/leo/leomecha.c create mode 100644 src/libleo/leo/leomode_sel.c create mode 100644 src/libleo/leo/leomotor.c create mode 100644 src/libleo/leo/leomseq_tbl.c create mode 100644 src/libleo/leo/leoram.c create mode 100644 src/libleo/leo/leord_capa.c create mode 100644 src/libleo/leo/leord_diskid.c create mode 100644 src/libleo/leo/leoread.c create mode 100644 src/libleo/leo/leoreset.c create mode 100644 src/libleo/leo/leorezero.c create mode 100644 src/libleo/leo/leoseek.c create mode 100644 src/libleo/leo/leotempbuffer.c create mode 100644 src/libleo/leo/leotestunit.c create mode 100644 src/libleo/leo/leotimer.c create mode 100644 src/libleo/leo/leotranslat.c create mode 100644 src/libleo/leo/leoutil.c create mode 100644 src/libleo/leo/leowrite.c diff --git a/Makefile b/Makefile index 2a2f7df3b7..eb42cd4736 100644 --- a/Makefile +++ b/Makefile @@ -524,6 +524,9 @@ $(BUILD_DIR)/src/libultra/libc/%.o: OPTFLAGS := -O2 $(BUILD_DIR)/src/libultra/os/%.o: OPTFLAGS := -O1 endif +$(BUILD_DIR)/src/libleo/%.o: CC := $(CC_OLD) +$(BUILD_DIR)/src/libleo/%.o: OPTFLAGS := -O2 + $(BUILD_DIR)/assets/misc/z_select_static/%.o: GBI_DEFINES := -DF3DEX_GBI # For using asm_processor on some files: diff --git a/include/stack.h b/include/stack.h new file mode 100644 index 0000000000..231f0d061b --- /dev/null +++ b/include/stack.h @@ -0,0 +1,10 @@ +#ifndef STACK_H +#define STACK_H + +#define STACK(stack, size) \ + u64 stack[ALIGN8(size) / sizeof(u64)] + +#define STACK_TOP(stack) \ + ((u8*)(stack) + sizeof(stack)) + +#endif diff --git a/include/ultra64/leo.h b/include/ultra64/leo.h new file mode 100644 index 0000000000..3bc8a1dd6e --- /dev/null +++ b/include/ultra64/leo.h @@ -0,0 +1,214 @@ +#ifndef ULTRA64_LEO_H +#define ULTRA64_LEO_H + +#ifdef _LANGUAGE_C_PLUS_PLUS +extern "C" { +#endif + +#include "pi.h" +#include "leoappli.h" + +#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) + +typedef u32 LEOError; + +typedef u8 LEOSpdlMode; + +typedef u8 LEOStatus; + +typedef struct LEOVersion { + /* 0x0 */ u8 driver; // version of sw + /* 0x1 */ u8 drive; // version of hw + /* 0x2 */ u8 deviceType; // dev type, always 00 + /* 0x3 */ u8 nDevices; // # of devices, always 01 +} LEOVersion; // size = 0x4 + +typedef struct LEOCapacity { + /* 0x0 */ u32 startLBA; + /* 0x4 */ u32 endLBA; + /* 0x8 */ u32 nbytes; +} LEOCapacity; // size = 0xC + +typedef struct LEODiskTime { + /* 0x0 */ u8 pad; + /* 0x1 */ u8 yearhi; + /* 0x2 */ u8 yearlo; + /* 0x3 */ u8 month; + /* 0x4 */ u8 day; + /* 0x5 */ u8 hour; + /* 0x6 */ u8 minute; + /* 0x7 */ u8 second; +} LEODiskTime; // size = 0x8 + +typedef struct LEOSerialNum { + /* 0x0 */ u64 lineNumber; + /* 0x8 */ LEODiskTime time; +} LEOSerialNum; // size = 0x10 + +typedef struct LEODiskID { + /* 0x0 */ u8 gameName[4]; + /* 0x4 */ u8 gameVersion; + /* 0x5 */ u8 diskNumber; + /* 0x6 */ u8 ramUsage; + /* 0x7 */ u8 diskUsage; + /* 0x8 */ LEOSerialNum serialNumber; + /* 0x18 */ u8 company[2]; + /* 0x1A */ u8 freeArea[6]; +} LEODiskID; // size = 0x20 + +// Not attempting to number this struct until required since it's scary +typedef struct LEOCmd { + /* 0x00 */ LEOCmdHeader header; + union { + struct { + /* 0x0C */ u32 lba; + /* 0x10 */ u32 transferBlks; + /* 0x14 */ void* buffPtr; + /* 0x18 */ u32 rwBytes; +#ifdef _LONGCMD + /* 0x1C */ u32 size; +#endif + } readWrite; + struct { + /* 0x0C */ u32 lba; + } seek; + struct { + /* 0x0C */ void* bufferPointer; + } readdiskid; + /* 0x0C */ LEODiskTime time; + struct { + /* 0x0C */ u8 reserve1; + /* 0x0D */ u8 reserve2; + /* 0x0E */ u8 standbyTime; + /* 0x0F */ u8 sleepTime; + /* 0x10 */ u32 reserve3; + } modeSelect; + } data; +} LEOCmd; // size = 0x1C + + +#define _nbytes readwrite.rwBytes +#define _result header.status + +#endif // defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) + + +#define LEO_SW_VERSION 6 // This will be returned by LeoInquiry command + +#define OS_PRIORITY_LEOMGR OS_PRIORITY_PIMGR + +#define DDROM_FONT_START 0x000A0000 +#define DDROM_WAVEDATA_START 0x00140000 + +/* + * Definition for osLeoSpdlMotor() + */ +#define ACTIVE 0 +#define STANDBY 1 +#define SLEEP 2 +#define BRAKE 4 + +#define LEO_MOTOR_ACTIVE 0 +#define LEO_MOTOR_STANDBY 1 +#define LEO_MOTOR_SLEEP 2 +#define LEO_MOTOR_BRAKE 4 + +#define NUM_LBAS 4292 + +#define BLK_SIZE_ZONE0 19720 +#define BLK_SIZE_ZONE1 18360 +#define BLK_SIZE_ZONE2 17680 +#define BLK_SIZE_ZONE3 16320 +#define BLK_SIZE_ZONE4 14960 +#define BLK_SIZE_ZONE5 13600 +#define BLK_SIZE_ZONE6 12240 +#define BLK_SIZE_ZONE7 10880 +#define BLK_SIZE_ZONE8 9520 + +#define MAX_BLK_SIZE BLK_SIZE_ZONE0 +#define MIN_BLK_SIZE BLK_SIZE_ZONE8 + +#define LEO_ERROR_GOOD 0 +#define LEO_ERROR_DRIVE_NOT_READY 1 +#define LEO_ERROR_DIAGNOSTIC_FAILURE 2 +#define LEO_ERROR_COMMAND_PHASE_ERROR 3 +#define LEO_ERROR_DATA_PHASE_ERROR 4 +#define LEO_ERROR_REAL_TIME_CLOCK_FAILURE 5 +#define LEO_ERROR_BUSY 8 +#define LEO_ERROR_INCOMPATIBLE_MEDIUM_INSTALLED 11 +#define LEO_ERROR_UNKNOWN_FORMAT 11 +#define LEO_ERROR_NO_SEEK_COMPLETE 21 +#define LEO_ERROR_WRITE_FAULT 22 +#define LEO_ERROR_UNRECOVERED_READ_ERROR 23 +#define LEO_ERROR_NO_REFERENCE_POSITION_FOUND 24 +#define LEO_ERROR_TRACK_FOLLOWING_ERROR 25 +#define LEO_ERROR_TRACKING_OR_SPDL_SERVO_FAILURE 25 +#define LEO_ERROR_INVALID_COMMAND_OPERATION_CODE 31 +#define LEO_ERROR_LBA_OUT_OF_RANGE 32 +#define LEO_ERROR_WRITE_PROTECT_ERROR 33 +#define LEO_ERROR_COMMAND_CLEARED_BY_HOST 34 +#define LEO_ERROR_COMMAND_TERMINATED 34 +#define LEO_ERROR_QUEUE_FULL 35 +#define LEO_ERROR_ILLEGAL_TIMER_VALUE 36 +#define LEO_ERROR_WAITING_NMI 37 +#define LEO_ERROR_DEVICE_COMMUNICATION_FAILURE 41 +#define LEO_ERROR_MEDIUM_NOT_PRESENT 42 +#define LEO_ERROR_POWERONRESET_DEVICERESET_OCCURED 43 +#define LEO_ERROR_RAMPACK_NOT_CONNECTED 44 +#define LEO_ERROR_MEDIUM_MAY_HAVE_CHANGED 47 +#define LEO_ERROR_EJECTED_ILLEGALLY_RESUME 49 + +#define LEO_ERROR_NOT_BOOTED_DISK 45 +#define LEO_ERROR_DIDNOT_CHANGED_DISK_AS_EXPECTED 46 + +#define LEO_ERROR_RTC_NOT_SET_CORRECTLY 48 +#define LEO_ERROR_DIAGNOSTIC_FAILURE_RESET 50 +#define LEO_ERROR_EJECTED_ILLEGALLY_RESET 51 + +#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) + +#define GET_ERROR(x) ((x).header.sense) + +extern LEODiskID leoBootID; +extern OSPiHandle* __osDiskHandle; // For exceptasm to get disk info + +// Initialize routine +s32 LeoCreateLeoManager(OSPri comPri, OSPri intPri, OSMesg* cmdBuf, s32 cmdMsgCnt); +s32 LeoCJCreateLeoManager(OSPri comPri, OSPri intPri, OSMesg* cmdBuf, s32 cmdMsgCnt); +s32 LeoCACreateLeoManager(OSPri comPri, OSPri intPri, OSMesg* cmdBuf, s32 cmdMsgCnt); +u32 LeoDriveExist(void); + +// Synchronous functions +s32 LeoClearQueue(void); +s32 LeoByteToLBA(s32 startlba, u32 nbytes, s32* lba); +s32 LeoLBAToByte(s32 startlba, u32 nlbas, s32* bytes); +s32 LeoReadCapacity(LEOCapacity* cap, s32 dir); +s32 LeoInquiry(LEOVersion* ver); +s32 LeoTestUnitReady(LEOStatus* status); + +// Asynchronous functions +s32 LeoSpdlMotor(LEOCmd* cmdBlock, LEOSpdlMode mode, OSMesgQueue* mq); +s32 LeoSeek(LEOCmd* cmdBlock, u32 lba, OSMesgQueue* mq); +s32 LeoRezero(LEOCmd* cmdBlock, OSMesgQueue* mq); +s32 LeoReadWrite(LEOCmd* cmdBlock, s32 direction, u32 LBA, void* vAddr, u32 nLBAs, OSMesgQueue* mq); +s32 LeoReadDiskID(LEOCmd* cmdBlock, LEODiskID* vaddr, OSMesgQueue* mq); +s32 LeoSetRTC(LEOCmd* cmdBlock, LEODiskTime* RTCdata, OSMesgQueue* mq); +s32 LeoReadRTC(LEOCmd* cmdBlock, OSMesgQueue* mq); +s32 LeoModeSelectAsync(LEOCmd* cmdBlock, u32 standby, u32 sleep, OSMesgQueue* mq); + +// Font routines +int LeoGetKAdr(int sjis); +int LeoGetAAdr(int code, int* dx, int* dy, int* cy); +int LeoGetAAdr2(u32 ccode, int* dx, int* dy, int* cy); + +// Boot function +void LeoBootGame(void* entry); + +#endif // defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) + +#ifdef _LANGUAGE_C_PLUS_PLUS +} +#endif + +#endif + diff --git a/include/ultra64/leoappli.h b/include/ultra64/leoappli.h new file mode 100644 index 0000000000..ef526ee5a5 --- /dev/null +++ b/include/ultra64/leoappli.h @@ -0,0 +1,198 @@ +#ifndef ULTRA64_LEOAPPLI_H +#define ULTRA64_LEOAPPLI_H + +#include "thread.h" +#include "message.h" + +#define LEO_DISK_TYPE_MIN 0 +#define LEO_DISK_TYPE_MAX 6 + +#define LEO_LBA_MIN 0 +#define LEO_LBA_MAX 4291 + +#define LEO_LBA_ROM_TOP LEO_LBA_MIN +#define LEO_LBA_ROM_END0 1417 +#define LEO_LBA_ROM_END1 1965 +#define LEO_LBA_ROM_END2 2513 +#define LEO_LBA_ROM_END3 3061 +#define LEO_LBA_ROM_END4 3609 +#define LEO_LBA_ROM_END5 4087 +#define LEO_LBA_ROM_END6 LEO_LBA_MAX +#define LEO_LBA_RAM_TOP0 (LEO_LBA_ROM_END0+1) +#define LEO_LBA_RAM_TOP1 (LEO_LBA_ROM_END1+1) +#define LEO_LBA_RAM_TOP2 (LEO_LBA_ROM_END2+1) +#define LEO_LBA_RAM_TOP3 (LEO_LBA_ROM_END3+1) +#define LEO_LBA_RAM_TOP4 (LEO_LBA_ROM_END4+1) +#define LEO_LBA_RAM_TOP5 (LEO_LBA_ROM_END5+1) +#define LEO_LBA_RAM_TOP6 (LEO_LBA_ROM_END6+1) +#define LEO_LBA_RAM_END6 LEO_LBA_MAX + +void leoInitialize(OSPri compri, OSPri intpri, OSMesg* command_que_buf, u32 cmd_buff_size); +void leoCommand(void* cmd_blk_addr); +void LeoReset(void); +s32 LeoResetClear(void); + +#define LEO_PRIORITY_WRK (OS_PRIORITY_PIMGR-1) +#define LEO_PRIORITY_INT OS_PRIORITY_PIMGR + +#define LEO_COMMAND_CLEAR_QUE 0x01 +#define LEO_COMMAND_INQUIRY 0x02 +#define LEO_COMMAND_TEST_UNIT_READY 0x03 +#define LEO_COMMAND_REZERO 0x04 +#define LEO_COMMAND_READ 0x05 +#define LEO_COMMAND_WRITE 0x06 +#define LEO_COMMAND_SEEK 0x07 +#define LEO_COMMAND_START_STOP 0x08 +#define LEO_COMMAND_READ_CAPACITY 0x09 +#define LEO_COMMAND_TRANSLATE 0x0A +#define LEO_COMMAND_MODE_SELECT 0x0B +#define LEO_COMMAND_READ_DISK_ID 0x0C +#define LEO_COMMAND_READ_TIMER 0x0D +#define LEO_COMMAND_SET_TIMER 0x0E +// should be +// #define LEO_COMMAND_CLEAR_RESET 0x0F + +#define LEO_CONTROL_POST 0x80 // ENABLE POST QUEUE +#define LEO_CONTROL_START 0x01 // START COMMAND +#define LEO_CONTROL_STBY 0x02 // STAND-BY MODE(NOT SLEEP MODE) +#define LEO_CONTROL_WRT 0x01 // READ RE-WRITE-ABLE CAPACITY +#define LEO_CONTROL_TBL 0x01 // TRANSLATE BYTE TO LBA +#define LEO_CONTROL_BRAKE 0x04 // SLEEP MODE(BRAKE ON) + +#define LEO_TEST_UNIT_MR 0x01 // MEDIUM REMOVED +#define LEO_TEST_UNIT_RE 0x02 // HEAD RETRACTED +#define LEO_TEST_UNIT_SS 0x04 // SPINDLE STOPPED + +#define LEO_STATUS_GOOD 0x00 +#define LEO_STATUS_CHECK_CONDITION 0x02 +#define LEO_STATUS_BUSY 0x08 + +#define LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION 00 +#define LEO_SENSE_DRIVE_NOT_READY 01 +#define LEO_SENSE_DIAGNOSTIC_FAILURE 02 +#define LEO_SENSE_COMMAND_PHASE_ERROR 03 +#define LEO_SENSE_DATA_PHASE_ERROR 04 +#define LEO_SENSE_REAL_TIME_CLOCK_FAILURE 05 +#define LEO_SENSE_INCOMPATIBLE_MEDIUM_INSTALLED 11 +#define LEO_SENSE_UNKNOWN_FORMAT 11 +#define LEO_SENSE_NO_SEEK_COMPLETE 21 +#define LEO_SENSE_WRITE_FAULT 22 +#define LEO_SENSE_UNRECOVERED_READ_ERROR 23 +#define LEO_SENSE_NO_REFERENCE_POSITION_FOUND 24 +#define LEO_SENSE_TRACK_FOLLOWING_ERROR 25 +#define LEO_SENSE_TRACKING_OR_SPDL_SERVO_FAILURE 25 +#define LEO_SENSE_INVALID_COMMAND_OPERATION_CODE 31 +#define LEO_SENSE_LBA_OUT_OF_RANGE 32 +#define LEO_SENSE_WRITE_PROTECT_ERROR 33 +#define LEO_SENSE_COMMAND_TERMINATED 34 +#define LEO_SENSE_QUEUE_FULL 35 +#define LEO_SENSE_ILLEGAL_TIMER_VALUE 36 +#define LEO_SENSE_WAITING_NMI 37 +#define LEO_SENSE_DEVICE_COMMUNICATION_FAILURE 41 +#define LEO_SENSE_MEDIUM_NOT_PRESENT 42 +#define LEO_SENSE_POWERONRESET_DEVICERESET_OCCURED 43 +#define LEO_SENSE_MEDIUM_MAY_HAVE_CHANGED 47 +#define LEO_SENSE_EJECTED_ILLEGALLY_RESUME 49 + +typedef struct LEOCmdHeader { + /* 0x0 */ u8 command; + /* 0x1 */ u8 reserve1; + /* 0x2 */ u8 control; + /* 0x3 */ u8 reserve3; + /* 0x4 */ u8 status; + /* 0x5 */ u8 sense; + /* 0x6 */ u8 reserve6; + /* 0x7 */ u8 reserve7; + /* 0x8 */ OSMesgQueue* post; +} LEOCmdHeader; // 0xC + +typedef struct LEOCmdClearQueue { + /* 0x0 */ LEOCmdHeader header; +} LEOCmdClearQueue; // 0xC + +typedef struct LEOCmdInquiry { + /* 0x00 */ LEOCmdHeader header; + /* 0x0C */ u8 devType; + /* 0x0D */ u8 version; + /* 0x0E */ u8 devNum; + /* 0x0F */ u8 leoBiosVer; + /* 0x10 */ u32 reserve5; +} LEOCmdInquiry; // size = 0x14 + +typedef struct LEOCmdTestUnitReady { + /* 0x0 */ LEOCmdHeader header; + /* 0xC */ u8 test; + /* 0xD */ u8 reserve2; + /* 0xE */ u8 reserve3; + /* 0xF */ u8 reserve4; +} LEOCmdTestUnitReady; // size = 0x10 + +typedef struct LEOCmdRezero { + /* 0x0 */ LEOCmdHeader header; +} LEOCmdRezero; // size = 0xC + +typedef struct LEOCmdRead { + /* 0x00 */ LEOCmdHeader header; + /* 0x0C */ u32 lba; + /* 0x10 */ u32 transferBlks; + /* 0x14 */ void* buffPtr; + /* 0x18 */ u32 rwBytes; +} LEOCmdRead; // size = 0x1C + +typedef LEOCmdRead LEOCmdWrite; + +typedef struct LEOCmdSeek { + /* 0x0 */ LEOCmdHeader header; + /* 0xC */ u32 lba; +} LEOCmdSeek; // size = 0x10 + +typedef struct LEOCmdStartStop { + /* 0x0 */ LEOCmdHeader header; +} LEOCmdStartStop; // size = 0xC + +typedef struct LEOCmdReadCapacity { + /* 0x00 */ LEOCmdHeader header; + /* 0x0C */ u32 startLba; + /* 0x10 */ u32 endLba; + /* 0x14 */ u32 capaBytes; +} LEOCmdReadCapacity; // size = 0x18 + +typedef struct LEOCmdTranslate { + /* 0x00 */ LEOCmdHeader header; + /* 0x0C */ u32 startLba; + /* 0x10 */ u32 inParam; + /* 0x14 */ u32 outParam; +} LEOCmdTranslate; // size = 0x18 + +typedef struct LEOCmdModeSelect { + /* 0x00 */ LEOCmdHeader header; + /* 0x0C */ u8 pageCode; + /* 0x0D */ u8 reserve1; + /* 0x0E */ u8 standbyTime; + /* 0x0F */ u8 sleepTime; + /* 0x10 */ u8 ledOnTime; + /* 0x11 */ u8 ledOffTime; + /* 0x12 */ u8 reserve18; + /* 0x13 */ u8 reserve19; +} LEOCmdModeSelect; // size = 0x14 + +typedef struct LEOCmdReadDiskId { + /* 0x0 */ LEOCmdHeader header; + /* 0xC */ void* bufferPointer; +} LEOCmdReadDiskId; // size = 0x10 + +typedef struct LEOCmdReadTimer { + /* 0x00 */ LEOCmdHeader header; + /* 0x0C */ u8 reserve12; + /* 0x0D */ u8 reserve13; + /* 0x0E */ u8 year; + /* 0x0F */ u8 month; + /* 0x10 */ u8 day; + /* 0x11 */ u8 hour; + /* 0x12 */ u8 minute; + /* 0x13 */ u8 second; +} LEOCmdReadTimer; // size = 0x14 + +typedef LEOCmdReadTimer LEOCmdSetTimer; + +#endif diff --git a/include/ultra64/leodrive.h b/include/ultra64/leodrive.h index 36b28f4b9e..cb70b9a1fc 100644 --- a/include/ultra64/leodrive.h +++ b/include/ultra64/leodrive.h @@ -1,7 +1,14 @@ #ifndef ULTRA64_LEODRIVE_H #define ULTRA64_LEODRIVE_H +#include "leo.h" +#include "leoappli.h" +#include "message.h" +#include "pi.h" #include "rcp.h" +#include "stack.h" +#include "thread.h" +#include "ultratypes.h" #define ASIC_BASE PI_DOM2_ADDR1 @@ -44,4 +51,144 @@ // ASIC_STATUS read bits #define LEO_STATUS_MECHANIC_INTR 0x02000000 // Mechanic Interrupt Raised +typedef union { + /* 0x0 */ u8 u8_data[4]; + /* 0x0 */ u16 u16_data[2]; + /* 0x0 */ u32 u32_data; +} data_trans_form; // size = 0x4 + +typedef struct { + /* 0x00 */ u8* pntr; + /* 0x04 */ u8* c2buff_e; + /* 0x08 */ u8 err_pos[4]; + /* 0x0C */ u8 err_num; + /* 0x0D */ u8 bytes; + /* 0x0E */ u16 blkbytes; +} block_param_form; // size = 0x10 + +typedef struct { + /* 0x0 */ u16 lba; + /* 0x2 */ u16 cylinder; + /* 0x4 */ u16 blk_bytes; + /* 0x6 */ u8 sec_bytes; + /* 0x7 */ u8 head; + /* 0x8 */ u8 zone; + /* 0x9 */ u8 rdwr_blocks; + /* 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 + +void leomain(void* arg); +void leointerrupt(void* arg); + +OSPiHandle* osLeoDiskInit(void); +s32 __osLeoInterrupt(void); + +void leoClr_queue(void); +void leoInquiry(void); +void leoTest_unit_rdy(void); +void leoRezero(void); +void leoRead(void); +void leoWrite(void); +void leoSeek(void); +void leoStart_stop(void); +void leoRd_capacity(void); +void leoTranslate(); +void leoMode_sel(void); +void leoReadDiskId(void); +void leoReadTimer(void); +void leoSetTimer(void); +void leoClr_reset(void); + +u16 leoLba_to_phys(u32 lba); +u16 leoLba_to_vzone(u32 lba); + +u8 leoAnalize_asic_status(void); +u8 leoChk_asic_ready(u32 asic_cmd); +u8 leoChk_done_status(u32 asic_cmd); +u8 leoSend_asic_cmd_i(u32 asic_cmd, u32 asic_data); +u8 leoWait_mecha_cmd_done(u32 asic_cmd); +u8 leoSend_asic_cmd_w(u32 asic_cmd, u32 asic_data); +u8 leoSend_asic_cmd_w_nochkDiskChange(u32 asic_cmd, u32 asic_data); +u8 leoDetect_index_w(void); +u8 leoRecal_i(void); +u8 leoRecal_w(void); +u8 leoSeek_i(u16 rwmode); +u8 leoSeek_w(void); +u8 leoRecv_event_mesg(s32 control); +u32 leoChk_err_retry(u32 sense); +u8 leoChk_cur_drvmode(void); +void leoDrive_reset(void); +u32 leoChkUnit_atten(void); +u32 leoRetUnit_atten(void); +void leoClrUA_RESET(void); +void leoClrUA_MEDIUM_CHANGED(void); +void leoSetUA_MEDIUM_CHANGED(void); +void leoInitUnit_atten(void); + +s32 __leoSetReset(void); + +void leoRead_common(unsigned int offset); + +int leoC2_Correction(void); + +void leoSet_mseq(u16 rwmode); + +extern leo_sys_form LEO_sys_data; +extern OSThread LEOcommandThread; +extern OSThread LEOinterruptThread; +extern STACK(LEOcommandThreadStack, 0x400); +extern STACK(LEOinterruptThreadStack, 0x400); +extern OSMesgQueue LEOcommand_que; +extern OSMesgQueue LEOevent_que; +extern OSMesgQueue LEOcontrol_que; +extern OSMesgQueue LEOdma_que; +extern OSMesgQueue LEOblock_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 u8* LEOwrite_pointer; +extern LEOCmd* LEOcur_command; +extern u32 LEOasic_bm_ctl_shadow; +extern u32 LEOasic_seq_ctl_shadow; +extern u8 LEOdrive_flag; +extern vu8 LEOclr_que_flag; +// needs to not be volatile in some files +// extern vu16 LEOrw_flags; +extern u8 LEOdisk_type; +extern tgt_param_form LEOtgt_param; +extern u32 LEO_country_code; + +extern const char LEOfirmware_rev[]; +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 LEOVersion __leoVersion; +extern STACK(leoDiskStack, 0xFF0); + +extern OSPiHandle* LEOPiInfo; + #endif diff --git a/include/z64.h b/include/z64.h index b84ce02a18..6b6cfb284a 100644 --- a/include/z64.h +++ b/include/z64.h @@ -92,12 +92,6 @@ #define THREAD_ID_DMAMGR 18 #define THREAD_ID_IRQMGR 19 -#define STACK(stack, size) \ - u64 stack[ALIGN8(size) / sizeof(u64)] - -#define STACK_TOP(stack) \ - ((u8*)(stack) + sizeof(stack)) - typedef struct KaleidoMgrOverlay { /* 0x00 */ void* loadedRamAddr; /* 0x04 */ RomFile file; diff --git a/spec b/spec index 80f74fba8e..b38975342b 100644 --- a/spec +++ b/spec @@ -106,7 +106,7 @@ beginseg #endif include "$(BUILD_DIR)/src/libultra/os/setfpccsr.o" include "$(BUILD_DIR)/src/libultra/os/getfpccsr.o" -#if OOT_DEBUG +#if PLATFORM_N64 || OOT_DEBUG include "$(BUILD_DIR)/src/libultra/io/epiwrite.o" #endif include "$(BUILD_DIR)/src/libultra/os/maptlbrdb.o" @@ -730,15 +730,6 @@ beginseg include "$(BUILD_DIR)/data/rsp.rodata.o" endseg -#if PLATFORM_N64 -beginseg - // TODO - name "n64dd" - address 0x801C7740 - include "$(BUILD_DIR)/baserom/n64dd.o" -endseg -#endif - beginseg name "buffers" flags NOLOAD @@ -748,6 +739,53 @@ beginseg include "$(BUILD_DIR)/src/buffers/audio_heap.o" endseg +#if PLATFORM_N64 +beginseg + name "n64dd" + // TODO: remaining n64dd files + include "$(BUILD_DIR)/src/libleo/api/readwrite.o" + include "$(BUILD_DIR)/src/libleo/leo/leofunc.o" + include "$(BUILD_DIR)/src/libleo/leo/leoram.o" + include "$(BUILD_DIR)/src/libleo/leo/leoint.o" + include "$(BUILD_DIR)/src/libleo/leo/leocmdex.o" + include "$(BUILD_DIR)/src/libleo/api/getaadr2.o" + include "$(BUILD_DIR)/src/libleo/leo/leoread.o" + include "$(BUILD_DIR)/src/libleo/api/lbatobyte.o" + include "$(BUILD_DIR)/src/libleo/leo/leoinquiry.o" + include "$(BUILD_DIR)/src/libleo/leo/leodiskinit.o" + include "$(BUILD_DIR)/src/libleo/api/seek.o" + include "$(BUILD_DIR)/src/libleo/leo/leord_diskid.o" + include "$(BUILD_DIR)/src/libleo/leo/leomecha.o" + include "$(BUILD_DIR)/src/libleo/api/spdlmotor.o" + include "$(BUILD_DIR)/src/libleo/leo/leo_tbl.o" + include "$(BUILD_DIR)/src/libleo/leo/leotempbuffer.o" + include "$(BUILD_DIR)/src/libleo/leo/leoc2_syndrome.o" + include "$(BUILD_DIR)/src/libleo/leo/leoc2ecc.o" + include "$(BUILD_DIR)/src/libleo/leo/leomseq_tbl.o" + include "$(BUILD_DIR)/src/libleo/leo/leomotor.o" + include "$(BUILD_DIR)/src/libleo/api/driveexist.o" + include "$(BUILD_DIR)/src/libleo/leo/leomode_sel.o" + include "$(BUILD_DIR)/src/libleo/leo/leord_capa.o" + include "$(BUILD_DIR)/src/libleo/leo/leoutil.o" + include "$(BUILD_DIR)/src/libleo/leo/leorezero.o" + include "$(BUILD_DIR)/src/libleo/api/clearqueue.o" + include "$(BUILD_DIR)/src/libleo/api/bytetolba.o" + include "$(BUILD_DIR)/src/libleo/leo/leoreset.o" + include "$(BUILD_DIR)/src/libleo/leo/leotranslat.o" + include "$(BUILD_DIR)/src/libleo/leo/leotimer.o" + include "$(BUILD_DIR)/src/libleo/api/getkadr.o" + include "$(BUILD_DIR)/src/libleo/api/getaadr.o" + include "$(BUILD_DIR)/src/libleo/leo/leoglobals.o" + include "$(BUILD_DIR)/src/libleo/leo/leowrite.o" + include "$(BUILD_DIR)/src/libleo/api/cjcreateleomanager.o" + include "$(BUILD_DIR)/src/libleo/leo/leointerrupt.o" + include "$(BUILD_DIR)/src/libleo/api/cacreateleomanager.o" + include "$(BUILD_DIR)/src/libleo/api/testunitready.o" + include "$(BUILD_DIR)/src/libleo/leo/leotestunit.o" + include "$(BUILD_DIR)/src/libleo/leo/leoseek.o" +endseg +#endif + beginseg name "ovl_title" compress diff --git a/src/boot/boot_main.c b/src/boot/boot_main.c index e67c768755..d12a87512c 100644 --- a/src/boot/boot_main.c +++ b/src/boot/boot_main.c @@ -1,5 +1,6 @@ #include "global.h" #include "boot.h" +#include "stack.h" #if PLATFORM_N64 #include "cic6105.h" #endif diff --git a/src/boot/idle.c b/src/boot/idle.c index c7d696aabd..d88a75cb00 100644 --- a/src/boot/idle.c +++ b/src/boot/idle.c @@ -1,4 +1,5 @@ #include "global.h" +#include "stack.h" #include "terminal.h" #pragma increment_block_number "gc-eu:64 gc-eu-mq:64 gc-jp:64 gc-jp-ce:64 gc-jp-mq:64 gc-us:64 gc-us-mq:64" diff --git a/src/boot/z_std_dma.c b/src/boot/z_std_dma.c index caec2809c4..7ee260b901 100644 --- a/src/boot/z_std_dma.c +++ b/src/boot/z_std_dma.c @@ -20,6 +20,7 @@ */ #include "global.h" #include "fault.h" +#include "stack.h" #include "terminal.h" #if PLATFORM_N64 #include "n64dd.h" diff --git a/src/code/fault_gc.c b/src/code/fault_gc.c index f78bc152dd..b7907e61aa 100644 --- a/src/code/fault_gc.c +++ b/src/code/fault_gc.c @@ -40,6 +40,8 @@ * DPad-Up may be pressed to enable sending fault pages over osSyncPrintf as well as displaying them on-screen. * DPad-Down disables sending fault pages over osSyncPrintf. */ +#pragma increment_block_number "gc-eu:240 gc-eu-mq:240 gc-eu-mq-dbg:224 gc-jp:240 gc-jp-ce:240 gc-jp-mq:240 gc-us:240" \ + "gc-us-mq:240" // Include versions.h first and redefine FAULT_VERSION // This allows this file to compile even when versions.h uses FAULT_N64 @@ -48,12 +50,10 @@ #define FAULT_VERSION FAULT_GC #include "global.h" -#include "fault.h" -#include "terminal.h" #include "alloca.h" - -#pragma increment_block_number "gc-eu:64 gc-eu-mq:64 gc-eu-mq-dbg:222 gc-jp:64 gc-jp-ce:64 gc-jp-mq:64 gc-us:64" \ - "gc-us-mq:64" +#include "fault.h" +#include "stack.h" +#include "terminal.h" void FaultDrawer_Init(void); void FaultDrawer_SetOsSyncPrintfEnabled(u32 enabled); diff --git a/src/code/fault_n64.c b/src/code/fault_n64.c index 69ead64414..da9d7bf6fd 100644 --- a/src/code/fault_n64.c +++ b/src/code/fault_n64.c @@ -6,6 +6,7 @@ #include "global.h" #include "fault.h" +#include "stack.h" #include "terminal.h" typedef struct FaultMgr { diff --git a/src/code/kanread.s b/src/code/kanread.s index 8f35b713bd..a163f9ead7 100644 --- a/src/code/kanread.s +++ b/src/code/kanread.s @@ -23,7 +23,7 @@ * @param sjis Shift-JIS Codepoint of glyph. * @return s32 offset into `kanji` file. * - * @remark Original name: "LeoGetKadr" + * @remark Almost identical to "LeoGetKadr" from libleo. */ LEAF(Kanji_OffsetFromShiftJIS) // Characters with codepoints >= 0x8800 are kanji. Arrangement is regular, diff --git a/src/code/main.c b/src/code/main.c index fa6b5f6729..ce1739a5cb 100644 --- a/src/code/main.c +++ b/src/code/main.c @@ -1,5 +1,6 @@ #include "global.h" #include "fault.h" +#include "stack.h" #include "terminal.h" #include "versions.h" #if PLATFORM_N64 diff --git a/src/libleo/api/bytetolba.c b/src/libleo/api/bytetolba.c new file mode 100644 index 0000000000..9b28baf2f1 --- /dev/null +++ b/src/libleo/api/bytetolba.c @@ -0,0 +1,44 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.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 LEO_ERROR_GOOD; +} diff --git a/src/libleo/api/cacreateleomanager.c b/src/libleo/api/cacreateleomanager.c new file mode 100644 index 0000000000..7628f58896 --- /dev/null +++ b/src/libleo/api/cacreateleomanager.c @@ -0,0 +1,80 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" +#include "libc/stdint.h" + +s32 LeoCACreateLeoManager(s32 comPri, s32 intPri, OSMesg* cmdBuf, s32 cmdMsgCnt) { + OSPiHandle* driveRomHandle; + OSPiHandle* leoDiskHandle; + volatile LEOCmdInquiry cmdBlockInq; + volatile LEOCmd cmdBlockID; + LEODiskID thisID; + u32 stat; + u32 data; + + if (__leoActive) { + return LEO_ERROR_GOOD; + } + + if (!LeoDriveExist()) { + return LEO_ERROR_DEVICE_COMMUNICATION_FAILURE; + } + + leoDiskHandle = osLeoDiskInit(); + driveRomHandle = osDriveRomInit(); + __leoActive = true; + + __osSetHWIntrRoutine(OS_INTR_CART, __osLeoInterrupt, STACK_TOP(leoDiskStack)); + leoInitialize(comPri, intPri, cmdBuf, cmdMsgCnt); + + if (osResetType == 1) { // NMI + __leoSetReset(); + } + + cmdBlockInq.header.command = 2; + cmdBlockInq.header.reserve1 = 0; + cmdBlockInq.header.control = 0; + cmdBlockInq.header.reserve3 = 0; + leoCommand((void*)&cmdBlockInq); + + { + volatile s32 dummy = (uintptr_t)__osSetHWIntrRoutine & 0xA48D3C; + + while (dummy < 0xE00000) { + dummy += (((uintptr_t)leoCommand & 0xFF) | 0x8A) << 0x10; + } + } + + while (cmdBlockInq.header.status == 8) {} + + if (cmdBlockInq.header.status != 0) { + return GET_ERROR(cmdBlockInq); + } + + __leoVersion.driver = cmdBlockInq.version; + __leoVersion.drive = 6; + __leoVersion.deviceType = cmdBlockInq.devType; + __leoVersion.nDevices = cmdBlockInq.devNum; + + stat = __leoVersion.driver & 0xF; + if (stat == 4) { + LEO_country_code = 0; + } else if ((stat == 3) || (stat == 1)) { + volatile u32 dummy; + + osEPiReadIo(driveRomHandle, 0x9FF00, &data); + data = (data & 0xFF000000) >> 24; + if (data != 4) { + while (true) {} + } + + dummy = 0x32F8EB20; + LEO_country_code = 0x2263EE56; + dummy += (uintptr_t)&__leoActive; + } else { + while (true) {} + } + + return LEO_ERROR_GOOD; +} diff --git a/src/libleo/api/cjcreateleomanager.c b/src/libleo/api/cjcreateleomanager.c new file mode 100644 index 0000000000..c10e1fd263 --- /dev/null +++ b/src/libleo/api/cjcreateleomanager.c @@ -0,0 +1,81 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" +#include "libc/stdint.h" + +s32 LeoCJCreateLeoManager(s32 comPri, s32 intPri, OSMesg* cmdBuf, s32 cmdMsgCnt) { + OSPiHandle* driveRomHandle; + OSPiHandle* leoDiskHandle; + volatile LEOCmdInquiry cmdBlockInq; + volatile LEOCmd cmdBlockID; + LEODiskID thisID; + u32 stat; + u32 data; + + if (__leoActive) { + return LEO_ERROR_GOOD; + } + + if (!LeoDriveExist()) { + return LEO_ERROR_DEVICE_COMMUNICATION_FAILURE; + } + + leoDiskHandle = osLeoDiskInit(); + driveRomHandle = osDriveRomInit(); + __leoActive = true; + + __osSetHWIntrRoutine(OS_INTR_CART, __osLeoInterrupt, STACK_TOP(leoDiskStack)); + leoInitialize(comPri, intPri, cmdBuf, cmdMsgCnt); + + if (osResetType == 1) { // NMI + __leoSetReset(); + } + + cmdBlockInq.header.command = 2; + cmdBlockInq.header.reserve1 = 0; + cmdBlockInq.header.control = 0; + cmdBlockInq.header.reserve3 = 0; + leoCommand((void*)&cmdBlockInq); + + { + volatile s32 dummy = (uintptr_t)&cmdBlockInq & 0xFFFFFF; + + while (dummy > 0) { + dummy -= ((uintptr_t)__leoSetReset & 0xFFFFFF) | 0x403DF4; + } + } + + while (cmdBlockInq.header.status == 8) {} + + if (cmdBlockInq.header.status != 0) { + return GET_ERROR(cmdBlockInq); + } + + __leoVersion.driver = cmdBlockInq.version; + __leoVersion.drive = 6; + __leoVersion.deviceType = cmdBlockInq.devType; + __leoVersion.nDevices = cmdBlockInq.devNum; + + stat = __leoVersion.driver & 0xF; + if (stat == 4) { + LEO_country_code = 0; + } else if ((stat == 3) || (stat == 1)) { + volatile u32 dummy; + + osEPiReadIo(driveRomHandle, 0x9FF00, &data); + data = (data & 0xFF000000) >> 24; + dummy = 0x3ED98F23; + if (data != 0xC3) { + while (true) {} + } + + dummy *= data; + dummy -= (uintptr_t)&cmdBlockInq; + LEO_country_code = 0xE848D316; + } else { + while (true) {} + } + + return LEO_ERROR_GOOD; +} diff --git a/src/libleo/api/clearqueue.c b/src/libleo/api/clearqueue.c new file mode 100644 index 0000000000..ed5b623280 --- /dev/null +++ b/src/libleo/api/clearqueue.c @@ -0,0 +1,20 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +s32 LeoClearQueue(void) { + LEOCmdClearQueue cmdBlock; + + if (!__leoActive) { + return -1; + } + + cmdBlock.header.command = 1; + cmdBlock.header.reserve1 = 0; + cmdBlock.header.control = 0; + cmdBlock.header.reserve3 = 0; + + leoCommand(&cmdBlock); + return LEO_ERROR_GOOD; +} diff --git a/src/libleo/api/driveexist.c b/src/libleo/api/driveexist.c new file mode 100644 index 0000000000..314a67064e --- /dev/null +++ b/src/libleo/api/driveexist.c @@ -0,0 +1,41 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +u32 LeoDriveExist(void) { + u32 data; + u32 saveMask; + u32 stat; + u32 latency; + u32 pulse; + u32 pageSize; + u32 relDuration; + + __osPiGetAccess(); + + while ((stat = IO_READ(PI_STATUS_REG)) & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) {} + + latency = IO_READ(PI_BSD_DOM1_LAT_REG); + pageSize = IO_READ(PI_BSD_DOM1_PGS_REG); + relDuration = IO_READ(PI_BSD_DOM1_RLS_REG); + pulse = IO_READ(PI_BSD_DOM1_PWD_REG); + + IO_WRITE(PI_BSD_DOM1_LAT_REG, 0xFF); + IO_WRITE(PI_BSD_DOM1_PGS_REG, 0); + IO_WRITE(PI_BSD_DOM1_RLS_REG, 3); + IO_WRITE(PI_BSD_DOM1_PWD_REG, 0xFF); + + data = IO_READ(0x06001010); // Something in the n64dd address space? + + IO_WRITE(PI_BSD_DOM1_LAT_REG, latency); + IO_WRITE(PI_BSD_DOM1_PGS_REG, pageSize); + IO_WRITE(PI_BSD_DOM1_RLS_REG, relDuration); + IO_WRITE(PI_BSD_DOM1_PWD_REG, pulse); + + __osPiRelAccess(); + if (data == 0x2129FFF8) { + return true; + } + return false; +} diff --git a/src/libleo/api/getaadr.s b/src/libleo/api/getaadr.s new file mode 100644 index 0000000000..a36d27a5b3 --- /dev/null +++ b/src/libleo/api/getaadr.s @@ -0,0 +1,332 @@ +#include "ultra64/asm.h" + +.set noat +.set noreorder + +.section .text + +.balign 16 + +LEAF(LeoGetAAdr) + bltz $a0, .out_of_range + slti $at, $a0, 0x908 + beqz $at, .out_of_range + nop + lui $v1, %hi(asc2tbl) + sll $t0, $a0, 2 + addiu $v1, %lo(asc2tbl) + add $t1, $t0, $v1 + lbu $t8, 2($t1) + lhu $t9, 0($t1) + li $at, 0x70000 + andi $t2, $t8, 0xF + addi $t3, $t2, 1 + sw $t3, ($a2) + lb $t0, 3($t1) + srl $t4, $t8, 4 + ori $at, $at, 0xEE80 + andi $t5, $t0, 1 + sll $t6, $t5, 4 + or $t7, $t6, $t4 + sw $t7, ($a1) + sll $v0, $t9, 1 + sra $v1, $t0, 1 + sw $v1, ($a3) + jr $ra + add $v0, $v0, $at +.out_of_range: + jr $ra + li $v0, -1 +END(LeoGetAAdr) + +DATA(asc2tbl) +.word 0x00009D14, 0x00232A14, 0x00296314, 0x002F8A14, 0x00457E18, 0x0063CA14, 0x0084AA14, 0x00A03314 +.word 0x00A45E14, 0x00BB4E14, 0x00CA6514, 0x00D3770E, 0x00E33302, 0x00E78108, 0x00EB2102, 0x00EC6C14 +.word 0x01008A14, 0x01163A14, 0x01217A14, 0x01377A14, 0x014D8A14, 0x01638A14, 0x01798A14, 0x018F7A14 +.word 0x01A58A14, 0x01BB8A14, 0x01D1170E, 0x01D5490E, 0x01DF770E, 0x01EF740A, 0x01F9770E, 0x02097A14 +.word 0x021FDC16, 0x024DBA14, 0x026E7A14, 0x0284BA14, 0x02A59A14, 0x02C16A14, 0x02D26A14, 0x02E3BA14 +.word 0x03048A14, 0x031A1A14, 0x03206A14, 0x03318A14, 0x03476A14, 0x0358CA14, 0x03799A14, 0x0395CA14 +.word 0x03B67A14, 0x03CCCA14, 0x03ED8A14, 0x04037A14, 0x04196A14, 0x042A8A14, 0x0440AA14, 0x045CDA14 +.word 0x04839A14, 0x049F9A14, 0x04BB7A14, 0x04D14D14, 0x04DF5C14, 0x04F33D14, 0x05015216, 0x050681FA +.word 0x050A9D14, 0x052D9810, 0x05449A14, 0x05609810, 0x05779A14, 0x05939810, 0x05AA5A14, 0x05BB9C10 +.word 0x05DC7A14, 0x05F22A14, 0x05F83D14, 0x06067A14, 0x061C2A14, 0x0622D810, 0x06427810, 0x06549810 +.word 0x066B9B10, 0x06899B10, 0x06A74810, 0x06B06810, 0x06BE5A14, 0x06CF770E, 0x06DF870E, 0x06EFB70E +.word 0x0707670E, 0x07138A0E, 0x0729670E, 0x07356D14, 0x074A1F16, 0x07526D14, 0x07675216, 0x076C9D14 +.word 0x078F9D14, 0x07B22A0E, 0x07B88B14, 0x07D08A14, 0x07E69816, 0x07FD9A14, 0x08193F16, 0x08296C14 +.word 0x083D5114, 0x0840CA14, 0x08616614, 0x086C650C, 0x0875830A, 0x087D9D14, 0x08A0CA14, 0x08C14114 +.word 0x08C35318, 0x08C98810, 0x08DB9D14, 0x08FE9D14, 0x09213216, 0x09249A0E, 0x09407A14, 0x0956440E +.word 0x095B3302, 0x095F9D14, 0x09826614, 0x098D650C, 0x09960A15, 0x09C2C514, 0x09D4070F, 0x09F47A0E +.word 0x0A0ABE1C, 0x0A37BE1C, 0x0A64BE1C, 0x0A91BD1A, 0x0ABBBD1A, 0x0AE5BE1C, 0x0B12FA14, 0x0B3EBE14 +.word 0x0B6B7E1C, 0x0B897E1C, 0x0BA77E1C, 0x0BC57D1A, 0x0BE13E1C, 0x0BF04E1C, 0x0BFF4E1C, 0x0C0E5D1A +.word 0x0C239D14, 0x0C469D1A, 0x0C69BE1C, 0x0C96BE1C, 0x0CC3BE1C, 0x0CF0BD1A, 0x0D1ABD1A, 0x0D44770E +.word 0x0D54CC16, 0x0D7B8E1C, 0x0D998E1C, 0x0DB77E1C, 0x0DD57D1A, 0x0DF19D14, 0x0E149D14, 0x0E379A14 +.word 0x0E539B16, 0x0E719B16, 0x0E8F9B16, 0x0EAD9B16, 0x0ECB9A14, 0x0EE79B16, 0x0F050811, 0x0F299B10 +.word 0x0F479B16, 0x0F659B16, 0x0F839B16, 0x0FA19A14, 0x0FBD3B16, 0x0FC93A16, 0x0FD44B16, 0x0FE04A14 +.word 0x0FEB7912, 0x0FFF8B16, 0x10179B16, 0x10359B16, 0x10539B16, 0x10719B16, 0x108F9A14, 0x10AB760C +.word 0x10B99910, 0x10D28B16, 0x10EA8B16, 0x11028B16, 0x111A8A14, 0x11309D14, 0x11539D14, 0x11769D14 +.word 0x11996F18, 0x11B13A14, 0x11BC7514, 0x11C88912, 0x11DC9D16, 0x11FFEA14, 0x1226CA14, 0x12474514 +.word 0x124D4D14, 0x125B4D14, 0x12696614, 0x1274870E, 0x12843404, 0x12899108, 0x128E4204, 0x12916C14 +.word 0x12A5AA14, 0x12C17A14, 0x12D79A14, 0x12F3AA14, 0x130FAA14, 0x132B9B16, 0x1349AA14, 0x1365AA14 +.word 0x1381AA14, 0x139DAA14, 0x13B9370E, 0x13C1390E, 0x13CB770E, 0x13DB750C, 0x13E7770E, 0x13F79A14 +.word 0x1413CC14, 0x143ACA14, 0x145BBA14, 0x147CBA14, 0x149DBA14, 0x14BEBA14, 0x14DFBA14, 0x1500BA14 +.word 0x1521CA14, 0x15426A14, 0x1553AA14, 0x156FCA14, 0x1590AA14, 0x15ACFA14, 0x15D8CA14, 0x15F9BA14 +.word 0x161AAA14, 0x1636CE14, 0x1663CA14, 0x16849A14, 0x16A0CA14, 0x16C1BA14, 0x16E2CA14, 0x1703EA14 +.word 0x172ACA14, 0x174BCA14, 0x176CAA14, 0x17883D14, 0x17966C14, 0x17AA3D14, 0x17B85214, 0x17BD92FC +.word 0x17C55F1A, 0x17DD870E, 0x17EDAA14, 0x1809870E, 0x18199A14, 0x1835970E, 0x18497A14, 0x185F9C10 +.word 0x1880BA14, 0x18A15A14, 0x18B26E14, 0x18C9AA14, 0x18E55A14, 0x18F6F70E, 0x1916A70E, 0x192A970E +.word 0x193EAB0E, 0x195C9B0E, 0x197A770E, 0x198A770E, 0x199A6912, 0x19A9A70E, 0x19BDA60E, 0x19CFD70E +.word 0x19EBA70E, 0x19FFAB0E, 0x1A1D870E, 0x1A2D6D14, 0x1A423F16, 0x1A526D14, 0x1A675214, 0x1A6C6F18 +.word 0x1A846F16, 0x1A9C3A0E, 0x1AA78B14, 0x1ABFAA14, 0x1ADB8614, 0x1AE9BA14, 0x1B0A2F16, 0x1B128A14 +.word 0x1B285214, 0x1B2DBB14, 0x1B516614, 0x1B5C860C, 0x1B6A730A, 0x1B726E16, 0x1B89BB14, 0x1BAD5012 +.word 0x1BAF5316, 0x1BB58910, 0x1BC95F18, 0x1BE15F18, 0x1BF95316, 0x1BFFA90C, 0x1C188A14, 0x1C2E540E +.word 0x1C363404, 0x1C3B6D14, 0x1C506614, 0x1C5B860C, 0x1C690913, 0x1C91C512, 0x1CA3D70E, 0x1CBF9A0E +.word 0x1CDBCD1A, 0x1D05CD1A, 0x1D2FCD1A, 0x1D59CD1A, 0x1D83CD1A, 0x1DADCE1C, 0x1DDA2A15, 0x1E0CBD14 +.word 0x1E36BD1A, 0x1E60BD1A, 0x1E8ABD1A, 0x1EB4BC18, 0x1EDB6D1A, 0x1EF06D1A, 0x1F056D1A, 0x1F1A6D1A +.word 0x1F2F5F1A, 0x1F47BD1A, 0x1F71CD1A, 0x1F9BCD1A, 0x1FC5CD1A, 0x1FEFCD1A, 0x2019CD1A, 0x2043970E +.word 0x2057CB14, 0x207BAD1A, 0x209EBD1A, 0x20C8BD1A, 0x20F2BD1A, 0x211C6F1A, 0x21345F1A, 0x214CAA14 +.word 0x21689B16, 0x21869B16, 0x21A49A14, 0x21C0AA14, 0x21DC9A14, 0x21F89B16, 0x2216D70E, 0x22329B0E +.word 0x22508B16, 0x22689B16, 0x22869A14, 0x22A29A14, 0x22BE5B16, 0x22D05B16, 0x22E25A14, 0x22F35A14 +.word 0x23048912, 0x2318AA14, 0x23349B16, 0x23529B16, 0x23709A14, 0x238C9A14, 0x23A89A14, 0x23C49910 +.word 0x23DD9A10, 0x23F9AB16, 0x2417AB16, 0x2435AA14, 0x2451AA14, 0x246D5F18, 0x24855F18, 0x249DAE14 +.word 0x24C39D14, 0x24E62A14, 0x24EC5314, 0x24F28912, 0x25068D16, 0x2522CA14, 0x2543CA14, 0x25642314 +.word 0x25663C14, 0x25733C14, 0x25806514, 0x2589770E, 0x25993302, 0x259D9006, 0x25A03102, 0x25A26C14 +.word 0x25B69A14, 0x25D26A14, 0x25E38A14, 0x25F99A14, 0x26159A14, 0x26318A14, 0x26478A14, 0x265D9912 +.word 0x26769A14, 0x26928A14, 0x26A8260C, 0x26AC480C, 0x26B5870E, 0x26C5740A, 0x26CF770E, 0x26DF8A14 +.word 0x26F5DC14, 0x2723CA14, 0x2744A912, 0x275DAA14, 0x2779B912, 0x2797A912, 0x27B0A912, 0x27C9BA14 +.word 0x27EAC912, 0x28085912, 0x28179912, 0x2830B912, 0x284E9912, 0x2867D912, 0x288AB912, 0x28A8CA14 +.word 0x28C99912, 0x28E2CD14, 0x290CB912, 0x292A9A14, 0x2946A912, 0x295FB912, 0x297DC912, 0x299B0913 +.word 0x29C3C912, 0x29E1B912, 0x29FF9912, 0x2A183B12, 0x2A246C14, 0x2A383B12, 0x2A445214, 0x2A4981FA +.word 0x2A4D9D14, 0x2A70970E, 0x2A849A14, 0x2AA0770E, 0x2AB09A14, 0x2ACC870E, 0x2ADC6A14, 0x2AED9C10 +.word 0x2B0E9A14, 0x2B2A4912, 0x2B346D12, 0x2B499A14, 0x2B655A14, 0x2B76F70E, 0x2B96A70E, 0x2BAA970E +.word 0x2BBE9B0E, 0x2BDCAB0E, 0x2BFA770E, 0x2C0A770E, 0x2C1A6912, 0x2C29A70E, 0x2C3D970E, 0x2C51C70E +.word 0x2C69A70E, 0x2C7D9B0E, 0x2C9B770E, 0x2CAB5C12, 0x2CBF2F16, 0x2CC76C12, 0x2CDB5214, 0x2CE08D14 +.word 0x2CFC9D14, 0x2D1F2A0E, 0x2D257B14, 0x2D3D9A14, 0x2D599714, 0x2D6DB912, 0x2D8B2F16, 0x2D937A14 +.word 0x2DA95112, 0x2DACCB14, 0x2DD07714, 0x2DE0760C, 0x2DEE730A, 0x2DF69D14, 0x2E19BB14, 0x2E3D5112 +.word 0x2E405316, 0x2E468810, 0x2E589D14, 0x2E7B9D14, 0x2E9E4214, 0x2EA19A0C, 0x2EBD7A14, 0x2ED3440E +.word 0x2ED82302, 0x2EDA8D14, 0x2EF66714, 0x2F02760C, 0x2F100A15, 0x2F3CC614, 0x2F51C70E, 0x2F698A0E +.word 0x2F7FCD1A, 0x2FA9CD1A, 0x2FD3BD1A, 0x2FFDCD1A, 0x3027CC18, 0x304ECE1C, 0x307B0913, 0x30A3BD14 +.word 0x30CDAD1A, 0x30F0BD1A, 0x311ABD1A, 0x3144AC18, 0x31654D1A, 0x31734D1A, 0x31814D1A, 0x318F5C18 +.word 0x31A39D14, 0x31C6BD1A, 0x31F0CD1A, 0x321ACD1A, 0x3244CD1A, 0x326ECD1A, 0x3298CC18, 0x32BFA70E +.word 0x32D3BB14, 0x32F7BD1A, 0x3321CD1A, 0x334BBD1A, 0x3375BC18, 0x339C8D14, 0x33B88D14, 0x33D49A14 +.word 0x33F09A14, 0x340C9A14, 0x34289A14, 0x34449A14, 0x34609912, 0x34799B16, 0x3497C70E, 0x34AF7A0E +.word 0x34C58A14, 0x34DB8A14, 0x34F17A14, 0x35077912, 0x351B5A14, 0x352C5A14, 0x353D5A14, 0x354E6912 +.word 0x355D7912, 0x35719A14, 0x358D8A14, 0x35A38A14, 0x35B98A14, 0x35CF8A14, 0x35E58912, 0x35F9870E +.word 0x36099910, 0x3622AA14, 0x363EAA14, 0x365AAA14, 0x36769912, 0x368F8D14, 0x36AB8D14, 0x36C79D12 +.word 0x36EA6F18, 0x37024912, 0x370C7412, 0x37166B14, 0x37288C14, 0x37427912, 0x37568810, 0x37684412 +.word 0x376D5C12, 0x37815C12, 0x37957612, 0x37A39710, 0x37B74404, 0x37BCA108, 0x37C13306, 0x37C57B14 +.word 0x37DD8912, 0x37F17912, 0x38057912, 0x38198912, 0x382D8912, 0x38417912, 0x38557912, 0x38697912 +.word 0x387D8912, 0x38918912, 0x38A5370E, 0x38AD480C, 0x38B69710, 0x38CA940E, 0x38D79710, 0x38EB7912 +.word 0x38FF8B14, 0x3917A912, 0x39309912, 0x39498912, 0x395D8912, 0x39719912, 0x398A9912, 0x39A39912 +.word 0x39BC9912, 0x39D57912, 0x39E99912, 0x3A029912, 0x3A1B9912, 0x3A34A912, 0x3A4D9912, 0x3A669912 +.word 0x3A7F8912, 0x3A939B12, 0x3AB19912, 0x3ACA8912, 0x3ADE8912, 0x3AF29912, 0x3B0B9912, 0x3B24A912 +.word 0x3B3D8912, 0x3B518912, 0x3B657912, 0x3B794C12, 0x3B867B14, 0x3B9E4C12, 0x3BAB6214, 0x3BB0A2FC +.word 0x3BB85F1A, 0x3BD0870E, 0x3BE09912, 0x3BF9870E, 0x3C098912, 0x3C1D870E, 0x3C2D8912, 0x3C419A0E +.word 0x3C5D8912, 0x3C718A14, 0x3C877D14, 0x3CA39912, 0x3CBC8912, 0x3CD0A70E, 0x3CE4970E, 0x3CF8970E +.word 0x3D0C9B0E, 0x3D2AAB0E, 0x3D48970E, 0x3D5C770E, 0x3D6C8912, 0x3D80970E, 0x3D94970E, 0x3DA8A70E +.word 0x3DBC870E, 0x3DCC9A0E, 0x3DE8770E, 0x3DF86D12, 0x3E0D2F16, 0x3E156D12, 0x3E2A6212, 0x3E2F6F16 +.word 0x3E476F16, 0x3E5F4912, 0x3E697A14, 0x3E7F7912, 0x3E938612, 0x3EA19912, 0x3EBA3F16, 0x3ECA8A12 +.word 0x3EE06112, 0x3EE3A812, 0x3EFA7712, 0x3F0A550C, 0x3F13950E, 0x3F226E16, 0x3F399812, 0x3F506112 +.word 0x3F534316, 0x3F578812, 0x3F695F18, 0x3F815F18, 0x3F995214, 0x3F9E9A0E, 0x3FBA7912, 0x3FCE320C +.word 0x3FD14404, 0x3FD66D14, 0x3FEB7712, 0x3FFB650C, 0x40048710, 0x40148310, 0x401C860E, 0x402A7912 +.word 0x403EAC18, 0x405FAC18, 0x4080AC18, 0x40A1AB16, 0x40BFAB16, 0x40DDAD1A, 0x4100B912, 0x411E8C12 +.word 0x41388C18, 0x41529C18, 0x41739C18, 0x41948B16, 0x41AC7C18, 0x41C67C18, 0x41E07C18, 0x41FA7B16 +.word 0x42125F1A, 0x422AAB16, 0x42489C18, 0x42699C18, 0x428A9C18, 0x42AB9B16, 0x42C99B16, 0x42E7870E +.word 0x42F79A12, 0x43139C18, 0x43349C18, 0x4355AC18, 0x4376AB16, 0x43946F1A, 0x43AC5F1A, 0x43C48912 +.word 0x43D88A14, 0x43EE8A14, 0x44049A14, 0x44209912, 0x44398912, 0x444D8B16, 0x4465970E, 0x44798A0E +.word 0x448F8A14, 0x44A58A14, 0x44BB9A14, 0x44D79912, 0x44F08A14, 0x45068A14, 0x451C7A14, 0x45327912 +.word 0x45468912, 0x455A9912, 0x45738A14, 0x45898A14, 0x459F9912, 0x45B89912, 0x45D19912, 0x45EAA912 +.word 0x46039910, 0x461C9A14, 0x46389A14, 0x46548A14, 0x466A9912, 0x46835F18, 0x469B5F18, 0x46B38C12 +.word 0x46CD3C16, 0x46DA3C16, 0x46E77516, 0x46F39A14, 0x470F7E18, 0x472DDC16, 0x475BBC16, 0x47824516 +.word 0x47884F18, 0x47984F18, 0x47A85516, 0x47B1870E, 0x47C15504, 0x47CA810A, 0x47CE4304, 0x47D28F18 +.word 0x47F29C16, 0x48134B16, 0x481F8B16, 0x48378C16, 0x48519B16, 0x486F8C16, 0x48898C16, 0x48A38B16 +.word 0x48BB8C16, 0x48D58C16, 0x48EF380E, 0x48F84A0E, 0x4903970E, 0x4917850C, 0x4923870E, 0x49337C16 +.word 0x494DCC16, 0x4974BB16, 0x49988B16, 0x49B09C16, 0x49D1AB16, 0x49EF7B16, 0x4A077B16, 0x4A1FBC16 +.word 0x4A46AB16, 0x4A643B16, 0x4A706C16, 0x4A849B16, 0x4AA26B16, 0x4AB4DC16, 0x4AE2AC16, 0x4B03CC16 +.word 0x4B2A8B16, 0x4B42CC16, 0x4B698B16, 0x4B818C16, 0x4B9B7B16, 0x4BB39C16, 0x4BD4BC16, 0x4BFBFC16 +.word 0x4C2FAB16, 0x4C4DAB16, 0x4C6B9B16, 0x4C893E18, 0x4C988C18, 0x4CB24E18, 0x4CC16316, 0x4CC781FC +.word 0x4CCB3C16, 0x4CD8880E, 0x4CEA8D18, 0x4D06680E, 0x4D149D18, 0x4D37880E, 0x4D495C18, 0x4D5D8B0E +.word 0x4D757C18, 0x4D8F3B16, 0x4D9B3F16, 0x4DAB8C18, 0x4DC53C18, 0x4DD2B70E, 0x4DEA770E, 0x4DFA980E +.word 0x4E119B0E, 0x4E2F9B0E, 0x4E4D670E, 0x4E59680E, 0x4E674912, 0x4E71780E, 0x4E83980E, 0x4E9AD80E +.word 0x4EBAA70E, 0x4ECE9B0E, 0x4EEC770E, 0x4EFC5F18, 0x4F142C18, 0x4F1B4F18, 0x4F2B7114, 0x4F2F3C16 +.word 0x4F3C3C10, 0x4F493B0E, 0x4F556A14, 0x4F669C16, 0x4F879810, 0x4F9E9B16, 0x4FBC2C18, 0x4FC38E18 +.word 0x4FE16216, 0x4FE6DC16, 0x50146616, 0x501F7710, 0x502F840C, 0x50393C1A, 0x5046DC16, 0x50747116 +.word 0x50784316, 0x507C8912, 0x50903C14, 0x509D3C14, 0x50AA4316, 0x50AE7B0E, 0x50C6AE16, 0x50EC6610 +.word 0x50F75504, 0x51003C18, 0x510D6616, 0x51188710, 0x5128FC16, 0x515CE616, 0x5175D80E, 0x51958B0E +.word 0x51ADCC18, 0x51D4BC18, 0x51FBBC18, 0x5222BC18, 0x5249CC18, 0x5270BC18, 0x5297FB16, 0x52C79E16 +.word 0x52ED6C18, 0x53016C18, 0x53157C18, 0x532F7C18, 0x53494C18, 0x53564C18, 0x53636C18, 0x53777C18 +.word 0x53913C18, 0x539EAD18, 0x53C1CD18, 0x53EBCD18, 0x5415CD18, 0x543FCD18, 0x5469CC18, 0x5490970E +.word 0x54A4CC16, 0x54CB9D18, 0x54EE9D18, 0x55119D18, 0x55349D18, 0x55573C18, 0x55643C18, 0x55719D18 +.word 0x55948C16, 0x55AE9C16, 0x55CF8C16, 0x55E99B14, 0x56078C16, 0x56219C16, 0x5642C80E, 0x565D6A0E +.word 0x566E8C16, 0x56887C16, 0x56A28C16, 0x56BC7C16, 0x56D64B16, 0x56E24B16, 0x56EE6B16, 0x57007B16 +.word 0x57187B16, 0x57307A14, 0x57469C16, 0x57678C16, 0x57818C16, 0x579B9B14, 0x57B99C16, 0x57DA880E +.word 0x57EC980E, 0x58038C16, 0x581D8C16, 0x58378C16, 0x58518C16, 0x586B3C16, 0x58783C16, 0x58859F16 +.word 0x58AD6F18, 0x58C55C16, 0x58D98516, 0x58E59B14, 0x59038E18, 0x5921BC16, 0x5948AC16, 0x59695516 +.word 0x59724F18, 0x59825F18, 0x599A6516, 0x59A3970E, 0x59B75504, 0x59C0810A, 0x59C43304, 0x59C8AF18 +.word 0x59F09C16, 0x5A115B16, 0x5A239B16, 0x5A418C16, 0x5A5B9B16, 0x5A799C16, 0x5A9A9C16, 0x5ABBAC16 +.word 0x5ADC8C16, 0x5AF69C16, 0x5B17480E, 0x5B206A0E, 0x5B31970E, 0x5B45950C, 0x5B54970E, 0x5B687C16 +.word 0x5B82CC16, 0x5BA9BB16, 0x5BCD9B16, 0x5BEB9C16, 0x5C0CBB16, 0x5C309B16, 0x5C4E9B16, 0x5C6CBC16 +.word 0x5C93BB16, 0x5CB75B16, 0x5CC98C16, 0x5CE3BB16, 0x5D077B16, 0x5D1FDC16, 0x5D4DCC16, 0x5D74DC16 +.word 0x5DA29B16, 0x5DC0CC16, 0x5DE79B16, 0x5E059C16, 0x5E268B16, 0x5E3EAC16, 0x5E5FBC16, 0x5E860C17 +.word 0x5EBABB16, 0x5EDEAB16, 0x5EFCBB16, 0x5F205E18, 0x5F376E18, 0x5F4E6E18, 0x5F655316, 0x5F6B91FC +.word 0x5F706F1A, 0x5F88980E, 0x5F9F9D18, 0x5FC2680E, 0x5FD0AD18, 0x5FF3880E, 0x60056C18, 0x60199B0E +.word 0x60378C18, 0x60515B16, 0x60636F16, 0x607B9C18, 0x609C5C18, 0x60B0C70E, 0x60C8870E, 0x60D8880E +.word 0x60EA9B0E, 0x61089B0E, 0x6126770E, 0x6136680E, 0x61446912, 0x6153780E, 0x6165980E, 0x617CD80E +.word 0x619CA70E, 0x61B0AB0E, 0x61CEA70E, 0x61E26F18, 0x61FA4C18, 0x62076F18, 0x621F7114, 0x62236F18 +.word 0x623B6F16, 0x62534B0E, 0x625F7A14, 0x6275AC16, 0x6296A810, 0x62ADAB16, 0x62CB4C18, 0x62D88E18 +.word 0x62F66216, 0x62FBDC16, 0x63297616, 0x63378710, 0x6347940C, 0x63546F18, 0x636CDC16, 0x639A6116 +.word 0x639D4316, 0x63A19912, 0x63BA6F18, 0x63D26F18, 0x63EA5316, 0x63F09B0E, 0x640E9E16, 0x64346610 +.word 0x643F5504, 0x64486F18, 0x64607616, 0x646E8710, 0x647EFA14, 0x64AAD514, 0x64BFC60C, 0x64D47B0E +.word 0x64ECCC18, 0x6513BC18, 0x653ABC18, 0x6561CC18, 0x6588CC18, 0x65AFBC18, 0x65D6FB16, 0x6606AE16 +.word 0x662C8C18, 0x66468C18, 0x66609C18, 0x66819C18, 0x66A25C18, 0x66B66C18, 0x66CA7C18, 0x66E47C18 +.word 0x66FE6F1A, 0x6716CD18, 0x6740DD18, 0x6771CD18, 0x679BCD18, 0x67C5CD18, 0x67EFDD18, 0x6820A70E +.word 0x6834FC16, 0x6868AD18, 0x688BAD18, 0x68AEAD18, 0x68D1AD18, 0x68F46F1A, 0x690C6F1A, 0x69249D18 +.word 0x69479C16, 0x69689C16, 0x69899C16, 0x69AA9B14, 0x69C89C16, 0x69E99C16, 0x6A0AD80E, 0x6A2A7A0E +.word 0x6A408C16, 0x6A5A8C16, 0x6A748C16, 0x6A8E8C16, 0x6AA85B16, 0x6ABA5B16, 0x6ACC6B16, 0x6ADE6B16 +.word 0x6AF07B16, 0x6B089A14, 0x6B248C16, 0x6B3E9C16, 0x6B5F9C16, 0x6B808B14, 0x6B988C16, 0x6BB2980E +.word 0x6BC9980E, 0x6BE08C16, 0x6BFA8C16, 0x6C148C16, 0x6C2E8C16, 0x6C486F18, 0x6C606F18, 0x6C78AF16 +.word 0x6CA06F18, 0x6CB82A14, 0x6CBE4314, 0x6CC29A14, 0x6CDE8D16, 0x6CFADB14, 0x6D249B14, 0x6D422314 +.word 0x6D445D14, 0x6D594D14, 0x6D675414, 0x6D6F870E, 0x6D7F2402, 0x6D829108, 0x6D872102, 0x6D885A14 +.word 0x6D998B14, 0x6DB15A14, 0x6DC28A14, 0x6DD88B14, 0x6DF08A14, 0x6E068B14, 0x6E1E8B14, 0x6E368A14 +.word 0x6E4C8B14, 0x6E648B14, 0x6E7C270E, 0x6E802A0E, 0x6E86970E, 0x6E9A850C, 0x6EA6970E, 0x6EBA7A14 +.word 0x6ED0DB14, 0x6EFAAA14, 0x6F169A14, 0x6F32AB14, 0x6F509A14, 0x6F6C9A14, 0x6F889A14, 0x6FA4AB14 +.word 0x6FC2AA14, 0x6FDE2A14, 0x6FE47B14, 0x6FFC9A14, 0x70188A14, 0x702EBA14, 0x704F9A14, 0x706BBB14 +.word 0x708F9A14, 0x70ABBB14, 0x70CF9A14, 0x70EB9B14, 0x7109AA14, 0x71259B14, 0x7143AA14, 0x715FEA14 +.word 0x7186AA14, 0x71A2AA14, 0x71BE9A14, 0x71DA3D14, 0x71E87A14, 0x71FE4D14, 0x720C5214, 0x721190FC +.word 0x72145F1A, 0x722C8910, 0x72408B14, 0x72588910, 0x726C7C16, 0x72868910, 0x729A6A14, 0x72AB8C10 +.word 0x72C57A14, 0x72DB2A14, 0x72E14E14, 0x72F07A14, 0x73062A14, 0x730CB810, 0x73277810, 0x73398910 +.word 0x734D8C10, 0x73678C10, 0x73815810, 0x738F7910, 0x73A34A12, 0x73AE780E, 0x73C0870E, 0x73D0B70E +.word 0x73E8770E, 0x73F88B0E, 0x7410770E, 0x74205D14, 0x74352A14, 0x743B6D14, 0x74506114, 0x74536F18 +.word 0x746B6F16, 0x74832A0E, 0x74898B12, 0x74A18B14, 0x74B98710, 0x74C99A14, 0x74E52A14, 0x74EB7E14 +.word 0x75094114, 0x750BBA14, 0x752C5414, 0x7534650C, 0x753D840A, 0x75476E16, 0x755EBA14, 0x757F6114 +.word 0x75823316, 0x7586870E, 0x75965F18, 0x75AE5F18, 0x75C64214, 0x75C99B0E, 0x75E78D14, 0x7603430C +.word 0x76072402, 0x760A6D14, 0x761F5414, 0x7627550C, 0x7630FB14, 0x7660C514, 0x7672E80E, 0x76928A0E +.word 0x76A8AD1A, 0x76CBAD1A, 0x76EEAD1A, 0x7711AD1A, 0x7734AD1A, 0x7757AE1C, 0x777DFA14, 0x77A9AD14 +.word 0x77CC8D1A, 0x77E88D1A, 0x78048D1A, 0x78208C18, 0x783A4D1A, 0x78483D1A, 0x78565D1A, 0x786B5D1A +.word 0x78805F1A, 0x7898AD1A, 0x78BBCE1A, 0x78E8BE1A, 0x7915BE1A, 0x7942BE1A, 0x796FCD18, 0x7999870E +.word 0x79A9BB14, 0x79CD9E1A, 0x79F39E1A, 0x7A199E1A, 0x7A3FAE1A, 0x7A656F1A, 0x7A7D5F1A, 0x7A958B14 +.word 0x7AAD8C16, 0x7AC78C16, 0x7AE18C16, 0x7AFB8B14, 0x7B138B14, 0x7B2B8C16, 0x7B45D910, 0x7B687C10 +.word 0x7B828C16, 0x7B9C8C16, 0x7BB68C16, 0x7BD08B14, 0x7BE84B16, 0x7BF44B16, 0x7C005B16, 0x7C124B16 +.word 0x7C1E7B14, 0x7C367A14, 0x7C4C8C16, 0x7C668C16, 0x7C808C16, 0x7C9A8B14, 0x7CB28B14, 0x7CCA870E +.word 0x7CDA8910, 0x7CEE7C16, 0x7D088C16, 0x7D227C16, 0x7D3C7B14, 0x7D545F18, 0x7D6C5F18, 0x7D848E14 +.word 0x7DA26F16, 0x7DBA3A14, 0x7DC56414, 0x7DCD9A14, 0x7DE98D16, 0x7E05EB14, 0x7E2FBB14, 0x7E533414 +.word 0x7E584D14, 0x7E664D14, 0x7E746414, 0x7E7C870E, 0x7E8C3402, 0x7E91920A, 0x7E993102, 0x7E9B7A14 +.word 0x7EB18B14, 0x7EC95A14, 0x7EDA8A14, 0x7EF08B14, 0x7F088A14, 0x7F1E8B14, 0x7F368B14, 0x7F4E8A14 +.word 0x7F648B14, 0x7F7C9B14, 0x7F9A370E, 0x7FA23A0E, 0x7FADA80E, 0x7FC4960C, 0x7FD6980E, 0x7FED9A14 +.word 0x8009DC16, 0x8037BA14, 0x8058AA14, 0x8074BB14, 0x8098AA14, 0x80B49A14, 0x80D09A14, 0x80ECBB14 +.word 0x8110AA14, 0x812C3A14, 0x81378B14, 0x814FAA14, 0x816B9A14, 0x8187BA14, 0x81A8AA14, 0x81C4BB14 +.word 0x81E89A14, 0x8204BB14, 0x8228AA14, 0x8244AB14, 0x8262AA14, 0x827E9B14, 0x829CAA14, 0x82B8FA14 +.word 0x82E4AA14, 0x8300AA14, 0x831C9A14, 0x83384D14, 0x83466A14, 0x83575D14, 0x836C6216, 0x837190FC +.word 0x83745F18, 0x838C8910, 0x83A09B14, 0x83BE8910, 0x83D29B14, 0x83F09910, 0x84095A14, 0x841A8C10 +.word 0x84348A14, 0x844A3A14, 0x84554E14, 0x84648A14, 0x847A2A14, 0x8480C810, 0x849B8810, 0x84AD9910 +.word 0x84C68C10, 0x84E09C10, 0x85015810, 0x850F8910, 0x85235A14, 0x8534880E, 0x8546870E, 0x8556C70E +.word 0x856E870E, 0x857E8B0E, 0x8596870E, 0x85A65D14, 0x85BB3A14, 0x85C66D14, 0x85DB7216, 0x85E16F18 +.word 0x85F96F14, 0x86113A0E, 0x861C8B12, 0x86348B14, 0x864C8710, 0x865C9A14, 0x86783A14, 0x86838D14 +.word 0x869F6114, 0x86A2BA14, 0x86C36514, 0x86CC750C, 0x86D8950C, 0x86E75F16, 0x86FFBA14, 0x87206114 +.word 0x87234318, 0x8727970E, 0x873B5F16, 0x87535F16, 0x876B4114, 0x876DAB0E, 0x878B9D14, 0x87AE430C +.word 0x87B23402, 0x87B76F16, 0x87CF6514, 0x87D8650C, 0x87E1EC14, 0x880FC512, 0x8821E90E, 0x88448A0E +.word 0x885AAD1A, 0x887DBD1A, 0x88A7BD1A, 0x88D1BD1A, 0x88FBAD1A, 0x891EBE1C, 0x894BFA14, 0x8977AE14 +.word 0x899D9D1A, 0x89C09D1A, 0x89E39D1A, 0x8A069D1A, 0x8A294D1A, 0x8A374D1A, 0x8A456D1A, 0x8A5A6D1A +.word 0x8A6F5F18, 0x8A87AD1A, 0x8AAABE1A, 0x8AD7BE1A, 0x8B04BE1A, 0x8B31BE1A, 0x8B5EBE1A, 0x8B8B870E +.word 0x8B9BBB14, 0x8BBF9E1A, 0x8BE59E1A, 0x8C0BAE1A, 0x8C31AE1A, 0x8C575F18, 0x8C6F5F18, 0x8C878B14 +.word 0x8C9F8B14, 0x8CB79B14, 0x8CD58C16, 0x8CEF8C16, 0x8D098B14, 0x8D219D18, 0x8D44D910, 0x8D678C10 +.word 0x8D818B14, 0x8D999B14, 0x8DB79C16, 0x8DD88B14, 0x8DF05A14, 0x8E015A14, 0x8E125A14, 0x8E236A14 +.word 0x8E348B14, 0x8E4C8B16, 0x8E649B14, 0x8E829B14, 0x8EA09C16, 0x8EC19C16, 0x8EE29B14, 0x8F00870E +.word 0x8F10A910, 0x8F298B14, 0x8F418B14, 0x8F598C16, 0x8F738C16, 0x8F8D5F18, 0x8FA55F18, 0x8FBD8F16 +.word 0x8FDD6F16, 0x8FF54A12, 0x90004312, 0x90049A12, 0x90209C14, 0x9041BA12, 0x90628A12, 0x90782312 +.word 0x907A6C12, 0x908E5C12, 0x90A25412, 0x90AA870C, 0x90BA3300, 0x90BE8006, 0x90C02100, 0x90C17A12 +.word 0x90D78A12, 0x90ED5A12, 0x90FE9A12, 0x911A8A12, 0x91308A12, 0x91469A12, 0x91628A12, 0x91788A12 +.word 0x918E8A12, 0x91A47A12, 0x91BA370E, 0x91C24A0E, 0x91CD980E, 0x91E4940A, 0x91F1980E, 0x92087A12 +.word 0x921ECB14, 0x9242AA12, 0x925E9A12, 0x927ABB14, 0x929EAA12, 0x92BABA12, 0x92DBAA12, 0x92F7BB14 +.word 0x931BBA12, 0x933C4A12, 0x93478A12, 0x935DBA12, 0x937E8A12, 0x9394CA12, 0x93B5AA12, 0x93D1BB14 +.word 0x93F5AA12, 0x9411BB14, 0x9435AA12, 0x94519B14, 0x946F9A12, 0x948BAA12, 0x94A7AA12, 0x94C3DA12 +.word 0x94EABA12, 0x950B9A12, 0x9527BA12, 0x95485C12, 0x955C3A12, 0x95675C12, 0x957B5112, 0x957E80FC +.word 0x95803F18, 0x9590780E, 0x95A29A12, 0x95BE880E, 0x95D09A12, 0x95EC880E, 0x95FE5A12, 0x960F9B0E +.word 0x962D8A12, 0x96434A12, 0x964E6D12, 0x96638A12, 0x96794A12, 0x9684C80E, 0x969F880E, 0x96B1880E +.word 0x96C39B0E, 0x96E18B0E, 0x96F9680E, 0x9707780E, 0x97195A12, 0x972A880E, 0x973C880E, 0x974EA80E +.word 0x9765980E, 0x977C9B0E, 0x979A880E, 0x97AC7C12, 0x97C63A12, 0x97D16C12, 0x97E56112, 0x97E86F18 +.word 0x98004F14, 0x98104A0E, 0x981B8A10, 0x98319A12, 0x984D860E, 0x985B9A12, 0x98774A12, 0x98827D12 +.word 0x989E5112, 0x98A1BA12, 0x98C25514, 0x98CB740A, 0x98D5840A, 0x98DF5F14, 0x98F7BA12, 0x99185112 +.word 0x991B3214, 0x991E870C, 0x992E5F16, 0x99465F16, 0x995E3112, 0x9960BB0E, 0x99848C12, 0x999E330C +.word 0x99A22300, 0x99A46F16, 0x99BC5514, 0x99C5640A, 0x99CDFB14, 0x99FDB412, 0x9A0CD80E, 0x9A2C7A0E +.word 0x9A42AD18, 0x9A65AD18, 0x9A889D18, 0x9AABAD18, 0x9ACEAD18, 0x9AF1AE1A, 0x9B17FA12, 0x9B43BE14 +.word 0x9B70BD18, 0x9B9AAD18, 0x9BBDAD18, 0x9BE0AD18, 0x9C035D18, 0x9C186D18, 0x9C2D6D18, 0x9C426D18 +.word 0x9C573F18, 0x9C67BD18, 0x9C91BD18, 0x9CBBBD18, 0x9CE5BD18, 0x9D0FBD18, 0x9D39BD18, 0x9D63980E +.word 0x9D7ADB14, 0x9DA4AD18, 0x9DC7AD18, 0x9DEAAD18, 0x9E0DAD18, 0x9E305F18, 0x9E485F18, 0x9E608A12 +.word 0x9E768B14, 0x9E8E8B14, 0x9EA68B14, 0x9EBE8B14, 0x9ED68A12, 0x9EEC8C16, 0x9F06D80E, 0x9F267B0E +.word 0x9F3E8B14, 0x9F567B14, 0x9F6E8B14, 0x9F868A12, 0x9F9C3B14, 0x9FA85B14, 0x9FBA5B14, 0x9FCC5A12 +.word 0x9FDD8A12, 0x9FF38B14, 0xA00B8B14, 0xA0238B14, 0xA03B8B14, 0xA0538B14, 0xA06B8A12, 0xA081860C +.word 0xA08F980E, 0xA0A67B14, 0xA0BE8B14, 0xA0D68B14, 0xA0EE8A12, 0xA1045E16, 0xA11B5E16, 0xA1329D12 +.word 0xA1556F1A, 0xA16D1B16, 0xA1735316, 0xA1797B16, 0xA1915D18, 0xA1A67B16, 0xA1BE5B16, 0xA1D02316 +.word 0xA1D22F18, 0xA1DA2F18, 0xA1E23316, 0xA1E6540C, 0xA1EE2404, 0xA1F15008, 0xA1F31204, 0xA1F53A16 +.word 0xA2004B16, 0xA20C2B16, 0xA2124B16, 0xA21E5B16, 0xA2304B16, 0xA23C5B16, 0xA24E4B16, 0xA25A5B16 +.word 0xA26C4B16, 0xA2785B16, 0xA28A1710, 0xA28E280E, 0xA2936810, 0xA2A1530C, 0xA2A75810, 0xA2B54B16 +.word 0xA2C17C18, 0xA2DB5B16, 0xA2ED4B16, 0xA2F96C18, 0xA30D5B16, 0xA31F5B16, 0xA3315C18, 0xA3456C18 +.word 0xA3595B16, 0xA36B2A16, 0xA3714B16, 0xA37D6B16, 0xA38F5B16, 0xA3A17B16, 0xA3B96B16, 0xA3CB6C18 +.word 0xA3DF5B16, 0xA3F16D18, 0xA4065C18, 0xA41A6C18, 0xA42E6A16, 0xA43F5B16, 0xA4516B16, 0xA4638C18 +.word 0xA47D5B16, 0xA48F5B16, 0xA4A15B16, 0xA4B32E16, 0xA4BB3A16, 0xA4C62E16, 0xA4CE531A, 0xA4D470FC +.word 0xA4D65F1C, 0xA4EE4810, 0xA4F75B16, 0xA5095912, 0xA5185B16, 0xA52A5810, 0xA5383C18, 0xA5454B10 +.word 0xA5514B16, 0xA55D2B16, 0xA5632E16, 0xA56B4B16, 0xA5772B16, 0xA57D6810, 0xA58B4810, 0xA5945912 +.word 0xA5A34B10, 0xA5AF5B10, 0xA5C13810, 0xA5CA5912, 0xA5D93A14, 0xA5E44810, 0xA5ED5810, 0xA5FB6810 +.word 0xA6094810, 0xA6125B10, 0xA6245810, 0xA6324E16, 0xA6412E16, 0xA6494E16, 0xA6586116, 0xA65B6C18 +.word 0xA66F5E16, 0xA6862B10, 0xA68C5C14, 0xA6A04B16, 0xA6AC5712, 0xA6B84A16, 0xA6C32B16, 0xA6C94E16 +.word 0xA6D83116, 0xA6DA7B16, 0xA6F23618, 0xA6F9650E, 0xA702440C, 0xA7076B16, 0xA7197B16, 0xA7317016 +.word 0xA7332218, 0xA735570E, 0xA7415F1A, 0xA7595F1A, 0xA7712116, 0xA7725B10, 0xA7845E16, 0xA79B230E +.word 0xA79D2300, 0xA79F6D16, 0xA7B43618, 0xA7BB640C, 0xA7C38B16, 0xA7DB7516, 0xA7E78810, 0xA7F95B10 +.word 0xA80B5E1C, 0xA8225E1C, 0xA8395E1C, 0xA8506E1C, 0xA8675D1A, 0xA87C5F1E, 0xA8948B16, 0xA8AC6F18 +.word 0xA8C45F1E, 0xA8DC5E1C, 0xA8F35F1E, 0xA90B5D1A, 0xA9202E1C, 0xA9282E1C, 0xA9305F1E, 0xA9484D1A +.word 0xA9565F1C, 0xA96E6E1C, 0xA9857E1C, 0xA9A37E1C, 0xA9C17F1E, 0xA9E17E1C, 0xA9FF7D1A, 0xAA1B4810 +.word 0xAA246C18, 0xAA386E1C, 0xAA4F6E1C, 0xAA666F1E, 0xAA7E6D1A, 0xAA936F1C, 0xAAAB5F1C, 0xAAC34B16 +.word 0xAACF5B16, 0xAAE15B16, 0xAAF35C18, 0xAB076B16, 0xAB194A14, 0xAB245C18, 0xAB387810, 0xAB4A4B10 +.word 0xAB565B16, 0xAB685B16, 0xAB7A5C18, 0xAB8E4A14, 0xAB992B16, 0xAB9F2B16, 0xABA55B16, 0xABB74A14 +.word 0xABC24B16, 0xABCE6B16, 0xABE05B16, 0xABF25B16, 0xAC045C18, 0xAC186B16, 0xAC2A4A14, 0xAC35560E +.word 0xAC405810, 0xAC4E5B16, 0xAC604B16, 0xAC6C5C18, 0xAC804A14, 0xAC8B5F1A, 0xACA36F1A, 0xACBB4D14 +.word 0xACC96F1A, 0xACE12C18, 0xACE85318, 0xACEE8C18, 0xAD087E18, 0xAD266B16, 0xAD388C18, 0xAD522318 +.word 0xAD543F18, 0xAD643F18, 0xAD745318, 0xAD7A8710, 0xAD8A2302, 0xAD8C710A, 0xAD902102, 0xAD915E1A +.word 0xADA85B16, 0xADBA4B16, 0xADC65B16, 0xADD85B16, 0xADEA7B16, 0xAE025B16, 0xAE145B16, 0xAE267B16 +.word 0xAE3E5B16, 0xAE505B16, 0xAE622710, 0xAE662910, 0xAE6B7A12, 0xAE81740C, 0xAE8B7A12, 0xAEA16C18 +.word 0xAEB58C18, 0xAECF7C18, 0xAEE96C18, 0xAEFD6C18, 0xAF116C18, 0xAF255C18, 0xAF395C18, 0xAF4D6C18 +.word 0xAF616C18, 0xAF752C18, 0xAF7C6C18, 0xAF908C18, 0xAFAA5C18, 0xAFBE8C18, 0xAFD87C18, 0xAFF26C18 +.word 0xB0066C18, 0xB01A7C18, 0xB0346C18, 0xB0486C18, 0xB05C6C18, 0xB0706C18, 0xB0847C18, 0xB09EAC18 +.word 0xB0BF8C18, 0xB0D98C18, 0xB0F36C18, 0xB1073F1C, 0xB1175E1A, 0xB12E3F1C, 0xB13E5216, 0xB14380FC +.word 0xB1455F1C, 0xB15D5912, 0xB16C5C18, 0xB1805810, 0xB18E5C18, 0xB1A25912, 0xB1B14C18, 0xB1BE5C12 +.word 0xB1D25C18, 0xB1E62C18, 0xB1ED4F18, 0xB1FD6C18, 0xB2112C18, 0xB2187912, 0xB22C5912, 0xB23B5912 +.word 0xB24A5C12, 0xB25E5C12, 0xB2725912, 0xB2815A14, 0xB2924B16, 0xB29E5810, 0xB2AC7810, 0xB2BE8810 +.word 0xB2D07810, 0xB2E27A10, 0xB2F85810, 0xB3065E16, 0xB31D1C18, 0xB3245E16, 0xB33B6116, 0xB33E6C18 +.word 0xB3525E16, 0xB3692B10, 0xB36F6C14, 0xB3837B16, 0xB39B7914, 0xB3AF8B16, 0xB3C71C18, 0xB3CE7D16 +.word 0xB3EA4016, 0xB3EB7B16, 0xB4033618, 0xB40AA912, 0xB423820C, 0xB4296B16, 0xB43B7B16, 0xB4538016 +.word 0xB4553218, 0xB4588A14, 0xB46E3418, 0xB4733418, 0xB4783118, 0xB47A8A10, 0xB4906E16, 0xB4A7430E +.word 0xB4AB2302, 0xB4AD3418, 0xB4B23618, 0xB4B9A912, 0xB4D28B16, 0xB4EA8216, 0xB4F08910, 0xB5046B10 +.word 0xB5167E1C, 0xB5347E1C, 0xB5527F1E, 0xB5727E1C, 0xB5907E1C, 0xB5AE7F1E, 0xB5CE8C18, 0xB5E86E18 +.word 0xB5FF5F1E, 0xB6175F1E, 0xB62F5F1E, 0xB6475E1C, 0xB65E3F1E, 0xB66E3F1E, 0xB67E5F1E, 0xB6964E1C +.word 0xB6A57C18, 0xB6BF7E1C, 0xB6DD6F1E, 0xB6F56F1E, 0xB70D6F1E, 0xB7256F1E, 0xB73D6E1C, 0xB7547812 +.word 0xB7668C18, 0xB7806E1C, 0xB7976E1C, 0xB7AE6E1C, 0xB7C56D1A, 0xB7DA8D1A, 0xB7F68E1C, 0xB8146D1A +.word 0xB8295B16, 0xB83B5B16, 0xB84D5C18, 0xB8616B16, 0xB8735A14, 0xB8845C18, 0xB8988912, 0xB8AC5D12 +.word 0xB8C15B16, 0xB8D35B16, 0xB8E55B16, 0xB8F75A14, 0xB9083B16, 0xB9143B16, 0xB9205B16, 0xB9324A14 +.word 0xB93D5B16, 0xB94F6B16, 0xB9615B16, 0xB9735B16, 0xB9855C18, 0xB9996B16, 0xB9AB5A14, 0xB9BC8710 +.word 0xB9CC7B14, 0xB9E45B16, 0xB9F65B16, 0xBA085B16, 0xBA1A5A14, 0xBA2B7C16, 0xBA455C16, 0xBA597B14 +.word 0xBA716F18, 0xBA893B16, 0xBA956414, 0xBA9D6912, 0xBAAC6D16, 0xBAC17B14, 0xBAD97B14, 0xBAF14414 +.word 0xBAF64D16, 0xBB043D16, 0xBB127912, 0xBB266912, 0xBB353302, 0xBB39610A, 0xBB3C3202, 0xBB3F8D16 +.word 0xBB5B6B16, 0xBB6D5B16, 0xBB7F7B16, 0xBB976B16, 0xBBA97B16, 0xBBC17B16, 0xBBD97B16, 0xBBF16B16 +.word 0xBC037B16, 0xBC1B7B16, 0xBC333810, 0xBC3C3910, 0xBC467C18, 0xBC60730E, 0xBC687C18, 0xBC826B16 +.word 0xBC947B16, 0xBCAC7B16, 0xBCC47B16, 0xBCDC6B16, 0xBCEE7B16, 0xBD067B16, 0xBD1E7B16, 0xBD367B16 +.word 0xBD4E8B16, 0xBD665B16, 0xBD786B16, 0xBD8A8B16, 0xBDA27B16, 0xBDBA7B16, 0xBDD27B16, 0xBDEA6B16 +.word 0xBDFC8B16, 0xBE147C16, 0xBE2E7B16, 0xBE466B16, 0xBE587B16, 0xBE707B16, 0xBE887B16, 0xBEA08B16 +.word 0xBEB87B16, 0xBED07B16, 0xBEE87B16, 0xBF003D18, 0xBF0E8D16, 0xBF2A3D18, 0xBF387114, 0xBF3CA0FA +.word 0xBF3F6F1A, 0xBF577810, 0xBF69AB16, 0xBF878810, 0xBF997B16, 0xBFB17810, 0xBFC36B16, 0xBFD58910 +.word 0xBFE97B16, 0xC0015B16, 0xC0134C16, 0xC0208B16, 0xC0384B16, 0xC0447810, 0xC0567810, 0xC0686810 +.word 0xC0767910, 0xC08A7910, 0xC09E6810, 0xC0AC6810, 0xC0BA5A14, 0xC0CB7810, 0xC0DD7810, 0xC0EF8810 +.word 0xC1018810, 0xC1137910, 0xC1276810, 0xC1354D18, 0xC1432D18, 0xC14A4D18, 0xC1585116, 0xC15B6F1C +.word 0xC2276F16, 0xC23F6F16, 0xC1738A16, 0xC189AB16, 0xC2576F16, 0xC1A7C914, 0xC1C52D16, 0xC1CC6A16 +.word 0xC1DD6116, 0xC26F6F16, 0xC2876F16, 0xC1E07D18, 0xC1FCC40C, 0xC20B7D18, 0xC29F6F16, 0xC2B76F16 +.word 0xC2CF4318, 0xC2D3A914, 0xC2ECA912, 0xC305AB16, 0xC4126F18, 0xC323A910, 0xC33C8914, 0xC350430E +.word 0xC3543404, 0xC359DB14, 0xC383A016, 0xC386DB16, 0xC3B0ED18, 0xC3E1ED18, 0xC42A6F18, 0xC4426F18 +.word 0xC45AA20E, 0xC4624306, 0xC4666D18, 0xC47BA810, 0xC4925A18, 0xC4A35A12, 0xC4B46A18, 0xC4C57A12 +.word 0xC4DB5D18, 0xC4F05D18, 0xC5055D18, 0xC51A6D18, 0xC52FD914, 0xC552D914, 0xC575B914, 0xC593E510 +.word 0xC5A8F50E, 0xC5C07D16, 0xC5DC6D16, 0xC5F1EB14, 0xC61BEB14, 0xC645D912, 0xC668D912, 0xC68BAD16 +.word 0xC6AEAD16, 0xC6D1FA14, 0xC6FD9C16, 0xC71E6F16, 0xC7366F16, 0xC74E6F16, 0xC7666F16, 0xC77E6F16 +.word 0xC796E612, 0xC7AFA810, 0xC7C65118, 0xC7C96318, 0xC7CF3418, 0xC7D44810, 0xC7DDD30E, 0xC7EBA30E +.word 0xC7F55D18, 0xC80AC20E, 0xC8138B16, 0xC82BB912, 0xC8496F1A, 0xC8616F1A, 0xC8796F1A, 0xC8916F1A +.word 0xC8A90F17, 0xC8E9960E, 0xC8FB7810, 0xC90D960E, 0xC91F7810, 0xC9319E14, 0xC957F810, 0xC97B9E16 +.word 0xC9A1F810, 0xC9C5CC14, 0xC9ECDC16, 0xCA1ADC14, 0xCA48DC14, 0xCA76EF16, 0xCAAE070F, 0xCACE070F +.word 0xCAEE8F16, 0xCB0EED14, 0xCB3FED14, 0xCB70ED14, 0xCBA1EF16, 0xCBD9CB12, 0xCBFDCB12, 0xCC21CB12 +ENDDATA(asc2tbl) diff --git a/src/libleo/api/getaadr2.s b/src/libleo/api/getaadr2.s new file mode 100644 index 0000000000..e3ea0868bb --- /dev/null +++ b/src/libleo/api/getaadr2.s @@ -0,0 +1,33 @@ +#include "ultra64/asm.h" + +.set noat +.set noreorder + +.section .text + +.balign 16 + +LEAF(LeoGetAAdr2) + li $at, 0x10000 + srl $t8, $a0, 0xF + ori $at, $at, 0xFFFE + and $v1, $t8, $at + li $at, 0x70000 + ori $at, $at, 0xEE80 + srl $t2, $a0, 0x8 + add $v0, $v1, $at + andi $t3, $t2, 0xF + andi $t5, $a0, 0xFE + addi $t4, $t3, 1 + sll $t6, $t5, 0x18 + andi $t9, $a0, 0x1 + srl $v1, $a0, 0xC + sw $t4, ($a2) + sra $t7, $t6, 0x19 + sll $t8, $t9, 0x4 + andi $t1, $v1, 0xF + sw $t7, ($a3) + or $t2, $t1, $t8 + jr $ra + sw $t2, ($a1) +END(LeoGetAAdr2) diff --git a/src/libleo/api/getkadr.s b/src/libleo/api/getkadr.s new file mode 100644 index 0000000000..22d85cb593 --- /dev/null +++ b/src/libleo/api/getkadr.s @@ -0,0 +1,229 @@ +#include "ultra64/asm.h" + +.set noat +.set noreorder + +.section .text + +.balign 16 + +/** + * int LeoGetKAdr(int sjis); + * + * Returns the storage offset address into the N64 Disk Drive mask ROM for + * a kanji character corresponding to a given 2-byte Shift-JIS codepoint. + * An error value -1 will be returned if `sjis` is outside the range 0x8140 to 0x9872. + * + * A nice Shift-JIS codepoint table: https://uic.io/en/charset/show/shift_jis/ + * The Mask ROM contains the 'Level 1' kanji (0x889F-0x9872), and a reworked + * version of the non-kanji section that includes extra English and Hylian glyphs. + * + * @param sjis Shift-JIS Codepoint of glyph. + * @return int Storage offset address into the N64 Disk Drive mask ROM. + */ +LEAF(LeoGetKAdr) + // Check if the codepoint is in the range 0x8140 to 0x9872. + li $at, 0x8140 + slt $at, $a0, $at + bnez $at, .out_of_range + li $at, 0x9873 + slt $at, $a0, $at + beqz $at, .out_of_range + // Characters with codepoints >= 0x8800 are kanji. Arrangement is regular, + // so convert index directly. + li $at, 0x8800 + slt $at, $a0, $at + bnez $at, .nonkanji + // 0xBC is number of glyphs in one block in the `kanji` file: + // 0x100 possible codepoints with the same byte1 + // - 0x40 unused at beginning + // - 1 unused at 0x7F + // - 3 unused at 0xFD, 0xFE, 0xFF + li $a2, 0xBC + // Get byte1 and adjust so starts at 0 + srl $a1, $a0, 8 + addi $a1, $a1, -0x88 + multu $a2, $a1 + // Get byte2 and adjust so starts at 0 + andi $a3, $a0, 0xFF + addi $a3, $a3, -0x40 + slti $at, $a3, (0x80 - 0x40) + mflo $a2 + // 0x__7F is always empty and elided in the file, so decrement if larger + bnezl $at, .kanji_lower_halfblock + mflo $a2 + addi $a3, $a3, -1 + mflo $a2 +.kanji_lower_halfblock: + addi $a3, $a3, 0x30A + add $a3, $a3, $a2 + jr $ra + sll $v0, $a3, 7 + // returns (0x30A + (adjusted byte2) + (adjusted byte1) * 0xBC) * FONT_CHAR_TEX_SIZE + +// Non-kanji are arranged with irregular gaps, use the lookup table. +.nonkanji: + // Get byte1 and adjust so starts at 0 + srl $a1, $a0, 8 + addi $a1, $a1, -0x81 + multu $a2, $a1 + // Get byte2 and adjust so starts at 0 + andi $a3, $a0, 0xFF + addi $a3, $a3, -0x40 + slti $at, $a3, (0x80 - 0x40) + mflo $a2 + // 0x__7F is always empty and elided in the file, so decrement if larger + bnezl $at, .nonkanji_lower_halfblock + mflo $a2 + addi $a3, $a3, -1 + mflo $a2 +.nonkanji_lower_halfblock: + add $a3, $a3, $a2 + lui $a2, %hi(kantbl) + sll $a3, $a3, 1 + addiu $a2, %lo(kantbl) + add $a3, $a3, $a2 + lh $a2, ($a3) + jr $ra + sll $v0, $a2, 7 + // returns kantbl[(adjusted byte2) + (adjusted byte1) * 0xBC] * FONT_CHAR_TEX_SIZE +.out_of_range: + jr $ra + li $v0, -1 +END(LeoGetKAdr) + +/** + * Nearly equivalent C code (Equivalent for all valid input, will behave differently on overflow due to the use of `add` in the original): + * + * extern u16 kantbl[]; + * + * int LeoGetKAdr(int sjis) { + * u32 byte1; + * u32 byte2; + * + * if (sjis < 0x8140 || sjis > 0x9872) { + * return -1; + * } + * + * byte1 = (u32)sjis >> 8; + * byte2 = sjis & 0xFF; + * + * byte2 -= 0x40; + * if (byte2 >= 0x40) { + * byte2--; + * } + * + * if (sjis >= 0x8800) { + * byte1 -= 0x88; + * return (0x30A + byte2 + byte1 * 0xBC) * FONT_CHAR_TEX_SIZE; + * } else { + * byte1 -= 0x81; + * return kantbl[byte2 + byte1 * 0xBC] * FONT_CHAR_TEX_SIZE; + * } + * } + */ + +/** + * Index table, formatting follows conventional Shift-JIS character table layout, + * with space for the missing 0x__7F,0x__FD,0x__FE,0x__FF entries, and split + * into blocks by high byte. + */ +DATA(kantbl) +// 0x___0 0x___1 0x___2 0x___3 0x___4 0x___5 0x___6 0x___7 0x___8 0x___9 0x___A 0x___B 0x___C 0x___D 0x___E 0x___F +/* 0x814_ */ .half 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F +/* 0x815_ */ .half 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F +/* 0x816_ */ .half 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F +/* 0x817_ */ .half 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E +/* 0x818_ */ .half 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E +/* 0x819_ */ .half 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E +/* 0x81A_ */ .half 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x0000, 0x0000, 0x0000 +/* 0x81B_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073 +/* 0x81C_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x0000 +/* 0x81D_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F +/* 0x81E_ */ .half 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x81F_ */ .half 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x0000, 0x0000, 0x0000, 0x0000, 0x0091 + +// 0x___0 0x___1 0x___2 0x___3 0x___4 0x___5 0x___6 0x___7 0x___8 0x___9 0x___A 0x___B 0x___C 0x___D 0x___E 0x___F +/* 0x824_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0092 +/* 0x825_ */ .half 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x826_ */ .half 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB +/* 0x827_ */ .half 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x828_ */ .half 0x0000, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4 +/* 0x829_ */ .half 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x0000, 0x0000, 0x0000, 0x0000, 0x00D0 +/* 0x82A_ */ .half 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0 +/* 0x82B_ */ .half 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0 +/* 0x82C_ */ .half 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x0100 +/* 0x82D_ */ .half 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F, 0x0110 +/* 0x82E_ */ .half 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F, 0x0120 +/* 0x82F_ */ .half 0x0121, 0x0122, 0x0123, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + +// 0x___0 0x___1 0x___2 0x___3 0x___4 0x___5 0x___6 0x___7 0x___8 0x___9 0x___A 0x___B 0x___C 0x___D 0x___E 0x___F +/* 0x834_ */ .half 0x0124, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F, 0x0130, 0x0131, 0x0132, 0x0133 +/* 0x835_ */ .half 0x0134, 0x0135, 0x0136, 0x0137, 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x013F, 0x0140, 0x0141, 0x0142, 0x0143 +/* 0x836_ */ .half 0x0144, 0x0145, 0x0146, 0x0147, 0x0148, 0x0149, 0x014A, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F, 0x0150, 0x0151, 0x0152, 0x0153 +/* 0x837_ */ .half 0x0154, 0x0155, 0x0156, 0x0157, 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F, 0x0160, 0x0161, 0x0162 +/* 0x838_ */ .half 0x0163, 0x0164, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F, 0x0170, 0x0171, 0x0172 +/* 0x839_ */ .half 0x0173, 0x0174, 0x0175, 0x0176, 0x0177, 0x0178, 0x0179, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x017A +/* 0x83A_ */ .half 0x017B, 0x017C, 0x017D, 0x017E, 0x017F, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185, 0x0186, 0x0187, 0x0188, 0x0189, 0x018A +/* 0x83B_ */ .half 0x018B, 0x018C, 0x018D, 0x018E, 0x018F, 0x0190, 0x0191, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192 +/* 0x83C_ */ .half 0x0193, 0x0194, 0x0195, 0x0196, 0x0197, 0x0198, 0x0199, 0x019A, 0x019B, 0x019C, 0x019D, 0x019E, 0x019F, 0x01A0, 0x01A1, 0x01A2 +/* 0x83D_ */ .half 0x01A3, 0x01A4, 0x01A5, 0x01A6, 0x01A7, 0x01A8, 0x01A9, 0x01AA, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x83E_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x83F_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + +// 0x___0 0x___1 0x___2 0x___3 0x___4 0x___5 0x___6 0x___7 0x___8 0x___9 0x___A 0x___B 0x___C 0x___D 0x___E 0x___F +/* 0x844_ */ .half 0x01AB, 0x01AC, 0x01AD, 0x01AE, 0x01AF, 0x01B0, 0x01B1, 0x01B2, 0x01B3, 0x01B4, 0x01B5, 0x01B6, 0x01B7, 0x01B8, 0x01B9, 0x01BA +/* 0x845_ */ .half 0x01BB, 0x01BC, 0x01BD, 0x01BE, 0x01BF, 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C5, 0x01C6, 0x01C7, 0x01C8, 0x01C9, 0x01CA +/* 0x846_ */ .half 0x01CB, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x847_ */ .half 0x01CC, 0x01CD, 0x01CE, 0x01CF, 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7, 0x01D8, 0x01D9, 0x01DA +/* 0x848_ */ .half 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF, 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E4, 0x01E5, 0x01E6, 0x01E7, 0x01E8, 0x01E9, 0x01EA +/* 0x849_ */ .half 0x01EB, 0x01EC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01ED +/* 0x84A_ */ .half 0x01EE, 0x01EF, 0x01F0, 0x01F1, 0x01F2, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7, 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD +/* 0x84B_ */ .half 0x01FE, 0x01FF, 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, 0x020A, 0x020B, 0x020C, 0x020D +/* 0x84C_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x84D_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x84E_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x84F_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + +// 0x___0 0x___1 0x___2 0x___3 0x___4 0x___5 0x___6 0x___7 0x___8 0x___9 0x___A 0x___B 0x___C 0x___D 0x___E 0x___F +/* 0x854_ */ .half 0x020E, 0x020F, 0x0210, 0x0211, 0x0212, 0x0213, 0x0214, 0x0215, 0x0216, 0x0217, 0x0218, 0x0219, 0x021A, 0x021B, 0x021C, 0x021D +/* 0x855_ */ .half 0x021E, 0x021F, 0x0220, 0x0221, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0222, 0x0223 +/* 0x856_ */ .half 0x0224, 0x0225, 0x0226, 0x0227, 0x0228, 0x0229, 0x022A, 0x022B, 0x022C, 0x022D, 0x022E, 0x022F, 0x0230, 0x0231, 0x0232, 0x0233 +/* 0x857_ */ .half 0x0234, 0x0235, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0236, 0x0237, 0x0238 +/* 0x858_ */ .half 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x859_ */ .half 0x0000, 0x023F, 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, 0x0248, 0x0000, 0x0000, 0x0000, 0x0000, 0x0249 +/* 0x85A_ */ .half 0x024A, 0x024B, 0x024C, 0x024D, 0x024E, 0x024F, 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257, 0x0000, 0x0000 +/* 0x85B_ */ .half 0x0000, 0x0000, 0x0000, 0x0258, 0x0259, 0x025A, 0x025B, 0x025C, 0x025D, 0x025E, 0x025F, 0x0260, 0x0261, 0x0262, 0x0263, 0x0264 +/* 0x85C_ */ .half 0x0265, 0x0266, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x85D_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0267, 0x0268, 0x0269, 0x026A, 0x026B +/* 0x85E_ */ .half 0x026C, 0x026D, 0x026E, 0x026F, 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, 0x0278, 0x0279, 0x027A, 0x027B +/* 0x85F_ */ .half 0x027C, 0x027D, 0x027E, 0x027F, 0x0280, 0x0281, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + +// 0x___0 0x___1 0x___2 0x___3 0x___4 0x___5 0x___6 0x___7 0x___8 0x___9 0x___A 0x___B 0x___C 0x___D 0x___E 0x___F +/* 0x864_ */ .half 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287, 0x0288, 0x0289, 0x028A, 0x028B, 0x028C, 0x028D, 0x028E, 0x028F, 0x0290, 0x0291 +/* 0x865_ */ .half 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, 0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x0000, 0x0000 +/* 0x866_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x867_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x868_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x869_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4 +/* 0x86A_ */ .half 0x02A5, 0x02A6, 0x02A7, 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x86B_ */ .half 0x0000, 0x0000, 0x0000, 0x02AC, 0x02AD, 0x02AE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x86C_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x02AF, 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6, 0x02B7 +/* 0x86D_ */ .half 0x02B8, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x86E_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x86F_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + +// 0x___0 0x___1 0x___2 0x___3 0x___4 0x___5 0x___6 0x___7 0x___8 0x___9 0x___A 0x___B 0x___C 0x___D 0x___E 0x___F +/* 0x874_ */ .half 0x02C0, 0x02C1, 0x02C2, 0x02C3, 0x02C4, 0x02C5, 0x02C6, 0x02C7, 0x02C8, 0x02C9, 0x02CA, 0x02CB, 0x02CC, 0x02CD, 0x02CE, 0x02CF +/* 0x875_ */ .half 0x02D0, 0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7, 0x02D8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x876_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x877_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x878_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x879_ */ .half 0x0000, 0x02D9, 0x02DA, 0x02DB, 0x02DC, 0x02DD, 0x02DE, 0x02DF, 0x02E0, 0x02E1, 0x02E2, 0x02E3, 0x02E4, 0x02E5, 0x02E6, 0x02E7 +/* 0x87A_ */ .half 0x02E8, 0x02E9, 0x02EA, 0x02EB, 0x02EC, 0x02ED, 0x02EE, 0x02EF, 0x02F0, 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, 0x02F7 +/* 0x87B_ */ .half 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, 0x02FD, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x02FE, 0x02FF, 0x0300 +/* 0x87C_ */ .half 0x0301, 0x0302, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x87D_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x87E_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0303, 0x0304, 0x0305, 0x0306, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +/* 0x87F_ */ .half 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0307, 0x0308, 0x0309 +ENDDATA(kantbl) diff --git a/src/libleo/api/lbatobyte.c b/src/libleo/api/lbatobyte.c new file mode 100644 index 0000000000..dc5b1f5dbe --- /dev/null +++ b/src/libleo/api/lbatobyte.c @@ -0,0 +1,40 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.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--; + startlba++; + 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/api/readwrite.c b/src/libleo/api/readwrite.c new file mode 100644 index 0000000000..a4c27d26f9 --- /dev/null +++ b/src/libleo/api/readwrite.c @@ -0,0 +1,33 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.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 = 5; + } else { + cmdBlock->header.command = 6; + } + + cmdBlock->header.reserve1 = 0; + + if (mq != NULL) { + cmdBlock->header.control = 0x80; + } else { + cmdBlock->header.control = 0; + } + + cmdBlock->header.reserve3 = 0; + cmdBlock->header.post = mq; + cmdBlock->data.readWrite.lba = LBA; + cmdBlock->data.readWrite.transferBlks = nLBAs; + cmdBlock->data.readWrite.buffPtr = vAddr; + + leoCommand(cmdBlock); + return LEO_ERROR_GOOD; +} diff --git a/src/libleo/api/seek.c b/src/libleo/api/seek.c new file mode 100644 index 0000000000..dbbc4651ac --- /dev/null +++ b/src/libleo/api/seek.c @@ -0,0 +1,24 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +s32 LeoSeek(LEOCmd* cmdBlock, u32 lba, 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.readWrite.lba = lba; + + if (mq != NULL) { + cmdBlock->header.control |= LEO_CONTROL_POST; + cmdBlock->header.post = mq; + } + + leoCommand(cmdBlock); + return LEO_ERROR_GOOD; +} diff --git a/src/libleo/api/spdlmotor.c b/src/libleo/api/spdlmotor.c new file mode 100644 index 0000000000..8c0ffa9ffa --- /dev/null +++ b/src/libleo/api/spdlmotor.c @@ -0,0 +1,38 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +s32 LeoSpdlMotor(LEOCmd* cmdBlock, u8 mode, OSMesgQueue* mq) { + if (!__leoActive) { + return -1; + } + + cmdBlock->header.command = 8; + cmdBlock->header.reserve1 = 0; + + switch (mode) { + case LEO_MOTOR_ACTIVE: + cmdBlock->header.control = 1; + break; + case LEO_MOTOR_STANDBY: + cmdBlock->header.control = 2; + break; + case LEO_MOTOR_SLEEP: + cmdBlock->header.control = 0; + break; + case LEO_MOTOR_BRAKE: + cmdBlock->header.control = 4; + break; + } + + cmdBlock->header.reserve3 = 0; + + if (mq != NULL) { + cmdBlock->header.post = mq; + cmdBlock->header.control |= 0x80; + } + + leoCommand(cmdBlock); + return LEO_ERROR_GOOD; +} diff --git a/src/libleo/api/testunitready.c b/src/libleo/api/testunitready.c new file mode 100644 index 0000000000..f5770f86b7 --- /dev/null +++ b/src/libleo/api/testunitready.c @@ -0,0 +1,28 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +s32 LeoTestUnitReady(u8* status) { + volatile LEOCmdTestUnitReady cmdBlock; + + if (!__leoActive) { + return -1; + } + + if (IO_READ(PI_STATUS_REG) & PI_STATUS_DMA_BUSY) { + return LEO_ERROR_BUSY; + } + + cmdBlock.header.command = 3; + cmdBlock.header.reserve1 = 0; + cmdBlock.header.control = 0; + cmdBlock.header.reserve3 = 0; + + leoCommand((void*)&cmdBlock); + + while (cmdBlock.header.status == 8) {} + + *status = cmdBlock.test; + return GET_ERROR(cmdBlock); +} diff --git a/src/libleo/leo/leo_tbl.c b/src/libleo/leo/leo_tbl.c new file mode 100644 index 0000000000..f4093fbd53 --- /dev/null +++ b/src/libleo/leo/leo_tbl.c @@ -0,0 +1,58 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +const char LEOfirmware_rev[] = "B014A26"; + +const u8 LEOBYTE_TBL1[] = { + 0xE8, 0xD8, 0xD0, 0xC0, 0xB0, 0xA0, 0x90, 0x80, 0x70, +}; + +const u16 LEOBYTE_TBL2[] = { + 0x4D08, 0x47B8, 0x4510, 0x3FC0, 0x3A70, 0x3520, 0x2FD0, 0x2A80, 0x2530, +}; + +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 }, +}; + +const u16 LEOZONE_SCYL_TBL[] = { + 0x0000, 0x009E, 0x013C, 0x01D1, 0x0266, 0x02FB, 0x0390, 0x0425, + 0x0091, 0x012F, 0x01C4, 0x0259, 0x02EE, 0x0383, 0x0418, 0x048A, +}; + +const u8 LEOVZONE_PZONEHD_TBL[][0x10] = { + { 0x00, 0x01, 0x02, 0x09, 0x08, 0x03, 0x04, 0x05, 0x06, 0x07, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A }, + { 0x00, 0x01, 0x02, 0x03, 0x0A, 0x09, 0x08, 0x04, 0x05, 0x06, 0x07, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x0B, 0x0A, 0x09, 0x08, 0x05, 0x06, 0x07, 0x0F, 0x0E, 0x0D, 0x0C }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x06, 0x07, 0x0F, 0x0E, 0x0D }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x0F, 0x0E }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x0F }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }, +}; + +const u16 LEOZONE_OUTERCYL_TBL[] = { + 0x0000, 0x009E, 0x013C, 0x01D1, 0x0266, 0x02FB, 0x0390, 0x0425, +}; + +const u16 LEORAM_START_LBA[] = { + 0x05A2, 0x07C6, 0x09EA, 0x0C0E, 0x0E32, 0x1010, 0x10DC, +}; + +const s32 LEORAM_BYTE[] = { + 0x024A9DC0, 0x01C226C0, 0x01450F00, 0x00D35680, 0x006CFD40, 0x001DA240, 0x00000000, +}; diff --git a/src/libleo/leo/leoc2_syndrome.c b/src/libleo/leo/leoc2_syndrome.c new file mode 100644 index 0000000000..fe72a3e89e --- /dev/null +++ b/src/libleo/leo/leoc2_syndrome.c @@ -0,0 +1,3 @@ +#include "n64dd.h" + +u8 LEOC2_Syndrome[2][0xE8 * 4]; diff --git a/src/libleo/leo/leoc2ecc.c b/src/libleo/leo/leoc2ecc.c new file mode 100644 index 0000000000..4d268df51b --- /dev/null +++ b/src/libleo/leo/leoc2ecc.c @@ -0,0 +1,495 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +void leoC2_single_ecc(void); +void leoC2_double_ecc(void); +void leoC2_3_ecc(void); +void leoC2_4_ecc(void); +int leoAlpha_mult(int i, int k); +int leoAlpha_div(int i, int k); + +extern u8 LEO_TempBuffer[0xE8]; + +const u8 ganlog[512] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1D, 0x3A, 0x74, 0xE8, 0xCD, 0x87, 0x13, 0x26, 0x4C, 0x98, 0x2D, + 0x5A, 0xB4, 0x75, 0xEA, 0xC9, 0x8F, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x9D, 0x27, 0x4E, 0x9C, 0x25, 0x4A, + 0x94, 0x35, 0x6A, 0xD4, 0xB5, 0x77, 0xEE, 0xC1, 0x9F, 0x23, 0x46, 0x8C, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x5D, + 0xBA, 0x69, 0xD2, 0xB9, 0x6F, 0xDE, 0xA1, 0x5F, 0xBE, 0x61, 0xC2, 0x99, 0x2F, 0x5E, 0xBC, 0x65, 0xCA, 0x89, 0x0F, + 0x1E, 0x3C, 0x78, 0xF0, 0xFD, 0xE7, 0xD3, 0xBB, 0x6B, 0xD6, 0xB1, 0x7F, 0xFE, 0xE1, 0xDF, 0xA3, 0x5B, 0xB6, 0x71, + 0xE2, 0xD9, 0xAF, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xBD, 0x67, 0xCE, 0x81, 0x1F, + 0x3E, 0x7C, 0xF8, 0xED, 0xC7, 0x93, 0x3B, 0x76, 0xEC, 0xC5, 0x97, 0x33, 0x66, 0xCC, 0x85, 0x17, 0x2E, 0x5C, 0xB8, + 0x6D, 0xDA, 0xA9, 0x4F, 0x9E, 0x21, 0x42, 0x84, 0x15, 0x2A, 0x54, 0xA8, 0x4D, 0x9A, 0x29, 0x52, 0xA4, 0x55, 0xAA, + 0x49, 0x92, 0x39, 0x72, 0xE4, 0xD5, 0xB7, 0x73, 0xE6, 0xD1, 0xBF, 0x63, 0xC6, 0x91, 0x3F, 0x7E, 0xFC, 0xE5, 0xD7, + 0xB3, 0x7B, 0xF6, 0xF1, 0xFF, 0xE3, 0xDB, 0xAB, 0x4B, 0x96, 0x31, 0x62, 0xC4, 0x95, 0x37, 0x6E, 0xDC, 0xA5, 0x57, + 0xAE, 0x41, 0x82, 0x19, 0x32, 0x64, 0xC8, 0x8D, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xDD, 0xA7, 0x53, 0xA6, 0x51, + 0xA2, 0x59, 0xB2, 0x79, 0xF2, 0xF9, 0xEF, 0xC3, 0x9B, 0x2B, 0x56, 0xAC, 0x45, 0x8A, 0x09, 0x12, 0x24, 0x48, 0x90, + 0x3D, 0x7A, 0xF4, 0xF5, 0xF7, 0xF3, 0xFB, 0xEB, 0xCB, 0x8B, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x7D, 0xFA, 0xE9, 0xCF, + 0x83, 0x1B, 0x36, 0x6C, 0xD8, 0xAD, 0x47, 0x8E, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1D, 0x3A, 0x74, + 0xE8, 0xCD, 0x87, 0x13, 0x26, 0x4C, 0x98, 0x2D, 0x5A, 0xB4, 0x75, 0xEA, 0xC9, 0x8F, 0x03, 0x06, 0x0C, 0x18, 0x30, + 0x60, 0xC0, 0x9D, 0x27, 0x4E, 0x9C, 0x25, 0x4A, 0x94, 0x35, 0x6A, 0xD4, 0xB5, 0x77, 0xEE, 0xC1, 0x9F, 0x23, 0x46, + 0x8C, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x5D, 0xBA, 0x69, 0xD2, 0xB9, 0x6F, 0xDE, 0xA1, 0x5F, 0xBE, 0x61, 0xC2, + 0x99, 0x2F, 0x5E, 0xBC, 0x65, 0xCA, 0x89, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xFD, 0xE7, 0xD3, 0xBB, 0x6B, 0xD6, 0xB1, + 0x7F, 0xFE, 0xE1, 0xDF, 0xA3, 0x5B, 0xB6, 0x71, 0xE2, 0xD9, 0xAF, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0D, 0x1A, + 0x34, 0x68, 0xD0, 0xBD, 0x67, 0xCE, 0x81, 0x1F, 0x3E, 0x7C, 0xF8, 0xED, 0xC7, 0x93, 0x3B, 0x76, 0xEC, 0xC5, 0x97, + 0x33, 0x66, 0xCC, 0x85, 0x17, 0x2E, 0x5C, 0xB8, 0x6D, 0xDA, 0xA9, 0x4F, 0x9E, 0x21, 0x42, 0x84, 0x15, 0x2A, 0x54, + 0xA8, 0x4D, 0x9A, 0x29, 0x52, 0xA4, 0x55, 0xAA, 0x49, 0x92, 0x39, 0x72, 0xE4, 0xD5, 0xB7, 0x73, 0xE6, 0xD1, 0xBF, + 0x63, 0xC6, 0x91, 0x3F, 0x7E, 0xFC, 0xE5, 0xD7, 0xB3, 0x7B, 0xF6, 0xF1, 0xFF, 0xE3, 0xDB, 0xAB, 0x4B, 0x96, 0x31, + 0x62, 0xC4, 0x95, 0x37, 0x6E, 0xDC, 0xA5, 0x57, 0xAE, 0x41, 0x82, 0x19, 0x32, 0x64, 0xC8, 0x8D, 0x07, 0x0E, 0x1C, + 0x38, 0x70, 0xE0, 0xDD, 0xA7, 0x53, 0xA6, 0x51, 0xA2, 0x59, 0xB2, 0x79, 0xF2, 0xF9, 0xEF, 0xC3, 0x9B, 0x2B, 0x56, + 0xAC, 0x45, 0x8A, 0x09, 0x12, 0x24, 0x48, 0x90, 0x3D, 0x7A, 0xF4, 0xF5, 0xF7, 0xF3, 0xFB, 0xEB, 0xCB, 0x8B, 0x0B, + 0x16, 0x2C, 0x58, 0xB0, 0x7D, 0xFA, 0xE9, 0xCF, 0x83, 0x1B, 0x36, 0x6C, 0xD8, 0xAD, 0x47, 0x8E, 0x01, 0x02 +}; + +const u8 glog[512] = { + 0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1A, 0xC6, 0x03, 0xDF, 0x33, 0xEE, 0x1B, 0x68, 0xC7, 0x4B, 0x04, 0x64, 0xE0, + 0x0E, 0x34, 0x8D, 0xEF, 0x81, 0x1C, 0xC1, 0x69, 0xF8, 0xC8, 0x08, 0x4C, 0x71, 0x05, 0x8A, 0x65, 0x2F, 0xE1, 0x24, + 0x0F, 0x21, 0x35, 0x93, 0x8E, 0xDA, 0xF0, 0x12, 0x82, 0x45, 0x1D, 0xB5, 0xC2, 0x7D, 0x6A, 0x27, 0xF9, 0xB9, 0xC9, + 0x9A, 0x09, 0x78, 0x4D, 0xE4, 0x72, 0xA6, 0x06, 0xBF, 0x8B, 0x62, 0x66, 0xDD, 0x30, 0xFD, 0xE2, 0x98, 0x25, 0xB3, + 0x10, 0x91, 0x22, 0x88, 0x36, 0xD0, 0x94, 0xCE, 0x8F, 0x96, 0xDB, 0xBD, 0xF1, 0xD2, 0x13, 0x5C, 0x83, 0x38, 0x46, + 0x40, 0x1E, 0x42, 0xB6, 0xA3, 0xC3, 0x48, 0x7E, 0x6E, 0x6B, 0x3A, 0x28, 0x54, 0xFA, 0x85, 0xBA, 0x3D, 0xCA, 0x5E, + 0x9B, 0x9F, 0x0A, 0x15, 0x79, 0x2B, 0x4E, 0xD4, 0xE5, 0xAC, 0x73, 0xF3, 0xA7, 0x57, 0x07, 0x70, 0xC0, 0xF7, 0x8C, + 0x80, 0x63, 0x0D, 0x67, 0x4A, 0xDE, 0xED, 0x31, 0xC5, 0xFE, 0x18, 0xE3, 0xA5, 0x99, 0x77, 0x26, 0xB8, 0xB4, 0x7C, + 0x11, 0x44, 0x92, 0xD9, 0x23, 0x20, 0x89, 0x2E, 0x37, 0x3F, 0xD1, 0x5B, 0x95, 0xBC, 0xCF, 0xCD, 0x90, 0x87, 0x97, + 0xB2, 0xDC, 0xFC, 0xBE, 0x61, 0xF2, 0x56, 0xD3, 0xAB, 0x14, 0x2A, 0x5D, 0x9E, 0x84, 0x3C, 0x39, 0x53, 0x47, 0x6D, + 0x41, 0xA2, 0x1F, 0x2D, 0x43, 0xD8, 0xB7, 0x7B, 0xA4, 0x76, 0xC4, 0x17, 0x49, 0xEC, 0x7F, 0x0C, 0x6F, 0xF6, 0x6C, + 0xA1, 0x3B, 0x52, 0x29, 0x9D, 0x55, 0xAA, 0xFB, 0x60, 0x86, 0xB1, 0xBB, 0xCC, 0x3E, 0x5A, 0xCB, 0x59, 0x5F, 0xB0, + 0x9C, 0xA9, 0xA0, 0x51, 0x0B, 0xF5, 0x16, 0xEB, 0x7A, 0x75, 0x2C, 0xD7, 0x4F, 0xAE, 0xD5, 0xE9, 0xE6, 0xE7, 0xAD, + 0xE8, 0x74, 0xD6, 0xF4, 0xEA, 0xA8, 0x50, 0x58, 0xAF, 0xFF, 0x01, 0x19, 0x02, 0x32, 0x1A, 0xC6, 0x03, 0xDF, 0x33, + 0xEE, 0x1B, 0x68, 0xC7, 0x4B, 0x04, 0x64, 0xE0, 0x0E, 0x34, 0x8D, 0xEF, 0x81, 0x1C, 0xC1, 0x69, 0xF8, 0xC8, 0x08, + 0x4C, 0x71, 0x05, 0x8A, 0x65, 0x2F, 0xE1, 0x24, 0x0F, 0x21, 0x35, 0x93, 0x8E, 0xDA, 0xF0, 0x12, 0x82, 0x45, 0x1D, + 0xB5, 0xC2, 0x7D, 0x6A, 0x27, 0xF9, 0xB9, 0xC9, 0x9A, 0x09, 0x78, 0x4D, 0xE4, 0x72, 0xA6, 0x06, 0xBF, 0x8B, 0x62, + 0x66, 0xDD, 0x30, 0xFD, 0xE2, 0x98, 0x25, 0xB3, 0x10, 0x91, 0x22, 0x88, 0x36, 0xD0, 0x94, 0xCE, 0x8F, 0x96, 0xDB, + 0xBD, 0xF1, 0xD2, 0x13, 0x5C, 0x83, 0x38, 0x46, 0x40, 0x1E, 0x42, 0xB6, 0xA3, 0xC3, 0x48, 0x7E, 0x6E, 0x6B, 0x3A, + 0x28, 0x54, 0xFA, 0x85, 0xBA, 0x3D, 0xCA, 0x5E, 0x9B, 0x9F, 0x0A, 0x15, 0x79, 0x2B, 0x4E, 0xD4, 0xE5, 0xAC, 0x73, + 0xF3, 0xA7, 0x57, 0x07, 0x70, 0xC0, 0xF7, 0x8C, 0x80, 0x63, 0x0D, 0x67, 0x4A, 0xDE, 0xED, 0x31, 0xC5, 0xFE, 0x18, + 0xE3, 0xA5, 0x99, 0x77, 0x26, 0xB8, 0xB4, 0x7C, 0x11, 0x44, 0x92, 0xD9, 0x23, 0x20, 0x89, 0x2E, 0x37, 0x3F, 0xD1, + 0x5B, 0x95, 0xBC, 0xCF, 0xCD, 0x90, 0x87, 0x97, 0xB2, 0xDC, 0xFC, 0xBE, 0x61, 0xF2, 0x56, 0xD3, 0xAB, 0x14, 0x2A, + 0x5D, 0x9E, 0x84, 0x3C, 0x39, 0x53, 0x47, 0x6D, 0x41, 0xA2, 0x1F, 0x2D, 0x43, 0xD8, 0xB7, 0x7B, 0xA4, 0x76, 0xC4, + 0x17, 0x49, 0xEC, 0x7F, 0x0C, 0x6F, 0xF6, 0x6C, 0xA1, 0x3B, 0x52, 0x29, 0x9D, 0x55, 0xAA, 0xFB, 0x60, 0x86, 0xB1, + 0xBB, 0xCC, 0x3E, 0x5A, 0xCB, 0x59, 0x5F, 0xB0, 0x9C, 0xA9, 0xA0, 0x51, 0x0B, 0xF5, 0x16, 0xEB, 0x7A, 0x75, 0x2C, + 0xD7, 0x4F, 0xAE, 0xD5, 0xE9, 0xE6, 0xE7, 0xAD, 0xE8, 0x74, 0xD6, 0xF4, 0xEA, 0xA8, 0x50, 0x58, 0xAF, 0xFF +}; + +block_param_form LEOc2_param; + +int leoC2_Correction(void) { + switch (LEOc2_param.err_num) { + case 0: + break; + case 1: + leoC2_single_ecc(); + break; + case 2: + leoC2_double_ecc(); + break; + case 3: + leoC2_3_ecc(); + break; + case 4: + leoC2_4_ecc(); + break; + default: + return 0xFFFF; + } + return 0; +} + +// static +void leoC2_single_ecc(void) { + u8* pointer; + unsigned int byte; + u8* p_s; + + if (LEOc2_param.err_pos[0] < 0x55) { + byte = LEOc2_param.bytes; + pointer = &LEOc2_param.pntr[(LEOc2_param.err_pos[0] + 1) * byte]; + p_s = LEOc2_param.c2buff_e; + + do { + *(--pointer) ^= *(p_s -= 4); + } while (--byte != 0); + } +} + +// static +void leoC2_double_ecc(void) { + unsigned int s0; + unsigned int error_k; + u8* pointer1; + u8* pointer2; + unsigned int k; + unsigned int m; + unsigned int a; + unsigned int d; + unsigned int byte; + u8* p_s; + + k = 0x58 - LEOc2_param.err_pos[0]; + m = 0x58 - LEOc2_param.err_pos[1]; + d = ganlog[k] ^ ganlog[m]; + d = glog[leoAlpha_div(1, d)]; + byte = LEOc2_param.bytes; + + if (LEOc2_param.err_pos[1] < 0x55) { + goto c2_2_2; + } + pointer2 = &LEO_TempBuffer[sizeof(LEO_TempBuffer)]; + if (LEOc2_param.err_pos[0] < 0x55) { + goto c2_2_1; + } + return; + +c2_2_2: + pointer2 = &LEOc2_param.pntr[(LEOc2_param.err_pos[1] + 1) * byte]; +c2_2_1: + pointer1 = &LEOc2_param.pntr[(LEOc2_param.err_pos[0] + 1) * byte]; + p_s = LEOc2_param.c2buff_e; + + do { + p_s -= 4; + s0 = p_s[0]; + if (s0 != 0) { + a = ganlog[m + glog[s0]] ^ p_s[1]; + } else { + a = p_s[1]; + } + pointer1--; + pointer2--; + if (a != 0) { + error_k = ganlog[glog[a] + d]; + *pointer1 ^= error_k; + *pointer2 ^= error_k ^ s0; + } else { + *pointer2 ^= s0; + } + } while (--byte != 0); +} + +// static +void leoC2_3_ecc(void) { + unsigned int s0; + unsigned int error_i; + unsigned int error_j; + unsigned int error_k; + u8* pointer1; + u8* pointer2; + u8* pointer3; + unsigned int byte; + unsigned int ii; + unsigned int jj; + unsigned int kk; + unsigned int c; + unsigned int f; + unsigned int o; + unsigned int b; + unsigned int d; + unsigned int h; + unsigned int a; + unsigned int e; + unsigned int g; + unsigned int p; + u8* p_s; + + ii = 0x58 - LEOc2_param.err_pos[0]; + jj = 0x58 - LEOc2_param.err_pos[1]; + kk = 0x58 - LEOc2_param.err_pos[2]; + ii = ganlog[ii]; + jj = ganlog[jj]; + kk = ganlog[kk]; + c = leoAlpha_mult(kk, kk); + f = leoAlpha_mult(jj, jj); + o = leoAlpha_mult(ii, ii); + b = c ^ f; + d = c ^ o; + h = f ^ o; + a = leoAlpha_mult(jj, c) ^ leoAlpha_mult(kk, f); + e = leoAlpha_mult(kk, o) ^ leoAlpha_mult(ii, c); + g = leoAlpha_mult(jj, o) ^ leoAlpha_mult(ii, f); + c = jj ^ kk; + f = kk ^ ii; + o = ii ^ jj; + p = a ^ e ^ g; + p = leoAlpha_div(1, p); + a = glog[a]; + b = glog[b]; + c = glog[c]; + d = glog[d]; + e = glog[e]; + f = glog[f]; + g = glog[g]; + h = glog[h]; + o = glog[o]; + p = glog[p]; + byte = LEOc2_param.bytes; + if (LEOc2_param.err_pos[2] < 0x55) { + goto c2_3_3; + } + pointer3 = &LEO_TempBuffer[sizeof(LEO_TempBuffer)]; + if (LEOc2_param.err_pos[1] < 0x55) { + goto c2_3_2; + } + pointer2 = &LEO_TempBuffer[sizeof(LEO_TempBuffer)]; + if (LEOc2_param.err_pos[0] < 0x55) { + goto c2_3_1; + } + return; + +c2_3_3: + pointer3 = &LEOc2_param.pntr[(LEOc2_param.err_pos[2] + 1) * byte]; +c2_3_2: + pointer2 = &LEOc2_param.pntr[(LEOc2_param.err_pos[1] + 1) * byte]; +c2_3_1: + pointer1 = &LEOc2_param.pntr[(LEOc2_param.err_pos[0] + 1) * byte]; + p_s = LEOc2_param.c2buff_e; + + do { + p_s -= 4; + s0 = p_s[0]; + if (s0) { + s0 = glog[s0]; + error_i = ganlog[s0 + a]; + error_j = ganlog[s0 + e]; + error_k = ganlog[s0 + g]; + } else { + error_i = error_j = error_k = 0; + } + s0 = p_s[1]; + if (s0) { + s0 = glog[s0]; + error_i ^= ganlog[s0 + b]; + error_j ^= ganlog[s0 + d]; + error_k ^= ganlog[s0 + h]; + } + s0 = p_s[2]; + if (s0) { + s0 = glog[s0]; + error_i ^= ganlog[s0 + c]; + error_j ^= ganlog[s0 + f]; + error_k ^= ganlog[s0 + o]; + } + pointer1--; + pointer2--; + pointer3--; + if (error_i) { + *pointer1 ^= ganlog[glog[error_i] + p]; + } + if (error_j) { + *pointer2 ^= ganlog[glog[error_j] + p]; + } + if (error_k) { + *pointer3 ^= ganlog[glog[error_k] + p]; + } + } while (--byte != 0); +} + +// static +void leoC2_4_ecc(void) { + unsigned int s0; + unsigned int R0; + unsigned int R1; + unsigned int R2; + unsigned int R3; + u8* pointer1; + u8* pointer2; + u8* pointer3; + u8* pointer4; + unsigned int aa; + unsigned int bb; + unsigned int dd; + unsigned int ee; + unsigned int gg; + unsigned int hh; + unsigned int pp; + unsigned int qq; + unsigned int ll; + unsigned int ii; + unsigned int jj; + unsigned int kk; + unsigned int byte; + unsigned int s; + unsigned int a; + unsigned int e; + unsigned int g; + unsigned int p; + unsigned int c; + unsigned int f; + unsigned int o; + unsigned int r; + unsigned int t; + unsigned int u; + unsigned int v; + unsigned int b; + unsigned int d; + unsigned int h; + unsigned int q; + u8* p_s; + + ii = 0x58 - LEOc2_param.err_pos[0]; + jj = 0x58 - LEOc2_param.err_pos[1]; + kk = 0x58 - LEOc2_param.err_pos[2]; + ll = 0x58 - LEOc2_param.err_pos[3]; + + ii = ganlog[ii]; + jj = ganlog[jj]; + kk = ganlog[kk]; + ll = ganlog[ll]; + s = ganlog[0]; + + aa = leoAlpha_div(s, ii); + bb = leoAlpha_div(s, jj); + ee = leoAlpha_div(s, kk); + dd = leoAlpha_div(s, ll); + + a = leoAlpha_mult(bb, ee); + e = leoAlpha_mult(ee, dd); + g = leoAlpha_mult(dd, bb); + p = leoAlpha_mult(dd, aa); + c = leoAlpha_mult(aa, ee); + f = leoAlpha_mult(aa, bb); + + b = a ^ e ^ g; + d = e ^ p ^ c; + h = p ^ f ^ g; + q = f ^ a ^ c; + a = bb ^ ee ^ dd; + e = ee ^ dd ^ aa; + g = dd ^ aa ^ bb; + p = aa ^ bb ^ ee; + + c = leoAlpha_mult(leoAlpha_mult(bb, ee), dd); + f = leoAlpha_mult(leoAlpha_mult(ee, dd), aa); + o = leoAlpha_mult(leoAlpha_mult(dd, aa), bb); + r = leoAlpha_mult(leoAlpha_mult(aa, bb), ee); + + s = leoAlpha_mult(leoAlpha_mult(leoAlpha_div(ii, jj) ^ 1, leoAlpha_div(ii, kk) ^ 1), leoAlpha_div(ii, ll) ^ 1); + s = leoAlpha_div(1, s); + t = leoAlpha_mult(leoAlpha_mult(leoAlpha_div(jj, ii) ^ 1, leoAlpha_div(jj, kk) ^ 1), leoAlpha_div(jj, ll) ^ 1); + t = leoAlpha_div(1, t); + u = leoAlpha_mult(leoAlpha_mult(leoAlpha_div(kk, ii) ^ 1, leoAlpha_div(kk, jj) ^ 1), leoAlpha_div(kk, ll) ^ 1); + u = leoAlpha_div(1, u); + v = leoAlpha_mult(leoAlpha_mult(leoAlpha_div(ll, ii) ^ 1, leoAlpha_div(ll, jj) ^ 1), leoAlpha_div(ll, kk) ^ 1); + v = leoAlpha_div(1, v); + + aa = glog[leoAlpha_mult(a, s)]; + bb = glog[leoAlpha_mult(b, s)]; + c = leoAlpha_mult(c, s); + ee = glog[leoAlpha_mult(e, t)]; + dd = glog[leoAlpha_mult(d, t)]; + f = leoAlpha_mult(f, t); + gg = glog[leoAlpha_mult(g, u)]; + hh = glog[leoAlpha_mult(h, u)]; + o = leoAlpha_mult(o, u); + pp = glog[leoAlpha_mult(p, v)]; + qq = glog[leoAlpha_mult(q, v)]; + r = leoAlpha_mult(r, v); + + s = glog[s]; + c = glog[c]; + t = glog[t]; + f = glog[f]; + u = glog[u]; + o = glog[o]; + v = glog[v]; + r = glog[r]; + + byte = LEOc2_param.bytes; + + if (LEOc2_param.err_pos[3] < 0x55) { + goto c2_4_4; + } + pointer4 = &LEO_TempBuffer[sizeof(LEO_TempBuffer)]; + if (LEOc2_param.err_pos[2] < 0x55) { + goto c2_4_3; + } + pointer3 = &LEO_TempBuffer[sizeof(LEO_TempBuffer)]; + if (LEOc2_param.err_pos[1] < 0x55) { + goto c2_4_2; + } + pointer2 = &LEO_TempBuffer[sizeof(LEO_TempBuffer)]; + if (LEOc2_param.err_pos[0] < 0x55) { + goto c2_4_1; + } + return; + +c2_4_4: + pointer4 = &LEOc2_param.pntr[(LEOc2_param.err_pos[3] + 1) * byte]; +c2_4_3: + pointer3 = &LEOc2_param.pntr[(LEOc2_param.err_pos[2] + 1) * byte]; +c2_4_2: + pointer2 = &LEOc2_param.pntr[(LEOc2_param.err_pos[1] + 1) * byte]; +c2_4_1: + pointer1 = &LEOc2_param.pntr[(LEOc2_param.err_pos[0] + 1) * byte]; + p_s = LEOc2_param.c2buff_e; + + do { + p_s -= 4; + s0 = p_s[0]; + if (!s0) { + R0 = R1 = R2 = R3 = 0; + } else { + s0 = glog[s0]; + R0 = ganlog[s0 + s]; + R1 = ganlog[s0 + t]; + R2 = ganlog[s0 + u]; + R3 = ganlog[s0 + v]; + } + s0 = p_s[1]; + if (s0) { + s0 = glog[s0]; + R0 ^= (!a) ? 0 : ganlog[s0 + aa]; + R1 ^= (!e) ? 0 : ganlog[s0 + ee]; + R2 ^= (!g) ? 0 : ganlog[s0 + gg]; + R3 ^= (!p) ? 0 : ganlog[s0 + pp]; + } + s0 = p_s[2]; + if (s0) { + s0 = glog[s0]; + R0 ^= (!b) ? 0 : ganlog[s0 + bb]; + R1 ^= (!d) ? 0 : ganlog[s0 + dd]; + R2 ^= (!h) ? 0 : ganlog[s0 + hh]; + R3 ^= (!q) ? 0 : ganlog[s0 + qq]; + } + s0 = p_s[3]; + if (s0) { + s0 = glog[s0]; + R0 ^= ganlog[s0 + c]; + R1 ^= ganlog[s0 + f]; + R2 ^= ganlog[s0 + o]; + R3 ^= ganlog[s0 + r]; + } + pointer1--; + pointer2--; + pointer3--; + pointer4--; + if (R0) { + *pointer1 ^= R0; + } + if (R1) { + *pointer2 ^= R1; + } + if (R2) { + *pointer3 ^= R2; + } + if (R3) { + *pointer4 ^= R3; + } + } while (--byte != 0); +} + +// static +int leoAlpha_mult(int i, int k) { + if (i == 0 || k == 0) { + return 0; + } + return ganlog[glog[i] + glog[k]]; +} + +// static +int leoAlpha_div(int i, int k) { + if (i == 0 || k == 0) { + return 0; + } + return ganlog[0xFF + (glog[i] - glog[k])]; +} diff --git a/src/libleo/leo/leocmdex.c b/src/libleo/leo/leocmdex.c new file mode 100644 index 0000000000..ca3101fb0a --- /dev/null +++ b/src/libleo/leo/leocmdex.c @@ -0,0 +1,262 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +extern vu16 LEOrw_flags; + +static void (*cmd_tbl[16])(void) = { + NULL, leoClr_queue, leoInquiry, leoTest_unit_rdy, leoRezero, leoRead, + leoWrite, leoSeek, leoStart_stop, leoRd_capacity, leoTranslate, leoMode_sel, + leoReadDiskId, leoReadTimer, leoSetTimer, leoClr_reset, +}; + +static LEOCmdRead system_read_cmd = { + { LEO_COMMAND_READ, 0, 0, 0, 0, 0, 0, 0, 0 }, 12, 1, 0, 0, +}; + +static const u8 system_lba[8] = { 0, 1, 8, 9, 0, 0, 0, 0 }; + +OSPiHandle* LEOPiInfo; +OSIoMesg LEOPiDmaParam; +s32 currentCommand; + +u8 leoRead_system_area(void); + +void leomain(void* arg0) { + u32 cur_status; + u32 sense_code; + u8 disktype_bak; + + ((u8*)&LEO_country_code)[0] = *(vu8*)OS_PHYSICAL_TO_K1(0x10); + ((u8*)&LEO_country_code)[1] = *(vu8*)OS_PHYSICAL_TO_K1(0x90); + ((u8*)&LEO_country_code)[2] = *(vu8*)OS_PHYSICAL_TO_K1(0x110); + ((u8*)&LEO_country_code)[3] = *(vu8*)OS_PHYSICAL_TO_K1(0x190); + + LEOasic_seq_ctl_shadow = 0; + LEOasic_bm_ctl_shadow = 0; + LEOdrive_flag = 0; + LEOclr_que_flag = 0; + leoInitUnit_atten(); + LEOPiInfo = osLeoDiskInit(); + LEOPiDmaParam.hdr.pri = 1; + LEOPiDmaParam.hdr.retQueue = &LEOdma_que; + osEPiReadIo(LEOPiInfo, ASIC_STATUS, &cur_status); + if (!(cur_status & 0x400000) && (cur_status & 0x06800000)) { + leoDrive_reset(); + } + + while (true) { + osRecvMesg(&LEOcommand_que, (OSMesg*)&LEOcur_command, OS_MESG_BLOCK); + currentCommand = LEOcur_command->header.command; + if (LEOcur_command->header.command == 0) { + leoDrive_reset(); + osRecvMesg(&LEOevent_que, NULL, OS_MESG_NOBLOCK); + continue; + } + + sense_code = leoChk_asic_ready(0x10001); + cur_status = leoChkUnit_atten(); + + do { + if (cur_status == 0) { + if (sense_code == 0) { + continue; + } + } else { + switch (sense_code) { + case 3: + case 37: + case 41: + case 43: + break; + case 49: + if (leoRetUnit_atten() == 43) { + sense_code = 43; + } + break; + default: + sense_code = leoRetUnit_atten(); + } + } + + switch (sense_code) { + case 47: + switch (LEOcur_command->header.command) { + case 2: + case 8: + case 11: + case 12: + case 13: + case 14: + case 15: + continue; + } + break; + case 49: + switch (LEOcur_command->header.command) { + case 2: + case 11: + case 13: + case 14: + case 15: + continue; + default: + sense_code = 42; + } + break; + case 43: + switch (LEOcur_command->header.command) { + case 15: + leoClrUA_RESET(); + FALLTHROUGH; + case 2: + case 13: + case 14: + continue; + } + break; + default: + /* empty */; + } + + if (LEOcur_command->header.command == 3) { + LEOcur_command->data.modeSelect.reserve1 = leoChk_cur_drvmode(); + } + LEOcur_command->header.sense = sense_code; + LEOcur_command->header.status = 2; + goto post_exe; + } while (0); + + if (LEOdrive_flag == 0) { + switch (LEOcur_command->header.command) { + case 2: + case 3: + case 8: + case 11: + case 13: + case 14: + case 15: + break; + default: + if (LEO_country_code == 0) { + osEPiReadIo(LEOPiInfo, ASIC_ID_REG, &cur_status); + if ((cur_status & 0x70000) != 0x40000) { + while (true) {} + } + } + + if (leoRead_system_area() != 0) { + LEOcur_command->header.status = 2; + goto post_exe; + } + + if ((LEOcur_command->header.sense = + leoSend_asic_cmd_w(0xB0001, LEO_sys_data.param.disk_type << 16)) != 0) { + LEOcur_command->header.status = 2; + goto post_exe; + } + + if ((LEO_sys_data.param.disk_type & 0xF0) != 0x10) { + goto invalid_disktype; + } + + LEOdisk_type = (LEO_sys_data.param.disk_type & 0xF); + if (LEOdisk_type >= 7) { + invalid_disktype: + LEOcur_command->header.sense = 0xBU; + LEOcur_command->header.status = 2; + goto post_exe; + } + + LEOdrive_flag = -1; + } + } + + cmd_tbl[LEOcur_command->header.command](); + + post_exe: + if (LEOcur_command->header.control & 0x80) { + osSendMesg(LEOcur_command->header.post, (void*)(s32)LEOcur_command->header.sense, OS_MESG_BLOCK); + } + if (LEOclr_que_flag != 0) { + leoClr_queue(); + } + } +} + +u8 leoRead_system_area(void) { + LEOCmdRead dummy_cmd; + void* backup_pointer; + u32 retry_cntr; + s32 read_mode; + + backup_pointer = LEOcur_command; + LEOcur_command = (LEOCmd*)&dummy_cmd; + read_mode = 0; + retry_cntr = 0; + + while (true) { + LEOdisk_type = 0; + // For lba_to_phys to avoid dealing with alternative tracks on the disk + LEO_sys_data.param.defect_num[0] = 0; + LEOrw_flags = 0x3000; + dummy_cmd = system_read_cmd; + dummy_cmd.buffPtr = &LEO_sys_data; + + if (read_mode == 0) { + // read System LBA 12 (+0, this is an offset value for leoRead_common) + // see system_read_cmd premade struct + leoRead_common(0); + switch (dummy_cmd.header.sense) { + case LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION: + do { + // if expecting a retail disk, LBA 12 is expected to do a read error, if not then freeze + } while (LEO_country_code != 0); + retry_cntr = 0; + read_mode--; + continue; + case LEO_SENSE_UNRECOVERED_READ_ERROR: + do { + // if expecting a development disk, LBA 12 is expected to read correctly, if not then freeze + } while (LEO_country_code == 0); + retry_cntr = 0; + read_mode--; + continue; + } + } else { + // read System LBA 0,1,8,9 (or 2,3,10,11 for dev) + dummy_cmd.lba = system_lba[retry_cntr & 3]; + if (LEO_country_code == 0) { + dummy_cmd.lba += 2; + } + leoRead_common(0); + if (dummy_cmd.header.status == LEO_STATUS_GOOD) { + do { + // if disk country and set country code in libleo mismatch, then freeze + } while (LEO_sys_data.param.country != LEO_country_code); + goto sys_read_end; + } + } + + system_retry: + if (leoChk_err_retry(dummy_cmd.header.sense) != LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION) { + break; + } + if (retry_cntr++ >= 0x40U) { + break; + } + if ((retry_cntr & 7) == 0) { + // Recalibrate drive every 8th tries + if ((dummy_cmd.header.sense = leoSend_asic_cmd_w(0x30001, 0)) == LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION) { + continue; + } + goto system_retry; + } + } + +sys_read_end: + LEOcur_command = backup_pointer; + LEOcur_command->header.sense = dummy_cmd.header.sense; + return GET_ERROR(*LEOcur_command); +} diff --git a/src/libleo/leo/leodiskinit.c b/src/libleo/leo/leodiskinit.c new file mode 100644 index 0000000000..6c11f728e2 --- /dev/null +++ b/src/libleo/leo/leodiskinit.c @@ -0,0 +1,33 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +extern OSPiHandle* __osPiTable; + +OSPiHandle __LeoDiskHandle; +OSPiHandle* __osDiskHandle; + +OSPiHandle* osLeoDiskInit(void) { + u32 saveMask; + + __LeoDiskHandle.type = DEVICE_TYPE_64DD; + __LeoDiskHandle.baseAddress = (u32)OS_PHYSICAL_TO_K1(ASIC_C2_BUFF); + __LeoDiskHandle.latency = 3; + __LeoDiskHandle.pulse = 6; + __LeoDiskHandle.pageSize = 6; + __LeoDiskHandle.relDuration = 2; + __LeoDiskHandle.domain = PI_DOMAIN2; + __LeoDiskHandle.speed = 0; + + bzero(&__LeoDiskHandle.transferInfo, sizeof(__OSTranxInfo)); + saveMask = __osDisableInt(); + + __LeoDiskHandle.next = __osPiTable; + __osPiTable = &__LeoDiskHandle; + __osDiskHandle = &__LeoDiskHandle; + + __osRestoreInt(saveMask); + + return &__LeoDiskHandle; +} diff --git a/src/libleo/leo/leofunc.c b/src/libleo/leo/leofunc.c new file mode 100644 index 0000000000..20809e55f6 --- /dev/null +++ b/src/libleo/leo/leofunc.c @@ -0,0 +1,134 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +static s32 __leoResetCalled = false; +static s32 __leoQueuesCreated = false; + +static OSMesgQueue LEOpost_que; +static OSMesg LEOpost_que_buf[1]; + +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, STACK_TOP(LEOcommandThreadStack), compri); + osStartThread(&LEOcommandThread); + osCreateThread(&LEOinterruptThread, 1, leointerrupt, NULL, STACK_TOP(LEOinterruptThreadStack), intpri); + osStartThread(&LEOinterruptThread); + osSetEventMesg(2, &LEOevent_que, (OSMesg)0x30000); + osSendMesg(&LEOblock_que, NULL, OS_MESG_NOBLOCK); + __osRestoreInt(savedMask); + + if (oldPri != -1) { + osSetThreadPri(NULL, oldPri); + } +} + +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, OS_MESG_BLOCK); + } + return; + } + osRecvMesg(&LEOblock_que, NULL, OS_MESG_BLOCK); + ((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, OS_MESG_BLOCK); + } + break; + + case 5: + case 6: + ((LEOCmd*)cmd_blk_addr)->data.readWrite.rwBytes = 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, OS_MESG_NOBLOCK) != 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, OS_MESG_BLOCK); +} + +static const u8 zero[] = { 0 }; + +void LeoReset(void) { + __leoResetCalled = true; + if (__leoQueuesCreated) { + LEOclr_que_flag = 0xFF; + leoClr_queue(); + LEOclr_que_flag = 0; + osRecvMesg(&LEOevent_que, NULL, OS_MESG_NOBLOCK); + osSendMesg(&LEOevent_que, (OSMesg)0xA0000, OS_MESG_BLOCK); + osSendMesg(&LEOcommand_que, (OSMesg)zero, OS_MESG_BLOCK); + } +} + +s32 __leoSetReset(void) { + leoDrive_reset(); + return 0; +} + +// SENSE or ERROR? +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, OS_MESG_NOBLOCK) != 0) { + return LEO_SENSE_QUEUE_FULL; + } + osRecvMesg(&LEOpost_que, NULL, OS_MESG_BLOCK); + if (resetclear.status == LEO_STATUS_GOOD) { + return LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + } + return resetclear.sense; +} diff --git a/src/libleo/leo/leoglobals.c b/src/libleo/leo/leoglobals.c new file mode 100644 index 0000000000..ca11ec6c4e --- /dev/null +++ b/src/libleo/leo/leoglobals.c @@ -0,0 +1,8 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +s32 __leoActive = false; + +LEOVersion __leoVersion; diff --git a/src/libleo/leo/leoinquiry.c b/src/libleo/leo/leoinquiry.c new file mode 100644 index 0000000000..cfa4f1c27f --- /dev/null +++ b/src/libleo/leo/leoinquiry.c @@ -0,0 +1,23 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +void leoInquiry(void) { + u32 asic_id; + u32 asic_data; + + osEPiReadIo(LEOPiInfo, ASIC_ID_REG, &asic_id); + if (leoSend_asic_cmd_w(0x1B0000, 0) == 0) { + osEPiReadIo(LEOPiInfo, ASIC_DATA, &asic_data); + if (asic_data & 0x10000) { + asic_id |= 0x100000; + } + } + + ((LEOCmdInquiry*)LEOcur_command)->devType = 0; + ((LEOCmdInquiry*)LEOcur_command)->version = asic_id >> 0x10; + ((LEOCmdInquiry*)LEOcur_command)->devNum = 1; + ((LEOCmdInquiry*)LEOcur_command)->leoBiosVer = 0; + LEOcur_command->header.status = LEO_STATUS_GOOD; +} diff --git a/src/libleo/leo/leoint.c b/src/libleo/leo/leoint.c new file mode 100644 index 0000000000..f337b15080 --- /dev/null +++ b/src/libleo/leo/leoint.c @@ -0,0 +1,298 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +extern vu16 LEOrw_flags; + +extern u8 LEOC2_Syndrome[2][0xE8 * 4]; +extern OSIoMesg LEOPiDmaParam; +extern block_param_form LEOc2_param; + +u8 LEOc2ctrl_que_buf[8]; +OSMesgQueue LEOc2ctrl_que; + +u32 read_write_track(void); +u32 leoChk_mecha_int(void); +void leosetup_BM(void); +u32 leochk_err_reg(void); + +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.transferBlks; + LEOwrite_pointer = LEOcur_command->data.readWrite.buffPtr; + + 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.rwBytes = LEOwrite_pointer - (u8*)LEOcur_command->data.readWrite.buffPtr; + } while (tg_blocks != 0); + result = 0x90000; // Inaccessible? + + complete: + osSendMesg(&LEOcontrol_que, (OSMesg)result, OS_MESG_BLOCK); + } +} + +// static +u32 read_write_track(void) { + u32 message; + u32 block; + u32 retry_cntr; + block_param_form block_param; + + block_param.bytes = LEOtgt_param.sec_bytes; + block_param.blkbytes = LEOtgt_param.blk_bytes; + if (LEOrw_flags & 0x2000) { + // Sector Mode + block_param.blkbytes = block_param.bytes; + } + block_param.pntr = LEOwrite_pointer; + LEOwrite_pointer += block_param.blkbytes; + if (LEOtgt_param.rdwr_blocks == 2) { + LEOwrite_pointer += block_param.blkbytes; + } + retry_cntr = 0; + for (;;) { + LEOPiInfo->transferInfo.transferMode = 1; + LEOPiInfo->transferInfo.blockNum = 0; + LEOPiInfo->transferInfo.block[0].C1ErrNum = 0; + LEOPiInfo->transferInfo.block[0].sectorSize = block_param.bytes; + LEOPiInfo->transferInfo.block[0].dramAddr = block_param.pntr; + LEOPiInfo->transferInfo.block[0].C2Addr = &LEOC2_Syndrome[0]; + if (LEOrw_flags & 0x2000) { + // Sector Mode + LEOtgt_param.rdwr_blocks = 1; + LEOPiInfo->transferInfo.transferMode = 3; + } else if (LEOtgt_param.rdwr_blocks == 2) { + LEOPiInfo->transferInfo.transferMode = 2; + LEOPiInfo->transferInfo.block[1] = LEOPiInfo->transferInfo.block[0]; + LEOPiInfo->transferInfo.block[1].C2Addr = &LEOC2_Syndrome[1]; + LEOPiInfo->transferInfo.block[1].dramAddr = + ((u8*)LEOPiInfo->transferInfo.block[1].dramAddr + block_param.blkbytes); + } + message = leoChk_mecha_int(); + if (message == 0) { + if (LEOrw_flags & 0x8000) { + // Write Mode + leoSet_mseq(1); + } else { + // Read Mode + leoSet_mseq(0); + } + leosetup_BM(); + LEOPiInfo->transferInfo.bmCtlShadow = LEOasic_bm_ctl_shadow; + LEOPiInfo->transferInfo.seqCtlShadow = LEOasic_seq_ctl_shadow; + if (LEOrw_flags & 0x8000) { + u16 bnum; + + LEOPiInfo->transferInfo.cmdType = 1; + osWritebackDCache(block_param.pntr, block_param.blkbytes * LEOtgt_param.rdwr_blocks); + osEPiStartDma(LEOPiInfo, &LEOPiDmaParam, 1); + osRecvMesg(&LEOdma_que, NULL, OS_MESG_BLOCK); + LEOasic_bm_ctl_shadow = LEOPiInfo->transferInfo.bmCtlShadow; + LEOasic_seq_ctl_shadow = LEOPiInfo->transferInfo.seqCtlShadow; + bnum = LEOPiInfo->transferInfo.blockNum; + message = LEOPiInfo->transferInfo.block[bnum].errStatus; + if (message == 0) { + return message; + } + goto track_end; + } else { + if (LEOrw_flags & 0x4000) { + osRecvMesg(&LEOc2ctrl_que, NULL, OS_MESG_BLOCK); + osSendMesg(&LEOc2ctrl_que, NULL, OS_MESG_NOBLOCK); + } + LEOPiInfo->transferInfo.cmdType = 0; + osInvalDCache(block_param.pntr, block_param.blkbytes * LEOtgt_param.rdwr_blocks); + osEPiStartDma(LEOPiInfo, &LEOPiDmaParam, 0); + block = 0; + while (LEOtgt_param.rdwr_blocks != 0) { + osRecvMesg(&LEOdma_que, NULL, OS_MESG_BLOCK); + LEOasic_bm_ctl_shadow = LEOPiInfo->transferInfo.bmCtlShadow; + LEOasic_seq_ctl_shadow = LEOPiInfo->transferInfo.seqCtlShadow; + message = LEOPiInfo->transferInfo.block[block].errStatus; + if (message != 0) { + goto track_end; + } + if (LEOrw_flags & 0x2000) { + return 0; + } + if (LEOPiInfo->transferInfo.block[block].C1ErrNum) { + if (LEOPiInfo->transferInfo.block[block].C1ErrSector[0] < 0x55) { + u8* temp; + u32 c2datasize; + + if (LEOtgt_param.rdwr_blocks == 1) { + osEPiReadIo(LEOPiInfo, ASIC_ERR_SECTOR, &message); + if (message & 0x10000000) { + message = 4; + goto track_end; + } + } + + if (block == 0) { + temp = LEOC2_Syndrome[0]; + } else { + temp = LEOC2_Syndrome[1]; + } + c2datasize = block_param.bytes * 4; + block_param.c2buff_e = temp + c2datasize; + osInvalDCache(temp, c2datasize); + block_param.err_num = LEOPiInfo->transferInfo.block[block].C1ErrNum; + block_param.err_pos[0] = LEOPiInfo->transferInfo.block[block].C1ErrSector[0]; + block_param.err_pos[1] = LEOPiInfo->transferInfo.block[block].C1ErrSector[1]; + block_param.err_pos[2] = LEOPiInfo->transferInfo.block[block].C1ErrSector[2]; + block_param.err_pos[3] = LEOPiInfo->transferInfo.block[block].C1ErrSector[3]; + osRecvMesg(&LEOc2ctrl_que, NULL, OS_MESG_BLOCK); + LEOrw_flags |= 0x4000; + LEOc2_param = block_param; + osSendMesg(&LEOcontrol_que, (OSMesg)0x80000, OS_MESG_BLOCK); + } + } else { + if (LEOtgt_param.rdwr_blocks == 1) { + if ((*(u32*)&LEOC2_Syndrome[block][0x00] | *(u32*)&LEOC2_Syndrome[block][0x04] | + *(u32*)&LEOC2_Syndrome[block][0x08] | *(u32*)&LEOC2_Syndrome[block][0x0C]) != 0) { + message = 0x17; + goto track_end; + } + } + } + block++; + block_param.pntr += block_param.blkbytes; + LEOtgt_param.start_block ^= 1; + LEOtgt_param.rdwr_blocks--; + } + } + return 0; + } + track_end: + if (message == 0x16) { + message = leochk_err_reg(); + } + do_retry: + if (leoChk_err_retry(message) || (LEOrw_flags & 0x1000) || retry_cntr++ == 0x40) { + break; + } + if ((retry_cntr & 7) == 0) { + message = leoSend_asic_cmd_w(0x30001, 0); + if (message != 0) { + goto do_retry; + } + } + if (message == 0x18 || (message == 0x17 && retry_cntr == 0x20)) { + message = leoDetect_index_w(); + if (message != 0) { + goto do_retry; + } + } + if (LEOrw_flags & 0x8000) { + message = leoSeek_i(1); + } else { + message = leoSeek_i(0); + } + if (message != 0) { + goto do_retry; + } + } + return message; +} + +// static +u32 leoChk_mecha_int(void) { + u32 stat = leoWait_mecha_cmd_done(0x10001); + u32 index_stat; + + if (stat == 0) { + osEPiReadIo(LEOPiInfo, ASIC_CUR_TK, &index_stat); + if ((index_stat & 0x60000000) != 0x60000000) { + stat = 0x18; + } + } + return stat; +} + +// static +void leosetup_BM(void) { + osEPiWriteIo(LEOPiInfo, ASIC_BM_CTL, LEOasic_bm_ctl_shadow | 0x10000000); + osEPiWriteIo(LEOPiInfo, ASIC_BM_CTL, 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, ASIC_BM_CTL, LEOasic_bm_ctl_shadow); +} + +// static +u32 leochk_err_reg(void) { + u32 sense; + u32 index_status; + + osEPiReadIo(LEOPiInfo, ASIC_ERR_SECTOR, &sense); + osEPiWriteIo(LEOPiInfo, ASIC_BM_CTL, LEOasic_bm_ctl_shadow | 0x10000000); + osEPiWriteIo(LEOPiInfo, ASIC_BM_CTL, LEOasic_bm_ctl_shadow); + + if (sense & 0x04000000) { + return LEO_ERROR_EJECTED_ILLEGALLY_RESUME; + } + + if (sense & 0x10000000) { + return LEO_ERROR_DATA_PHASE_ERROR; + } + + if (sense & (0x40000000 | 0x2000000)) { + if (LEOrw_flags & 0x8000) { + return LEO_ERROR_WRITE_FAULT; + } + return LEO_ERROR_UNRECOVERED_READ_ERROR; + } + + if (sense & 0x80000000) { + return LEO_ERROR_NO_REFERENCE_POSITION_FOUND; + } + + osEPiReadIo(LEOPiInfo, ASIC_CUR_TK, &index_status); + if ((index_status & 0x60000000) == 0x60000000) { + return LEO_ERROR_TRACK_FOLLOWING_ERROR; + } + + return LEO_ERROR_NO_REFERENCE_POSITION_FOUND; +} diff --git a/src/libleo/leo/leointerrupt.c b/src/libleo/leo/leointerrupt.c new file mode 100644 index 0000000000..e11d345080 --- /dev/null +++ b/src/libleo/leo/leointerrupt.c @@ -0,0 +1,208 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" +#include "ultra64/internal.h" + +extern OSThread* __osRunQueue; +extern OSHWIntr __OSGlobalIntMask; +void __osLeoAbnormalResume(void); +void __osLeoResume(void); + +STACK(leoDiskStack, 0xFF0); + +s32 __osLeoInterrupt(void) { + u32 stat = 0; + volatile u32 pi_stat; + u32 bm_stat; + __OSTranxInfo* info = &__osDiskHandle->transferInfo; + __OSBlockInfo* blockInfo = &info->block[info->blockNum]; + + pi_stat = IO_READ(PI_STATUS_REG); + if (pi_stat & PI_STATUS_DMA_BUSY) { + __OSGlobalIntMask &= ~0x800; + blockInfo->errStatus = 0x1D; + __osLeoResume(); + return 1; + } + + pi_stat = IO_READ(PI_STATUS_REG); + while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + pi_stat = IO_READ(PI_STATUS_REG); + } + + stat = IO_READ(ASIC_STATUS); + if (stat & 0x2000000) { + pi_stat = IO_READ(PI_STATUS_REG); + while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + pi_stat = IO_READ(PI_STATUS_REG); + } + + IO_WRITE(ASIC_BM_CTL, info->bmCtlShadow | 0x1000000); + blockInfo->errStatus = 0; + return 0; + } + if (info->cmdType == 2) { + return 1; + } + if (stat & 0x8000000) { + pi_stat = IO_READ(PI_STATUS_REG); + while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + pi_stat = IO_READ(PI_STATUS_REG); + } + + stat = IO_READ(ASIC_STATUS); + blockInfo->errStatus = 0x16; + __osLeoResume(); + IO_WRITE(PI_STATUS_REG, 2); + __OSGlobalIntMask |= 0x100401; + return 1; + } + if (info->cmdType == 1) { + if (!(stat & 0x40000000)) { + if ((info->sectorNum + 1) != (info->transferMode * 0x55)) { + blockInfo->errStatus = 0x18; + __osLeoAbnormalResume(); + return 1; + } + IO_WRITE(PI_STATUS_REG, 2); + __OSGlobalIntMask |= 0x100401; + blockInfo->errStatus = 0; + __osLeoResume(); + return 1; + } else { + blockInfo->dramAddr = (u8*)(blockInfo->dramAddr) + blockInfo->sectorSize; + info->sectorNum++; + __osEPiRawStartDma(__osDiskHandle, 1, ASIC_SECTOR_BUFF, blockInfo->dramAddr, blockInfo->sectorSize); + return 1; + } + } else if (info->cmdType == 0) { + if (info->transferMode == 3) { + if (((s32)blockInfo->C1ErrNum + 0x11) < info->sectorNum) { + blockInfo->errStatus = 0; + __osLeoAbnormalResume(); + return 1; + } + if ((stat & 0x40000000) == 0) { + blockInfo->errStatus = 0x17; + __osLeoAbnormalResume(); + return 1; + } + } else { + blockInfo->dramAddr = (u8*)(blockInfo->dramAddr) + blockInfo->sectorSize; + } + + bm_stat = IO_READ(ASIC_BM_STATUS); + if (((bm_stat & 0x200000) && (bm_stat & 0x400000)) || (bm_stat & 0x2000000)) { + if (blockInfo->C1ErrNum >= 4) { + if ((info->transferMode != 3) || (info->sectorNum >= 0x53)) { + blockInfo->errStatus = 0x17; + __osLeoAbnormalResume(); + return 1; + } + } else { + int errNum = blockInfo->C1ErrNum; + + blockInfo->C1ErrSector[errNum] = info->sectorNum + 1; + } + blockInfo->C1ErrNum++; + } + + if (stat & 0x10000000) { + if (info->sectorNum != 0x57) { + blockInfo->errStatus = 0x18; + __osLeoAbnormalResume(); + return 1; + } + if ((info->transferMode == 2) && (info->blockNum == 0)) { + info->blockNum = 1; + info->sectorNum = -1; + info->block[1].dramAddr = (u8*)(info->block[1].dramAddr) - info->block[1].sectorSize; + blockInfo->errStatus = 0x16; + } else { + IO_WRITE(PI_STATUS_REG, 2); + __OSGlobalIntMask |= 0x100401; + info->cmdType = 2; + blockInfo->errStatus = 0; + } + __osEPiRawStartDma(__osDiskHandle, 0, ASIC_C2_BUFF, blockInfo->C2Addr, blockInfo->sectorSize * 4); + return 1; + } + if ((info->sectorNum == -1) && (info->transferMode == 2) && (info->blockNum == 1)) { + __OSBlockInfo* bptr = info->block; + + if (bptr->C1ErrNum == 0) { + if (((u32*)bptr->C2Addr)[0] | ((u32*)bptr->C2Addr)[1] | ((u32*)bptr->C2Addr)[2] | + ((u32*)bptr->C2Addr)[3]) { + bptr->errStatus = 0x17; + __osLeoAbnormalResume(); + return 1; + } + } + bptr->errStatus = 0; + __osLeoResume(); + } + info->sectorNum++; + if (stat & 0x40000000) { + if (info->sectorNum >= 0x55) { + blockInfo->errStatus = 0x18; + __osLeoAbnormalResume(); + return 1; + } + __osEPiRawStartDma(__osDiskHandle, 0, ASIC_SECTOR_BUFF, blockInfo->dramAddr, blockInfo->sectorSize); + blockInfo->errStatus = 0; + return 1; + } else if (info->sectorNum < 0x55) { + blockInfo->errStatus = 0x18; + __osLeoAbnormalResume(); + return 1; + } + return 1; + } else { + blockInfo->errStatus = 4; + __osLeoAbnormalResume(); + return 1; + } +} + +// static +void __osLeoAbnormalResume(void) { + __OSTranxInfo* info; + u32 pi_stat; + + info = &__osDiskHandle->transferInfo; + pi_stat = IO_READ(PI_STATUS_REG); + while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + pi_stat = IO_READ(PI_STATUS_REG); + } + + IO_WRITE(ASIC_BM_CTL, info->bmCtlShadow | 0x10000000); + pi_stat = IO_READ(PI_STATUS_REG); + while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + pi_stat = IO_READ(PI_STATUS_REG); + } + + IO_WRITE(ASIC_BM_CTL, info->bmCtlShadow); + __osLeoResume(); + IO_WRITE(PI_STATUS_REG, 2); + __OSGlobalIntMask |= 0x100401; +} + +// static +void __osLeoResume(void) { + __OSEventState* es; + OSMesgQueue* mq; + s32 last; + + es = &__osEventStateTab[8]; + mq = es->queue; + if ((mq == 0) || (mq->validCount >= mq->msgCount)) { + return; + } + last = (mq->first + mq->validCount) % mq->msgCount; + mq->msg[last] = es->msg; + mq->validCount++; + if (mq->mtqueue->next != NULL) { + __osEnqueueThread(&__osRunQueue, __osPopThread(&mq->mtqueue)); + } +} diff --git a/src/libleo/leo/leomecha.c b/src/libleo/leo/leomecha.c new file mode 100644 index 0000000000..861b2970fb --- /dev/null +++ b/src/libleo/leo/leomecha.c @@ -0,0 +1,344 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +extern s32 currentCommand; + +static u32 asic_cur_status; +static u32 unit_atten; + +u8 leoAnalize_asic_status(void) { + u32 curr_stat; + + osEPiReadIo(LEOPiInfo, ASIC_STATUS, &asic_cur_status); + curr_stat = asic_cur_status ^ 0x1000000; + + // 0xFE3C0000? + if (curr_stat & 0x1C3FFFF) { + // 0xFE3E0000? + if (curr_stat & 0x1C1FFFF) { + LEOdrive_flag = 0; + } + if (curr_stat & 0xFFFF) { + return 41; + } + if ((curr_stat & 0xC00000) == 0x800000) { + return 3; + } + if (curr_stat & 0x400000) { + unit_atten |= 2; + return 43; + } + if (curr_stat & 0x1000000) { + return 49; + } + if (curr_stat & 0x10000) { + unit_atten |= 1; + return 47; + } + if (curr_stat & 0x20000) { + return 21; + } + } + return 0; +} + +u8 leoChk_asic_ready(u32 asic_cmd) { + u32 sense_code = leoAnalize_asic_status(); + + switch (sense_code) { + case 47: + if (asic_cmd == 0x80000) { + return 0; + } + case 43: + if (!(asic_cur_status & 0x800000)) { + if (asic_cmd == 0x90000) { + return 0; + } + if (leoRecv_event_mesg(OS_MESG_NOBLOCK) != 0) { + return 37; + } + osEPiWriteIo(LEOPiInfo, ASIC_CMD, 0x90000); + if (leoRecv_event_mesg(OS_MESG_BLOCK) != 0) { + return 37; + } + } + default: + break; + + case 49: + if (asic_cmd & 1) { + break; + } + + case 21: + return 0; + } + return sense_code; +} + +// Which of LEO_ERROR or LEO_SENSE should be used where? +u8 leoChk_done_status(u32 asic_cmd) { + u32 asic_data; + u32 code = leoAnalize_asic_status(); + + switch (code) { + case 43: + case 47: + if (!(asic_cur_status & 0x800000)) { + if (leoRecv_event_mesg(OS_MESG_NOBLOCK) != 0) { + return 37; + } + + osEPiWriteIo(LEOPiInfo, ASIC_CMD, 0x90000); + if (leoRecv_event_mesg(OS_MESG_BLOCK) != 0) { + return 37; + } + } + break; + + case 49: + if (asic_cmd & 1) { + break; + } + return 0; + + case 21: + osEPiWriteIo(LEOPiInfo, ASIC_DATA, 0); + if (leoRecv_event_mesg(OS_MESG_NOBLOCK) != 0) { + return 37; + } + + osEPiWriteIo(LEOPiInfo, ASIC_CMD, 0xC0000); + if (leoRecv_event_mesg(OS_MESG_BLOCK) != 0) { + return 37; + } + + osEPiReadIo(LEOPiInfo, ASIC_DATA, &asic_data); + code = leoChk_asic_ready(0xC0000); + if (code != 0) { + return code; + } + + if (asic_data & 0x10000) { + return 2; + } + if (asic_data & 0x20000) { + return 24; + } + if (asic_data & 0x40000) { + return 1; + } + if (asic_data & 0x80000) { + return 21; + } + if (asic_data & 0x200000) { + return 11; + } + return 41; + + default: + break; + } + + return code; +} + +u8 leoSend_asic_cmd_i(u32 asic_cmd, u32 asic_data) { + u8 status = leoChk_asic_ready(asic_cmd); + + if (status != 0) { + return LEOcur_command->header.sense = status; + } + + osEPiWriteIo(LEOPiInfo, ASIC_DATA, asic_data); + if (leoRecv_event_mesg(OS_MESG_NOBLOCK) != 0) { + return LEOcur_command->header.sense = 37; + } + + osEPiWriteIo(LEOPiInfo, ASIC_CMD, asic_cmd); + return 0; +} + +// Is this using the sense defines? +u8 leoWait_mecha_cmd_done(u32 asic_cmd) { + u32 done_stat; + + if (leoRecv_event_mesg(OS_MESG_BLOCK)) { + return 37; + } + + done_stat = leoChk_done_status(asic_cmd); + if (done_stat != 0) { + return done_stat; + } + + return 0; +} + +u8 leoSend_asic_cmd_w(u32 asic_cmd, u32 asic_data) { + u32 wstatus = leoSend_asic_cmd_i(asic_cmd, asic_data); + + if (wstatus != 0) { + return wstatus; + } + + return leoWait_mecha_cmd_done(asic_cmd); +} + +u8 leoSend_asic_cmd_w_nochkDiskChange(u32 asic_cmd, u32 asic_data) { + u8 status; + u32 done_stat; + + status = leoChk_asic_ready(asic_cmd); + if ((status != 0x2F) && (status != 0)) { + return LEOcur_command->header.sense = status; + } + + osEPiWriteIo(LEOPiInfo, ASIC_DATA, asic_data); + if (leoRecv_event_mesg(OS_MESG_NOBLOCK) != 0) { + return LEOcur_command->header.sense = 0x25; + } + + osEPiWriteIo(LEOPiInfo, ASIC_CMD, asic_cmd); + if (leoRecv_event_mesg(OS_MESG_BLOCK) != 0) { + return 0x25; + } + + done_stat = leoChk_done_status(asic_cmd); + if ((done_stat != 0x2F) && (done_stat != 0)) { + return done_stat; + } + + return 0; +} + +u8 leoDetect_index_w(void) { + return leoSend_asic_cmd_w(0xE0001, 0); +} + +u8 leoRecal_i(void) { + return leoSend_asic_cmd_i(0x30001, 0); +} + +u8 leoRecal_w(void) { + return leoSend_asic_cmd_w(0x30001, 0); +} + +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); + } else { + return leoSend_asic_cmd_i(0x20001, tgt_tk); + } +} + +u8 leoSeek_w(void) { + u8 sksense = leoSeek_i(0); + + if (sksense != 0) { + return sksense; + } + + return leoWait_mecha_cmd_done(0x10001); +} + +u8 leoRecv_event_mesg(s32 control) { + u32 done_mesg; + + if (osRecvMesg(&LEOevent_que, (OSMesg*)&done_mesg, control) == 0) { + if (done_mesg == 0xA0000) { + leoDrive_reset(); + return -1; + } + } + + return 0; +} + +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; + case LEO_SENSE_MEDIUM_MAY_HAVE_CHANGED: + unit_atten |= 1; + 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; + } + } + + return 0; +} + +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, ASIC_HARD_RESET, 0xAAAA0000); +} + +u32 leoChkUnit_atten(void) { + return unit_atten; +} + +u32 leoRetUnit_atten(void) { + if (unit_atten & 2) { + return 43; + } + if (unit_atten & 1) { + return 47; + } + return 0; +} + +void leoClrUA_RESET(void) { + unit_atten &= ~2; +} + +void leoClrUA_MEDIUM_CHANGED(void) { + unit_atten &= ~1; +} + +void leoSetUA_MEDIUM_CHANGED(void) { + unit_atten |= 1; +} + +void leoInitUnit_atten(void) { + unit_atten = 1; +} diff --git a/src/libleo/leo/leomode_sel.c b/src/libleo/leo/leomode_sel.c new file mode 100644 index 0000000000..cd45fd8350 --- /dev/null +++ b/src/libleo/leo/leomode_sel.c @@ -0,0 +1,27 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +void leoMode_sel(void) { + u32 sense; + + sense = leoSend_asic_cmd_w_nochkDiskChange(0x60000, LEOcur_command->data.time.yearlo << 0x10); + if (sense != LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION) { + goto mselerror; + } + sense = leoSend_asic_cmd_w_nochkDiskChange(0x70000, LEOcur_command->data.time.month << 0x10); + if (sense != LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION) { + goto mselerror; + } + sense = leoSend_asic_cmd_w_nochkDiskChange(0x150000, LEOcur_command->data.readWrite.transferBlks); + 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/leo/leomotor.c b/src/libleo/leo/leomotor.c new file mode 100644 index 0000000000..251ac2a95b --- /dev/null +++ b/src/libleo/leo/leomotor.c @@ -0,0 +1,36 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.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; +} diff --git a/src/libleo/leo/leomseq_tbl.c b/src/libleo/leo/leomseq_tbl.c new file mode 100644 index 0000000000..4944e63336 --- /dev/null +++ b/src/libleo/leo/leomseq_tbl.c @@ -0,0 +1,60 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +extern OSIoMesg LEOPiDmaParam; +extern vu16 LEOrw_flags; + +// bss +static u32 mseq_tbl[0x10]; + +// rodata +static const u32 rd_mseq_code[0x10] = { + 0x00010000, 0x00020200, 0x80030100, 0x82040000, 0xA8050000, 0xA0060600, 0x31760000, 0x00020300, + 0, 0, 0, 0, 0, 0, 0, 0x4060000, +}; +static 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) { + const u32* tbl; + u32 sct_byte_x; + u32 sct_byte_u; + u8 i; + + LEOasic_seq_ctl_shadow &= 0xBFFFFFFF; + osEPiWriteIo(LEOPiInfo, ASIC_SEQ_CTL, 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 = MSEQ_RAM_ADDR; + LEOPiDmaParam.size = 0x40; + LEOPiInfo->transferInfo.cmdType = 2; + osEPiStartDma(LEOPiInfo, &LEOPiDmaParam, 1); + osRecvMesg(&LEOdma_que, NULL, OS_MESG_BLOCK); + osEPiWriteIo(LEOPiInfo, ASIC_SEC_BYTE, (sct_byte_u | 0x5900) << 0x10); + + if (LEOrw_flags & 0x800) { + sct_byte_x += 0x100; + } + + osEPiWriteIo(LEOPiInfo, ASIC_HOST_SECBYTE, sct_byte_x << 8); + LEOasic_seq_ctl_shadow |= 0x40000000; + osEPiWriteIo(LEOPiInfo, ASIC_SEQ_CTL, LEOasic_seq_ctl_shadow); +} diff --git a/src/libleo/leo/leoram.c b/src/libleo/leo/leoram.c new file mode 100644 index 0000000000..7600632482 --- /dev/null +++ b/src/libleo/leo/leoram.c @@ -0,0 +1,41 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +leo_sys_form LEO_sys_data; + +OSThread LEOcommandThread; +OSThread LEOinterruptThread; + +STACK(LEOcommandThreadStack, 0x400); +STACK(LEOinterruptThreadStack, 0x400); + +OSMesgQueue LEOcommand_que; +OSMesgQueue LEOevent_que; +OSMesgQueue LEOcontrol_que; +OSMesgQueue LEOdma_que; +OSMesgQueue LEOblock_que; + +OSMesg LEOevent_que_buf[1]; +OSMesg LEOcontrol_que_buf[1]; +OSMesg LEOdma_que_buf[2]; +OSMesg LEOblock_que_buf[1]; + +u8* LEOwrite_pointer; +LEOCmd* LEOcur_command; + +u32 LEOasic_bm_ctl_shadow; +u32 LEOasic_seq_ctl_shadow; + +u8 LEOdrive_flag; +vu8 LEOclr_que_flag; + +// volatile? +vu16 LEOrw_flags; + +u8 LEOdisk_type; + +tgt_param_form LEOtgt_param; + +u32 LEO_country_code; diff --git a/src/libleo/leo/leord_capa.c b/src/libleo/leo/leord_capa.c new file mode 100644 index 0000000000..d060a64936 --- /dev/null +++ b/src/libleo/leo/leord_capa.c @@ -0,0 +1,17 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +void leoRd_capacity(void) { + if (LEOcur_command->header.control & LEO_CONTROL_WRT) { // Possibly LEO_CONTROL_TBL + LEOcur_command->data.readWrite.lba = LEORAM_START_LBA[LEOdisk_type] - 0x18; + LEOcur_command->data.readWrite.transferBlks = 0x10C3; + LEOcur_command->data.readWrite.buffPtr = (void*)LEORAM_BYTE[LEOdisk_type]; + } else { + LEOcur_command->data.readWrite.lba = 0; + LEOcur_command->data.readWrite.transferBlks = 0x10C3; + LEOcur_command->data.readWrite.buffPtr = (void*)0x3D78F40; // Total capacity, approx. 64.45 MB + } + LEOcur_command->header.status = LEO_STATUS_GOOD; +} diff --git a/src/libleo/leo/leord_diskid.c b/src/libleo/leo/leord_diskid.c new file mode 100644 index 0000000000..fde59bcc9c --- /dev/null +++ b/src/libleo/leo/leord_diskid.c @@ -0,0 +1,54 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +extern vu16 LEOrw_flags; +extern u8 LEO_TempBuffer[0xE8]; + +const u8 leo_disk_id_lba[] = { 14, 15 }; + +LEOCmdRead read_id_cmd = { + { LEO_COMMAND_READ, 0, 0, 0, 0, 0, 0, 0, 0 }, 14, 1, LEO_TempBuffer, 0, +}; + +void leoReadDiskId(void) { + LEOCmdRead dummy_cmd; + u8* temp_pointer; + u32 cntr; + + // Keep Disk ID Command and replace + temp_pointer = (u8*)LEOcur_command; + + // Read Disk ID to Temp Buffer + LEOcur_command = (LEOCmd*)&dummy_cmd; + for (cntr = 0; cntr < (sizeof(leo_disk_id_lba)); cntr++) { + LEOrw_flags = 0x2000; + dummy_cmd = read_id_cmd; + dummy_cmd.lba = leo_disk_id_lba[cntr]; + leoRead_common(0); + if (dummy_cmd.header.sense != LEO_SENSE_UNRECOVERED_READ_ERROR) { + break; + } + } + + // Put back the old ReadDiskID command + LEOcur_command = (LEOCmd*)temp_pointer; + + // Copy Disk ID to buffer pointed by ReadDiskID command + temp_pointer = (u8*)LEOcur_command->data.readdiskid.bufferPointer; + for (cntr = 0; cntr < (sizeof(LEODiskID)); cntr += sizeof(u32)) { + *(u32*)temp_pointer = *((u32*)&LEO_TempBuffer[cntr]); + temp_pointer += sizeof(u32); + } + + // Copy status and sense + LEOcur_command->header.sense = dummy_cmd.header.sense; + LEOcur_command->header.status = dummy_cmd.header.status; + + if (LEOcur_command->header.status == LEO_STATUS_GOOD) { + leoClrUA_MEDIUM_CHANGED(); + } else { + leoSetUA_MEDIUM_CHANGED(); + } +} diff --git a/src/libleo/leo/leoread.c b/src/libleo/leo/leoread.c new file mode 100644 index 0000000000..62017cd159 --- /dev/null +++ b/src/libleo/leo/leoread.c @@ -0,0 +1,70 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +extern vu16 LEOrw_flags; + +void leoRead(void) { + LEOrw_flags = 0; + leoRead_common(0x18); +} + +extern OSMesgQueue LEOc2ctrl_que; + +void leoRead_common(unsigned int offset) { + u32 tg_lba = LEOcur_command->data.readWrite.lba; + u32 tg_blocks = LEOcur_command->data.readWrite.transferBlks; + u32 message; + u16 retry_cnt; + + if ((tg_lba | tg_blocks) & 0xFFFF0000) { + goto invalid_lba; + } + + tg_lba += offset; + if ((tg_lba + tg_blocks) > 0x10DC) { // Unclear what this number represents + invalid_lba: + LEOcur_command->header.sense = LEO_SENSE_LBA_OUT_OF_RANGE; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + + if (tg_blocks == 0) { + if (tg_lba >= 0x10DC) { + goto invalid_lba; + } + LEOcur_command->header.sense = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + LEOcur_command->header.status = LEO_STATUS_GOOD; + return; + } + + LEOtgt_param.lba = tg_lba; + LEOrw_flags &= ~0xC000; + osSendMesg(&LEOc2ctrl_que, NULL, OS_MESG_NOBLOCK); + osStartThread(&LEOinterruptThread); + + for (;;) { + osRecvMesg(&LEOcontrol_que, (OSMesg*)&message, OS_MESG_BLOCK); + + switch (message) { + case 0x90000: + goto read_complete; + + case 0x80000: + leoC2_Correction(); + LEOrw_flags &= ~0x4000; + osSendMesg(&LEOc2ctrl_que, NULL, OS_MESG_NOBLOCK); + break; + + default: + LEOcur_command->header.sense = message; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + } + +read_complete: + LEOcur_command->header.sense = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + LEOcur_command->header.status = LEO_STATUS_GOOD; +} diff --git a/src/libleo/leo/leoreset.c b/src/libleo/leo/leoreset.c new file mode 100644 index 0000000000..ff6e0f9439 --- /dev/null +++ b/src/libleo/leo/leoreset.c @@ -0,0 +1,29 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.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/leo/leorezero.c b/src/libleo/leo/leorezero.c new file mode 100644 index 0000000000..73b58df765 --- /dev/null +++ b/src/libleo/leo/leorezero.c @@ -0,0 +1,28 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.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/leo/leoseek.c b/src/libleo/leo/leoseek.c new file mode 100644 index 0000000000..566866255e --- /dev/null +++ b/src/libleo/leo/leoseek.c @@ -0,0 +1,33 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +void leoSeek(void) { + u32 tgt_tk; // Unused + 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; +} diff --git a/src/libleo/leo/leotempbuffer.c b/src/libleo/leo/leotempbuffer.c new file mode 100644 index 0000000000..5016051caf --- /dev/null +++ b/src/libleo/leo/leotempbuffer.c @@ -0,0 +1,3 @@ +#include "n64dd.h" + +u8 LEO_TempBuffer[0xE8]; diff --git a/src/libleo/leo/leotestunit.c b/src/libleo/leo/leotestunit.c new file mode 100644 index 0000000000..a6a6dbdb62 --- /dev/null +++ b/src/libleo/leo/leotestunit.c @@ -0,0 +1,10 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +void leoTest_unit_rdy(void) { + ((LEOCmdTestUnitReady*)LEOcur_command)->test = leoChk_cur_drvmode(); + LEOcur_command->header.sense = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + LEOcur_command->header.status = LEO_STATUS_GOOD; +} diff --git a/src/libleo/leo/leotimer.c b/src/libleo/leo/leotimer.c new file mode 100644 index 0000000000..9ac64bb2bb --- /dev/null +++ b/src/libleo/leo/leotimer.c @@ -0,0 +1,189 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +typedef struct { + /* 0x0 */ u8 year; + /* 0x1 */ u8 month; + /* 0x2 */ u8 day; + /* 0x3 */ u8 hour; + /* 0x4 */ u8 minute; + /* 0x5 */ u8 second; +} __LOCTime; + +u8 __locReadTimer(__LOCTime* time); +u8 __locSetTimer(__LOCTime* time); + +static const u8 ymdupper[6] = { 99, 12, 31, 23, 59, 59 }; +static const u8 dayupper[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +void leoReadTimer(void) { + u8* rdparam; + u8 data[4]; + u8 sense_code; + __LOCTime time; + + 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; +} + +void leoSetTimer(void) { + LEOCmdReadTimer rd_timer; + u8* p_tmp = &LEOcur_command->data.time.yearlo; + u32 year; + u32 month; + u32 temp; + u32 ymd; + u8 result; + __LOCTime time; + + // Verify values (if they're correct BCD or within limits) + + for (ymd = 0; ymd < 6; ymd++) { + temp = *p_tmp; + + // Verify right nibble (only right nibble for some reason) + if ((temp & 0xF) > 9) { + // nibble is above 0x9 therefore the BCD value is invalid + LEOcur_command->header.sense = LEO_SENSE_ILLEGAL_TIMER_VALUE; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + + // Convert BCD value to binary value + temp = temp - ((temp >> 4) * 6); + + switch (ymd) { + case 2: + // Day value check + if (dayupper[month] < temp && (temp != 0x1D || (year & 3))) { + LEOcur_command->header.sense = LEO_SENSE_ILLEGAL_TIMER_VALUE; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + case 1: + // Month value cannot be 0 + if (temp == 0) { + LEOcur_command->header.sense = LEO_SENSE_ILLEGAL_TIMER_VALUE; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + default: + // Verify max value of each time info + if (ymdupper[ymd] < temp) { + LEOcur_command->header.sense = LEO_SENSE_ILLEGAL_TIMER_VALUE; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + } + + year = month; + month = temp; + p_tmp++; + } + + // Every value has been ymd good, now set the values in hardware + + // Prepare the time info to use + time.year = LEOcur_command->data.time.yearlo; + time.month = LEOcur_command->data.time.month; + time.day = LEOcur_command->data.time.day; + time.hour = LEOcur_command->data.time.hour; + time.minute = LEOcur_command->data.time.minute; + time.second = LEOcur_command->data.time.second; + + // Set the new time + result = __locSetTimer(&time); + if (result != 0) { + LEOcur_command->header.sense = result; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + // Get the time + result = __locReadTimer(&time); + if (result != 0) { + LEOcur_command->header.sense = result; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + // Check if the time is set correctly + if (time.year != LEOcur_command->data.time.yearlo || time.month != LEOcur_command->data.time.month || + time.day != LEOcur_command->data.time.day || time.hour != LEOcur_command->data.time.hour || + time.minute != LEOcur_command->data.time.minute || time.second != LEOcur_command->data.time.second) { + LEOcur_command->header.sense = LEO_SENSE_ILLEGAL_TIMER_VALUE; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + LEOcur_command->header.status = LEO_STATUS_GOOD; +} + +// static +u8 __locReadTimer(__LOCTime* time) { + u32 data; + u8 sense_code; + + sense_code = leoSend_asic_cmd_w_nochkDiskChange(0x140000, 0U); + if (sense_code != 0) { + return sense_code; + } + osEPiReadIo(LEOPiInfo, ASIC_DATA, &data); + time->minute = (u8)((u32)(data & 0xFF000000) >> 0x18); + time->second = (s8)((u32)(data & 0xFF0000) >> 0x10); + sense_code = leoSend_asic_cmd_w_nochkDiskChange(0x130000, 0U); + if (sense_code != 0) { + time->minute = (u8)(time->minute & 0xFF7F); + return sense_code; + } + osEPiReadIo(LEOPiInfo, ASIC_DATA, &data); + time->day = (s8)((u32)(data & 0xFF000000) >> 0x18); + time->hour = (s8)((u32)(data & 0xFF0000) >> 0x10); + sense_code = leoSend_asic_cmd_w_nochkDiskChange(0x120000, 0U); + if (sense_code != 0) { + time->minute = (u8)(time->minute & 0xFF7F); + return sense_code; + } + osEPiReadIo(LEOPiInfo, ASIC_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; +} + +// static +u8 __locSetTimer(__LOCTime* time) { + u32 YearMonthX10000h; + u32 DayHourX10000h; + u32 MinuteSecondX10000h; + u8 result; + + YearMonthX10000h = (time->year << 0x18) + (time->month << 0x10); + DayHourX10000h = (time->day << 0x18) + (time->hour << 0x10); + MinuteSecondX10000h = (time->minute << 0x18) + (time->second << 0x10); + if ((result = leoSend_asic_cmd_w_nochkDiskChange(0xF0000, YearMonthX10000h)) != 0 || + (result = leoSend_asic_cmd_w_nochkDiskChange(0x100000, DayHourX10000h)) != 0 || + (result = leoSend_asic_cmd_w_nochkDiskChange(0x110000, MinuteSecondX10000h)) != 0) { + return result; + } + return 0; +} diff --git a/src/libleo/leo/leotranslat.c b/src/libleo/leo/leotranslat.c new file mode 100644 index 0000000000..1f297a792b --- /dev/null +++ b/src/libleo/leo/leotranslat.c @@ -0,0 +1,83 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.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.transferBlks; + + 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.buffPtr = (void*)calc_blks; + } else { + calc_blks = LEOcur_command->data.readWrite.transferBlks; + + 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.buffPtr = (void*)calc_bytes; + } + + LEOcur_command->header.status = LEO_STATUS_GOOD; +} diff --git a/src/libleo/leo/leoutil.c b/src/libleo/leo/leoutil.c new file mode 100644 index 0000000000..08f88938cf --- /dev/null +++ b/src/libleo/leo/leoutil.c @@ -0,0 +1,107 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +u16 leoLba_to_phys(u32 lba) { + u16 vzone_num; + u16 zone_slba; + u16 zone_scyl; + u16 zone_tk; + u16 bad_tk_num; + u32 counter; + u16 def_offset; + u16 defect; + u8 def_zone_no; + + // A cylinder track is made of two blocks, so we may be able to only read one of it if the next block is on the next + // cylinder + LEOtgt_param.rdwr_blocks = 2 - (lba & 1); + + // Blocks are interleaved between cylinders + switch (lba & 3) { + case 0: + case 3: + LEOtgt_param.start_block = 0; + break; + default: + LEOtgt_param.start_block = 1; + break; + } + + // Get Virtual & Physical Disk Zones from LBA + vzone_num = leoLba_to_vzone(lba); + + // Set Parameter Disk Head & Zone + LEOtgt_param.zone = def_zone_no = LEOVZONE_PZONEHD_TBL[LEOdisk_type][vzone_num]; + LEOtgt_param.head = 0; + if (LEOtgt_param.zone > 7) { + LEOtgt_param.zone -= 7; + LEOtgt_param.head = 1; + } + + // Get the start cylinder from current zone + zone_scyl = LEOZONE_SCYL_TBL[def_zone_no]; + + // Get Virtual Zone LBA start, if Zone 0, it's LBA 0 + if (vzone_num != 0) { + zone_slba = LEOVZONE_TBL[LEOdisk_type][vzone_num - 1]; + } else { + zone_slba = 0; + } + // Get Cylinder relative of the current Zone + zone_tk = (lba - zone_slba) / 2; + // Calculate Physical Cylinder + if (LEOtgt_param.head != 0) { + LEOtgt_param.cylinder = zone_scyl - zone_tk; + zone_scyl = LEOZONE_OUTERCYL_TBL[LEOtgt_param.zone - 1]; + } else { + LEOtgt_param.cylinder = zone_scyl + zone_tk; + } + + // Get the relative offset to defect tracks for the current zone (if Zone 0, then it's 0) + if ((u32)def_zone_no != 0) { + def_offset = LEO_sys_data.param.defect_num[def_zone_no - 1]; + } else { + def_offset = 0; + } + // Get amount of defect tracks for the current zone + bad_tk_num = LEO_sys_data.param.defect_num[def_zone_no] - def_offset; + + // Skip defective cylinders + while (bad_tk_num != 0) { + defect = zone_scyl + LEO_sys_data.param.defect_data[def_offset]; + if (LEOtgt_param.cylinder < defect) { + break; + } + + LEOtgt_param.cylinder++; + def_offset++; + bad_tk_num--; + } + + // Set sector and block size info + LEOtgt_param.sec_bytes = LEOBYTE_TBL1[LEOtgt_param.zone]; + LEOtgt_param.blk_bytes = LEOBYTE_TBL2[LEOtgt_param.zone]; + + // For development disks + if (LEO_country_code == 0 && lba < 12) { + LEOtgt_param.sec_bytes = 0xC0; + LEOtgt_param.blk_bytes = 0x3FC0; + } + + return 0; +} + +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/leo/leowrite.c b/src/libleo/leo/leowrite.c new file mode 100644 index 0000000000..deeafc9ad8 --- /dev/null +++ b/src/libleo/leo/leowrite.c @@ -0,0 +1,54 @@ +#include "global.h" +#include "ultra64/leo.h" +#include "ultra64/leoappli.h" +#include "ultra64/leodrive.h" + +extern u16 LEOrw_flags; // N.B. 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.transferBlks; + 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/libultra/io/pimgr.c b/src/libultra/io/pimgr.c index 514fe26e8a..e8aa98d01b 100644 --- a/src/libultra/io/pimgr.c +++ b/src/libultra/io/pimgr.c @@ -1,4 +1,5 @@ #include "global.h" +#include "stack.h" #include "ultra64/internal.h" OSDevMgr __osPiDevMgr = { 0 }; diff --git a/src/libultra/io/vimgr.c b/src/libultra/io/vimgr.c index 2d541672b7..d9b3fc4355 100644 --- a/src/libultra/io/vimgr.c +++ b/src/libultra/io/vimgr.c @@ -1,4 +1,5 @@ #include "global.h" +#include "stack.h" #include "ultra64/internal.h" OSThread viThread;