X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fpsxbios.c;h=313bc5070756997b6d820c33261a2ec59207698f;hb=ea72f34a365392de7fdcdcb31c53307f2d12f90c;hp=85f79fd2f0f8b4145029aeb7d1ed77a45fc3b9c3;hpb=7650b7540c8cdfdad23e6a5ce5e591ab5f7c0bff;p=pcsx_rearmed.git diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 85f79fd2..313bc507 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -193,28 +193,21 @@ char *biosC0n[256] = { #define Rsp ((char *)PSXM(sp)) typedef struct { - u32 desc; - s32 status; - s32 mode; + u32 class; + u32 status; + u32 spec; + u32 mode; u32 fhandler; -} EvCB[32]; - -#define EvStUNUSED 0x0000 -#define EvStWAIT 0x1000 -#define EvStACTIVE 0x2000 -#define EvStALREADY 0x4000 + u32 unused[2]; +} EvCB; -#define EvMdINTR 0x1000 -#define EvMdNOINTR 0x2000 +#define EvStUNUSED 0x0000 +#define EvStDISABLED 0x1000 +#define EvStACTIVE 0x2000 +#define EvStALREADY 0x4000 -/* -typedef struct { - s32 next; - s32 func1; - s32 func2; - s32 pad; -} SysRPst; -*/ +#define EvMdCALL 0x1000 +#define EvMdMARK 0x2000 typedef struct { u32 status; @@ -258,23 +251,9 @@ typedef struct { } FileDesc; static int *pad_buf = NULL; -static char *pad_buf1 = NULL, *pad_buf2 = NULL; -static int pad_buf1len, pad_buf2len; -static int pad_stopped = 0; - -static u32 regs[35]; -static EvCB *EventCB; -static EvCB *HwEV; // 0xf0 -static EvCB *EvEV; // 0xf1 -static EvCB *RcEV; // 0xf2 -static EvCB *UeEV; // 0xf3 -static EvCB *SwEV; // 0xf4 -static EvCB *ThEV; // 0xff static u32 heap_size = 0; static u32 *heap_addr = NULL; static u32 *heap_end = NULL; -static int CardState = -1; -static int CurThread = 0; static FileDesc FDesc[32]; static u32 card_active_chan = 0; @@ -282,6 +261,7 @@ static u32 card_active_chan = 0; #define A_TT_ExCB 0x0100 #define A_TT_PCB 0x0108 #define A_TT_TCB 0x0110 +#define A_TT_EvCB 0x0120 #define A_A0_TABLE 0x0200 #define A_B0_TABLE 0x0874 #define A_C0_TABLE 0x0674 @@ -292,9 +272,18 @@ static u32 card_active_chan = 0; #define A_KMALLOC_PTR 0x7460 #define A_KMALLOC_SIZE 0x7464 #define A_KMALLOC_END 0x7468 +#define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry +#define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag') +#define A_CARD_IRQR_ENA 0x74bc // same for card +#define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data +#define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data +#define A_PAD_IN_LEN 0x74d8 +#define A_PAD_OUT_LEN 0x74e0 #define A_EEXIT_PTR 0x75d0 #define A_EXC_STACK 0x85d8 // exception stack top #define A_RCNT_VBL_ACK 0x8600 +#define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code +#define A_CD_EVENTS 0xb9b8 #define A_EXC_GP 0xf450 #define HLEOP(n) SWAPu32((0x3b << 26) | (n)); @@ -305,17 +294,34 @@ static u32 loadRam32(u32 addr) return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2))); } +static void *castRam8ptr(u32 addr) +{ + assert(!(addr & 0x5f800000)); + return psxM + (addr & 0x1fffff); +} + static void *castRam32ptr(u32 addr) { assert(!(addr & 0x5f800003)); return psxM + (addr & 0x1ffffc); } +static void *loadRam8ptr(u32 addr) +{ + return castRam8ptr(loadRam32(addr)); +} + static void *loadRam32ptr(u32 addr) { return castRam32ptr(loadRam32(addr)); } +static void storeRam8(u32 addr, u8 d) +{ + assert(!(addr & 0x5f800000)); + *((u8 *)psxM + (addr & 0x1fffff)) = d; +} + static void storeRam32(u32 addr, u32 d) { assert(!(addr & 0x5f800000)); @@ -377,14 +383,10 @@ static inline void softCallInException(u32 pc) { ra = sra; } -static inline void DeliverEvent(u32 ev, u32 spec) { - if (EventCB[ev][spec].status != EvStACTIVE) return; - -// EventCB[ev][spec].status = EvStALREADY; - if (EventCB[ev][spec].mode == EvMdINTR) { - softCall(EventCB[ev][spec].fhandler); - } else EventCB[ev][spec].status = EvStALREADY; -} +static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func); +static u32 DeliverEvent(u32 class, u32 spec); +static u32 UnDeliverEvent(u32 class, u32 spec); +static void CloseEvent(u32 ev); /* * // * @@ -397,8 +399,8 @@ static inline void DeliverEvent(u32 ev, u32 spec) { ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \ memcpy(Ra1, ptr, length); \ if (FDesc[1 + mcd].mode & 0x8000) { \ - DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \ - DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \ + DeliverEvent(0xf0000011, 0x0004); \ + DeliverEvent(0xf4000001, 0x0004); \ v0 = 0; } \ else v0 = length; \ FDesc[1 + mcd].offset += v0; \ @@ -412,8 +414,8 @@ static inline void DeliverEvent(u32 ev, u32 spec) { FDesc[1 + mcd].offset += length; \ SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \ if (FDesc[1 + mcd].mode & 0x8000) { \ - DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \ - DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \ + DeliverEvent(0xf0000011, 0x0004); \ + DeliverEvent(0xf4000001, 0x0004); \ v0 = 0; } \ else v0 = length; \ } @@ -1602,8 +1604,8 @@ void psxBios__bu_init() { // 70 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]); #endif - DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 - DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 + DeliverEvent(0xf0000011, 0x0004); + DeliverEvent(0xf4000001, 0x0004); pc0 = ra; } @@ -1616,13 +1618,13 @@ void psxBios__96_init() { // 71 pc0 = ra; } -static void psxBios_SysDeqIntRP_(); +static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2); +static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr); +static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr); static void psxBios_DequeueCdIntr_() { - a0 = 0; a1 = 0x91d0; - psxBios_SysDeqIntRP_(); - a0 = 0; a1 = 0x91e0; - psxBios_SysDeqIntRP_(); + psxBios_SysDeqIntRP_(0, 0x91d0); + psxBios_SysDeqIntRP_(0, 0x91e0); use_cycles(16); } @@ -1634,11 +1636,11 @@ static void psxBios_DequeueCdIntr() { // a3 static void psxBios_CdRemove() { // 56, 72 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]); - // CloseEvent 0xf1000000 - // CloseEvent 0xf1000001 - // CloseEvent 0xf1000002 - // CloseEvent 0xf1000003 - // CloseEvent 0xf1000004 + CloseEvent(loadRam32(A_CD_EVENTS + 0x00)); + CloseEvent(loadRam32(A_CD_EVENTS + 0x04)); + CloseEvent(loadRam32(A_CD_EVENTS + 0x08)); + CloseEvent(loadRam32(A_CD_EVENTS + 0x0c)); + CloseEvent(loadRam32(A_CD_EVENTS + 0x10)); psxBios_DequeueCdIntr_(); // EnterCriticalSection - should be done at the beginning, @@ -1693,24 +1695,24 @@ void psxBios__card_info() { // ab switch (port) { case 0x0: case 0x1: - ret = 0x2; + ret = 0x0004; if (McdDisable[port & 1]) - ret = 0x8; + ret = 0x0100; break; default: #ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan); #endif - ret = 0x11; + ret = 0x0302; break; } if (McdDisable[0] && McdDisable[1]) - ret = 0x8; + ret = 0x0100; - DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 -// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 - DeliverEvent(0x81, ret); // 0xf4000001, 0x0004 + DeliverEvent(0xf0000011, 0x0004); +// DeliverEvent(0xf4000001, 0x0004); + DeliverEvent(0xf4000001, ret); v0 = 1; pc0 = ra; } @@ -1721,8 +1723,8 @@ void psxBios__card_load() { // ac card_active_chan = a0; -// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 - DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 +// DeliverEvent(0xf0000011, 0x0004); + DeliverEvent(0xf4000001, 0x0004); v0 = 1; pc0 = ra; } @@ -1806,154 +1808,176 @@ void psxBios_ResetRCnt() { // 06 pc0 = ra; } +static u32 DeliverEvent(u32 class, u32 spec) { + EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB); + u32 evcb_len = loadRam32(A_TT_EvCB + 4); + u32 ret = loadRam32(A_TT_EvCB) + evcb_len; + u32 i, lim = evcb_len / 0x1c; -/* gets ev for use with EventCB */ -#define GetEv() \ - ev = (a0 >> 24) & 0xf; \ - if (ev == 0xf) ev = 0x5; \ - ev*= 32; \ - ev+= a0&0x1f; - -/* gets spec for use with EventCB */ -#define GetSpec() \ - spec = 0; \ - switch (a1) { \ - case 0x0301: spec = 16; break; \ - case 0x0302: spec = 17; break; \ - default: \ - for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \ - break; \ + for (i = 0; i < lim; i++, ev++) { + use_cycles(8); + if (SWAP32(ev->status) != EvStACTIVE) + continue; + use_cycles(4); + if (SWAP32(ev->class) != class) + continue; + use_cycles(4); + if (SWAP32(ev->spec) != spec) + continue; + use_cycles(6); + ret = SWAP32(ev->mode); + if (ret == EvMdMARK) { + ev->status = SWAP32(EvStALREADY); + continue; + } + use_cycles(8); + if (ret == EvMdCALL) { + ret = SWAP32(ev->fhandler); + if (ret) { + v0 = ret; + softCall(ret); + ret = v0; + } + } } + use_cycles(29); + return ret; +} -void psxBios_DeliverEvent() { // 07 - int ev, spec; - int i; - - GetEv(); - GetSpec(); - -#ifdef PSXBIOS_LOG - PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec); -#endif - - DeliverEvent(ev, spec); +static u32 UnDeliverEvent(u32 class, u32 spec) { + EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB); + u32 evcb_len = loadRam32(A_TT_EvCB + 4); + u32 ret = loadRam32(A_TT_EvCB) + evcb_len; + u32 i, lim = evcb_len / 0x1c; - pc0 = ra; + for (i = 0; i < lim; i++, ev++) { + use_cycles(8); + if (SWAP32(ev->status) != EvStALREADY) + continue; + use_cycles(4); + if (SWAP32(ev->class) != class) + continue; + use_cycles(4); + if (SWAP32(ev->spec) != spec) + continue; + use_cycles(6); + if (SWAP32(ev->mode) == EvMdMARK) + ev->status = SWAP32(EvStACTIVE); + } + use_cycles(28); + return ret; } -void psxBios_OpenEvent() { // 08 - int ev, spec; - int i; - - GetEv(); - GetSpec(); +static void psxBios_DeliverEvent() { // 07 + u32 ret; + PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1); -#ifdef PSXBIOS_LOG - PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3); -#endif + ret = DeliverEvent(a0, a1); + mips_return(ret); +} - EventCB[ev][spec].status = EvStWAIT; - EventCB[ev][spec].mode = a2; - EventCB[ev][spec].fhandler = a3; +static s32 get_free_EvCB_slot() { + EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB); + u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c; - v0 = ev | (spec << 8); - pc0 = ra; + use_cycles(19); + for (i = 0; i < lim; i++, ev++) { + use_cycles(8); + if (ev->status == SWAP32(EvStUNUSED)) + return i; + } + return -1; } -void psxBios_CloseEvent() { // 09 - int ev, spec; - - ev = a0 & 0xff; - spec = (a0 >> 8) & 0xff; +static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) { + u32 ret = get_free_EvCB_slot(); + if ((s32)ret >= 0) { + EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret; + ev->class = SWAP32(class); + ev->status = SWAP32(EvStDISABLED); + ev->spec = SWAP32(spec); + ev->mode = SWAP32(mode); + ev->fhandler = SWAP32(func); + ret |= 0xf1000000u; + } + return ret; +} -#ifdef PSXBIOS_LOG - PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec); -#endif +static void psxBios_OpenEvent() { // 08 + u32 ret = OpenEvent(a0, a1, a2, a3); + PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n", + biosB0n[0x08], a0, a1, a2, a3, ret); + mips_return_c(ret, 36); +} - EventCB[ev][spec].status = EvStUNUSED; +static void CloseEvent(u32 ev) +{ + u32 base = loadRam32(A_TT_EvCB); + storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED); +} - v0 = 1; pc0 = ra; +static void psxBios_CloseEvent() { // 09 + PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0, + loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4)); + CloseEvent(a0); + mips_return_c(1, 10); } -void psxBios_WaitEvent() { // 0a - int ev, spec; +static void psxBios_WaitEvent() { // 0a + u32 base = loadRam32(A_TT_EvCB); + u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4); + PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status); - ev = a0 & 0xff; - spec = (a0 >> 8) & 0xff; -#ifdef PSXBIOS_LOG - PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec); -#endif - if (EventCB[ev][spec].status == EvStUNUSED) - { - v0 = 0; - pc0 = ra; + use_cycles(15); + if (status == EvStALREADY) { + storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE); + mips_return(1); return; } - - if (EventCB[ev][spec].status == EvStALREADY) + if (status != EvStACTIVE) { - /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */ - if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE; - v0 = 1; - pc0 = ra; + mips_return_c(0, 2); return; } - v0 = 0; - pc0 = ra; + // retrigger this hlecall after the next emulation event + pc0 -= 4; + if ((s32)(next_interupt - psxRegs.cycle) > 0) + psxRegs.cycle = next_interupt; + psxBranchTest(); } -void psxBios_TestEvent() { // 0b - int ev, spec; - - ev = a0 & 0xff; - spec = (a0 >> 8) & 0xff; - - if (EventCB[ev][spec].status == EvStALREADY) - { - if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE; - v0 = 1; - } - else - { - v0 = 0; +static void psxBios_TestEvent() { // 0b + u32 base = loadRam32(A_TT_EvCB); + u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4); + u32 ret = 0; + PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status); + if (status == EvStALREADY) { + storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE); + ret = 1; } -#ifdef PSXBIOS_LOG - PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0); -#endif - - pc0 = ra; + mips_return_c(ret, 15); } -void psxBios_EnableEvent() { // 0c - int ev, spec; - - ev = a0 & 0xff; - spec = (a0 >> 8) & 0xff; +static void psxBios_EnableEvent() { // 0c + u32 base = loadRam32(A_TT_EvCB); + u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4); + PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status); + if (status != EvStUNUSED) + storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE); -#ifdef PSXBIOS_LOG - PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec); -#endif - - EventCB[ev][spec].status = EvStACTIVE; - - v0 = 1; pc0 = ra; + mips_return_c(1, 15); } -void psxBios_DisableEvent() { // 0d - int ev, spec; +static void psxBios_DisableEvent() { // 0d + u32 base = loadRam32(A_TT_EvCB); + u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4); + PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status); + if (status != EvStUNUSED) + storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED); - ev = a0 & 0xff; - spec = (a0 >> 8) & 0xff; - -#ifdef PSXBIOS_LOG - PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec); -#endif - - EventCB[ev][spec].status = EvStWAIT; - - v0 = 1; pc0 = ra; + mips_return_c(1, 15); } /* @@ -2032,36 +2056,55 @@ void psxBios_ChangeTh() { // 10 } void psxBios_InitPAD() { // 0x12 -#ifdef PSXBIOS_LOG - PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]); -#endif + u32 i, *ram32 = (u32 *)psxM; + PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3); - pad_buf1 = (char*)Ra0; - pad_buf1len = a1; - pad_buf2 = (char*)Ra2; - pad_buf2len = a3; + // printf("%s", "PS-X Control PAD Driver Ver 3.0"); + // PAD_dr_enable = 0; + ram32[A_PAD_OUTBUF/4 + 0] = 0; + ram32[A_PAD_OUTBUF/4 + 1] = 0; + ram32[A_PAD_OUT_LEN/4 + 0] = 0; + ram32[A_PAD_OUT_LEN/4 + 1] = 0; + ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0); + ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2); + ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1); + ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3); - v0 = 1; pc0 = ra; + for (i = 0; i < a1; i++) { + use_cycles(4); + storeRam8(a0 + i, 0); + } + for (i = 0; i < a3; i++) { + use_cycles(4); + storeRam8(a2 + i, 0); + } + write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c); + + ram32[A_PAD_IRQR_ENA/4] = SWAP32(1); + + mips_return_c(1, 200); } void psxBios_StartPAD() { // 13 -#ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]); -#endif - pad_stopped = 0; - psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1)); + + psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E); + psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E); + psxHwWrite16(0x1f801070, ~1); + psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1); + storeRam32(A_PAD_ACK_VBL, 1); + storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0); psxRegs.CP0.n.SR |= 0x401; - pc0 = ra; + + mips_return_c(1, 300); } void psxBios_StopPAD() { // 14 -#ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]); -#endif - pad_stopped = 1; - pad_buf1 = NULL; - pad_buf2 = NULL; - pc0 = ra; + storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1); + psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E); + psxRegs.CP0.n.SR |= 0x401; + mips_return_void_c(200); } void psxBios_PAD_init() { // 15 @@ -2123,22 +2166,12 @@ void psxBios_HookEntryInt() { // 19 mips_return_void_c(3); } -void psxBios_UnDeliverEvent() { // 0x20 - int ev, spec; - int i; - - GetEv(); - GetSpec(); - -#ifdef PSXBIOS_LOG - PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec); -#endif - - if (EventCB[ev][spec].status == EvStALREADY && - EventCB[ev][spec].mode == EvMdNOINTR) - EventCB[ev][spec].status = EvStACTIVE; +static void psxBios_UnDeliverEvent() { // 0x20 + u32 ret; + PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1); - pc0 = ra; + ret = UnDeliverEvent(a0, a1); + mips_return(ret); } char ffile[64], *pfile; @@ -2246,8 +2279,8 @@ void psxBios_lseek() { // 0x33 case 0: // SEEK_SET FDesc[a0].offset = a1; v0 = a1; -// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 -// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 +// DeliverEvent(0xf0000011, 0x0004); +// DeliverEvent(0xf4000001, 0x0004); break; case 1: // SEEK_CUR @@ -2426,11 +2459,11 @@ void psxBios_firstfile() { // 42 nfile = 0; if (!strncmp(pa0, "bu00", 4)) { // firstfile() calls _card_read() internally, so deliver it's event - DeliverEvent(0x11, 0x2); + DeliverEvent(0xf0000011, 0x0004); bufile(1); } else if (!strncmp(pa0, "bu10", 4)) { // firstfile() calls _card_read() internally, so deliver it's event - DeliverEvent(0x11, 0x2); + DeliverEvent(0xf0000011, 0x0004); bufile(2); } } @@ -2554,33 +2587,37 @@ void psxBios_delete() { // 45 } void psxBios_InitCARD() { // 4a -#ifdef PSXBIOS_LOG + u32 *ram32 = (u32 *)psxM; PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0); -#endif + write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c); + // (maybe) todo: early_card_irq, FlushCache etc - CardState = 0; + ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0); - pc0 = ra; + mips_return_c(0, 300); } void psxBios_StartCARD() { // 4b -#ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]); -#endif + psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E); + psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E); - if (CardState == 0) CardState = 1; + psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1); + storeRam32(A_PAD_ACK_VBL, 1); + storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0); + storeRam32(A_CARD_IRQR_ENA, 1); + psxRegs.CP0.n.SR |= 0x401; - pc0 = ra; + mips_return_c(1, 200); } void psxBios_StopCARD() { // 4c -#ifdef PSXBIOS_LOG PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]); -#endif - - if (CardState == 1) CardState = 0; - - pc0 = ra; + storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1); + psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E); + storeRam32(A_CARD_IRQR_ENA, 0); + psxRegs.CP0.n.SR |= 0x401; + mips_return_void_c(200); } void psxBios__card_write() { // 0x4e @@ -2613,8 +2650,8 @@ void psxBios__card_write() { // 0x4e } } - DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 -// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 + DeliverEvent(0xf0000011, 0x0004); +// DeliverEvent(0xf4000001, 0x0004); v0 = 1; pc0 = ra; } @@ -2647,8 +2684,8 @@ void psxBios__card_read() { // 0x4f } } - DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004 -// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004 + DeliverEvent(0xf0000011, 0x0004); +// DeliverEvent(0xf4000001, 0x0004); v0 = 1; pc0 = ra; } @@ -2736,12 +2773,13 @@ void psxBios__card_chan() { // 0x58 pc0 = ra; } -void psxBios_ChangeClearPad() { // 5b -#ifdef PSXBIOS_LOG +static void psxBios_ChangeClearPad() { // 5b + u32 ret; PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0); -#endif + ret = loadRam32(A_PAD_ACK_VBL); + storeRam32(A_PAD_ACK_VBL, a0); - pc0 = ra; + mips_return_c(ret, 6); } void psxBios__card_status() { // 5c @@ -2764,8 +2802,6 @@ void psxBios__card_wait() { // 5d /* System calls C0 */ -static void psxBios_SysEnqIntRP(); - static void psxBios_InitRCnt() { // 00 int i; PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0); @@ -2775,15 +2811,13 @@ static void psxBios_InitRCnt() { // 00 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0); psxHwWrite16(0x1f801100 + i*0x10 + 0, 0); } - a1 = 0x6d88; - psxBios_SysEnqIntRP(); + psxBios_SysEnqIntRP_(a0, 0x6d88); mips_return_c(0, 9); } static void psxBios_InitException() { // 01 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0); - a1 = 0x6da8; - psxBios_SysEnqIntRP(); + psxBios_SysEnqIntRP_(a0, 0x6da8); mips_return_c(0, 9); } @@ -2791,40 +2825,44 @@ static void psxBios_InitException() { // 01 * int SysEnqIntRP(int index , long *queue); */ -static void psxBios_SysEnqIntRP() { // 02 +static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) { u32 old, base = loadRam32(A_TT_ExCB); - PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1); - old = loadRam32(base + (a0 << 3)); - storeRam32(base + (a0 << 3), a1); - storeRam32(a1, old); + old = loadRam32(base + (priority << 3)); + storeRam32(base + (priority << 3), chain_eptr); + storeRam32(chain_eptr, old); mips_return_c(0, 9); } +static void psxBios_SysEnqIntRP() { // 02 + PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1); + psxBios_SysEnqIntRP_(a0, a1); +} + /* * int SysDeqIntRP(int index , long *queue); */ -static void psxBios_SysDeqIntRP_() { // 03 +static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) { u32 ptr, next, base = loadRam32(A_TT_ExCB); u32 lim = 0, ret = 0; // as in original: no arg checks of any kind, bug if a1 == 0 - ptr = loadRam32(base + (a0 << 3)); + ptr = loadRam32(base + (priority << 3)); while (ptr) { next = loadRam32(ptr); - if (ptr == a1) { - storeRam32(base + (a0 << 3), next); + if (ptr == chain_rm_eptr) { + storeRam32(base + (priority << 3), next); ret = ptr; use_cycles(6); break; } - while (next && next != a1 && lim++ < 100) { + while (next && next != chain_rm_eptr && lim++ < 100) { ptr = next; next = loadRam32(ptr); use_cycles(8); } - if (next == a1) { + if (next == chain_rm_eptr) { next = loadRam32(next); storeRam32(ptr, next); ret = ptr; @@ -2833,16 +2871,22 @@ static void psxBios_SysDeqIntRP_() { // 03 break; } if (lim == 100) - PSXBIOS_LOG("bad chain %u %x\n", a0, base); + PSXBIOS_LOG("bad chain %u %x\n", priority, base); mips_return_c(ret, 12); } static void psxBios_SysDeqIntRP() { // 03 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1); - psxBios_SysDeqIntRP_(); + psxBios_SysDeqIntRP_(a0, a1); } +static void psxBios_get_free_EvCB_slot() { // 04 + PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]); + s32 ret = get_free_EvCB_slot(); + mips_return_c(ret, 0); +} + static void psxBios_SysInitMemory_(u32 base, u32 size) { storeRam32(base, 0); storeRam32(A_KMALLOC_PTR, base); @@ -2880,8 +2924,7 @@ static void psxBios_ChangeClearRCnt() { // 0a static void psxBios_InitDefInt() { // 0c PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0); // should also clear the autoack table - a1 = 0x6d98; - psxBios_SysEnqIntRP(); + psxBios_SysEnqIntRP_(a0, 0x6d98); mips_return_c(0, 20 + 6*2); } @@ -2948,6 +2991,8 @@ static const struct { { 0x1920, hleop_exc1_3_1 }, { 0x1794, hleop_exc1_3_2 }, { 0x2458, hleop_exc3_0_2 }, + { 0x49bc, hleop_exc_padcard1 }, + { 0x4a4c, hleop_exc_padcard2 }, }; static int chain_hle_op(u32 handler) @@ -2966,7 +3011,7 @@ static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2) d[1] = SWAPu32(handler1); d[2] = SWAPu32(handler2); - // install hle traps + // install the hle traps PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1)); PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2)); } @@ -3007,11 +3052,18 @@ static void setup_tt(u32 tcb_cnt, u32 evcb_cnt) storeRam32(p_pcb, p_tcb); storeRam32(p_tcb, 0x4000); // first TCB + + // default events + storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0)); + storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0)); + storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0)); + storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0)); + storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0)); + DeliverEvent(0xf0000003, 0x0010); } void psxBiosInit() { - u32 base, size; - u32 *ptr, *ram32; + u32 *ptr, *ram32, *rom32; int i; uLongf len; @@ -3311,7 +3363,7 @@ void psxBiosInit() { biosC0[0x01] = psxBios_InitException; biosC0[0x02] = psxBios_SysEnqIntRP; biosC0[0x03] = psxBios_SysDeqIntRP; - //biosC0[0x04] = psxBios_get_free_EvCB_slot; + biosC0[0x04] = psxBios_get_free_EvCB_slot; //biosC0[0x05] = psxBios_get_free_TCB_slot; //biosC0[0x06] = psxBios_ExceptionHandler; //biosC0[0x07] = psxBios_InstallExeptionHandler; @@ -3338,33 +3390,23 @@ void psxBiosInit() { //biosC0[0x1c] = psxBios_PatchAOTable; //************** THE END *************************************** /**/ - base = 0x1000; - size = sizeof(EvCB) * 32; - EventCB = (void *)&psxR[base]; base += size * 6; - memset(EventCB, 0, size * 6); - HwEV = EventCB; - EvEV = EventCB + 32; - RcEV = EventCB + 32 * 2; - UeEV = EventCB + 32 * 3; - SwEV = EventCB + 32 * 4; - ThEV = EventCB + 32 * 5; - - pad_stopped = 1; + pad_buf = NULL; - pad_buf1 = NULL; - pad_buf2 = NULL; - pad_buf1len = pad_buf2len = 0; heap_addr = NULL; heap_end = NULL; heap_size = 0; - CardState = -1; - CurThread = 0; memset(FDesc, 0, sizeof(FDesc)); card_active_chan = 0; // initial RNG seed psxMu32ref(0x9010) = SWAPu32(0xac20cc00); + rom32 = (u32 *)psxR; + rom32[0x100/4] = SWAP32(0x19951204); + rom32[0x104/4] = SWAP32(3); + strcpy(psxR + 0x108, "PCSX authors"); + strcpy(psxR + 0x12c, "PCSX HLE"); + // fonts len = 0x80000 - 0x66000; uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140)); @@ -3430,9 +3472,14 @@ void psxBiosInit() { // patch: +3d8, +4dc, +594, +62c, +9c8, +1988 // call: +7a0=4b70, +884=4c54, +894=4c64 ptr[0x5b] = SWAP32(0x43d0); - ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra - ram32[0x4c54/4] = SWAP32(0x03e00008); // jr $ra + ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf + + ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1 + ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra + ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ... + ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra + ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ... ptr = (u32 *)&psxM[A_C0_TABLE]; for (i = 0; i < 256/2; i++) @@ -3479,8 +3526,6 @@ void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) { } static void biosPadHLE() { - int i, bufcount; - if (pad_buf != NULL) { u32 *buf = (u32*)pad_buf; @@ -3512,15 +3557,6 @@ static void biosPadHLE() { *buf |= PAD2_poll(0) << 16; } } - if (!pad_stopped) { - if (pad_buf1) { - psxBios_PADpoll(1); - } - - if (pad_buf2) { - psxBios_PADpoll(2); - } - } } static void handle_chain_x_x_1(u32 enable, u32 irqbit) @@ -3550,7 +3586,7 @@ void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000); //if (--cdrom_irq_counter == 0) // 0xa0009180 - // DeliverEvent(); // 0xf0000003, 0x10 + // DeliverEvent(0xf0000003, 0x10); use_cycles(22); ret = 1; } @@ -3581,7 +3617,7 @@ void hleExc0_2_2_syscall() // not in any A/B/C table if (code != R3000E_Syscall) { if (code != 0) { - // DeliverEvent(); // 0xf0000010, 0x1000 + DeliverEvent(0xf0000010, 0x1000); psxBios_SystemErrorUnresolvedException(); } mips_return_c(0, 17); @@ -3610,7 +3646,7 @@ void hleExc0_2_2_syscall() // not in any A/B/C table break; } default: - // DeliverEvent(); // 0xf0000010, 0x4000 + DeliverEvent(0xf0000010, 0x4000); break; } use_cycles(30); @@ -3627,10 +3663,7 @@ static void handle_chain_1_x_2(u32 ev_index, u32 irqbit) { u32 ret = 0; if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) { - // DeliverEvent 0xf2000000 + ev_index, 2 - if (RcEV[ev_index][1].status == EvStACTIVE) { - softCall(RcEV[ev_index][1].fhandler); - } + DeliverEvent(0xf2000000 + ev_index, 0x0002); ret = 1; } mips_return_c(ret, 22); @@ -3694,7 +3727,7 @@ void hleExc3_0_2_defint(void) size_t i; for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) { if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) { - // DeliverEvent 0xf0000000 + ev, 0x1000 + DeliverEvent(0xf0000000 + tab[i].ev, 0x1000); use_cycles(7); } @@ -3702,6 +3735,33 @@ void hleExc3_0_2_defint(void) mips_return_c(0, 11 + 7*11 + 7*11 + 12); } +void hleExcPadCard1(void) +{ + if (loadRam32(A_PAD_IRQR_ENA)) { + u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0); + u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4); + int i, bufcount; + + psxBios_PADpoll(1); + psxBios_PADpoll(2); + biosPadHLE(); + use_cycles(100); + } + if (loadRam32(A_PAD_ACK_VBL)) + psxHwWrite16(0x1f801070, ~1); + if (loadRam32(A_CARD_IRQR_ENA)) { + // todo, maybe + } + + mips_return_c(0, 18); +} + +void hleExcPadCard2(void) +{ + u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1; + mips_return_c(ret, 15); +} + void psxBiosException() { u32 tcbPtr = loadRam32(A_TT_PCB); u32 *chains = loadRam32ptr(A_TT_ExCB); @@ -3750,10 +3810,6 @@ void psxBiosException() { } assert(lim < 100); - // TODO make this a chain entry - if (psxHu32(0x1070) & 1) - biosPadHLE(); - // return from exception (custom or default) use_cycles(23); ptr = loadRam32(A_EEXIT_PTR); @@ -3791,16 +3847,8 @@ void psxBiosFreeze(int Mode) { u32 base = 0x40000; bfreezepsxMptr(pad_buf, int); - bfreezepsxMptr(pad_buf1, char); - bfreezepsxMptr(pad_buf2, char); bfreezepsxMptr(heap_addr, u32); - bfreezel(&pad_buf1len); - bfreezel(&pad_buf2len); - bfreezes(regs); - bfreezel(&CardState); - bfreezel(&CurThread); bfreezes(FDesc); bfreezel(&card_active_chan); - bfreezel(&pad_stopped); bfreezel(&heap_size); }