Finish libleo main api

This commit is contained in:
Diamond Lewis 2023-07-14 15:13:21 -05:00
parent 5e7c1d39a1
commit 0d10a88c02
14 changed files with 905 additions and 44 deletions

View File

@ -1,23 +0,0 @@
name: C/C++ CI
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: configure
run: ./configure
- name: make
run: make
- name: make check
run: make check
- name: make distcheck
run: make distcheck

19
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: C/C++ CI
on:
push:
branches: [ "master" ]
pull_request:
branches:
- '**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build
run: |
echo "Passed"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

View File

@ -1,6 +1,20 @@
#ifndef LIBLEO_INTERNAL_H
#define LIBLEO_INTERNAL_H
#include "PR/os_internal.h"
#include "PR/rcp.h"
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
/* libleo conversion tables */
extern const u8 LEOBYTE_TBL1[];
extern const u16 LEOBYTE_TBL2[];
@ -11,7 +25,119 @@ extern const u16 LEOZONE_OUTERCYL_TBL[];
extern const u16 LEORAM_START_LBA[];
extern const s32 LEORAM_BYTE[];
extern s32 __leoActive;
/* Memory Map */
#define LEO_BASE_REG 0x05000000
#define LEO_CMD (LEO_BASE_REG + 0x508)
#define LEO_STATUS (LEO_BASE_REG + 0x508)
#define LEO_BM_CTL (LEO_BASE_REG + 0x510)
#define LEO_BM_STATUS (LEO_BASE_REG + 0x510)
#define LEO_SEQ_CTL (LEO_BASE_REG + 0x518)
#define LEO_SEQ_STATUS (LEO_BASE_REG + 0x518)
#define LEO_C2_BUFF (LEO_BASE_REG + 0x000) //C2 Sector Buffer
#define LEO_SECTOR_BUFF (LEO_BASE_REG + 0x400) //Data Sector Buffer
#define LEO_DATA (LEO_BASE_REG + 0x500) //Data
#define LEO_MISC_REG (LEO_BASE_REG + 0x504) //Misc Register
#define LEO_CUR_TK (LEO_BASE_REG + 0x50C) //Current Track
#define LEO_ERR_SECTOR (LEO_BASE_REG + 0x514) //Sector Error Status
#define LEO_CUR_SECTOR (LEO_BASE_REG + 0x51C) //Current Sector
#define LEO_HARD_RESET (LEO_BASE_REG + 0x520) //Hard Reset
#define LEO_C1_S0 (LEO_BASE_REG + 0x524) //C1
#define LEO_HOST_SECBYTE (LEO_BASE_REG + 0x528) //Sector Size (in bytes)
#define LEO_C1_S2 (LEO_BASE_REG + 0x52C) //C1
#define LEO_SEC_BYTE (LEO_BASE_REG + 0x530) //Sectors per Block, Full Size
#define LEO_C1_S4 (LEO_BASE_REG + 0x534) //C1
#define LEO_C1_S6 (LEO_BASE_REG + 0x538) //C1
#define LEO_CUR_ADDR (LEO_BASE_REG + 0x53C) //Current Address?
#define LEO_ID_REG (LEO_BASE_REG + 0x540) //ID
#define LEO_TEST_REG (LEO_BASE_REG + 0x544) //Test Read
#define LEO_TEST_PIN_SEL (LEO_BASE_REG + 0x548) //Test Write
#define LEO_RAM_ADDR (LEO_BASE_REG + 0x580) //Microsequencer RAM
#define LEO_STATUS_PRESENCE_MASK 0xFFFF
#define LEO_STATUS_DATA_REQUEST 0x40000000
#define LEO_STATUS_C2_TRANSFER 0x10000000
#define LEO_STATUS_BUFFER_MANAGER_ERROR 0x08000000
#define LEO_STATUS_BUFFER_MANAGER_INTERRUPT 0x04000000
#define LEO_STATUS_MECHANIC_INTERRUPT 0x02000000
#define LEO_STATUS_DISK_PRESENT 0x01000000
#define LEO_STATUS_BUSY_STATE 0x00800000
#define LEO_STATUS_RESET_STATE 0x00400000
#define LEO_STATUS_MOTOR_NOT_SPINNING 0x00100000
#define LEO_STATUS_HEAD_RETRACTED 0x00080000
#define LEO_STATUS_WRITE_PROTECT_ERROR 0x00040000
#define LEO_STATUS_MECHANIC_ERROR 0x00020000
#define LEO_STATUS_DISK_CHANGE 0x00010000
/* ASIC commands */
#define ASIC_NO_OPERATION 0x00000000
#define ASIC_RD_SEEK 0x00010001
#define ASIC_WR_SEEK 0x00020001
#define ASIC_RECAL 0x00030001
#define ASIC_SLEEP 0x00040000
#define ASIC_START 0x00050001
#define ASIC_SET_STBY 0x00060000
#define ASIC_SET_SLEEP 0x00070000
#define ASIC_CLR_CHGFLG 0x00080000
#define ASIC_CLR_RSTFLG 0x00090000
#define ASIC_RD_VERSION 0x000a0000
#define ASIC_SET_DTYPE 0x000b0001
#define ASIC_REQ_STATUS 0x000c0000
#define ASIC_STANDBY 0x000d0000
#define ASIC_INDEX_LOCK_RETRY 0x000e0001
#define ASIC_SET_TIMER_YEAR 0x000f0000
#define ASIC_SET_TIMER_DATE 0x00100000
#define ASIC_SET_TIMER_MINUTE 0x00110000
#define ASIC_READ_TIMER_YEAR 0x00120000
#define ASIC_READ_TIMER_DATE 0x00130000
#define ASIC_READ_TIMER_MINUTE 0x00140000
#define ASIC_NEED_DISK_IN 0x00000001
// Functions
extern u8 leoAnalize_asic_status(void);
extern u8 leoChk_asic_ready(u32 asic_cmd);
extern u8 leoChk_done_status(u32 asic_cmd);
extern u8 leoSend_asic_cmd_i(u32 asic_cmd, u32 asic_data);
extern u8 leoWait_mecha_cmd_done(u32 asic_cmd);
extern u8 leoSend_asic_cmd_w(u32 asic_cmd, u32 asic_data);
extern u8 leoSend_asic_cmd_w_nochkDiskChange(u32 asic_cmd, u32 asic_data);
extern u8 leoDetect_index_w(void);
extern u8 leoRecal_i(void);
extern u8 leoRecal_w(void);
extern u8 leoSeek_i(u16 rwmode);
extern u8 leoSeek_w(void);
extern s32 leoRecv_event_mesg(s32 control);
extern u32 leoChk_err_retry(u32 sense);
extern u8 leoChk_cur_drvmode(void);
extern void leoDrive_reset(void);
extern u32 leoChkUnit_atten(void);
extern u32 leoRetUnit_atten(void);
extern void leoClrUA_RESET(void);
extern void leoClrUA_MEDIUM_CHANGED(void);
extern void leoSetUA_MEDIUM_CHANGED(void);
extern void leoInitUnit_atten(void);
extern int leoC2_Correction(void);
extern s32 leoVerifyRTC(u8 yearhi, u8 yearlo);
extern s32 __leoSetReset(void);
extern s32 __osLeoInterrupt(void);
extern s32 __leoActive;
extern s32 LEO_country_code;
extern u8 leoDiskStack[];
extern u8 LEOdisk_type;
extern u8 LEOdrive_flag;
extern LEOVersion __leoVersion;
extern LEOCmd* LEOcur_command;
extern OSMesgQueue LEOevent_que;
extern OSMesgQueue LEOc2ctrl_que;
extern OSMesgQueue LEOcontrol_que;
extern OSPiHandle* LEOPiInfo;
extern OSThread LEOinterruptThread;
extern tgt_param_form LEOtgt_param;
extern vu16 LEOrw_flags;
#endif

View File

@ -130,20 +130,21 @@ segments:
- [0x51C50, asm, libleo/leofunc]
- [0x520C0, asm, libleo/leoint]
- [0x52AC0, asm, libleo/leocmdex]
- [0x53150, asm, libleo/leoread]
- [0x53150, c, libleo/leoread]
- [0x53310, asm, libleo/lbatobyte]
- [0x53460, asm, libleo/driverominit]
- [0x535C0, asm, libleo/inquiry]
- [0x53670, c, libleo/leodiskinit]
- [0x53710, c, libleo/readdiskid]
- [0x53770, asm, libleo/leord_diskid]
- [0x53900, asm, libleo/leomecha]
- [0x53900, c, libleo/leomecha]
- [0x54250, asm, libleo/spdlmotor]
- [0x54310, asm, libleo/leoc2ecc]
- [0x54310, c, libleo/leoc2ecc]
- [0x55400, c, libleo/setrtc]
- [0x55570, asm, libleo/leomseq_tbl]
- [0x55720, asm, libleo/leomotor]
- [0x55810, asm, libleo/leomode_sel]
- [0x558C0, asm, libleo/leord_capa]
- [0x558C0, c, libleo/leord_capa]
- [0x55960, asm, libleo/leoutil]
- [0x55BB0, asm, libleo/leorezero]
- [0x55C50, asm, libleo/bytetolba]
@ -151,11 +152,11 @@ segments:
- [0x55ED0, asm, libleo/leotranslat]
- [0x56170, asm, libleo/leotimer]
- [0x56680, asm, libleo/leowrite]
- [0x567B0, asm, libleo/cjcreateleomanager]
- [0x569F0, asm, libleo/leointerrupt]
- [0x567B0, c, libleo/cjcreateleomanager]
- [0x569F0, c, libleo/leointerrupt]
- [0x570C0, c, libleo/driveexist]
- [0x57190, c, libleo/testunitready]
- [0x57230, asm, libleo/leotestunit]
- [0x57230, c, libleo/leotestunit]
- [0x57270, c, libleo/readrtc]
- [0x572D0, asm, libleo/leoseek]
- [0x57390, c, libleo/seek]

View File

@ -0,0 +1,83 @@
#include <ultra64.h>
#include "libleo/internal.h"
#ifdef NON_MATCHING
// https://decomp.me/scratch/OYMx2
s32 LeoCJCreateLeoManager(OSPri comPri, OSPri 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 = 1;
__osSetHWIntrRoutine(1, __osLeoInterrupt, leoDiskStack + 0xFF0);
leoInitialize(comPri, intPri, cmdBuf, cmdMsgCnt);
if (osResetType == 1) {
__leoSetReset();
}
cmdBlockInq.header.command = 2;
cmdBlockInq.header.reserve1 = 0;
cmdBlockInq.header.control = 0;
cmdBlockInq.header.reserve3 = 0;
leoCommand((void*)&cmdBlockInq);
{
volatile s32 dummy = (u32) &cmdBlockInq & 0xFFFFFF;
while (dummy > 0) {
dummy -= ((u32)__leoSetReset & 0xFFFFFF) | 0x403DF4;
}
}
while (cmdBlockInq.header.status == 8);
if (cmdBlockInq.header.status != 0) {
return cmdBlockInq.header.sense;
}
__leoVersion.driver = cmdBlockInq.version;
__leoVersion.drive = 6;
__leoVersion.deviceType = cmdBlockInq.dev_type;
__leoVersion.ndevices = cmdBlockInq.dev_num;
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) >> 0x18);
dummy = 0x3ED98F23;
if (data != 0xC3) {
while (1) {}
}
dummy *= data;
dummy -= (u32)&cmdBlockInq;
LEO_country_code = -0x17B72CEA;
} else {
while (1) {}
}
return LEO_ERROR_GOOD;
}
#else
#pragma GLOBAL_ASM("asm/nonmatchings/libleo/cjcreateleomanager/LeoCJCreateLeoManager.s")
#endif

15
src/libleo/leoc2ecc.c Normal file
View File

@ -0,0 +1,15 @@
#include "common.h"
#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoC2_Correction.s")
#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoC2_single_ecc.s")
#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoC2_double_ecc.s")
#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoC2_3_ecc.s")
#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoC2_4_ecc.s")
#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoAlpha_mult.s")
#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoAlpha_div.s")

31
src/libleo/leodiskinit.c Normal file
View File

@ -0,0 +1,31 @@
#include <ultra64.h>
#include "PR/R4300.h"
#include "libleo/internal.h"
extern OSPiHandle __LeoDiskHandle;
extern OSPiHandle* __osDiskHandle;
extern OSPiHandle* __osPiTable;
OSPiHandle* osLeoDiskInit(void) {
u32 prevInt;
__LeoDiskHandle.type = DEVICE_TYPE_64DD;
__LeoDiskHandle.baseAddress = PHYS_TO_K1(PI_DOM2_ADDR1);
__LeoDiskHandle.latency = 3;
__LeoDiskHandle.pulse = 6;
__LeoDiskHandle.pageSize = 6;
__LeoDiskHandle.relDuration = 2;
__LeoDiskHandle.domain = PI_DOMAIN2;
__LeoDiskHandle.speed = 0;
bzero(&__LeoDiskHandle.transferInfo, sizeof(__OSTranxInfo));
prevInt = __osDisableInt();
__LeoDiskHandle.next = __osPiTable;
__osPiTable = &__LeoDiskHandle;
__osDiskHandle = &__LeoDiskHandle;
__osRestoreInt(prevInt);
return &__LeoDiskHandle;
}

206
src/libleo/leointerrupt.c Normal file
View File

@ -0,0 +1,206 @@
#include <ultra64.h>
#include "ultra64/internal.h"
#include "libleo/internal.h"
#include "PR/os_system.h"
extern OSThread* __osRunQueue;
extern OSThread *__osPopThread(OSThread **);
extern void __osEnqueueThread(OSThread **, OSThread *);
extern OSIntMask __osGlobalIntMask;
void __osLeoAbnormalResume(void);
void __osLeoResume(void);
extern s32 osEPiRawStartDma(OSPiHandle *, s32, u32, void *, u32);
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 = HW_REG(PI_STATUS_REG, u32);
if (pi_stat & PI_STATUS_DMA_BUSY) {
__osGlobalIntMask &= ~0x800;
blockInfo->errStatus = 0x1D;
__osLeoResume();
return 1;
}
pi_stat = HW_REG(PI_STATUS_REG, u32);
while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) {
pi_stat = HW_REG(PI_STATUS_REG, u32);
}
stat = HW_REG(0x5000508, u32);
if (stat & 0x2000000) {
pi_stat = HW_REG(PI_STATUS_REG, u32);
while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) {
pi_stat = HW_REG(PI_STATUS_REG, u32);
}
HW_REG(0x5000510, u32) = info->bmCtlShadow | 0x1000000;
blockInfo->errStatus = 0;
return 0;
}
if (info->cmdType == 2) {
return 1;
}
if (stat & 0x8000000) {
pi_stat = HW_REG(PI_STATUS_REG, u32);
while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) {
pi_stat = HW_REG(PI_STATUS_REG, u32);
}
stat = HW_REG(0x5000508, u32);
blockInfo->errStatus = 0x16;
__osLeoResume();
HW_REG(PI_STATUS_REG, u32) = 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;
}
HW_REG(PI_STATUS_REG, u32) = 2;
__osGlobalIntMask |= 0x100401;
blockInfo->errStatus = 0;
__osLeoResume();
return 1;
} else {
blockInfo->dramAddr = (u8*)(blockInfo->dramAddr) + blockInfo->sectorSize;
info->sectorNum++;
osEPiRawStartDma(__osDiskHandle, 1, 0x5000400, 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 = HW_REG(0x5000510, u32);
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 {
HW_REG(PI_STATUS_REG, u32) = 2;
__osGlobalIntMask |= 0x100401;
info->cmdType = 2;
blockInfo->errStatus = 0;
}
osEPiRawStartDma(__osDiskHandle, 0, 0x5000000U, 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, 0x5000400, 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;
}
}
void __osLeoAbnormalResume(void) {
__OSTranxInfo* info;
u32 pi_stat;
info = &__osDiskHandle->transferInfo;
pi_stat = HW_REG(PI_STATUS_REG, u32);
while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) {
pi_stat = HW_REG(PI_STATUS_REG, u32);
}
HW_REG(0x5000510, u32) = info->bmCtlShadow | 0x10000000;
pi_stat = HW_REG(PI_STATUS_REG, u32);
while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) {
pi_stat = HW_REG(PI_STATUS_REG, u32);
}
HW_REG(0x5000510, u32) = info->bmCtlShadow;
__osLeoResume();
HW_REG(PI_STATUS_REG, u32) = 2;
__osGlobalIntMask |= 0x100401;
}
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));
}
}

278
src/libleo/leomecha.c Normal file
View File

@ -0,0 +1,278 @@
#include <ultra64.h>
#include "libleo/internal.h"
extern s32 currentCommand;
extern u32 asic_cur_status; // static?
extern u32 unit_atten; // static?
s32 osEPiWriteIo(OSPiHandle *, u32 , u32 );
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
u8 leoAnalize_asic_status(void) {
u32 curr_stat;
osEPiReadIo(LEOPiInfo, LEO_STATUS, &asic_cur_status);
if ((curr_stat = asic_cur_status ^ 0x1000000) & 0x1C3FFFF) {
if (curr_stat & 0x1C1FFFF) {
LEOdrive_flag = 0;
}
if (curr_stat & LEO_STATUS_PRESENCE_MASK) {
return 41;
}
if ((curr_stat & 0xC00000) == LEO_STATUS_BUSY_STATE) {
return LEO_SENSE_COMMAND_PHASE_ERROR;
}
if (curr_stat & LEO_STATUS_RESET_STATE) {
unit_atten |= 2;
return LEO_SENSE_POWERONRESET_DEVICERESET_OCCURED;
}
if (curr_stat & LEO_STATUS_DISK_PRESENT) {
return LEO_SENSE_EJECTED_ILLEGALLY_RESUME;
}
if (curr_stat & LEO_STATUS_DISK_CHANGE) {
unit_atten |= 1;
return LEO_SENSE_MEDIUM_MAY_HAVE_CHANGED;
}
if (curr_stat & LEO_STATUS_MECHANIC_ERROR) {
return LEO_SENSE_NO_SEEK_COMPLETE;
}
}
return LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION;
}
u8 leoChk_asic_ready(u32 asic_cmd) {
u32 sense_code = leoAnalize_asic_status();
switch (sense_code) {
case LEO_SENSE_MEDIUM_MAY_HAVE_CHANGED:
if (asic_cmd == ASIC_CLR_CHGFLG) {
return LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION;
}
case LEO_SENSE_POWERONRESET_DEVICERESET_OCCURED:
if (!(asic_cur_status & LEO_STATUS_BUSY_STATE)) {
if (asic_cmd == ASIC_CLR_RSTFLG) {
return LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION;
}
if (leoRecv_event_mesg(0) != 0) {
return LEO_SENSE_WAITING_NMI;
}
osEPiWriteIo(LEOPiInfo, LEO_CMD, ASIC_CLR_RSTFLG);
if (leoRecv_event_mesg(1) != 0) {
return LEO_SENSE_WAITING_NMI;
}
}
default:
break;
case LEO_SENSE_EJECTED_ILLEGALLY_RESUME:
if (asic_cmd & ASIC_NEED_DISK_IN) {
break;
}
case LEO_SENSE_NO_SEEK_COMPLETE:
return LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION;
}
return sense_code;
}
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(0) != 0) {
return 37;
}
osEPiWriteIo(LEOPiInfo, 0x5000508, 0x90000);
if (leoRecv_event_mesg(1) != 0) {
return 37;
}
}
break;
case 49:
if (asic_cmd & 1) {
break;
}
return 0;
case 21:
osEPiWriteIo(LEOPiInfo, 0x5000500, 0);
if (leoRecv_event_mesg(0) != 0) {
return 37;
}
osEPiWriteIo(LEOPiInfo, 0x5000508, 0xC0000);
if (leoRecv_event_mesg(1) != 0) {
return 37;
}
osEPiReadIo(LEOPiInfo, 0x5000500, &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, LEO_DATA, asic_data);
if (leoRecv_event_mesg(0) != 0) {
return LEOcur_command->header.sense = LEO_SENSE_WAITING_NMI;
}
osEPiWriteIo(LEOPiInfo, LEO_STATUS, asic_cmd);
return 0;
}
u8 leoWait_mecha_cmd_done(u32 asic_cmd) {
u32 done_stat;
if (leoRecv_event_mesg(1)) {
return LEO_SENSE_WAITING_NMI;
}
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 != LEO_SENSE_MEDIUM_MAY_HAVE_CHANGED) && (status != 0)) {
return LEOcur_command->header.sense = status;
}
osEPiWriteIo(LEOPiInfo, LEO_DATA, asic_data);
if (leoRecv_event_mesg(0) != 0) {
return LEOcur_command->header.sense = LEO_SENSE_WAITING_NMI;
}
osEPiWriteIo(LEOPiInfo, LEO_STATUS, asic_cmd);
if (leoRecv_event_mesg(1) != 0) {
return LEO_SENSE_WAITING_NMI;
}
done_stat = leoChk_done_status(asic_cmd);
if ((done_stat != LEO_SENSE_MEDIUM_MAY_HAVE_CHANGED) && (done_stat != 0)) {
return done_stat;
}
return 0;
}
u8 leoDetect_index_w(void) {
return leoSend_asic_cmd_w(ASIC_INDEX_LOCK_RETRY, 0);
}
u8 leoRecal_i(void) {
return leoSend_asic_cmd_i(ASIC_RECAL, 0);
}
u8 leoRecal_w(void) {
return leoSend_asic_cmd_w(ASIC_RECAL, 0);
}
#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leomecha/leoSeek_i.s")
u8 leoSeek_w(void) {
u8 sksense = leoSeek_i(0);
if (sksense != 0) {
return sksense;
}
return leoWait_mecha_cmd_done(ASIC_RD_SEEK);
}
s32 leoRecv_event_mesg(s32 control) {
u32 done_mesg;
if (osRecvMesg(&LEOevent_que, (OSMesg*)&done_mesg, control) == 0) {
if (done_mesg == 0xA0000) {
leoDrive_reset();
return 0xFF;
}
}
return 0;
}
#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leomecha/leoChk_err_retry.s")
#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leomecha/leoChk_cur_drvmode.s")
void leoDrive_reset() {
osEPiWriteIo(LEOPiInfo, LEO_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;
}

26
src/libleo/leord_capa.c Normal file
View File

@ -0,0 +1,26 @@
#include <ultra64.h>
#include "libleo/internal.h"
// static?
const u16 LEORAM_START_LBA[] = {
0x05A2, 0x07C6, 0x09EA, 0x0C0E, 0x0E32, 0x1010, 0x10DC,
};
// static?
const s32 LEORAM_BYTE[] = {
0x024A9DC0, 0x01C226C0, 0x01450F00, 0x00D35680, 0x006CFD40, 0x001DA240, 0x00000000,
};
void leoRd_capacity(void) {
if (LEOcur_command->header.control & LEO_CONTROL_WRT) {
LEOcur_command->data.readwrite.lba = LEORAM_START_LBA[LEOdisk_type] - 0x18;
LEOcur_command->data.readwrite.xfer_blks = LEO_LBA_MAX;
LEOcur_command->data.readwrite.buff_ptr = LEORAM_BYTE[LEOdisk_type];
} else {
LEOcur_command->data.readwrite.lba = 0;
LEOcur_command->data.readwrite.xfer_blks = LEO_LBA_MAX;
LEOcur_command->data.readwrite.buff_ptr = 0x3D78F40; // Total capacity, approx. 64.45 MB
}
LEOcur_command->header.status = LEO_STATUS_GOOD;
}
// #pragma GLOBAL_ASM("asm/nonmatchings/libleo/leord_capa/leoRd_capacity.s")

64
src/libleo/leoread.c Normal file
View File

@ -0,0 +1,64 @@
#include <ultra64.h>
#include "libleo/internal.h"
void leoRead_common(u32 offset);
void leoRead(void) {
LEOrw_flags = 0;
leoRead_common(0x18);
}
void leoRead_common(u32 offset) {
u32 tg_lba = LEOcur_command->data.readwrite.lba;
u32 tg_blocks = LEOcur_command->data.readwrite.xfer_blks;
u32 message;
if ((tg_lba | tg_blocks) >> 0x10 != 0) {
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) {
LEOcur_command->header.sense = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION;
LEOcur_command->header.status = LEO_STATUS_GOOD;
return;
}
goto invalid_lba;
}
LEOtgt_param.lba = tg_lba;
LEOrw_flags &= 0x3FFF;
osSendMesg(&LEOc2ctrl_que, NULL, OS_MESG_NOBLOCK);
osStartThread(&LEOinterruptThread);
while (true) {
osRecvMesg(&LEOcontrol_que, (OSMesg)&message, OS_MESG_BLOCK);
switch (message) {
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;
case 0x90000:
LEOcur_command->header.sense = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION;
LEOcur_command->header.status = LEO_STATUS_GOOD;
return;
}
}
}

8
src/libleo/leotestunit.c Normal file
View File

@ -0,0 +1,8 @@
#include <ultra64.h>
#include "libleo/internal.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;
}

View File

@ -30,19 +30,15 @@ s32 LeoSetRTC(LEOCmd* cmdBlock, LEODiskTime* RTCdata, OSMesgQueue* mq) {
*/
// https://decomp.me/scratch/NUHIy
s32 leoVerifyRTC(u8 yearhi, u8 yearlo) {
u32 year;
s32 hiMask;
u32 loMask;
hiMask = yearhi & 0xFF;
loMask = yearlo & 0xFF;
if (((loMask & 0xF) >= 0xA) || ((loMask & 0xF0) >= 0x91) || ((hiMask & 0xF) >= 0xA) || ((hiMask & 0xF0) >= 0x91)) {
return 1;
}
year = (((hiMask - ((hiMask >> 4) * 6)) * 0x64) + loMask) - ((loMask >> 4) * 6);
if ((year < 0x7CCU) || (year >= 0x830U)) {
return 1;
}
return 0;
u32 year;
if (((yearlo & 0xF) >= 0xA) || ((yearlo & 0xF0) >= 0x91) || ((yearhi & 0xF) >= 0xA) || ((yearhi & 0xF0) >= 0x91)) {
return 1;
}
year = (((yearhi - ((yearhi >> 4) * 6)) * 0x64) + yearlo) - ((yearlo >> 4) * 6);
if ((year < 0x7CCU) || (year >= 0x830U)) {
return 1;
}
return 0;
}
#else
#pragma GLOBAL_ASM("asm/nonmatchings/libleo/setrtc/leoVerifyRTC.s")

View File

@ -40,6 +40,8 @@ __osGbpakSelectBank = 0x80065AD0;
__osGetId = 0x8005C894;
__osIdCheckSum = 0x8005C2E4;
__osLeoInterrupt = 0x80055DF0;
__osLeoAbnormalResume = 0x80056350;
__osLeoResume = 0x80056404;
__osPackEepReadData = 0x80065E44;
__osPackEepWriteData = 0x8005BEF8;
__osPackReadData = 0x80058F20;
@ -88,6 +90,30 @@ guScaleF = 0x80056CF0;
guTranslate = 0x8005E5E8;
guTranslateF = 0x8005E5A0;
ldiv = 0x80064C10;
LEOcur_command = 0x801006C8;
LEOPiInfo = 0x80100710;
unit_atten = 0x80100844;
asic_cur_status = 0x80100840;
currentCommand = 0x80100730;
LEOinterruptThread = 0x800FFC88;
LEOc2ctrl_que = 0x801006F8;
LEOcontrol_que = 0x80100668;
LEORAM_START_LBA = 0x8007DD18;
LEORAM_BYTE = 0x8007DD28;
LEOdrive_flag = 0x801006D4;
LEOevent_que = 0x80100650;
LEOtgt_param = 0x801006E0;
leoDiskStack = 0x801020D0;
LEOdisk_type = 0x801006D8;
LEO_country_code = 0x801006EC;
LEOrw_flags = 0x801006D6;
leoC2_Correction = 0x80053710;
leoC2_single_ecc = 0x8005379C;
leoC2_double_ecc = 0x80053870;
leoC2_3_ecc = 0x80053AF0;
leoC2_4_ecc = 0x80053ED8;
leoAlpha_mult = 0x80054774;
leoAlpha_div = 0x800547B8;
leoAnalize_asic_status = 0x80052D00;
leoChk_asic_ready = 0x80052E0C;
leoChk_cur_drvmode = 0x80053540;
@ -113,7 +139,9 @@ leoRead_system_area = 0x8005233C;
leoRecal_i = 0x800532EC;
leoRecal_w = 0x80053314;
leoRecv_event_mesg = 0x800533DC;
leoInitUnit_atten = 0x80053640;
leoRetUnit_atten = 0x800535BC;
leoChkUnit_atten = 0x800535B0;
leoRezero = 0x80054FB0;
leoSeek_i = 0x8005333C;
leoSeek_w = 0x800533A0;
@ -318,6 +346,7 @@ osTvType = 0x80000300;
__osGetCause = 0x80063E00;
CartRomHandle = 0x80102430;
LeoDiskHandle = 0x801024A8;
__LeoDiskHandle = 0x801007C0;
__osGlobalIntMask = 0x800796B0;
__osShutdown = 0x800796AC;
osViClock = 0x800796A8;
@ -327,6 +356,7 @@ alGlobals = 0x80079640;
guPerspectiveF = 0x8005A5C0;
guPerspective = 0x8005A7F0;
alSeqFileNew = 0x80058278;
__osDiskHandle = 0x80100834;
__osPiTable = 0x8007A87C;
osViRepeatLine = 0x8005B230;
osPfsIsPlug = 0x8005B2A0;
@ -387,6 +417,7 @@ __osPfsLastChannel = 0x8007AE50;
__osViDevMgr = 0x8007AE90;
__osLeoDevMgr = 0x80079514;
__leoActive = 0x800795B0;
__leoVersion = 0x801010D0;
__additional_scanline = 0x8007AEAC;
viThread = 0x80103950;
viThreadStack = 0x80103B00;