#define k1 (psxRegs.GPR.n.k1)
#define gp (psxRegs.GPR.n.gp)
#define sp (psxRegs.GPR.n.sp)
-#define fp (psxRegs.GPR.n.s8)
+#define fp (psxRegs.GPR.n.fp)
#define ra (psxRegs.GPR.n.ra)
#define pc0 (psxRegs.pc)
} 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 heap_size = 0;
static u32 *heap_addr = NULL;
static u32 *heap_end = NULL;
#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
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));
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);
}
}
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);
+
+ // 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);
+
+ 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);
- pad_buf1 = (char*)Ra0;
- pad_buf1len = a1;
- pad_buf2 = (char*)Ra2;
- pad_buf2len = a3;
+ ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
- v0 = 1; pc0 = ra;
+ 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
}
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
- pc0 = ra;
+ ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
+
+ 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);
- pc0 = ra;
+ 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;
+
+ mips_return_c(1, 200);
}
void psxBios_StopCARD() { // 4c
-#ifdef PSXBIOS_LOG
PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
-#endif
-
- 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
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
/* System calls C0 */
-static void psxBios_SysEnqIntRP();
-
static void psxBios_InitRCnt() { // 00
int i;
PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
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);
}
* 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;
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
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);
}
void (*biosC0[256+128])();
void (**biosB0)() = biosC0 + 128;
-#include "sjisfont.h"
-
-void setup_mips_code()
+static void setup_mips_code()
{
u32 *ptr;
ptr = (u32 *)&psxM[A_SYSCALL];
ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
- ptr[0x68/4] = SWAPu32(0x24630004); // addiu $v1, $v1, 4
ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
ptr[0xb0/4] = HLEOP(hleop_exception);
{ 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)
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));
}
DeliverEvent(0xf0000003, 0x0010);
}
+static const u32 gpu_ctl_def[] = {
+ 0x00000000, 0x01000000, 0x03000000, 0x04000000,
+ 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
+};
+
+static const u32 gpu_data_def[] = {
+ 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
+ 0xe5001000, 0xe6000000,
+ 0x02000000, 0x00000000, 0x01ff03ff
+};
+
+// from 1f801d80
+static const u16 spu_config[] = {
+ 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
+ 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
+ 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
+ 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
+ 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
+};
+
+void psxBiosSetupBootState(void)
+{
+ boolean hle = Config.HLE;
+ u32 *hw = (u32 *)psxH;
+ int i;
+
+ // see also SetBootRegs()
+ if (hle) {
+ v0 = 1; v1 = 4;
+ a0 = 1; a2 = a3 = 0; a3 = 0x2a;
+ t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
+ s0 = 0xa000b870;
+ k0 = 0xbfc0d968; k1 = 0xf1c;
+ ra = 0xf0001234; // just to easily detect attempts to return
+ psxRegs.CP0.n.Cause = 0x20;
+ psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
+
+ hw[0x1000/4] = SWAP32(0x1f000000);
+ hw[0x1004/4] = SWAP32(0x1f802000);
+ hw[0x1008/4] = SWAP32(0x0013243f);
+ hw[0x100c/4] = SWAP32(0x00003022);
+ hw[0x1010/4] = SWAP32(0x0013243f);
+ hw[0x1014/4] = SWAP32(0x200931e1);
+ hw[0x1018/4] = SWAP32(0x00020943);
+ hw[0x101c/4] = SWAP32(0x00070777);
+ hw[0x1020/4] = SWAP32(0x0000132c);
+ hw[0x1060/4] = SWAP32(0x00000b88);
+ hw[0x1070/4] = SWAP32(0x00000001);
+ hw[0x1074/4] = SWAP32(0x0000000c);
+ hw[0x2040/4] = SWAP32(0x00000900);
+ }
+
+ hw[0x10a0/4] = SWAP32(0x00ffffff);
+ hw[0x10a8/4] = SWAP32(0x00000401);
+ hw[0x10b0/4] = SWAP32(0x0008b000);
+ hw[0x10b4/4] = SWAP32(0x00010200);
+ hw[0x10e0/4] = SWAP32(0x000eccf4);
+ hw[0x10e4/4] = SWAP32(0x00000400);
+ hw[0x10e8/4] = SWAP32(0x00000002);
+ hw[0x10f0/4] = SWAP32(0x00009099);
+ hw[0x10f4/4] = SWAP32(0x8c8c0000);
+
+ if (hle) {
+ psxRcntWmode(0, 0);
+ psxRcntWmode(1, 0);
+ psxRcntWmode(2, 0);
+ }
+
+ // gpu
+ for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
+ GPU_writeStatus(gpu_ctl_def[i]);
+ for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
+ GPU_writeData(gpu_data_def[i]);
+ HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
+
+ // spu
+ for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
+ SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
+}
+
+#include "sjisfont.h"
+
void psxBiosInit() {
u32 *ptr, *ram32, *rom32;
int i;
//************** THE END ***************************************
/**/
- 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;
len = 0x80000 - 0x69d68;
uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
- // memory size 2 MB
- psxHu32ref(0x1060) = SWAPu32(0x00000b88);
-
/* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
Here are some examples of games not working with this fix in place :
// 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++)
}
static void biosPadHLE() {
- int i, bufcount;
-
if (pad_buf != NULL) {
u32 *buf = (u32*)pad_buf;
*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)
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);
}
tcb->lo = SWAP32(psxRegs.GPR.n.lo);
tcb->hi = SWAP32(psxRegs.GPR.n.hi);
- tcb->epc = SWAP32(psxRegs.CP0.n.EPC);
+ //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
tcb->sr = SWAP32(psxRegs.CP0.n.SR);
tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
sp = fp = loadRam32(A_EXC_SP);
}
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);
u32 base = 0x40000;
bfreezepsxMptr(pad_buf, int);
- bfreezepsxMptr(pad_buf1, char);
- bfreezepsxMptr(pad_buf2, char);
bfreezepsxMptr(heap_addr, u32);
bfreezes(FDesc);
bfreezel(&card_active_chan);
- bfreezel(&pad_stopped);
bfreezel(&heap_size);
}