1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-07-04 06:54:33 +00:00

[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 <angheloalf95@gmail.com>
Co-authored-by: Elliptic Ellipsis <elliptic.ellipsis@gmail.com>

* 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 <angheloalf95@gmail.com>
Co-authored-by: Elliptic Ellipsis <elliptic.ellipsis@gmail.com>
Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com>
This commit is contained in:
cadmic 2024-09-03 12:30:14 -07:00 committed by GitHub
parent 6f396e7cc8
commit 2152d1df2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
56 changed files with 4363 additions and 22 deletions

View file

@ -524,6 +524,9 @@ $(BUILD_DIR)/src/libultra/libc/%.o: OPTFLAGS := -O2
$(BUILD_DIR)/src/libultra/os/%.o: OPTFLAGS := -O1 $(BUILD_DIR)/src/libultra/os/%.o: OPTFLAGS := -O1
endif 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 $(BUILD_DIR)/assets/misc/z_select_static/%.o: GBI_DEFINES := -DF3DEX_GBI
# For using asm_processor on some files: # For using asm_processor on some files:

10
include/stack.h Normal file
View file

@ -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

214
include/ultra64/leo.h Normal file
View file

@ -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

198
include/ultra64/leoappli.h Normal file
View file

@ -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

View file

@ -1,7 +1,14 @@
#ifndef ULTRA64_LEODRIVE_H #ifndef ULTRA64_LEODRIVE_H
#define ULTRA64_LEODRIVE_H #define ULTRA64_LEODRIVE_H
#include "leo.h"
#include "leoappli.h"
#include "message.h"
#include "pi.h"
#include "rcp.h" #include "rcp.h"
#include "stack.h"
#include "thread.h"
#include "ultratypes.h"
#define ASIC_BASE PI_DOM2_ADDR1 #define ASIC_BASE PI_DOM2_ADDR1
@ -44,4 +51,144 @@
// ASIC_STATUS read bits // ASIC_STATUS read bits
#define LEO_STATUS_MECHANIC_INTR 0x02000000 // Mechanic Interrupt Raised #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 #endif

View file

@ -92,12 +92,6 @@
#define THREAD_ID_DMAMGR 18 #define THREAD_ID_DMAMGR 18
#define THREAD_ID_IRQMGR 19 #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 { typedef struct KaleidoMgrOverlay {
/* 0x00 */ void* loadedRamAddr; /* 0x00 */ void* loadedRamAddr;
/* 0x04 */ RomFile file; /* 0x04 */ RomFile file;

58
spec
View file

@ -106,7 +106,7 @@ beginseg
#endif #endif
include "$(BUILD_DIR)/src/libultra/os/setfpccsr.o" include "$(BUILD_DIR)/src/libultra/os/setfpccsr.o"
include "$(BUILD_DIR)/src/libultra/os/getfpccsr.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" include "$(BUILD_DIR)/src/libultra/io/epiwrite.o"
#endif #endif
include "$(BUILD_DIR)/src/libultra/os/maptlbrdb.o" include "$(BUILD_DIR)/src/libultra/os/maptlbrdb.o"
@ -730,15 +730,6 @@ beginseg
include "$(BUILD_DIR)/data/rsp.rodata.o" include "$(BUILD_DIR)/data/rsp.rodata.o"
endseg endseg
#if PLATFORM_N64
beginseg
// TODO
name "n64dd"
address 0x801C7740
include "$(BUILD_DIR)/baserom/n64dd.o"
endseg
#endif
beginseg beginseg
name "buffers" name "buffers"
flags NOLOAD flags NOLOAD
@ -748,6 +739,53 @@ beginseg
include "$(BUILD_DIR)/src/buffers/audio_heap.o" include "$(BUILD_DIR)/src/buffers/audio_heap.o"
endseg 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 beginseg
name "ovl_title" name "ovl_title"
compress compress

View file

@ -1,5 +1,6 @@
#include "global.h" #include "global.h"
#include "boot.h" #include "boot.h"
#include "stack.h"
#if PLATFORM_N64 #if PLATFORM_N64
#include "cic6105.h" #include "cic6105.h"
#endif #endif

View file

@ -1,4 +1,5 @@
#include "global.h" #include "global.h"
#include "stack.h"
#include "terminal.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" #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"

View file

@ -20,6 +20,7 @@
*/ */
#include "global.h" #include "global.h"
#include "fault.h" #include "fault.h"
#include "stack.h"
#include "terminal.h" #include "terminal.h"
#if PLATFORM_N64 #if PLATFORM_N64
#include "n64dd.h" #include "n64dd.h"

View file

@ -40,6 +40,8 @@
* DPad-Up may be pressed to enable sending fault pages over osSyncPrintf as well as displaying them on-screen. * 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. * 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 // Include versions.h first and redefine FAULT_VERSION
// This allows this file to compile even when versions.h uses FAULT_N64 // This allows this file to compile even when versions.h uses FAULT_N64
@ -48,12 +50,10 @@
#define FAULT_VERSION FAULT_GC #define FAULT_VERSION FAULT_GC
#include "global.h" #include "global.h"
#include "fault.h"
#include "terminal.h"
#include "alloca.h" #include "alloca.h"
#include "fault.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" \ #include "stack.h"
"gc-us-mq:64" #include "terminal.h"
void FaultDrawer_Init(void); void FaultDrawer_Init(void);
void FaultDrawer_SetOsSyncPrintfEnabled(u32 enabled); void FaultDrawer_SetOsSyncPrintfEnabled(u32 enabled);

View file

@ -6,6 +6,7 @@
#include "global.h" #include "global.h"
#include "fault.h" #include "fault.h"
#include "stack.h"
#include "terminal.h" #include "terminal.h"
typedef struct FaultMgr { typedef struct FaultMgr {

View file

@ -23,7 +23,7 @@
* @param sjis Shift-JIS Codepoint of glyph. * @param sjis Shift-JIS Codepoint of glyph.
* @return s32 offset into `kanji` file. * @return s32 offset into `kanji` file.
* *
* @remark Original name: "LeoGetKadr" * @remark Almost identical to "LeoGetKadr" from libleo.
*/ */
LEAF(Kanji_OffsetFromShiftJIS) LEAF(Kanji_OffsetFromShiftJIS)
// Characters with codepoints >= 0x8800 are kanji. Arrangement is regular, // Characters with codepoints >= 0x8800 are kanji. Arrangement is regular,

View file

@ -1,5 +1,6 @@
#include "global.h" #include "global.h"
#include "fault.h" #include "fault.h"
#include "stack.h"
#include "terminal.h" #include "terminal.h"
#include "versions.h" #include "versions.h"
#if PLATFORM_N64 #if PLATFORM_N64

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

332
src/libleo/api/getaadr.s Normal file
View file

@ -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)

33
src/libleo/api/getaadr2.s Normal file
View file

@ -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)

229
src/libleo/api/getkadr.s Normal file
View file

@ -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)

View file

@ -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;
}

View file

@ -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;
}

24
src/libleo/api/seek.c Normal file
View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

58
src/libleo/leo/leo_tbl.c Normal file
View file

@ -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,
};

View file

@ -0,0 +1,3 @@
#include "n64dd.h"
u8 LEOC2_Syndrome[2][0xE8 * 4];

495
src/libleo/leo/leoc2ecc.c Normal file
View file

@ -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])];
}

262
src/libleo/leo/leocmdex.c Normal file
View file

@ -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);
}

View file

@ -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;
}

134
src/libleo/leo/leofunc.c Normal file
View file

@ -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;
}

View file

@ -0,0 +1,8 @@
#include "global.h"
#include "ultra64/leo.h"
#include "ultra64/leoappli.h"
#include "ultra64/leodrive.h"
s32 __leoActive = false;
LEOVersion __leoVersion;

View file

@ -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;
}

298
src/libleo/leo/leoint.c Normal file
View file

@ -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;
}

View file

@ -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));
}
}

344
src/libleo/leo/leomecha.c Normal file
View file

@ -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;
}

View file

@ -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;
}

36
src/libleo/leo/leomotor.c Normal file
View file

@ -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;
}

View file

@ -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);
}

41
src/libleo/leo/leoram.c Normal file
View file

@ -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;

View file

@ -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;
}

View file

@ -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();
}
}

70
src/libleo/leo/leoread.c Normal file
View file

@ -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;
}

29
src/libleo/leo/leoreset.c Normal file
View file

@ -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;
}
}

View file

@ -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;
}

33
src/libleo/leo/leoseek.c Normal file
View file

@ -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;
}

View file

@ -0,0 +1,3 @@
#include "n64dd.h"
u8 LEO_TempBuffer[0xE8];

View file

@ -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;
}

189
src/libleo/leo/leotimer.c Normal file
View file

@ -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;
}

View file

@ -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;
}

107
src/libleo/leo/leoutil.c Normal file
View file

@ -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;
}

54
src/libleo/leo/leowrite.c Normal file
View file

@ -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;
}

View file

@ -1,4 +1,5 @@
#include "global.h" #include "global.h"
#include "stack.h"
#include "ultra64/internal.h" #include "ultra64/internal.h"
OSDevMgr __osPiDevMgr = { 0 }; OSDevMgr __osPiDevMgr = { 0 };

View file

@ -1,4 +1,5 @@
#include "global.h" #include "global.h"
#include "stack.h"
#include "ultra64/internal.h" #include "ultra64/internal.h"
OSThread viThread; OSThread viThread;