From 23c9dc7556cc19e0aedeee4babdb64ba18e60713 Mon Sep 17 00:00:00 2001 From: zerofrog Date: Sat, 5 Jan 2008 14:18:24 +0000 Subject: [PATCH] fps2bios: forgot a file --- fps2bios/kernel/eeload/eekernel.c | 3619 +++++++++++++++++++++++++++++ 1 file changed, 3619 insertions(+) create mode 100644 fps2bios/kernel/eeload/eekernel.c diff --git a/fps2bios/kernel/eeload/eekernel.c b/fps2bios/kernel/eeload/eekernel.c new file mode 100644 index 0000000..c6c3d54 --- /dev/null +++ b/fps2bios/kernel/eeload/eekernel.c @@ -0,0 +1,3619 @@ +//[module] KERNEL +//[processor] EE +//[type] RAW +//[size] 80880(0x13BF0) +//[bios] 10000(0xB3200-0xC6DF0) +//[iopboot] NA +//[loaded @] 80000000 +//[name] NA +//[version] NA +//[memory map] [too many, see mem.txt] +//[handlers] +//[entry point] ENTRYPOINT @ 0x80001000 +//[made by] [RO]man, zerofrog & others +#include +#include + +#include "eekernel.h" +#include "eeinit.h" +#include "eedebug.h" +#include "romdir.h" + +#define PS2_LOADADDR 0x82000 + +// internal functions +int InitPgifHandler(); +int InitPgifHandler2(); + +struct ll* LL_unlink(struct ll *l); +struct ll* LL_rotate(struct ll *l); +struct ll *LL_unlinkthis(struct ll *l); +void LL_add(struct ll *l, struct ll *new); + +extern int (*table_GetCop0[32])(int reg); // 124E8-12564 +extern int (*table_SetCop0[32])(int reg, int val); // 12568-125E4 + +void DefaultCPUTimerHandler(); +void _excepRet(u32 eretpc, u32 v1, u32 a, u32 a1, u32 a2); +int __ExitThread(); +int __ExitDeleteThread(); +int __SleepThread(); +int _iWaitSema(int sid); + +void saveContext(); +void restoreContext(); + +int _SemasInit(); + +void _ThreadHandler(u32 epc, u32 stack); +void _ChangeThread(u32 entry, u32 stack_res, int waitSema); + +int __DeleteThread(int tid); +int __StartThread(int tid, void *arg); +int __load_module(char *name, void (*entry)(void*), void *stack_res, int prio); +void* __ExecPS2(void * entry, void * gp, int argc, char ** argv); + +void releaseTCB(int tid); +void unsetTCB(int tid); +void thread_2_ready(int tid); + +void FlushInstructionCache(); +void FlushDataCache(); +void FlushSecondaryCache(); + +void SifDmaInit(); + +u32 excepRetPc=0;//124E4 +int threadId=0; // 125EC +int threadPrio=0; // 125F0 +int threadStatus=0; // 125F4 + +char threadArgStrBuffer[256]; // 12608 +u64 hvParam; + +u32 machineType; +u64 gsIMR; +u32 memorySize; + +u8 g_kernelstack[0x2000] __attribute((aligned(128))); +u32 g_kernelstackend; // hopefully this is right after g_kernelstack + +int _HandlersCount; + +int VSyncFlag0; +int VSyncFlag1; + +struct ll handler_ll_free, *ihandlers_last=NULL, *ihandlers_first=NULL; +struct HCinfo intcs_array[14]; +struct ll *dhandlers_last=NULL, *dhandlers_first=NULL; +struct HCinfo dmacs_array[15]; +struct IDhandl pgifhandlers_array[161]; +void (*sbus_handlers[32])(int ca); +void (*CPUTimerHandler)() = DefaultCPUTimerHandler; //12480 + +u64 _alarm_unk = 0; +u64 rcnt3Valid=0;//16A68 +int rcnt3Count = 0; //16A70 +u32 dword_80016A78, dword_80016A7C, dword_80016A84, dword_80016A88; +//u32 rcnt3gp; //16A80 +//u32 rcnt3Mode; //16A84 +int rcnt3TargetTable[0x142]={0};//16A80 +u8 rcnt3TargetNum[0x40];//16F78 +int threads_count=0; + +u32 excepRA=0;//16FC0 +u32 excepSP=0;//16FD0 + +struct ll thread_ll_free; +struct ll thread_ll_priorities[128]; +int semas_count=0; +struct kSema* semas_last=0; + +struct TCB threads_array[256]; +struct kSema semas_array[256]; + +char tagindex=0;//1E104 +short transferscount=0;//1E106 +struct TAG tadrptr[31] __attribute((aligned(16)));//1E140 +int extrastorage[(16/4) * 8][31] __attribute((aligned(16)));//1E340 + +int osdConfigParam;//1F340 + +u32 sifEEbuff[32] __attribute((aligned(16))); +u32 sifRegs[32] __attribute((aligned(16))); +u32 sifIOPbuff; +u32 sif1tagdata; + +void _eret() +{ + __asm__("mfc0 $26, $12\n" + "ori $26, 0x13\n" + "mtc0 $26, $12\n" + "sync\n" + "eret\n" + "nop\n"); +} + +#define eret() __asm__("j _eret\nnop\n"); + +//////////////////////////////////////////////////////////////////// +//800006C0 SYSCALL 116 RFU116_SetSYSCALL +//////////////////////////////////////////////////////////////////// +void _SetSYSCALL(int num, int address) +{ + table_SYSCALL[num] = (void (*)())address; +} + +//////////////////////////////////////////////////////////////////// +//80000740 SYSCALL 114 SetPgifHandler +//////////////////////////////////////////////////////////////////// +void _SetPgifHandler(void (*handler)(int)) +{ + INTCTable[15] = handler; +} + +//////////////////////////////////////////////////////////////////// +//800007C0 SYSCALL 108 SetCPUTimerHandler +//////////////////////////////////////////////////////////////////// +void _SetCPUTimerHandler(void (*handler)()) +{ + CPUTimerHandler = handler; +} + +//////////////////////////////////////////////////////////////////// +//80000800 SYSCALL 109 SetCPUTimer +//////////////////////////////////////////////////////////////////// +void _SetCPUTimer(int compval) +{ + if( compval < 0 ) { + u32 status; + __asm__("mfc0 %0, $12\n" : "=r"(status) : ); + __asm__("mtc0 %0, $12\n" + "mtc0 $0, $9\n" : : "r"(status|0x18001)); + } + else if( compval == 0 ) { + u32 compare, status; + __asm__("mfc0 %0, $12\n" + "mfc0 %1, $11\n" + : "=r"(status), "=r"(compare) : ); + __asm__("mtc0 %0, $12\n" + "mtc0 $0, $9\n" + "mtc0 %1, $11\n" + : : "r"(status&~0x8000), "r"(compare) ); + } + else { + __asm__("mtc0 $0, $9\n" // count + "mtc0 %0, $11\n" // compare + : : "r"(compval)); + } +} + +//////////////////////////////////////////////////////////////////// +//800008C0 SYSCALL 020 EnableIntc +//////////////////////////////////////////////////////////////////// +int __EnableIntc(int ch) +{ + int intbit; + + intbit = 0x1 << ch; + if ((INTC_MASK & intbit) != 0) return 0; + + INTC_MASK = intbit; + + return 1; +} + +//////////////////////////////////////////////////////////////////// +//80000900 SYSCALL 021 DisableIntc +//////////////////////////////////////////////////////////////////// +int __DisableIntc(int ch) +{ + int intbit; + + intbit = 0x1 << ch; + if ((INTC_MASK & intbit) == 0) return 0; + + INTC_MASK = intbit; + + return 1; +} + +//////////////////////////////////////////////////////////////////// +//80000940 SYSCALL 022 EnableDmac +//////////////////////////////////////////////////////////////////// +int __EnableDmac(int ch) +{ + int dmabit; + + dmabit = 0x10000 << ch; + if ((DMAC_STAT & dmabit) != 0) return 0; + + DMAC_STAT = dmabit; + + return 1; +} + +//////////////////////////////////////////////////////////////////// +//80000980 SYSCALL 023 DisableDmac +//////////////////////////////////////////////////////////////////// +int __DisableDmac(int ch) +{ + int dmabit; + + dmabit = 0x10000 << ch; + if ((DMAC_STAT & dmabit) == 0) return 0; + + DMAC_STAT = dmabit; + + return 1; +} + +//////////////////////////////////////////////////////////////////// +//800009C0 SYSCALL 013 SetVTLBRefillHandler +//////////////////////////////////////////////////////////////////// +void* _SetVTLBRefillHandler(int cause, void (*handler)()) +{ + if ((cause-1) >= 3) return 0; + + VCRTable[cause] = handler; + + return handler; +} + +//////////////////////////////////////////////////////////////////// +//80000A00 SYSCALL 014 SetVCommonHandler +//////////////////////////////////////////////////////////////////// +void* _SetVCommonHandler(int cause, void (*handler)()) +{ + if ((cause-4) >= 10) return 0; + + VCRTable[cause] = handler; + + return handler; +} + +//////////////////////////////////////////////////////////////////// +//80000A40 SYSCALL 015 SetVInterruptHandler +//////////////////////////////////////////////////////////////////// +void* _SetVInterruptHandler(int cause, void (*handler)()) +{ + if (cause >= 8) return 0; + + VIntTable[cause] = handler; + // no return value... +} + +//////////////////////////////////////////////////////////////////// +//80000A80 SYSCALL 102,106 CpuConfig +//////////////////////////////////////////////////////////////////// +u32 _CpuConfig(u32 op) +{ + u32 cfg; + __asm__("mfc0 %0, $16\n" : "=r"(cfg) : ); + return table_CpuConfig[op](cfg); +} + +//////////////////////////////////////////////////////////////////// +//80000AB8 +//////////////////////////////////////////////////////////////////// +u32 _CpuConfig_0(u32 cfg) +{ + cfg |= 0x40000; + __asm__("mtc0 %0, $16\n" + "sync\n": : "r"(cfg)); + return cfg; +} + +//////////////////////////////////////////////////////////////////// +//80000AD0 +//////////////////////////////////////////////////////////////////// +u32 _CpuConfig_1(u32 cfg) +{ + cfg |= 0x2000; + __asm__("mtc0 %0, $16\n" + "sync\n": : "r"(cfg)); + return cfg; +} + +//////////////////////////////////////////////////////////////////// +//80000AEC +//////////////////////////////////////////////////////////////////// +u32 _CpuConfig_2(u32 cfg) +{ + cfg |= 0x1000; + __asm__("mtc0 %0, $16\n" + "sync\n": : "r"(cfg)); + return cfg; +} + +//////////////////////////////////////////////////////////////////// +//80000B04 +//////////////////////////////////////////////////////////////////// +u32 _CpuConfig_3(u32 cfg) +{ + cfg &= ~0x40000; + __asm__("mtc0 %0, $16\n" + "sync\n": : "r"(cfg)); + return cfg; +} + +//////////////////////////////////////////////////////////////////// +//80000B20 +//////////////////////////////////////////////////////////////////// +u32 _CpuConfig_4(u32 cfg) +{ + cfg &= ~0x2000; + __asm__("mtc0 %0, $16\n" + "sync\n": : "r"(cfg)); + return cfg; +} + +//////////////////////////////////////////////////////////////////// +//80000B40 +//////////////////////////////////////////////////////////////////// +u32 _CpuConfig_5(u32 cfg) +{ + cfg &= ~0x1000; + __asm__("mtc0 %0, $16\n" + "sync\n": : "r"(cfg)); + return cfg; +} + +//////////////////////////////////////////////////////////////////// +//80000B80 SYSCALL 125 PSMode +//////////////////////////////////////////////////////////////////// +void _PSMode() +{ + machineType|= 0x8000; +} + +//////////////////////////////////////////////////////////////////// +//80000BC0 SYSCALL 126 MachineType +//////////////////////////////////////////////////////////////////// +u32 _MachineType() +{ + return machineType; +} + +//////////////////////////////////////////////////////////////////// +//80000C00 +//////////////////////////////////////////////////////////////////// +u32 _SetMemorySize(u32 size) +{ + memorySize = size; + return size; +} + +//////////////////////////////////////////////////////////////////// +//80000C40 SYSCALL 127 GetMemorySize +//////////////////////////////////////////////////////////////////// +u32 _GetMemorySize() +{ + return memorySize; +} + +//////////////////////////////////////////////////////////////////// +//80000D00 SYSCALL 112 GsGetIMR +//////////////////////////////////////////////////////////////////// +u64 _GsGetIMR() +{ + return gsIMR; +} + +//////////////////////////////////////////////////////////////////// +//80000D40 SYSCALL 113 GsPutIMR +//////////////////////////////////////////////////////////////////// +u64 _GsPutIMR(u64 val) +{ + GS_IMR = val; + gsIMR = val; + return val; +} + +//////////////////////////////////////////////////////////////////// +//80000D80 SYSCALL 002 Exit +//////////////////////////////////////////////////////////////////// +int _Exit() +{ + return _RFU004_Exit(); +} + +//////////////////////////////////////////////////////////////////// +//80001000 ENTRYPOINT +//////////////////////////////////////////////////////////////////// +void __attribute__((noreturn)) _start() +{ + __asm__("lui $sp, %hi(g_kernelstackend)\n" + "addiu $sp, %lo(g_kernelstackend)\n"); + + __puts("EEKERNEL start\n"); + + memorySize = 32*1024*1024; + machineType = 0; + //memorySize = *(int*)0x70003FF0; + //machineType = machine_type; + + __printf("TlbInit\n"); + TlbInit(); + __printf("InitPgifHandler\n"); + InitPgifHandler(); + __printf("Initialize\n"); + Initialize(); +// __load_module_EENULL(); + + __asm__ ( + "li $26, %0\n" + "lw $26, 0($26)\n" + "mtc0 $26, $12\n" + "li $26, %1\n" + "lw $26, 0($26)\n" + "mtc0 $26, $16\n" + : : "i"(SRInitVal), "i"(ConfigInitVal) + ); + +// ee_deci2_manager_init(); + SifDmaInit(); +// __init_unk(0x81FE0); + SetVSyncFlag(0, 0); + + // call directly instread of loading module, might need to + // set thread0 as used since soem code assumes thread 0 is always + // main thread + //eeload_start(); + //launch_thread(__load_module("EELOAD", 0x82000, 0x81000, 0)); + + for (;;); +} + +//////////////////////////////////////////////////////////////////// +//80001300 +//////////////////////////////////////////////////////////////////// +void saveContext2() { + __asm__ ( + ".set noat\n" + "lui $26, %hi(SavedRegs)\n" + "sq $2, %lo(SavedRegs+0x000)($26)\n" + "sq $3, %lo(SavedRegs+0x010)($26)\n" + "sq $4, %lo(SavedRegs+0x020)($26)\n" + "sq $5, %lo(SavedRegs+0x030)($26)\n" + "sq $6, %lo(SavedRegs+0x040)($26)\n" + "sq $7, %lo(SavedRegs+0x050)($26)\n" + "sq $8, %lo(SavedRegs+0x060)($26)\n" + "sq $9, %lo(SavedRegs+0x070)($26)\n" + "sq $10, %lo(SavedRegs+0x080)($26)\n" + "sq $11, %lo(SavedRegs+0x090)($26)\n" + "sq $12, %lo(SavedRegs+0x0A0)($26)\n" + "sq $13, %lo(SavedRegs+0x0B0)($26)\n" + "sq $14, %lo(SavedRegs+0x0C0)($26)\n" + "sq $15, %lo(SavedRegs+0x0D0)($26)\n" + "sq $16, %lo(SavedRegs+0x0E0)($26)\n" + "sq $17, %lo(SavedRegs+0x0F0)($26)\n" + "sq $18, %lo(SavedRegs+0x100)($26)\n" + "sq $19, %lo(SavedRegs+0x110)($26)\n" + "sq $20, %lo(SavedRegs+0x120)($26)\n" + "sq $21, %lo(SavedRegs+0x130)($26)\n" + "sq $22, %lo(SavedRegs+0x140)($26)\n" + "sq $23, %lo(SavedRegs+0x150)($26)\n" + "sq $24, %lo(SavedRegs+0x160)($26)\n" + "sq $25, %lo(SavedRegs+0x170)($26)\n" + "sq $gp, %lo(SavedRegs+0x180)($26)\n" + "sq $fp, %lo(SavedRegs+0x190)($26)\n" + + "mfhi $2\n" + "sd $2, %lo(SavedRegs+0x1A0)($26)\n" + "mfhi1 $2\n" + "sd $2, %lo(SavedRegs+0x1A8)($26)\n" + + "mflo $2\n" + "sd $2, %lo(SavedRegs+0x1B0)($26)\n" + "mflo1 $2\n" + "sd $2, %lo(SavedRegs+0x1B8)($26)\n" + + "mfsa $2\n" + "sd $2, %lo(SavedRegs+0x1C0)($26)\n" + "jr $31\n" + "nop\n" + ".set at\n" + ); +} + +//////////////////////////////////////////////////////////////////// +//800013C0 +//////////////////////////////////////////////////////////////////// +void restoreContext2() { + __asm__ ( + ".set noat\n" + "lui $26, %hi(SavedRegs)\n" + "lq $2, %lo(SavedRegs+0x000)($26)\n" + "lq $3, %lo(SavedRegs+0x010)($26)\n" + "lq $4, %lo(SavedRegs+0x020)($26)\n" + "lq $5, %lo(SavedRegs+0x030)($26)\n" + "lq $6, %lo(SavedRegs+0x040)($26)\n" + "lq $7, %lo(SavedRegs+0x050)($26)\n" + "lq $8, %lo(SavedRegs+0x060)($26)\n" + "lq $9, %lo(SavedRegs+0x070)($26)\n" + "lq $10, %lo(SavedRegs+0x080)($26)\n" + "lq $11, %lo(SavedRegs+0x090)($26)\n" + "lq $12, %lo(SavedRegs+0x0A0)($26)\n" + "lq $13, %lo(SavedRegs+0x0B0)($26)\n" + "lq $14, %lo(SavedRegs+0x0C0)($26)\n" + "lq $15, %lo(SavedRegs+0x0D0)($26)\n" + "lq $16, %lo(SavedRegs+0x0E0)($26)\n" + "lq $17, %lo(SavedRegs+0x0F0)($26)\n" + "lq $18, %lo(SavedRegs+0x100)($26)\n" + "lq $19, %lo(SavedRegs+0x110)($26)\n" + "lq $20, %lo(SavedRegs+0x120)($26)\n" + "lq $21, %lo(SavedRegs+0x130)($26)\n" + "lq $22, %lo(SavedRegs+0x140)($26)\n" + "lq $23, %lo(SavedRegs+0x150)($26)\n" + "lq $24, %lo(SavedRegs+0x160)($26)\n" + "lq $25, %lo(SavedRegs+0x170)($26)\n" + "lq $gp, %lo(SavedRegs+0x180)($26)\n" + "lq $fp, %lo(SavedRegs+0x190)($26)\n" + + "ld $1, %lo(SavedRegs+0x1A0)($26)\n" + "mthi $1\n" + "ld $1, %lo(SavedRegs+0x1A8)($26)\n" + "mthi1 $1\n" + + "ld $1, %lo(SavedRegs+0x1B0)($26)\n" + "mtlo $1\n" + "ld $1, %lo(SavedRegs+0x1B8)($26)\n" + "mtlo1 $1\n" + + "ld $1, %lo(SavedRegs+0x1C0)($26)\n" + "mtsa $1\n" + + "jr $31\n" + "nop\n" + ".set at\n" + ); +} + +//////////////////////////////////////////////////////////////////// +//80001460 +//////////////////////////////////////////////////////////////////// +void erase_cpu_regs() +{ + __asm__( + ".set noat\n" + "padduw $1, $0, $0\n" + "padduw $2, $0, $0\n" + "padduw $3, $0, $0\n" + "padduw $4, $0, $0\n" + "padduw $5, $0, $0\n" + "padduw $6, $0, $0\n" + "padduw $7, $0, $0\n" + "padduw $8, $0, $0\n" + "padduw $9, $0, $0\n" + "padduw $10, $0, $0\n" + "padduw $11, $0, $0\n" + "padduw $12, $0, $0\n" + "padduw $13, $0, $0\n" + "padduw $14, $0, $0\n" + "padduw $15, $0, $0\n" + "padduw $16, $0, $0\n" + "padduw $17, $0, $0\n" + "padduw $18, $0, $0\n" + "padduw $19, $0, $0\n" + "padduw $20, $0, $0\n" + "padduw $21, $0, $0\n" + "padduw $22, $0, $0\n" + "padduw $23, $0, $0\n" + "padduw $24, $0, $0\n" + "padduw $25, $0, $0\n" + "padduw $gp, $0, $0\n" + "jr $31\n" + "padduw $fp, $0, $0\n" + ".set at\n" + ); +} + +//////////////////////////////////////////////////////////////////// +//800014D8 dummy intc handler +//////////////////////////////////////////////////////////////////// +void _DummyINTCHandler(int n) +{ + __printf("# INT: INTC (%d)\n", n); + while(1) { __asm__ ("nop\nnop\nnop\nnop\n"); } +} + +//////////////////////////////////////////////////////////////////// +//80001508 dummy dmac handler +//////////////////////////////////////////////////////////////////// +void _DummyDMACHandler(int n) +{ + __printf("# INT: DMAC (%d)\n", n); + while(1) { __asm__ ("nop\nnop\nnop\nnop\n"); } +} + +//////////////////////////////////////////////////////////////////// +//80001508 +//////////////////////////////////////////////////////////////////// +void DefaultCPUTimerHandler() +{ + __printf("# INT: CPU Timer\n"); +} + +//////////////////////////////////////////////////////////////////// +//80001564 SYSCALL 000 RFU000_FullReset +//80001564 SYSCALL 003 RFU003 (also) +//80001564 SYSCALL 008 RFU008 (too) +//////////////////////////////////////////////////////////////////// +void _RFU___() +{ + register int syscnum __asm__("$3"); + __printf("# Syscall: undefined (%d)\n", syscnum>>2); +} + +//////////////////////////////////////////////////////////////////// +//80001588 +//////////////////////////////////////////////////////////////////// +void _SetVSyncFlag(int flag0, int flag1) +{ + VSyncFlag0 = flag0; + VSyncFlag1 = flag1; +} + +//////////////////////////////////////////////////////////////////// +//800015A0 +//////////////////////////////////////////////////////////////////// +struct ll* _AddHandler() +{ + struct ll *l; + + l = LL_unlink(&handler_ll_free); + if (l == NULL) return NULL; + + _HandlersCount++; + return l; +} + +//////////////////////////////////////////////////////////////////// +//800015E8 +//////////////////////////////////////////////////////////////////// +void _RemoveHandler(int n) +{ + LL_add(&handler_ll_free, (struct ll*)&pgifhandlers_array[n]); + _HandlersCount--; +} + +//////////////////////////////////////////////////////////////////// +//80001630 +//////////////////////////////////////////////////////////////////// +void DefaultINTCHandler(int n) +{ + //TODO +} + +//////////////////////////////////////////////////////////////////// +//80001798 +//////////////////////////////////////////////////////////////////// +void DefaultDMACHandler(int n) +{ + //TODO +} + +//////////////////////////////////////////////////////////////////// +//800018B0 +//////////////////////////////////////////////////////////////////// +int __AddIntcHandler(int cause, int (*handler)(int), int next, void *arg, int flag) +{ + struct IDhandl *idh; + + if ((flag != 0) && (cause == INTC_SBUS)) return -1; + if (cause >= 15) return -1; + + idh = (struct IDhandl *)_AddHandler(); + if (idh == 0) return -1; + + idh->handler = handler; + __asm__ ("sw $gp, %0\n" : "=m"(idh->gp) : ); + idh->arg = arg; + idh->flag = flag; + + if (next==-1) //register_last + LL_add(&ihandlers_last[cause*12], (struct ll*)idh); + else if (next==0) //register_first + LL_add(&ihandlers_first[cause*12], (struct ll*)idh); + else{ + if (next>128) return -1; + if (pgifhandlers_array[next].flag==3) return -1; + LL_add((struct ll*)&pgifhandlers_array[next], (struct ll*)idh); + } + + intcs_array[cause].count++; + return (((u32)idh-(u32)&pgifhandlers_array) * 0xAAAAAAAB) / 8; +} + +//////////////////////////////////////////////////////////////////// +//80001A30 SYSCALL 016 AddIntcHandler +//////////////////////////////////////////////////////////////////// +int _AddIntcHandler(int cause, int (*handler)(int), int next, void *arg) +{ + __AddIntcHandler(cause, handler, next, arg, 2); +} + +//////////////////////////////////////////////////////////////////// +//80001A50 +//////////////////////////////////////////////////////////////////// +int _AddIntcHandler2(int cause, int (*handler)(int), int next, void *arg) +{ + __AddIntcHandler(cause, handler, next, arg, 0); +} + +//////////////////////////////////////////////////////////////////// +//80001AC8 SYSCALL 017 RemoveIntcHandler +//////////////////////////////////////////////////////////////////// +int _RemoveIntcHandler(int cause, int hid) +{ + if (hid >= 128) return -1; + + if (pgifhandlers_array[hid].flag == 3) return -1; + pgifhandlers_array[hid].flag = 3; + pgifhandlers_array[hid].handler = 0; + + LL_unlinkthis((struct ll*)&pgifhandlers_array[hid]); + _RemoveHandler(hid); + + intcs_array[cause].count--; +} + +//////////////////////////////////////////////////////////////////// +//80001B10 +//////////////////////////////////////////////////////////////////// +int __AddDmacHandler(int cause, int (*handler)(int), int next, void *arg, int flag) +{ + struct IDhandl *idh; + register int temp; + + if (cause >= 16) return -1; + + idh = (struct IDhandl *)_AddHandler(); + if (idh == 0) return -1; + + idh->handler = handler; + __asm__ ("sw $gp, %0\n" : "=m"(idh->gp) : ); + idh->arg = arg; + idh->flag = flag; + + if (next==-1) //register_last + LL_add(&dhandlers_last[cause*12], (struct ll*)idh); + else if (next==0) //register_first + LL_add(&dhandlers_first[cause*12], (struct ll*)idh); + else{ + if (next>128) return -1; + if (pgifhandlers_array[next].flag==3) return -1; + LL_add((struct ll*)&pgifhandlers_array[next], (struct ll*)idh); + } + + dmacs_array[cause].count++; + return (((u32)idh-(u32)&pgifhandlers_array) * 0xAAAAAAAB) / 8; +} + +//////////////////////////////////////////////////////////////////// +//80001C78 SYSCALL 018 AddDmacHandler +//////////////////////////////////////////////////////////////////// +int _AddDmacHandler(int cause, int (*handler)(int), int next, void *arg) +{ + __AddDmacHandler(cause, handler, next, arg, 2); +} + +//////////////////////////////////////////////////////////////////// +//80001C98 +//////////////////////////////////////////////////////////////////// +int _AddDmacHandler2(int cause, int (*handler)(int), int next, void *arg) +{ + __AddDmacHandler(cause, handler, next, arg, 0); +} + +//////////////////////////////////////////////////////////////////// +//80001CB8 SYSCALL 019 RemoveDmacHandler +//////////////////////////////////////////////////////////////////// +int _RemoveDmacHandler(int cause, int hid) +{ + if (hid >= 128) return -1; + + if (pgifhandlers_array[hid].flag == 3) return -1; + pgifhandlers_array[hid].flag = 3; + pgifhandlers_array[hid].handler = 0; + + LL_unlinkthis((struct ll*)&pgifhandlers_array[hid]); + _RemoveHandler(hid); + + dmacs_array[cause].count--; +} + +//////////////////////////////////////////////////////////////////// +//80001D58 +//////////////////////////////////////////////////////////////////// +void sbusHandler() +{ + //TODO +} + +//////////////////////////////////////////////////////////////////// +//80001E38 +//////////////////////////////////////////////////////////////////// +int __AddSbusIntcHandler(int cause, void (*handler)(int ca)) +{ + if (cause >= 32) return -1; + + if (sbus_handlers[cause] != 0) return -1; + + sbus_handlers[cause] = handler; + return cause; +} + +//////////////////////////////////////////////////////////////////// +//80001E78 SYSCALL 010 AddSbusIntcHandler +//////////////////////////////////////////////////////////////////// +int _AddSbusIntcHandler(int cause, void (*handler)(int ca)) +{ + if (cause < 16) return __AddSbusIntcHandler(cause, handler); + + return -1; +} + +//////////////////////////////////////////////////////////////////// +//80001EA8 +//////////////////////////////////////////////////////////////////// +int __RemoveSbusIntcHandler(int cause) +{ + if (cause >= 32) return -1; + + sbus_handlers[cause] = 0; + return cause; +} + +//////////////////////////////////////////////////////////////////// +//80001ED0 SYSCALL 011 RemoveSbusIntcHandler +//////////////////////////////////////////////////////////////////// +int _RemoveSbusIntcHandler(int cause) +{ + if (cause < 16) return __RemoveSbusIntcHandler(cause); + + return -1; +} + +//////////////////////////////////////////////////////////////////// +//80001F00 +//////////////////////////////////////////////////////////////////// +int __Interrupt2Iop(int cause) +{ + if (cause >= 32) { + return -1; + } + + SBUS_MSFLG = 1 << cause; + + SBUS_F240 = 0x100; + SBUS_F240 = 0x100; + SBUS_F240 = 0x100; + SBUS_F240 = 0x100; + SBUS_F240 = 0x100; + SBUS_F240 = 0x100; + SBUS_F240 = 0x100; + SBUS_F240 = 0x100; // eight times + + SBUS_F240 = 0x40100; + + return cause; +} + +//////////////////////////////////////////////////////////////////// +//80001F70 SYSCALL 012 Interrupt2Iop +//////////////////////////////////////////////////////////////////// +int _Interrupt2Iop(int cause) +{ + if (cause < 16) { + return _Interrupt2Iop(cause); + } else { + return -1; + } +} + +//////////////////////////////////////////////////////////////////// +//80001FA0 SYSCALL 092 EnableIntcHandler +//////////////////////////////////////////////////////////////////// +void _EnableIntcHandler(u32 id) +{ + pgifhandlers_array[id].flag = 2; +} + +//////////////////////////////////////////////////////////////////// +//80001FA0 SYSCALL 093 DisableIntcHandler +//////////////////////////////////////////////////////////////////// +void _DisableIntcHandler(u32 id) +{ + pgifhandlers_array[id].flag = 1; +} + +//////////////////////////////////////////////////////////////////// +//80001FA0 SYSCALL 094 EnableDmacHandler +//////////////////////////////////////////////////////////////////// +void _EnableDmacHandler(u32 id) +{ + pgifhandlers_array[id].flag = 2; +} + +//////////////////////////////////////////////////////////////////// +//80001FA0 SYSCALL 095 DisableDmacHandler +//////////////////////////////////////////////////////////////////// +void _DisableDmacHandler(u32 id) +{ + pgifhandlers_array[id].flag = 1; +} + +//////////////////////////////////////////////////////////////////// +//80002040 SYSCALL 083 iSetEventFlag +//////////////////////////////////////////////////////////////////// +int _iSetEventFlag(int ef, u32 bits) +{ + return _HandlersCount; //? +} + +//////////////////////////////////////////////////////////////////// +//800022D8 SYSCALL 24,30 +//////////////////////////////////////////////////////////////////// +int _SetAlarm(short a0, int a1, int a2) +{ + int mode = _alarm_unk & 0x1; + int i; + + i = 0; + while (mode) { + mode = (_alarm_unk >> i++) & 0x1; + if (i >= 64) { + return -1; + } + } + + _alarm_unk|= mode << i; + + __asm__("move %0, $gp\n" : "=r"(rcnt3TargetTable[0]) : ); + dword_80016A78 = a1; + dword_80016A7C = a2; + rcnt3TargetTable[1] = RCNT3_MODE; + i = RCNT3_MODE + a0; + if (i < -1) + i&= 0xffff; + dword_80016A88 = i; + + if (RCNT3_MODE < i) { + if (rcnt3Count <= 0) { + + } + } +} + +//////////////////////////////////////////////////////////////////// +//80002570 SYSCALL 25,31 ReleaseAlarm +//////////////////////////////////////////////////////////////////// +void _ReleaseAlarm() +{ + //TODO +} + +//////////////////////////////////////////////////////////////////// +//80002650 +//////////////////////////////////////////////////////////////////// +void rcnt3Handler() +{ + unsigned int i; + u32* ptr; + u32 storegp; + u32 addr; + + if (rcnt3Count < 2) { + RCNT3_MODE = 0x483; + } else { + RCNT3_MODE = 0x583; + RCNT3_TARGET = rcnt3TargetTable[2+rcnt3TargetNum[1] * 5]; + } + + for (;;) { + u32 id = (u32)rcnt3TargetNum[0]; + if (--rcnt3Count >= 0) { + // shift one down + for (i=0; i= 0) { + if (addr != rcnt3TargetTable[rcnt3TargetNum[0] * 5 + 2]) { + break; + } + } else break; + } +} + +//////////////////////////////////////////////////////////////////// +//800027F8 SYSCALL 082 SetEventFlag +//////////////////////////////////////////////////////////////////// +int _SetEventFlag(int ef, u32 bits) +{ + return rcnt3Count; //? +} + +//////////////////////////////////////////////////////////////////// +//800027F8 +//////////////////////////////////////////////////////////////////// +void _InitRCNT3() +{ + int i; + + rcnt3Count = 0; + rcnt3Valid = 0; + _alarm_unk = 0; + for (i=0; i<0x40; i++) rcnt3TargetNum[i] = 0; + + __EnableIntc(INTC_TIM3); +} + +//////////////////////////////////////////////////////////////////// +//80002840 +//////////////////////////////////////////////////////////////////// +void _excepRet(u32 eretpc, u32 v1, u32 a, u32 a1, u32 a2) +{ + __asm__("sw $31, %0\n" + "sw $sp, %1\n" + : "=m"(excepRA), "=m"(excepSP) : ); + __asm__("mtc0 $4, $14\n" + "sync\n" + "daddu $3, $5, $0\n" + "daddu $4, $6, $0\n" + "daddu $5, $7, $0\n" + "daddu $6, $8, $0\n" + "mfc0 $26, $12\n" + "ori $26, 0x12\n" + "mtc0 $26, $12\n" + "sync\n" + "eret\n" + "nop\n"); +} + +//////////////////////////////////////////////////////////////////// +//80002880 SYSCALL 005 RFU005 +//////////////////////////////////////////////////////////////////// +void _RFU005() +{ + __asm__ ( + ".set noat\n" + + "mfc0 $26, $12\n" + "ori $1, $0, 0xFFE4\n" + "and $26, $1\n" + "mtc0 $26, $12\n" + "sync\n" + + "lw $ra, excepRA\n" + "lw $sp, excepSP\n" + "jr $ra\n" + "nop\n" + + ".set at\n"); +} + +//////////////////////////////////////////////////////////////////// +//A00028C0 SYSCALL 097 EnableCache +//////////////////////////////////////////////////////////////////// +int _EnableCache(int cache) +{ + u32 cfg; + __asm__("mfc0 %0, $16\n" : "=r"(cfg) : ); + cfg |= ((cache&3)<<16); + __asm__("mtc0 %0, $16\n" + "sync\n" : : "r"(cfg) ); +} + +//////////////////////////////////////////////////////////////////// +//A0002980 SYSCALL 098 DisableCache +//////////////////////////////////////////////////////////////////// +int _DisableCache(int cache) +{ + u32 cfg; + __asm__("mfc0 %0, $16\n" : "=r"(cfg) : ); + cfg &= ~((cache&3)<<16); + __asm__("mtc0 %0, $16\n" + "sync\n" : : "r"(cfg) ); +} + +//////////////////////////////////////////////////////////////////// +//A0002A40 SYSCALL 100 FlushCache +//////////////////////////////////////////////////////////////////// +void _FlushCache(int op) +{ + if( op == 0 ) FlushInstructionCache(); + else if ( op == 1 ) FlushSecondaryCache(); + else if( op == 2 ) FlushDataCache(); + else { + FlushSecondaryCache(); + FlushDataCache(); + } +} + +//////////////////////////////////////////////////////////////////// +//80002AC0 +//////////////////////////////////////////////////////////////////// +void FlushInstructionCache() +{ +} + +//////////////////////////////////////////////////////////////////// +//80002A80 +//////////////////////////////////////////////////////////////////// +void FlushDataCache() +{ +} + +//////////////////////////////////////////////////////////////////// +//80002B00 +//////////////////////////////////////////////////////////////////// +void FlushSecondaryCache() +{ +} + +//////////////////////////////////////////////////////////////////// +//A0002B40 SYSCALL 101,105 _105 +//////////////////////////////////////////////////////////////////// +void _105(int op1, int op2) +{ + // flushing caches again +} + +//////////////////////////////////////////////////////////////////// +//A0002C00 SYSCALL 096 KSeg0 +//////////////////////////////////////////////////////////////////// +void _KSeg0(u32 arg) +{ + u32 cfg; + __asm__("mfc0 %0, $16\n" : "=r"(cfg) : ); + cfg = (arg&3)&((cfg>>3)<<3); // yes it is 0, don't ask + __asm__("mtc0 %0, $16\n" + "sync\n" : : "r"(cfg) ); +} + +//////////////////////////////////////////////////////////////////// +//80002C40 SYSCALL 099 GetCop0 +//////////////////////////////////////////////////////////////////// +int _GetCop0(int reg) +{ + return table_GetCop0[reg](reg); +} + +//////////////////////////////////////////////////////////////////// +//80002C58-80002D50 calls for table_GetCop0 +//////////////////////////////////////////////////////////////////// +int GetCop0_Index(int reg) { __asm__(" mfc0 $2, $0\n"); } +int GetCop0_Random(int reg) { __asm__(" mfc0 $2, $1\n"); } +int GetCop0_EntryLo0(int reg) { __asm__(" mfc0 $2, $2\n"); } +int GetCop0_EntryLo1(int reg) { __asm__(" mfc0 $2, $3\n"); } + +int GetCop0_Context(int reg) { __asm__(" mfc0 $2, $4\n"); } +int GetCop0_PageMask(int reg) { __asm__(" mfc0 $2, $5\n"); } +int GetCop0_Wired(int reg) { __asm__(" mfc0 $2, $6\n"); } +int GetCop0_Reg7(int reg) { return; } + +int GetCop0_BadVAddr(int reg) { __asm__(" mfc0 $2, $8\n"); } +int GetCop0_Count(int reg) { __asm__(" mfc0 $2, $9\n"); } +int GetCop0_EntryHi(int reg) { __asm__(" mfc0 $2, $10\n"); } +int GetCop0_Compare(int reg) { __asm__(" mfc0 $2, $11\n"); } + +int GetCop0_Status(int reg) { __asm__(" mfc0 $2, $12\n"); } +int GetCop0_Cause(int reg) { __asm__(" mfc0 $2, $13\n"); } +int GetCop0_ExceptPC(int reg) { __asm__(" mfc0 $2, $14\n"); } +int GetCop0_PRevID(int reg) { __asm__(" mfc0 $2, $15\n"); } + +int GetCop0_Config(int reg) { __asm__(" mfc0 $2, $16\n"); } +int GetCop0_Reg17(int reg) { return; } +int GetCop0_Reg18(int reg) { return; } +int GetCop0_Reg19(int reg) { return; } + +int GetCop0_Reg20(int reg) { return; } +int GetCop0_Reg21(int reg) { return; } +int GetCop0_Reg22(int reg) { return; } +int GetCop0_Reg23(int reg) { __asm__(" mfc0 $2, $23\n"); } + +int GetCop0_DebugReg24(int reg) { __asm__(" mfc0 $2, $24\n"); } +int GetCop0_Perf(int reg) { __asm__(" mfc0 $2, $25\n"); } +int GetCop0_Reg26(int reg) { return; } +int GetCop0_Reg27(int reg) { return; } + +int GetCop0_TagLo(int reg) { __asm__(" mfc0 $2, $28\n"); } +int GetCop0_TagHi(int reg) { __asm__(" mfc0 $2, $29\n"); } +int GetCop0_ErrorPC(int reg) { __asm__(" mfc0 $2, $30\n"); } +int GetCop0_Reg31(int reg) { return; } + +int (*table_GetCop0[32])(int reg) = { // 800124E8 + GetCop0_Index, GetCop0_Random, GetCop0_EntryLo0, GetCop0_EntryLo1, + GetCop0_Context, GetCop0_PageMask, GetCop0_Wired, GetCop0_Reg7, + GetCop0_BadVAddr, GetCop0_Count, GetCop0_EntryHi, GetCop0_Compare, + GetCop0_Status, GetCop0_Cause, GetCop0_ExceptPC, GetCop0_PRevID, + GetCop0_Config, GetCop0_Reg17, GetCop0_Reg18, GetCop0_Reg19, + GetCop0_Reg20, GetCop0_Reg21, GetCop0_Reg22, GetCop0_Reg23, + GetCop0_DebugReg24, GetCop0_Perf, GetCop0_Reg26, GetCop0_Reg27, + GetCop0_TagLo, GetCop0_TagHi, GetCop0_ErrorPC, GetCop0_Reg31 +}; + +//////////////////////////////////////////////////////////////////// +//80002D80 +//////////////////////////////////////////////////////////////////// +int SetCop0(int reg, int val) +{ + return table_SetCop0[reg](reg, val); +} + +//////////////////////////////////////////////////////////////////// +//80002D98-80002F74 calls for table_SetCop0 +//////////////////////////////////////////////////////////////////// +int SetCop0_Index(int reg, int val) { __asm__(" mfc0 $2, $0\nmtc0 %0, $0\nsync\n" : : "r"(val)); } +int SetCop0_Random(int reg, int val) { return -1; } +int SetCop0_EntryLo0(int reg, int val) { __asm__(" mfc0 $2, $2\nmtc0 %0, $2\nsync\n" : : "r"(val)); } +int SetCop0_EntryLo1(int reg, int val) { __asm__(" mfc0 $2, $3\nmtc0 %0, $3\nsync\n" : : "r"(val)); } + +int SetCop0_Context(int reg, int val) { __asm__(" mfc0 $2, $4\nmtc0 %0, $4\nsync\n" : : "r"(val)); } +int SetCop0_PageMask(int reg, int val) { __asm__(" mfc0 $2, $5\nmtc0 %0, $5\nsync\n" : : "r"(val)); } +int SetCop0_Wired(int reg, int val) { __asm__(" mfc0 $2, $6\nmtc0 %0, $6\nsync\n" : : "r"(val)); } +int SetCop0_Reg7(int reg, int val) { return -1; } + +int SetCop0_BadVAddr(int reg, int val) { return -1; } +int SetCop0_Count(int reg, int val) { __asm__(" mfc0 $2, $9\nmtc0 %0, $9\nsync\n" : : "r"(val)); } +int SetCop0_EntryHi(int reg, int val) { __asm__(" mfc0 $2, $10\nmtc0 %0, $10\nsync\n" : : "r"(val)); } +int SetCop0_Compare(int reg, int val) { __asm__(" mfc0 $2, $11\nmtc0 %0, $11\nsync\n" : : "r"(val)); } + +int SetCop0_Status(int reg, int val) { __asm__(" mfc0 $2, $12\nmtc0 %0, $12\nsync\n" : : "r"(val)); } +int SetCop0_Cause(int reg, int val) { return -1; } +int SetCop0_ExceptPC(int reg, int val) { __asm__(" mfc0 $2, $14\nmtc0 %0, $14\nsync\n" : : "r"(val)); } +int SetCop0_PRevID(int reg, int val) { return -1; } + +int SetCop0_Config(int reg, int val) { __asm__(" mfc0 $2, $16\nmtc0 %0, $16\nsync\n" : : "r"(val)); } +int SetCop0_Reg17(int reg, int val) { return -1; } +int SetCop0_Reg18(int reg, int val) { return -1; } +int SetCop0_Reg19(int reg, int val) { return -1; } + +int SetCop0_Reg20(int reg, int val) { return -1; } +int SetCop0_Reg21(int reg, int val) { return -1; } +int SetCop0_Reg22(int reg, int val) { return -1; } +int SetCop0_Reg23(int reg, int val) { __asm__(" mfc0 $2, $23\nmtc0 %0, $23\nsync\n" : : "r"(val)); } + +int SetCop0_DebugReg24(int reg, int val){ __asm__(" mfc0 $2, $24\nmtc0 %0, $24\nsync\n" : : "r"(val)); } +int SetCop0_Perf(int reg, int val) { __asm__(" mfc0 $2, $25\nmtc0 %0, $25\nsync\n" : : "r"(val)); } +int SetCop0_Reg26(int reg, int val) { return -1; } +int SetCop0_Reg27(int reg, int val) { return -1; } + +int SetCop0_TagLo(int reg, int val) { __asm__(" mfc0 $2, $28\nmtc0 %0, $28\nsync\n" : : "r"(val)); } +int SetCop0_TagHi(int reg, int val) { __asm__(" mfc0 $2, $29\nmtc0 %0, $29\nsync\n" : : "r"(val)); } +int SetCop0_ErrorPC(int reg, int val) { __asm__(" mfc0 $2, $30\nmtc0 %0, $30\nsync\n" : : "r"(val)); } +int SetCop0_Reg31(int reg, int val) { return -1; } + +int (*table_SetCop0[32])(int reg, int val) = { // 80012568 + SetCop0_Index, SetCop0_Random, SetCop0_EntryLo0, SetCop0_EntryLo1, + SetCop0_Context, SetCop0_PageMask, SetCop0_Wired, SetCop0_Reg7, + SetCop0_BadVAddr, SetCop0_Count, SetCop0_EntryHi, SetCop0_Compare, + SetCop0_Status, SetCop0_Cause, SetCop0_ExceptPC, SetCop0_PRevID, + SetCop0_Config, SetCop0_Reg17, SetCop0_Reg18, SetCop0_Reg19, + SetCop0_Reg20, SetCop0_Reg21, SetCop0_Reg22, SetCop0_Reg23, + SetCop0_DebugReg24, SetCop0_Perf, SetCop0_Reg26, SetCop0_Reg27, + SetCop0_TagLo, SetCop0_TagHi, SetCop0_ErrorPC, SetCop0_Reg31 +}; + +//////////////////////////////////////////////////////////////////// +//80002F80 SYSCALL 007 ExecPS2 +//////////////////////////////////////////////////////////////////// +int _ExecPS2(void * entry, void * gp, int argc, char ** argv) +{ + saveContext(); + __ExecPS2(entry, gp, argc, argv); + __asm__("mtc0 $2, $14\n" + "move $sp, %0\n" + "sd $2, 0x20($sp)\n" + : : "r"(SavedSP)); + + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//80002FC0 SYSCALL 033 DeleteThread +//////////////////////////////////////////////////////////////////// +int _DeleteThread(int tid) +{ + register int ret __asm__("$2"); + register u32 curepc __asm__("$4"); + + saveContext(); + + ret = __DeleteThread(tid); + if (ret < 0) { + __asm__("lw $sp, %0\n" : : "m"(SavedSP)); + // make sure the return value is also stored + __asm__("sd $2, 0x20($sp)\n"); + + restoreContext(); + eret(); + } + + + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); // EPC + _ThreadHandler(curepc, SavedSP); // returns entry in $3, stack in $4 + + __asm__("mtc0 $2, $14\n" + "move $sp, $3\n"); + + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//80003040 SYSCALL 034 StartThread +//////////////////////////////////////////////////////////////////// +int _StartThread(int tid, void *arg) +{ + register int ret __asm__("$2"); + register u32 curepc __asm__("$4"); + + saveContext(); + + ret = __StartThread(tid, arg); + + if (ret < 0) { + __asm__("lw $sp, %0\n" : : "m"(SavedSP)); + // make sure the return value is also stored + __asm__("sd $2, 0x20($sp)\n"); + + restoreContext(); + eret(); + } + + + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); // EPC + _ThreadHandler(curepc, SavedSP); // returns entry in $3, stack in $4 + + __asm__("mtc0 $2, $14\n" + "move $sp, $3\n"); + + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//800030C0 SYSCALL 035 ExitThread +//////////////////////////////////////////////////////////////////// +int _ExitThread() +{ + saveContext(); + + __ExitThread(); + __asm__("mtc0 $2, $14\n" + "sync\n" + "move $sp, $3\n"); + + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//80003100 SYSCALL 036 ExitDeleteThread +//////////////////////////////////////////////////////////////////// +int _ExitDeleteThread() +{ + saveContext(); + + __ExitDeleteThread(); + __asm__("mtc0 $2, $14\n" + "sync\n" + "move $sp, $3\n"); + + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//80003140 SYSCALL 037 TerminateThread +//////////////////////////////////////////////////////////////////// +int _TerminateThread(int tid) +{ + register int ret __asm__("$2"); + register u32 curepc __asm__("$4"); + + saveContext(); + + ret = _iTerminateThread(tid); + + if( ret < 0 ) { + __asm__("lw $sp, %0\n" : : "m"(SavedSP)); + // make sure the return value is also stored + __asm__("sd $2, 0x20($sp)\n"); + + restoreContext(); + eret(); + } + + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); // EPC + _ThreadHandler(curepc, SavedSP); // returns entry in $3, stack in $4 + + __asm__("mtc0 $2, $14\n" + "move $sp, $3\n"); + + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//800031C0 SYSCALL 043 RotateThreadReadyQueue +//////////////////////////////////////////////////////////////////// +void _RotateThreadReadyQueue(int pri) +{ + register int ret __asm__("$2"); + register u32 curepc __asm__("$4"); + + ret = pri; + saveContext(); + + ret = _iRotateThreadReadyQueue(pri); + + if( ret < 0 ) { + __asm__("lw $sp, %0\n" : : "m"(SavedSP)); + // make sure the return value is also stored + __asm__("sd $2, 0x20($sp)\n"); + + restoreContext(); + eret(); + } + + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); // EPC + _ThreadHandler(curepc, SavedSP); // returns entry in $3, stack in $4 + + __asm__("mtc0 $2, $14\n" + "move $sp, $3\n"); + + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//80003240 SYSCALL 045 ReleaseWaitThread +//////////////////////////////////////////////////////////////////// +void _ReleaseWaitThread(int tid) +{ + register int ret __asm__("$2"); + register u32 curepc __asm__("$4"); + + ret = tid; + saveContext(); + + ret = _iReleaseWaitThread(tid); + + if( ret < 0 ) { + __asm__("lw $sp, %0\n" : : "m"(SavedSP)); + // make sure the return value is also stored + __asm__("sd $2, 0x20($sp)\n"); + + restoreContext(); + eret(); + } + + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); // EPC + _ThreadHandler(curepc, SavedSP); // returns entry in $3, stack in $4 + + __asm__("mtc0 $2, $14\n" + "move $sp, $3\n"); + + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//800032C0 SYSCALL 052 SleepThread +//////////////////////////////////////////////////////////////////// +int _SleepThread() +{ + register int ret __asm__("$2"); + + ret = threadId; + saveContext(); + + ret = __SleepThread(); + if (ret < 0) { + register int curepc __asm__("$4"); + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); + _ChangeThread(curepc, SavedSP, 1); + + __asm__("mtc0 $2, $14\n" + "sync\n" + "move $sp, $3\n"); + restoreContext(); + eret(); + } + + __asm__("lw $sp, %0\n" + "sd %1, 0x20($sp)\n" : : "m"(SavedSP), "r"(ret) ); + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//80003340 SYSCALL 051 WakeupThread +//////////////////////////////////////////////////////////////////// +int _WakeupThread(int tid) +{ + register int ret __asm__("$2"); + + ret = tid; + saveContext(); + + ret = iWakeupThread(tid); + if( ret >= 0 ) { + register int curepc __asm__("$4"); + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); + _ThreadHandler(curepc, SavedSP); + + __asm__("mtc0 $2, $14\n" + "sync\n" + "move $sp, $3\n"); + restoreContext(); + eret(); + } + + __asm__("lw $sp, %0\n" + "sd %1, 0x20($sp)\n" : : "m"(SavedSP), "r"(ret) ); + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//800033C0 SYSCALL 057 ResumeThread +//////////////////////////////////////////////////////////////////// +int _ResumeThread(int tid) +{ + register int ret __asm__("$2"); + + ret = tid; + saveContext(); + + ret = _iResumeThread(tid); + if( ret >= 0 ) { + register int curepc __asm__("$4"); + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); + _ThreadHandler(curepc, SavedSP); + + __asm__("mtc0 $2, $14\n" + "sync\n" + "move $sp, $3\n"); + restoreContext(); + eret(); + } + + __asm__("lw $sp, %0\n" + "sd %1, 0x20($sp)\n" : : "m"(SavedSP), "r"(ret) ); + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//80003440 SYSCALL 068 WaitSema +//////////////////////////////////////////////////////////////////// +int _WaitSema(int sid) +{ + register int ret __asm__("$2"); + + ret = sid; + saveContext(); + + ret = _iWaitSema(sid); + if( ret == 0xFFFFFFFE ) { + register int curepc __asm__("$4"); + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); + _ChangeThread(curepc, SavedSP, 2); + + __asm__("mtc0 $2, $14\n" + "sync\n" + "move $sp, $3\n"); + restoreContext(); + eret(); + } + + __asm__("lw $sp, %0\n" : : "m"(SavedSP)); + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//800034C0 SYSCALL 066 SignalSema +//////////////////////////////////////////////////////////////////// +void _SignalSema(int sid) +{ + register int ret __asm__("$2"); + + ret = sid; + saveContext(); + + ret = _iSignalSema(sid); + if( ret >= 0 ) { + register int curepc __asm__("$4"); + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); + _ThreadHandler(curepc, SavedSP); + + __asm__("mtc0 $2, $14\n" + "sync\n" + "move $sp, $3\n"); + restoreContext(); + eret(); + } + + __asm__("lw $sp, %0\n" + "sd %1, 0x20($sp)\n" : : "m"(SavedSP), "r"(ret) ); + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//80003540 SYSCALL 065 DeleteSema +//////////////////////////////////////////////////////////////////// +int _DeleteSema(int sid) +{ + register int ret __asm__("$2"); + + ret = sid; + saveContext(); + + ret = _iDeleteSema(sid); + if( ret >= 0 ) { + register int curepc __asm__("$4"); + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); + _ThreadHandler(curepc, SavedSP); + + __asm__("mtc0 $2, $14\n" + "sync\n" + "move $sp, $3\n"); + restoreContext(); + eret(); + } + + __asm__("lw $sp, %0\n" + "sd %1, 0x20($sp)\n" : : "m"(SavedSP), "r"(ret) ); + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//800035C0 SYSCALL 041 ChangeThreadPriority +//return has to be void (even though it fills in v0) +//////////////////////////////////////////////////////////////////// +void _ChangeThreadPriority(int tid, int prio) +{ + register int ret __asm__("$2"); + + saveContext(); + ret = _iChangeThreadPriority(tid, prio); + + __asm__("lw $26, %0\n" + "sd %1, 0x20($26)\n" : : "m"(SavedSP), "r"(ret) ); + + if (ret>=0){ + register int curepc __asm__("$4"); + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); + _ThreadHandler(curepc, SavedSP); + + __asm__("mtc0 $2, $14\n" + "sync\n" + "move $sp, $3\n"); + restoreContext(); + eret(); + } + + // why twice? + __asm__("lw $sp, %0\n" + "sd %1, 0x20($sp)\n" : : "m"(SavedSP), "r"(ret) ); + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//8000363C +//////////////////////////////////////////////////////////////////// +void __ThreadHandler() +{ + register int curepc __asm__("$4"); + + saveContext(); + + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); + _ThreadHandler(curepc, SavedSP); + __asm__("mtc0 $2, $14\n" + "sync\n" + "move $sp, $3\n"); + restoreContext(); + eret(); +} + +//////////////////////////////////////////////////////////////////// +//80003680 +//////////////////////////////////////////////////////////////////// +void saveContext() +{ + __asm__ ( + "lui $26, %hi(SavedSP)\n" + "lq $26, %lo(SavedSP)($26)\n" + ); + __asm__ ( + "addiu $26, %0\n" + : : "i"(-sizeof(struct threadCtx)) + ); + __asm__ ( + ".set noat\n" + "lui $1, %hi(SavedAT)\n" + "lq $1, %lo(SavedAT)($1)\n" + "sq $1, 0x000($26)\n" + "sq $2, 0x010($26)\n" + "sq $3, 0x020($26)\n" + "sq $4, 0x030($26)\n" + "sq $5, 0x040($26)\n" + "sq $6, 0x050($26)\n" + "sq $7, 0x060($26)\n" + "sq $8, 0x070($26)\n" + "sq $9, 0x080($26)\n" + "sq $10, 0x090($26)\n" + "sq $11, 0x0A0($26)\n" + "sq $12, 0x0B0($26)\n" + "sq $13, 0x0C0($26)\n" + "sq $14, 0x0D0($26)\n" + "sq $15, 0x0E0($26)\n" + "sq $16, 0x0F0($26)\n" + "sq $17, 0x100($26)\n" + "sq $18, 0x110($26)\n" + "sq $19, 0x120($26)\n" + "sq $20, 0x130($26)\n" + "sq $21, 0x140($26)\n" + "sq $22, 0x150($26)\n" + "sq $23, 0x160($26)\n" + "sq $24, 0x170($26)\n" + "sq $25, 0x180($26)\n" + "sq $gp, 0x190($26)\n" + "lui $1, %hi(SavedSP)\n" + "lq $sp, %lo(SavedSP)($1)\n" + "sq $sp, 0x1A0($26)\n" + "sq $fp, 0x1B0($26)\n" + "lui $1, %hi(SavedRA)\n" + "lq $1, %lo(SavedRA)($1)\n" + "sq $1, 0x1C0($26)\n" + + "swc1 $0, 0x200($26)\n" + "swc1 $1, 0x204($26)\n" + "swc1 $2, 0x208($26)\n" + "swc1 $3, 0x20C($26)\n" + "swc1 $4, 0x210($26)\n" + "swc1 $5, 0x214($26)\n" + "swc1 $6, 0x218($26)\n" + "swc1 $7, 0x21C($26)\n" + "swc1 $8, 0x220($26)\n" + "swc1 $9, 0x224($26)\n" + "swc1 $10, 0x228($26)\n" + "swc1 $11, 0x22C($26)\n" + "swc1 $12, 0x230($26)\n" + "swc1 $13, 0x234($26)\n" + "swc1 $14, 0x238($26)\n" + "swc1 $15, 0x23C($26)\n" + "swc1 $16, 0x240($26)\n" + "swc1 $17, 0x244($26)\n" + "swc1 $18, 0x248($26)\n" + "swc1 $19, 0x24C($26)\n" + "swc1 $20, 0x250($26)\n" + "swc1 $21, 0x254($26)\n" + "swc1 $22, 0x258($26)\n" + "swc1 $23, 0x25C($26)\n" + "swc1 $24, 0x260($26)\n" + "swc1 $25, 0x264($26)\n" + "swc1 $26, 0x268($26)\n" + "swc1 $27, 0x26C($26)\n" + "swc1 $28, 0x270($26)\n" + "swc1 $29, 0x274($26)\n" + "swc1 $30, 0x278($26)\n" + "swc1 $31, 0x27C($26)\n" + + "mfsa $1\n" + "sw $1, 0x1F0($26)\n" + + "cfc1 $1, $31\n" + "sw $1, 0x1F4($26)\n" + + "lui $1, 0x8000\n" + "mtc1 $1, $1\n" + "mtc1 $1, $0\n" + "madd.s $f0, $f0, $f1\n" + "swc1 $0, 0x1F8($26)\n" + + "mfhi $1\n" + "sd $1, 0x1D0($26)\n" + "mfhi1 $1\n" + "sd $1, 0x1D8($26)\n" + + "mflo $1\n" + "sd $1, 0x1E0($26)\n" + "mflo1 $1\n" + "sd $1, 0x1E8($26)\n" + + "lui $1, %hi(SavedSP)\n" + "sw $26, %lo(SavedSP)($1)\n" + + "jr $31\n" + "lui $1, 0x8000\n" + ".set at\n" + ); +} + +//////////////////////////////////////////////////////////////////// +//80003800 +//////////////////////////////////////////////////////////////////// +void restoreContext() +{ + __asm__ ( + ".set noat\n" + + "lui $26, 0x8000\n" + "mtc1 $26, $1\n" + "lwc1 $0, 0x1F8($sp)\n" + "adda.s $f0, $f1\n" + + "lw $26, 0x1F0($sp)\n" + "mtsa $26\n" + + "lw $26, 0x1F4($sp)\n" + "ctc1 $26, $31\n" + + "ld $26, 0x1D0($sp)\n" + "mthi $26\n" + "ld $26, 0x1D8($sp)\n" + "mthi1 $26\n" + + "ld $26, 0x1E0($sp)\n" + "mtlo $26\n" + "ld $26, 0x1E8($sp)\n" + "mtlo1 $26\n" + + "lq $1, 0x000($sp)\n" + "lq $2, 0x010($sp)\n" + "lq $3, 0x020($sp)\n" + "lq $4, 0x030($sp)\n" + "lq $5, 0x040($sp)\n" + "lq $6, 0x050($sp)\n" + "lq $7, 0x060($sp)\n" + "lq $8, 0x070($sp)\n" + "lq $9, 0x080($sp)\n" + "lq $10, 0x090($sp)\n" + "lq $11, 0x0A0($sp)\n" + "lq $12, 0x0B0($sp)\n" + "lq $13, 0x0C0($sp)\n" + "lq $14, 0x0D0($sp)\n" + "lq $15, 0x0E0($sp)\n" + "lq $16, 0x0F0($sp)\n" + "lq $17, 0x100($sp)\n" + "lq $18, 0x110($sp)\n" + "lq $19, 0x120($sp)\n" + "lq $20, 0x130($sp)\n" + "lq $21, 0x140($sp)\n" + "lq $22, 0x150($sp)\n" + "lq $23, 0x160($sp)\n" + "lq $24, 0x170($sp)\n" + "lq $25, 0x180($sp)\n" + "lq $gp, 0x190($sp)\n" + "lq $fp, 0x1B0($sp)\n" + + "lwc1 $0, 0x200($sp)\n" + "lwc1 $1, 0x204($sp)\n" + "lwc1 $2, 0x208($sp)\n" + "lwc1 $3, 0x20C($sp)\n" + "lwc1 $4, 0x210($sp)\n" + "lwc1 $5, 0x214($sp)\n" + "lwc1 $6, 0x218($sp)\n" + "lwc1 $7, 0x21C($sp)\n" + "lwc1 $8, 0x220($sp)\n" + "lwc1 $9, 0x224($sp)\n" + "lwc1 $10, 0x228($sp)\n" + "lwc1 $11, 0x22C($sp)\n" + "lwc1 $12, 0x230($sp)\n" + "lwc1 $13, 0x234($sp)\n" + "lwc1 $14, 0x238($sp)\n" + "lwc1 $15, 0x23C($sp)\n" + "lwc1 $16, 0x240($sp)\n" + "lwc1 $17, 0x244($sp)\n" + "lwc1 $18, 0x248($sp)\n" + "lwc1 $19, 0x24C($sp)\n" + "lwc1 $20, 0x250($sp)\n" + "lwc1 $21, 0x254($sp)\n" + "lwc1 $22, 0x258($sp)\n" + "lwc1 $23, 0x25C($sp)\n" + "lwc1 $24, 0x260($sp)\n" + "lwc1 $25, 0x264($sp)\n" + "lwc1 $26, 0x268($sp)\n" + "lwc1 $27, 0x26C($sp)\n" + "lwc1 $28, 0x270($sp)\n" + "lwc1 $29, 0x274($sp)\n" + "lwc1 $30, 0x278($sp)\n" + "lwc1 $31, 0x27C($sp)\n" + "daddu $26, $31, $0\n" + "lq $31, 0x1C0($sp)\n" + "jr $26\n" + "lq $sp, 0x1A0($sp)\n" + ".set at\n" + ); +} + +//////////////////////////////////////////////////////////////////// +//80003940 +//////////////////////////////////////////////////////////////////// +void _ThreadHandler(u32 epc, u32 stack) +{ + register int tid; + + threads_array[threadId].entry =(void*)epc; + threads_array[threadId].status =THS_READY; + threads_array[threadId].stack_res =(void*)stack; + + for ( ; threadPrio < 129; threadPrio++) + if ((thread_ll_priorities[threadPrio].next != + &thread_ll_priorities[threadPrio]) || + (thread_ll_priorities[threadPrio].prev != + &thread_ll_priorities[threadPrio])){ + tid=threadId=(( (u32)thread_ll_priorities[threadPrio].prev - + (u32)threads_array)*0x286BCA1B)>>2; + break; + } + + if (threadPrio>=129){ + __printf("# No active threads\n"); + Exit(1); + tid=0; + } + + threads_array[tid].status=THS_RUN; + + if (threads_array[tid].waitSema){ + threads_array[tid].waitSema=0; + *(u32*)((u32)threads_array[tid].stack_res + 0x20) = -1; + } + + __asm__("move $2, %0\n" + "move $3, %1\n" + : : "r"(threads_array[tid].entry), "r"(threads_array[tid].stack_res) ); +} + +//////////////////////////////////////////////////////////////////// +//80003A78 +//////////////////////////////////////////////////////////////////// +void _ChangeThread(u32 entry, u32 stack_res, int waitSema) +{ + struct TCB *th; + struct ll *l, *p; + int prio; + + th = &threads_array[threadId]; + th->status = THS_WAIT; + th->waitSema = waitSema; + th->entry = (void (*)(void*))entry; + th->stack_res = (void*)stack_res; + + prio = threadPrio; + for (l = &thread_ll_priorities[prio]; ; l++, prio++) { + if (prio >= 129) { + __printf("# No active threads\n"); + Exit(1); l = 0; break; + } + + if (l->next != l) { p = l->next; break; } + if (l->prev == l) continue; + p = l->prev; break; + } + + if (l) { + threadPrio = prio; + threadId = (((u32)p - (u32)threads_array) * 0x286BCA1B) / 4; + } + + th = &threads_array[threadId]; + th->status = THS_RUN; + if (th->waitSema) { + th->waitSema = 0; + *(s64*)((u32)th->stack_res+0x20) = -1; + } + + __asm__("move $2, %0\n" + "move $3, %1\n" + : : "r"(th->entry), "r"(th->stack_res) ); +} + +//////////////////////////////////////////////////////////////////// +//80003C50 SYSCALL 032 CreateThread +//////////////////////////////////////////////////////////////////// +int _CreateThread(struct ThreadParam *param) +{ + struct TCB *th; + struct threadCtx *thctx; + int index; + int *ptr; + + th = (struct TCB *)LL_unlink((struct ll*)&thread_ll_free); + if (th == NULL) { + __printf("%s: failed to get free thread\n", __FUNCTION__); + return -1; + } + + threads_count++; + index=(((u32)th-(u32)threads_array) * 0x286BCA1B)/4; + + th->entry = param->entry; + th->stack_res = param->stack + param->stackSize - STACK_RES; + th->status = THS_DORMANT; + th->gpReg = param->gpReg; + th->initPriority = param->initPriority; + th->argstring = 0; + th->wakeupCount = 0; + th->semaId = 0; + th->stack = param->stack; + th->argc = 0; + th->entry_ = param->entry; + th->heap_base = threads_array[threadId].heap_base; + th->stackSize = param->stackSize; + th->currentPriority = param->initPriority; + th->waitSema = 0; + th->root = threads_array[threadId].root; + + thctx = th->stack_res; + thctx->gp = (u32)param->gpReg; + thctx->sp = (u32)&thctx[1]; + thctx->fp = (u32)&thctx[1]; + thctx->ra = (u32)threads_array[threadId].root; + + return index; +} + +//////////////////////////////////////////////////////////////////// +//80003E00 SYSCALL 37 iTerminateThread +//////////////////////////////////////////////////////////////////// +int _iTerminateThread(int tid) +{ + //TODO +} + +//////////////////////////////////////////////////////////////////// +//80003F00 +//////////////////////////////////////////////////////////////////// +int __DeleteThread(int tid) +{ + if ((tid>=256) || (tid==threadId) || (threads_array[tid].status!=THS_DORMANT)) + return -1; + + releaseTCB(tid); + return tid; +} + +//////////////////////////////////////////////////////////////////// +//80003F70 +//////////////////////////////////////////////////////////////////// +int __StartThread(int tid, void *arg) +{ + if ((tid>=256) || (tid==threadId) || (threads_array[tid].status!=THS_DORMANT)) + return -1; + + threads_array[tid].argstring = arg; + ((void**)threads_array[tid].stack_res)[0x10] = arg; //a0 + thread_2_ready(tid); + return tid; +} + +//////////////////////////////////////////////////////////////////// +//80003FF8 +//////////////////////////////////////////////////////////////////// +int __ExitThread() +{ + //TODO +} + +//////////////////////////////////////////////////////////////////// +//80004110 +//////////////////////////////////////////////////////////////////// +int __ExitDeleteThread() +{ + //TODO +} + +//////////////////////////////////////////////////////////////////// +//80004228 SYSCALL 39 DisableDispatchThread +//////////////////////////////////////////////////////////////////// +int _DisableDispatchThread() +{ + __printf("# DisableDispatchThread is not supported in this version\n"); + return threadId; +} + +//////////////////////////////////////////////////////////////////// +//80004258 SYSCALL 40 EnableDispatchThread +//////////////////////////////////////////////////////////////////// +int _EnableDispatchThread() +{ + __printf("# EnableDispatchThread is not supported in this version\n"); + return threadId; +} + +//////////////////////////////////////////////////////////////////// +//80004288 SYSCALL 042 iChangeThreadPriority +//////////////////////////////////////////////////////////////////// +int _iChangeThreadPriority(int tid, int prio) +{ + short oldPrio; + + if ((tid >= 256) || (prio < 0) || (prio >= 128)) return -1; + + if (tid == 0) tid = threadId; + if (threads_array[tid].status == 0) return -1; + if ((0 < (threads_array[tid].status ^ 0x10)) == 0) return -1; + + oldPrio = threads_array[tid].currentPriority; + if ((tid != threadId) && (threads_array[tid].status != THS_READY)) { + threads_array[tid].currentPriority = prio; + return oldPrio; + } + + if (threadPrio < prio) threadStatus = 1; + + unsetTCB(tid); + threads_array[tid].currentPriority = prio; + thread_2_ready(tid); + + return oldPrio; +} + +//////////////////////////////////////////////////////////////////// +//80004388 SYSCALL 044 iRotateThreadReadyQueue +//////////////////////////////////////////////////////////////////// +int _iRotateThreadReadyQueue(int prio) +{ + if (prio >= 128) return -1; + + LL_rotate(&thread_ll_priorities[prio]); + return prio; +} + +//////////////////////////////////////////////////////////////////// +//800043D0 SYSCALL 046 iReleaseWaitThread +//////////////////////////////////////////////////////////////////// +int _iReleaseWaitThread(int tid) +{ + if( (u32)(tid-1) >= 255 ) + return -1; + + if( (u32)threads_array[tid].status >= 17 ) + return tid; + + switch(threads_array[tid].status) { + case 0: + return -1; + case THS_WAIT: { + //443C + if( threads_array[tid].waitSema == 2 ) { + LL_unlinkthis((struct ll*)&threads_array[tid]); + semas_array[threads_array[tid].semaId].wait_threads--; + } + + int threadPrioOld = threadPrio; + threads_array[tid].status = THS_READY; + thread_2_ready(tid); + + if( threadPrio < threadPrioOld ) { + threadStatus = 1; + } + break; + } + case (THS_WAIT|THS_SUSPEND): + threads_array[tid].status = THS_SUSPEND; + if( threads_array[tid].waitSema != 2 ) + return tid; + + LL_unlinkthis((struct ll*)&threads_array[tid]); + semas_array[threads_array[tid].semaId].wait_threads--; + break; + } + + return tid; +} + +//////////////////////////////////////////////////////////////////// +//80004548 SYSCALL 047 GetThreadId +//////////////////////////////////////////////////////////////////// +int _GetThreadId() +{ + return threadId; +} + +//////////////////////////////////////////////////////////////////// +//80004558 SYSCALL 048 ReferThreadStatus +//////////////////////////////////////////////////////////////////// +int _ReferThreadStatus(int tid, struct ThreadParam *info) +{ + if (tid >= 256) return -1; + if (tid == 0) tid = threadId; + + if (info != NULL) { + info->entry = threads_array[tid].entry; + info->status = threads_array[tid].status; + info->stack = threads_array[tid].stack; + info->stackSize = threads_array[tid].stackSize; + info->gpReg = threads_array[tid].gpReg; + info->initPriority = threads_array[tid].initPriority; + info->currentPriority = threads_array[tid].currentPriority; + info->attr = threads_array[tid].attr; + info->waitSema = threads_array[tid].waitSema; + info->option = threads_array[tid].option; + info->waitId = threads_array[tid].semaId; + info->wakeupCount = threads_array[tid].wakeupCount; + } + + return threads_array[tid].status; +} + +//////////////////////////////////////////////////////////////////// +//80004658 +//////////////////////////////////////////////////////////////////// +int __SleepThread() +{ + if (threads_array[threadId].wakeupCount <= 0) { + unsetTCB(threadId); + return -1; + } + + threads_array[threadId].wakeupCount--; + return threadId; +} + +//////////////////////////////////////////////////////////////////// +//800046B0 SYSCALL 052 iWakeupThread +//////////////////////////////////////////////////////////////////// +int _iWakeupThread(int tid) +{ + register int prio; + + if (tid>=256) return -1; + + if (tid==0) tid = threadId; + + switch (threads_array[tid].status){ + case THS_WAIT: + if (threads_array[tid].waitSema=1){ + prio=threadPrio; + thread_2_ready(tid); + if (threadPrio=256) return -1; + tid = tid ? tid : threadId; + ret=threads_array[tid].wakeupCount; + threads_array[tid].wakeupCount=0; + return ret; +} + +//////////////////////////////////////////////////////////////////// +//800049B0 SYSCALL 080 RFU080_CreateEventFlag +//////////////////////////////////////////////////////////////////// +int _CreateEventFlag() +{ + return threads_count; // CreateEventFlag, why!?! +} + +//////////////////////////////////////////////////////////////////// +//800049C0 SYSCALL 064 CreateSema +//////////////////////////////////////////////////////////////////// +int _CreateSema(struct SemaParam *sema) +{ + register struct kSema *crt=semas_last; + + if ((crt==NULL) || (sema->init_count<0)) return -1; + + crt->wait_prev = (struct TCB*)&crt->wait_next; + semas_count++; + crt->count =sema->init_count; + crt->wait_next =(struct TCB*)&crt->wait_next; + semas_last = crt->free; + crt->max_count =sema->max_count; + crt->free =NULL; + crt->attr =sema->attr; + crt->wait_threads=0; + crt->option =sema->option; + + return (crt-semas_array); //sizeof(kSema)==32 +} + +//////////////////////////////////////////////////////////////////// +//80004A48 SYSCALL 073 iDeleteSema +//////////////////////////////////////////////////////////////////// +int _iDeleteSema(int sid) +{ + register thid, thprio; + if ((sid>=MAX_SEMAS) || (semas_array[sid].count<0)) return -1; + + semas_count--; + while (semas_array[sid].wait_threads>0){ + thid=(((u32)LL_unlink((struct ll*)&semas_array[sid].wait_next)-(u32)threads_array) * 0x286BCA1B)/4; + LL_unlinkthis((struct ll*)&threads_array[thid]); + semas_array[sid].wait_threads--; + if (threads_array[thid].status==THS_WAIT){ + thprio=threadPrio; + thread_2_ready(thid); + if (threadPrio=MAX_SEMAS) || (semas_array[sid].count<0)) return -1; + + if (semas_array[sid].wait_threads>0){ + thid=(((u32)LL_unlink((struct ll*)&semas_array[sid].wait_next)-(u32)threads_array)*0x286BCA1B)/4; + + LL_unlinkthis((struct ll*)&threads_array[thid]); + + semas_array[sid].wait_threads--; + + if (threads_array[thid].status==THS_WAIT){ + prio=threadPrio; + thread_2_ready(thid); + if (threadPrio < prio) + threadStatus=THS_RUN; + threads_array[thid].waitSema=0; //just a guess:P + } + else if (threads_array[thid].status==(THS_WAIT|THS_SUSPEND)){ + threads_array[thid].status =THS_SUSPEND; + threads_array[thid].waitSema=0; + } + }else + semas_array[sid].count++; + return sid; +} + +//////////////////////////////////////////////////////////////////// +//80004CF8 +//////////////////////////////////////////////////////////////////// +int _iWaitSema(int sid) +{ + if ((sid>=MAX_SEMAS) || (semas_array[sid].count<0)) return -1; + + if (semas_array[sid].count>0){ + semas_array[sid].count--; + return sid; + } + + semas_array[sid].wait_threads++; + + unsetTCB(threadId); + LL_add((struct ll*)&semas_array[sid].wait_next, (struct ll*)&threads_array[threadId]); + threads_array[threadId].semaId=sid; + + return -2; +} + +//////////////////////////////////////////////////////////////////// +//80004DC8 SYSCALL 069 PollSema, 070 iPollSema +//////////////////////////////////////////////////////////////////// +int _PollSema(int sid) +{ + if ((sid>=MAX_SEMAS) || (semas_array[sid].count<=0)) return -1; + + semas_array[sid].count--; + + return sid; +} + +//////////////////////////////////////////////////////////////////// +//80004E00 SYSCALL 071 ReferSemaStatus, 072 iReferSemaStatus +//////////////////////////////////////////////////////////////////// +int _ReferSemaStatus(int sid, struct SemaParam *sema) +{ + if ((sid>=MAX_SEMAS) || (semas_array[sid].count<0)) return -1; + + sema->count =semas_array[sid].count; + sema->max_count =semas_array[sid].max_count; + sema->wait_threads =semas_array[sid].wait_threads; + sema->attr =semas_array[sid].attr; + sema->option =semas_array[sid].option; + + return sid; +} + +//////////////////////////////////////////////////////////////////// +//80004E58 SYSCALL 081 RFU081_DeleteEventFlag +//////////////////////////////////////////////////////////////////// +int _DeleteEventFlag() +{ + return semas_count; // DeleteEventFlag, why!?! +} + +//////////////////////////////////////////////////////////////////// +//80004E68 +//////////////////////////////////////////////////////////////////// +int _SemasInit() +{ + int i; + + for (i=0; i<256; i++) { + semas_array[i].free = &semas_array[i+1]; + semas_array[i].count = -1; + semas_array[i].wait_threads = 0; + semas_array[i].wait_next = (struct TCB*)&semas_array[i].wait_next; + semas_array[i].wait_prev = (struct TCB*)&semas_array[i].wait_next; + } + semas_array[255].free = 0; + + semas_last = semas_array; + semas_count = 0; + + return 256; +} + +//////////////////////////////////////////////////////////////////// +//80004EC8 +//////////////////////////////////////////////////////////////////// +void __load_module_EENULL() +{ + int i; + + thread_ll_free.prev = &thread_ll_free; + thread_ll_free.next = &thread_ll_free; + + for (i=0; i<128; i++) { + thread_ll_priorities[i].prev = &thread_ll_priorities[i]; + thread_ll_priorities[i].next = &thread_ll_priorities[i]; + } + + threads_count = 0; + threadId = 0; + threadPrio = 0; + + for (i=0; i<256; i++) { + threads_array[i].status = 0; + LL_add(&thread_ll_free, (struct ll*)&threads_array[i]); + } + + _SemasInit(); + + threadStatus = 0; + __load_module("EENULL", (void (*)(void*))0x81FC0, (void*)0x81000, 0x80); +} + +//////////////////////////////////////////////////////////////////// +//80004FB0 +// makes the args from argc & argstring; args is in bss of program +//////////////////////////////////////////////////////////////////// +void _InitArgs(char *argstring, ARGS *args, int argc) +{ + int i; + char *p = args->args; + + args->argc = argc; + for (i=0; iargv[i] = p; //copy string pointer + while (*argstring) //copy the string itself + *p++ = *argstring++; + *p++ = *argstring++; //copy the '\0' + } +} + +//////////////////////////////////////////////////////////////////// +//80005198 SYSCALL 060 _InitializeMainThread +//////////////////////////////////////////////////////////////////// +void *_InitializeMainThread(u32 gp, void *stack, int stack_size, char *args, int root) +{ + struct TCB *th; + struct threadCtx *ctx; + + if ((int)stack == -1) + stack = (void*)((_GetMemorySize() - 4*1024) - stack_size); + + ctx = (struct threadCtx*)((u32)stack + stack_size - STACK_RES/4); + ctx->gp = gp; //+1C0 + ctx->ra = root; //+1F0 + ctx->fp = (u32)ctx+0x280; //+1E0 <- &280 + ctx->sp = (u32)ctx+0x280; //+1D0 <- &280 + + th = &threads_array[threadId]; + th->gpReg = (void*)gp; + th->stackSize = stack_size; + th->stack_res = ctx; + th->stack = stack; + th->root = (void*)root; + _InitArgs(th->argstring, (ARGS*)args, th->argc); + th->argstring = args; + + return ctx; +} + +//////////////////////////////////////////////////////////////////// +//800052A0 SYSCALL 061 RFU061_InitializeHeapArea +//////////////////////////////////////////////////////////////////// +void* _InitializeHeapArea(void *heap_base, int heap_size) +{ + void *ret; + + if (heap_size < 0) { + ret = threads_array[threadId].stack; + } else { + ret = heap_base + heap_size; + } + + threads_array[threadId].heap_base = ret; + return ret; +} + +//////////////////////////////////////////////////////////////////// +//800052D8 SYSCALL 062 RFU062_EndOfHeap +//////////////////////////////////////////////////////////////////// +void* _EndOfHeap() +{ + return threads_array[threadId].heap_base; +} + +//////////////////////////////////////////////////////////////////// +//80005390 +//////////////////////////////////////////////////////////////////// +int __load_module(char *name, void (*entry)(void*), void *stack_res, int prio) +{ + struct TCB *th; + int index; + int *ptr; + struct rominfo ri; + + th = (struct TCB*)LL_unlink(&thread_ll_free); + if (th) { + threads_count++; + index = (((u32)th-(u32)threads_array) * 0x286BCA1B)/4; + } else { + index = -1; + } + + threadId = index; + th->wakeupCount = 0; + th->semaId = 0; + th->attr = 0; + th->stack_res = stack_res; + th->option = 0; + th->entry = entry; + th->gpReg = 0; + th->currentPriority = prio; + th->status = THS_DORMANT; + th->waitSema = 0; + th->entry_ = entry; + th->argc = 0; + th->argstring = 0; + th->initPriority = prio; + + thread_2_ready(index); + + if (romdirGetFile(name, &ri) == NULL) { + __printf("# panic ! '%s' not found\n", name); + _Exit(1); + } + + if (ri.fileSize > 0) { + int i; + int *src = (int*)(0xbfc00000+ri.fileOffset); + int *dst = (int*)entry; + + for (i=0; i 0 ) { + int i; + for(i = 0; i < argc; ++i) + pbuf = strcpy(pbuf, argv[i]); + } + + threads_array[threadId].argc = argc+2; + threads_array[threadId].argstring = threadArgStrBuffer; + _CancelWakeupThread(threadId); + _iChangeThreadPriority(threadId, 0); + + // search for RESET + // search for filename romdir entry + if( romdirGetFile(filename, &ri) == NULL ) { + __printf("# panic ! '%s' not found\n", filename); + _Exit(); + } + + // terminate threads + curthreadid = 1; // skip main thread? + curtcb = &threads_array[curthreadid]; + + while(curthreadid < 256) { + if( curtcb->status && threadId != curthreadid ) { + if( curtcb->status == THS_DORMANT ) { + _DeleteThread(curthreadid); + } + else { + iTerminateThread(curthreadid); + _DeleteThread(curthreadid); + } + } + ++curthreadid; + ++curtcb; + } + + _SemasInit(); + threadStatus = 0; + InitPgifHandler2(); + + Restart(); + + if( ri.fileSize > 0 ) { + // copy to PS2_LOADADDR + int i; + u32* psrc = (u32*)(0xbfc00000+ri.fileOffset); + u32* pdst = (u32*)PS2_LOADADDR; + for(i = 0; i < ri.fileSize; i += 4) + *pdst++ = *psrc++; + } + + FlushInstructionCache(); + FlushDataCache(); + + __asm__("mtc0 %0, $14\n" + "sync\n" : : "r"(PS2_LOADADDR)); + erase_cpu_regs(); + __asm__("di\n" + "eret\n"); +} + +//////////////////////////////////////////////////////////////////// +//800057E8 +//////////////////////////////////////////////////////////////////// +void* __ExecPS2(void * entry, void * gp, int argc, char ** argv) +{ + char* pbuf = threadArgStrBuffer; + int i; + + if( argc > 0 ) { + for(i = 0; i < argc; ++i) + pbuf = eestrcpy(pbuf, argv[i]); + } + + threads_array[threadId].entry = entry; //0C + threads_array[threadId].wakeupCount = 0; //24 + threads_array[threadId].gpReg = gp; //14 + threads_array[threadId].semaId = 0; //20 + threads_array[threadId].argstring = threadArgStrBuffer; //38 + threads_array[threadId].argc = argc; //34 + threads_array[threadId].entry_ = entry; //30 + threads_array[threadId].currentPriority = 0; //18 + threads_array[threadId].waitSema = 0; //1C + threads_array[threadId].initPriority = 0; + FlushInstructionCache(); + FlushDataCache(); + + return entry; +} + +//////////////////////////////////////////////////////////////////// +//800058E8 +//////////////////////////////////////////////////////////////////// +int _ExecOSD(int argc, char **argv) +{ + return _LoadPS2Exe("rom0:OSDSYS", argc, argv); +} + +//////////////////////////////////////////////////////////////////// +//80005900 +//////////////////////////////////////////////////////////////////// +int _RFU004_Exit() +{ + char *bb = "BootBrowser"; + return _LoadPS2Exe("rom0:OSDSYS", 1, &bb); +} + +//////////////////////////////////////////////////////////////////// +//80005938 +//////////////////////////////////////////////////////////////////// +void releaseTCB(int tid) +{ + threads_count--; + threads_array[tid].status=0; + LL_add(&thread_ll_free, (struct ll*)&threads_array[tid]); +} + +//////////////////////////////////////////////////////////////////// +//80005978 +//////////////////////////////////////////////////////////////////// +void unsetTCB(int tid) +{ + if ((threads_array[tid].status) <= THS_READY) + LL_unlinkthis((struct ll*)&threads_array[tid]); +} + +//////////////////////////////////////////////////////////////////// +//800059B8 +//////////////////////////////////////////////////////////////////// +void thread_2_ready(int tid) +{ + threads_array[tid].status=THS_READY; + if (threads_array[tid].initPriority < threadPrio) + threadPrio=(short)threads_array[tid].initPriority; + LL_add( &thread_ll_priorities[threads_array[tid].initPriority], (struct ll*)&threads_array[tid] ); +} + +//////////////////////////////////////////////////////////////////// +//80005A58 +//////////////////////////////////////////////////////////////////// +struct ll* LL_unlink(struct ll *l) +{ + struct ll *p; + + if ((l==l->next) && (l==l->prev)) + return 0; + p=l->prev; + p->prev->next=p->next; + p->next->prev=p->prev; + return p; +} + +//////////////////////////////////////////////////////////////////// +//80005A98 +//////////////////////////////////////////////////////////////////// +struct ll* LL_rotate(struct ll *l) +{ + struct ll *p; + + if (p=LL_unlink(l)){ + p->prev=l; + p->next=l->next; + l->next->prev=p; + l->next=p; + return l->prev; + } + return NULL; +} + +//////////////////////////////////////////////////////////////////// +//80005AE8 +//////////////////////////////////////////////////////////////////// +struct ll *LL_unlinkthis(struct ll *l) +{ + l->prev->next=l->next; + l->next->prev=l->prev; + return l->next; +} + +//////////////////////////////////////////////////////////////////// +//80005B08 +//////////////////////////////////////////////////////////////////// +void LL_add(struct ll *l, struct ll *new) +{ + new->prev=l; + new->next=l->next; + l->next->prev=new; + l->next=new; +} + +//////////////////////////////////////////////////////////////////// +//80005B28 SYSCALL 9 (0x09) TlbWriteRandom +//////////////////////////////////////////////////////////////////// +int _TlbWriteRandom(u32 PageMask, u32 EntryHi, u32 EntryLo0, u32 EntryLo1) { + if ((EntryHi >> 24) != 4) return -1; + __asm__ ( + "mfc0 $2, $1\n" + "mtc0 $2, $0\n" + "mtc0 $4, $5\n" + "mtc0 $5, $10\n" + "mtc0 $6, $2\n" + "mtc0 $7, $3\n" + "sync\n" + "tlbwi\n" + "sync\n" + ); +} + +int _sifGetMSFLG() { + u32 msflg; + for (;;) { + msflg = SBUS_MSFLG; + __asm__ ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"); + __asm__ ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"); + __asm__ ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"); + + if (msflg == SBUS_MSFLG) return msflg; + } +} + +//////////////////////////////////////////////////////////////////// +//80005E58 +//////////////////////////////////////////////////////////////////// +int _sifGetSMFLG() { + u32 smflg; + for (;;) { + smflg = SBUS_SMFLG; + __asm__ ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"); + __asm__ ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"); + __asm__ ("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"); + + if (smflg == SBUS_SMFLG) return smflg; + } +} + +int _ResetSif1() +{ + sif1tagdata = 0xFFFF001E; + //*(int*)0xa0001e330 = 0x20000000; + //*(int*)0xa0001e334 = (u32)ptag&0x0fffffff; + D6_QWC = 0; + D6_TAG = (u32)&sif1tagdata&0x0fffffff; +} + +//////////////////////////////////////////////////////////////////// +//80006198 +//////////////////////////////////////////////////////////////////// +void SifDmaInit() +{ + int msflg; + memset(sifEEbuff, 0, sizeof(sifEEbuff)); + memset(sifRegs, 0, sizeof(sifRegs)); + + *(u32*)0xB000F260 = 0xFF; + D5_CHCR = 0; + D6_CHCR = 0; + + _SifSetDChain(); + *(u32*)0xB000F200 = (u32)sifEEbuff; + __printf("MSFLG = 0x10000\n"); + SBUS_MSFLG = 0x10000; + msflg = SBUS_MSFLG; + _ResetSif1(); + _SifSetReg(1, 0); + + while (!(_SifGetReg(4) & 0x10000)) { __asm__ ("nop\nnop\nnop\nnop\n"); } + + sifIOPbuff = *(u32*)0xB000F210; + + SBUS_MSFLG = 0x20000; + SBUS_MSFLG; +} + +//////////////////////////////////////////////////////////////////// +//800062A0 SYSCALL 120 (0x78) SifSetDChain +//////////////////////////////////////////////////////////////////// +void _SifSetDChain(){ + int var_10; + + D5_CHCR = 0; + D5_QWC = 0; + D5_CHCR = 0x184; // 0001 1000 0100 + var_10 = D5_CHCR; // read? +} + +//////////////////////////////////////////////////////////////////// +//800062D8 SYSCALL 107 (0x6B) SifStopDma +//////////////////////////////////////////////////////////////////// +void _SifStopDma(){ + int var_10; + + D5_CHCR = 0; + D5_QWC = 0; + var_10 = D5_CHCR; // read? +} + +//////////////////////////////////////////////////////////////////// +//80006370 +//////////////////////////////////////////////////////////////////// +void _SifDmaSend(void *src, void *dest, int size, int attr, int id) +{ + int qwc; + struct TAG* t1; + int *t3; + int tocopy; + + if (((++tagindex) & 0xFF) == 31){ + tagindex=0; + transferscount++; + } + + qwc=(size+15)/16; //rount up + + t1=(struct TAG*)KSEG1_ADDR(&tadrptr[tagindex]); + if (attr & SIF_DMA_TAG) { + t1->id_qwc = (id << 16) | qwc | + ((attr & SIF_DMA_INT_I) ? 0x80000000 : 0); //IRQ + t1->addr=(u32)src & 0x1FFFFFFF; + t3=(int*)KSEG1_ADDR(src); + qwc--; + } + else { + if (qwc >= 8){ //two transfers + tocopy=7; + t1->id_qwc=0x30000008; //(id)REF | (qwc)8; + t1->addr=(u32)&extrastorage[tagindex] | 0x1FFFFFFF; + t3=(int*)KSEG1_ADDR(&extrastorage[tagindex]); + + if (((++tagindex) & 0xff) == 31){ + tagindex=0; + transferscount++; + } + + t1=(struct TAG*)KSEG1_ADDR(&tadrptr[tagindex]); + t1->id_qwc=(id << 16) | (qwc - 7) | + ((attr & SIF_DMA_INT_I) ? 0x80000000 : 0);//IRQ + t1->addr=(u32)(src+112) | 0x1FFFFFFF; + } + else { + tocopy=qwc; + t1->id_qwc=(id << 16) | (qwc+1) | + ((attr & SIF_DMA_INT_I) ? 0x80000000 : 0);//IRQ + t1->addr=(u32)&extrastorage[tagindex] & 0x1FFFFFFF; + t3=(int*)KSEG1_ADDR(&extrastorage[tagindex]); + } + memcpy((char*)t3+16, (void*)KSEG1_ADDR(src), tocopy*16);//inline with qwords + } + t3[1]=qwc * 4; + t3[0]=(u32)((u32)dest & 0x00FFFFFF) | + ((((u32)(attr & SIF_DMA_INT_O)) ? 0x40000000 : 0) | + (((u32)(attr & SIF_DMA_ERT)) ? 0x80000000 : 0)); +} + +//////////////////////////////////////////////////////////////////// +//800065C8 +//////////////////////////////////////////////////////////////////// +int _SifDmaCount() +{ + register int count; + + count=((D6_TAG-(u32)tadrptr) & 0x1FFFFFFF) >> 4; + + count=count>0? count-1:30; + + if (count == tagindex) + return (D6_QWC ? 30 : 31); + + if (count < tagindex) + return count + 30 - tagindex; + + return count-tagindex-1; +} + +//////////////////////////////////////////////////////////////////// +//80006650 +//////////////////////////////////////////////////////////////////// +void _SifDmaPrepare(int count) +{ + register struct TAG *t0; + + if (count==31) return; + + t0=(struct TAG*)KSEG1_ADDR(&tadrptr[tagindex]); + if (count == 30){ + t0->id_qwc &= DMA_TAG_IRQ|DMA_TAG_PCE; //keep PCE|REFE|IRQ + t0->id_qwc |= DMA_TAG_REF<<28; + t0->id_qwc |= D6_QWC; + t0->addr = D6_MADR; + D6_QWC = 0; + D6_TAG = KUSEG_ADDR(t0); + }else + t0->id_qwc |= DMA_TAG_REF<<28; +} + +//////////////////////////////////////////////////////////////////// +//800066F8 SYSCALL 119 (0x77) SifSetDma +//////////////////////////////////////////////////////////////////// +u32 _SifSetDma(SifDmaTransfer_t *sdd, int len) +{ + int var_10; + int count, tmp; + int i, c, _len = len; + int nextindex; + + DMAC_ENABLEW = DMAC_ENABLER | 0x10000; //suspend + + D6_CHCR = 0; //kill any previous transfer?!? + var_10 = D6_CHCR; // read? + + DMAC_ENABLEW = DMAC_ENABLER & ~0x10000; //enable + + count = _SifDmaCount(); + +lenloop: + i=0; c=0; + while (_len > 0) { + if (!(sdd[i].attr & SIF_DMA_TAG)) { + if (sdd[i].size <= 112) c++; + else c+=2; + } else c++; + _len--; i++; + } + if (count < c) { count = 0; goto lenloop; } + + nextindex = ((tagindex+1) % 31) & 0xff; + if (nextindex == 0) + tmp = (transferscount + 1) & 0xFFFF; + else + tmp = transferscount; + + _SifDmaPrepare(count); + + while (len > 0) { + _SifDmaSend(sdd->src, sdd->dest, sdd->size, sdd->attr, DMA_TAG_REF<<12);//REF >> 16 + sdd++; len--; + } + + _SifDmaSend(sdd->src, sdd->dest, sdd->size, sdd->attr, DMA_TAG_REFE<<12);//REFE >> 16 + + D6_CHCR|= 0x184; + var_10 = D6_CHCR; // read? + return (tmp<<16)|(nextindex<<8)|c; +} + +//////////////////////////////////////////////////////////////////// +//800068B0 SYSCALL 118 (0x76) SifDmaStat +//////////////////////////////////////////////////////////////////// +int _SifDmaStat(int id) +{ + //TODO + return 0; +} + +//////////////////////////////////////////////////////////////////// +//80006B60 SYSCALL 121 (0x79) SifSetDma +//////////////////////////////////////////////////////////////////// +int _SifSetReg(int reg, u32 val) +{ + __printf("%s: reg=%d; val=%x\n", __FUNCTION__, reg, val); + + if (reg == 1) { + *(u32*)0xB000F200 = val; + return *(u32*)0xB000F200; + } else + if (reg == 3) { + SBUS_MSFLG = val; + return _sifGetMSFLG(); + } else + if (reg == 4) { + SBUS_SMFLG = val; + return _sifGetSMFLG(); + } else + if (reg >= 0) { + return 0; + } + + reg&= 0x7FFFFFFF; + if (reg >= 32) return 0; + + sifRegs[reg] = val; + return val; +} + +//////////////////////////////////////////////////////////////////// +//80006C18 SYSCALL 122 (0x7A) SifSetDma +//////////////////////////////////////////////////////////////////// +int _SifGetReg(int reg) +{ + //__printf("%s: reg=%x\n", __FUNCTION__, reg); + + if (reg == 1) { + return *(u32*)0xB000F200; + } else + if (reg == 2) { + return *(u32*)0xB000F210; + } else + if (reg == 3) { + return _sifGetMSFLG(); + } else + if (reg == 4) { + return _sifGetSMFLG(); + } else + if (reg >= 0) { + return 0; + } + + reg&= 0x7FFFFFFF; + if (reg >= 32) return 0; + + //__printf("ret=%x\n", sifRegs[reg]); + return sifRegs[reg]; +} + +//////////////////////////////////////////////////////////////////// +//80007428 SYSCALL 117 print +//////////////////////////////////////////////////////////////////// +void _print() +{ +} + +//////////////////////////////////////////////////////////////////// +//800074D8 +//////////////////////////////////////////////////////////////////// +void _SetGsCrt2() +{ + u32 tmp; + + tmp = *(int*)0x8001F344; + if (tmp == 0x40 || tmp == 0x60 || tmp == 0x61) { + *(char*)0xbf803218 = 0; + *(char*)0xbf803218 = 2; + return; + } + + *(short*)0xbf801470 = 0; + *(short*)0xbf801472 = 0; + *(short*)0xbf801472 = 1; +} + +//////////////////////////////////////////////////////////////////// +//800076B0 +//////////////////////////////////////////////////////////////////// +void _iJoinThread(int param) +{ + //TODO +} + +//////////////////////////////////////////////////////////////////// +//80008A60 +//////////////////////////////////////////////////////////////////// +void _SetGsCrt3(short arg0, short arg1, short arg2) +{ + __printf("_SetGsCrt3 unimplemented\n"); +} + +//////////////////////////////////////////////////////////////////// +//80009CE0 +//////////////////////////////////////////////////////////////////// +void _SetGsCrt4(short arg0, short arg1, short arg2) +{ + __printf("_SetGsCrt4 unimplemented\n"); +} + +//////////////////////////////////////////////////////////////////// +//8000A060 SYSCALL 002 SetGsCrt +//////////////////////////////////////////////////////////////////// +void _SetGsCrt(short arg0, short arg1, short arg2) +{ + u64 val, val2; + u64 tmp; + int count; + + if (arg1 == 0) { + tmp = (hvParam >> 3) & 0x7; + tmp^= 0x2; + if (tmp == 0) arg1 = 3; + else arg1 = 2; + } + + for (count=0x270f; count >= 0; count--) { + __asm__ ("nop\nnop\nnop\nnop\nnop\nnop\n"); + } + + *(int*)0x8001F344 = 0; + + if (arg1 == 2) { + if (arg0 != 0) { + val = 0x740834504LL; + val2 = 0x740814504LL; + + tmp = (hvParam & 0x1) << 25; + val|= tmp; + val2|= tmp; + + GS_SMODE1 = val; + GS_SYNCH1 = 0x7F5B61F06F040LL; + GS_SYNCH2 = 0x33A4D8; + GS_SYNCV = 0xC7800601A01801LL; + + GS_SMODE2 = (arg2 << 1) | 1; + GS_SRFSH = 8; + GS_SMODE1 = val2; + } else { + val = 0x740834504LL; + val2 = 0x740814504LL; + + tmp = (hvParam & 0x2) << 35; + val|= tmp; + val2|= tmp; + + tmp = (hvParam & 0x1) << 25; + val|= tmp; + val2|= tmp; + + GS_SMODE1 = val; + GS_SYNCH1 = 0x7F5B61F06F040LL; + GS_SYNCH2 = 0x33A4D8; + GS_SYNCV = 0xC7800601A01802LL; + GS_SMODE2 = 0; + GS_SRFSH = 8; + GS_SMODE1 = val2; + } + _SetGsCrt2(); + return; + } + + if (arg1 == 3) { + if (arg0 != 0) { + val = 0x740836504LL; + val2 = 0x740816504LL; + + tmp = (hvParam & 0x1) << 25; + val|= tmp; + val2|= tmp; + + GS_SMODE1 = val; + GS_SYNCH1 = 0x7F5C21FC83030LL; + GS_SYNCH2 = 0x3484BC; + GS_SYNCV = 0xA9000502101401LL; + + GS_SMODE2 = (arg2 << 1) | 1; + GS_SRFSH = 8; + GS_SMODE1 = val2; + } else { + val = 0x740836504LL; + val2 = 0x740816504LL; + + tmp = (hvParam & 0x2) << 35; + val|= tmp; + val2|= tmp; + + tmp = (hvParam & 0x1) << 25; + val|= tmp; + val2|= tmp; + + GS_SMODE1 = val; + GS_SYNCH1 = 0x7F5C21F683030LL; + GS_SYNCH2 = 0x3484BC; + GS_SYNCV = 0xA9000502101404LL; + GS_SMODE2 = 0; + GS_SRFSH = 8; + GS_SMODE1 = val2; + } + _SetGsCrt2(); + return; + } + + if (arg1 == 0x72) { + if (arg0 != 0) { + val = 0x740814504LL; + val|= (hvParam & 0x1) << 25; + + GS_SYNCH1 = 0x7F5B61F06F040LL; + GS_SYNCH2 = 0x33A4D8; + GS_SYNCV = 0xC7800601A01801LL; + + GS_SMODE2 = (arg2 << 1) | 1; + GS_SRFSH = 8; + GS_SMODE1 = val; + } else { + val = 0x740814504LL; + + val|= (hvParam & 0x2) << 35; + val|= (hvParam & 0x1) << 25; + + GS_SYNCH1 = 0x7F5B61F06F040LL; + GS_SYNCH2 = 0x33A4D8; + GS_SYNCV = 0xC7800601A01802LL; + GS_SMODE2 = 0; + GS_SRFSH = 8; + GS_SMODE1 = val; + } + return; + } + + if (arg1 == 0x73) { + if (arg0 != 0) { + val = 0x740816504LL; + val|= (hvParam & 0x1) << 25; + + GS_SYNCH1 = 0x7F5C21FC83030LL; + GS_SYNCH2 = 0x3484BC; + GS_SYNCV = 0xA9000502101401LL; + + GS_SMODE2 = (arg2 << 1) | 1; + GS_SRFSH = 8; + GS_SMODE1 = val; + } else { + val = 0x740816504; + + val|= (hvParam & 0x2) << 35; + val|= (hvParam & 0x1) << 25; + + GS_SYNCH1 = 0x7F5C21FC83030LL; + GS_SYNCH2 = 0x3484BC; + GS_SYNCV = 0xA9000502101404LL; + GS_SMODE2 = 0; + GS_SRFSH = 8; + GS_SMODE1 = val; + } + return; + } + + if ((u32)(arg1 - 26) >= 0x38) { + _SetGsCrt3(arg0, arg1, arg2); return; + } + + if (arg1 == 0x52) { + _SetGsCrt3(arg0, arg1, arg2); return; + } + + _SetGsCrt4(arg0, arg1, arg2); +} + +//////////////////////////////////////////////////////////////////// +//8000A768 SYSCALL 076 GetGsHParam +//////////////////////////////////////////////////////////////////// +void _GetGsHParam(int *p0, int *p1, int *p2, int *p3) +{ + u32 _hvParam = (u32)hvParam; + + *p0 = _hvParam >> 12; + *p1 = _hvParam >> 24; + *p2 = _hvParam >> 18; + *p3 = _hvParam >> 28; +} + +//////////////////////////////////////////////////////////////////// +//8000A7D0 SYSCALL 077 GetGsVParam +//////////////////////////////////////////////////////////////////// +int _GetGsVParam() +{ + return hvParam & 0x3; +} + +//////////////////////////////////////////////////////////////////// +//8000A800 SYSCALL 059 JoinThread +//////////////////////////////////////////////////////////////////// +void _JoinThread() +{ + _iJoinThread(0x87); +} + +//////////////////////////////////////////////////////////////////// +//8000A820 SYSCALL 078 SetGsHParam +//////////////////////////////////////////////////////////////////// +void _SetGsHParam(int a0, int a1, int a2, int a3) +{ + __printf("SetGsHParam(%x,%x,%x,%x)... probably will never be supported\n", a0, a1, a2, a3); + //write hvParam&1 to 12000010? +} + +//////////////////////////////////////////////////////////////////// +//8000A8F8 SYSCALL 079 SetGsVParam +//////////////////////////////////////////////////////////////////// +void _SetGsVParam(int VParam) +{ + hvParam&= ~0x1; + hvParam|= VParam & 0x1; +} + +//////////////////////////////////////////////////////////////////// +//8000A920 SYSCALL 075 GetOsdConfigParam +//////////////////////////////////////////////////////////////////// +void _GetOsdConfigParam(int *result) +{ + *result= (*result & 0xFFFFFFFE) | (osdConfigParam & 1); + *result= (*result & 0xFFFFFFF9) | (osdConfigParam & 6); + *result= (*result & 0xFFFFFFF7) | (osdConfigParam & 8); + *result= (*result & 0xFFFFFFEF) | (osdConfigParam & 0x10); + *result=((*result & 0xFFFFE01F) | (osdConfigParam & 0x1FE0)) & 0xFFFF1FFF; + ((u16*)result)[1]=((u16*)&osdConfigParam)[1]; +} + +//////////////////////////////////////////////////////////////////// +//8000A9C0 SYSCALL 074 SetOsdConfigParam +//////////////////////////////////////////////////////////////////// +void _SetOsdConfigParam(int *param) +{ + osdConfigParam= (osdConfigParam & 0xFFFFFFFE) | (*param & 1); + osdConfigParam= (osdConfigParam & 0xFFFFFFF9) | (*param & 6); + osdConfigParam= (osdConfigParam & 0xFFFFFFF7) | (*param & 8); + osdConfigParam= (osdConfigParam & 0xFFFFFFEF) | (*param & 0x10); + osdConfigParam=((osdConfigParam & 0xFFFFE01F) | (*param & 0x1FE0)) & 0xFFFF1FFF; + ((u16*)&osdConfigParam)[1]=((u16*)param)[1]; +} + +//////////////////////////////////////////////////////////////////// +//8000FCE8 +//////////////////////////////////////////////////////////////////// +void __exhandler(int a0) +{ +} + +//////////////////////////////////////////////////////////////////// +//80010F34 +//////////////////////////////////////////////////////////////////// +void __disableInterrupts() +{ + __asm__("mtc0 $0, $25\n" + "mtc0 $0, $24\n" + "li $3, 0xFFFFFFE0\n" + "mfc0 $2, $12\n" + "and $2, $3\n" + "mtc0 $2, $12\n" + "sync\n"); +} + +//////////////////////////////////////////////////////////////////// +//80010F58 +//////////////////////////////////////////////////////////////////// +void kSaveContext() +{ +} + +//////////////////////////////////////////////////////////////////// +//80011030 +//////////////////////////////////////////////////////////////////// +void kLoadContext() +{ +} + +//////////////////////////////////////////////////////////////////// +//800110F4 +//////////////////////////////////////////////////////////////////// +void kLoadDebug() +{ + kLoadContext(); + // lq $31, 0x1F0($27) + // lq $27, 0x1B0($27) + // j 80005020 - probably load debug services or restore prev program state +} + +//////////////////////////////////////////////////////////////////// +//80011108 +//////////////////////////////////////////////////////////////////// +int __exception() +{ + register u32 curepc __asm__("$2"); + int ret; + + __asm__("mfc0 %0, $14\n" : "=r"(curepc) : ); + + // check if epc is currently in the except handlers: + // _Deci2Handler, __exception1, and __exception + if (curepc >= (u32)__exception && curepc < (u32)__exception+0x300) { + __asm__("mfc0 %0, $13\n" : "=r"(ret) : ); + return (ret & 0x7C) >> 2; + } + + kSaveContext(); + + __disableInterrupts(); + __exhandler(1); + + kLoadContext(); + + __asm__("eret\n"); +} + +//////////////////////////////////////////////////////////////////// +//800111F0 +//////////////////////////////////////////////////////////////////// +void __exception1() +{ + kSaveContext(); + __disableInterrupts(); + //sub_8000CF68 + kLoadContext(); + __asm__("eret\n"); +}