u32 mcfile;
} FileDesc;
-static u32 heap_size = 0;
-static u32 *heap_addr = NULL;
-static u32 *heap_end = NULL;
+// todo: FileDesc layout is wrong
+// todo: get rid of these globals
static FileDesc FDesc[32];
-static u32 card_active_chan = 0;
+static char ffile[64], *pfile;
+static int nfile;
// fixed RAM offsets, SCPH1001 compatible
#define A_TT_ExCB 0x0100
#define A_PAD_IN_LEN 0x74d8
#define A_PAD_OUT_LEN 0x74e0
#define A_PAD_DR_DST 0x74c4
+#define A_CARD_CHAN1 0x7500
#define A_PAD_DR_BUF1 0x7570
#define A_PAD_DR_BUF2 0x7598
#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_HEAP_BASE 0x9000
+#define A_HEAP_SIZE 0x9004
+#define A_HEAP_END 0x9008
+#define A_HEAP_FLAG 0x900c
#define A_CD_EVENTS 0xb9b8
#define A_EXC_GP 0xf450
pc0 = ra;
}
+static void mips_return_void(void)
+{
+ pc0 = ra;
+}
+
static void use_cycles(u32 cycle)
{
psxRegs.cycle += cycle * 2;
PSXBIOS_LOG("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
memcpy(Ra1, ptr, length); \
+ psxCpu->Clear(a1, (length + 3) / 4); \
if (FDesc[1 + mcd].mode & 0x8000) { \
DeliverEvent(0xf0000011, 0x0004); \
DeliverEvent(0xf4000001, 0x0004); \
pc0 = ra;
}
-void psxBios_bcopy() { // 0x27
- char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
- v0 = a0;
- if (a0 == 0 || a2 > 0x7FFFFFFF)
- {
- pc0 = ra;
- return;
+static void do_memset(u32 dst, u32 v, s32 len)
+{
+ u32 d = dst;
+ s32 l = len;
+ while (l-- > 0) {
+ u8 *db = PSXM(d);
+ if (db != INVALID_PTR)
+ *db = v;
+ d++;
}
- while ((s32)a2-- > 0) *p1++ = *p2++;
- a2 = 0;
- pc0 = ra;
+ psxCpu->Clear(dst, (len + 3) / 4);
}
-void psxBios_bzero() { // 0x28
- char *p = (char *)Ra0;
- v0 = a0;
- /* Same as memset here (See memset below) */
- if (a1 > 0x7FFFFFFF || a1 == 0)
+static void do_memcpy(u32 dst, u32 src, s32 len)
+{
+ u32 d = dst, s = src;
+ s32 l = len;
+ while (l-- > 0) {
+ const u8 *sb = PSXM(s);
+ u8 *db = PSXM(d);
+ if (db != INVALID_PTR && sb != INVALID_PTR)
+ *db = *sb;
+ d++;
+ s++;
+ }
+ psxCpu->Clear(dst, (len + 3) / 4);
+}
+
+static void psxBios_memcpy();
+
+static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
+ //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
+ u32 ret = a0, cycles = 0;
+ if (a0 == 0) // ...but it checks src this time
{
- v0 = 0;
- pc0 = ra;
+ mips_return_c(0, 4);
return;
}
- else if (a0 == 0)
+ v1 = a0;
+ if ((s32)a2 > 0) {
+ do_memcpy(a1, a0, a2);
+ cycles = a2 * 6;
+ a0 += a2;
+ a1 += a2;
+ a2 = 0;
+ }
+ mips_return_c(ret, cycles + 5);
+}
+
+static void psxBios_bzero() { // 0x28
+ /* Same as memset here (See memset below) */
+ u32 ret = a0, cycles;
+ if (a0 == 0 || (s32)a1 <= 0)
{
- pc0 = ra;
+ mips_return_c(0, 6);
return;
}
- while ((s32)a1-- > 0) *p++ = '\0';
+ do_memset(a0, 0, a1);
+ cycles = a1 * 4;
+ a0 += a1;
a1 = 0;
- pc0 = ra;
+ // todo: many more cycles due to uncached bios mem
+ mips_return_c(ret, cycles + 5);
}
void psxBios_bcmp() { // 0x29
v0 = 0; pc0 = ra;
}
-void psxBios_memcpy() { // 0x2a
- char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
- v0 = a0;
- if (a0 == 0 || a2 > 0x7FFFFFFF)
+static void psxBios_memcpy() { // 0x2a
+ u32 ret = a0, cycles = 0;
+ if (a0 == 0)
{
- pc0 = ra;
+ mips_return_c(0, 4);
return;
}
- while ((s32)a2-- > 0) {
- *p1++ = *p2++;
+ v1 = a0;
+ if ((s32)a2 > 0) {
+ do_memcpy(a0, a1, a2);
+ cycles = a2 * 6;
+ a0 += a2;
+ a1 += a2;
+ a2 = 0;
}
- a2 = 0;
- pc0 = ra;
+ mips_return_c(ret, cycles + 5);
}
-void psxBios_memset() { // 0x2b
- char *p = (char *)Ra0;
- v0 = a0;
- if (a2 > 0x7FFFFFFF || a2 == 0)
- {
- v0 = 0;
- pc0 = ra;
- return;
- }
- if (a0 == 0)
+static void psxBios_memset() { // 0x2b
+ u32 ret = a0, cycles;
+ if (a0 == 0 || (s32)a2 <= 0)
{
- pc0 = ra;
+ mips_return_c(0, 6);
return;
}
- while ((s32)a2-- > 0) *p++ = (char)a1;
+ do_memset(a0, a1, a2);
+ cycles = a2 * 4;
+ a0 += a2;
a2 = 0;
- v0 = a0; pc0 = ra;
+ // todo: many more cycles due to uncached bios mem
+ mips_return_c(ret, cycles + 5);
}
void psxBios_memmove() { // 0x2c
- char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
- v0 = a0;
- if (a0 == 0 || a2 > 0x7FFFFFFF)
+ u32 ret = a0, cycles = 0;
+ if (a0 == 0)
{
- pc0 = ra;
+ mips_return_c(0, 4);
return;
}
- if (p2 <= p1 && p2 + a2 > p1) {
- a2++; // BUG: copy one more byte here
- p1 += a2;
- p2 += a2;
- while ((s32)a2-- > 0) *--p1 = *--p2;
- } else {
- while ((s32)a2-- > 0) *p1++ = *p2++;
+ v1 = a0;
+ if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
+ u32 dst = a0, len = a2 + 1;
+ a0 += a2;
+ a1 += a2;
+ while ((s32)a2 >= 0) { // BUG: copies one more byte here
+ const u8 *sb = PSXM(a1);
+ u8 *db = PSXM(a0);
+ if (db != INVALID_PTR && sb != INVALID_PTR)
+ *db = *sb;
+ a0--;
+ a1--;
+ a2--;
+ }
+ psxCpu->Clear(dst, (len + 3) / 4);
+ cycles = 10 + len * 8;
+ } else if ((s32)a2 > 0) {
+ do_memcpy(a0, a1, a2);
+ cycles = a2 * 6;
+ a0 += a2;
+ a1 += a2;
+ a2 = 0;
}
- pc0 = ra;
+ mips_return_c(ret, cycles + 5);
}
void psxBios_memcmp() { // 0x2d
pc0 = ra;
}
-void psxBios_malloc() { // 0x33
+// this isn't how the real bios works, but maybe good enough
+static void psxBios_malloc() { // 0x33
+ u32 *heap_addr, *heap_end;
u32 *chunk, *newchunk = NULL;
unsigned int dsize = 0, csize, cstat;
int colflag;
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
-#endif
- if (!a0 || (!heap_size || !heap_addr)) {
+ PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
+ heap_addr = loadRam32ptr(A_HEAP_BASE);
+ heap_end = loadRam32ptr(A_HEAP_END);
+ if (heap_addr >= heap_end) {
v0 = 0;
pc0 = ra;
return;
pc0 = ra;
}
-void psxBios_free() { // 0x34
-
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
- PSXBIOS_LOG("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
-
- if (a0)
- *(u32*)(Ra0-4) |= 1; // set chunk to free
- pc0 = ra;
+static void psxBios_free() { // 0x34
+ PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
+ storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
+ mips_return_void_c(5);
}
-void psxBios_calloc() { // 0x37
- void *pv0;
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
-#endif
+static void psxBios_calloc() { // 0x37
+ u32 ret, size;
+ PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
- a0 = a0 * a1;
+ a0 = size = a0 * a1;
psxBios_malloc();
- pv0 = Rv0;
- if (pv0)
- memset(pv0, 0, a0);
+ ret = v0;
+ if (ret) {
+ a0 = ret; a1 = size;
+ psxBios_bzero();
+ }
+ mips_return_c(ret, 21);
}
void psxBios_realloc() { // 0x38
/* InitHeap(void *block , int n) */
-void psxBios_InitHeap() { // 0x39
- unsigned int size;
-
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
-#endif
+static void psxBios_InitHeap() { // 0x39
+ PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
- if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
- else size = a1;
+ storeRam32(A_HEAP_BASE, a0);
+ storeRam32(A_HEAP_SIZE, a1);
+ storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
+ storeRam32(A_HEAP_FLAG, 0);
+ storeRam32(a0, 0);
- size &= 0xfffffffc;
-
- heap_addr = (u32 *)Ra0;
- heap_size = size;
- heap_end = (u32 *)((u8 *)heap_addr + heap_size);
- /* HACKFIX: Commenting out this line fixes GTA2 crash */
- //*heap_addr = SWAP32(size | 1);
-
- PSXBIOS_LOG("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
-
- pc0 = ra;
+ mips_return_void_c(14);
}
void psxBios_getchar() { //0x3b
mips_return_void_c(1000);
}
+static void FlushCache() {
+ psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
+ psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
+ k0 = 0xbfc0193c;
+ // runs from uncached mem so tons of cycles
+ use_cycles(500);
+}
+
/*
* long Load(char *name, struct EXEC *header);
*/
void *pa1;
pa1 = Ra1;
- if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
+ if (pa1 != INVALID_PTR && LoadCdromFile(Ra0, &eheader) == 0) {
memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
+ psxCpu->Clear(a1, sizeof(EXEC) / 4);
+ FlushCache();
v0 = 1;
} else v0 = 0;
PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
pc0 = SWAP32(header->_pc0);
}
-void psxBios_FlushCache() { // 44
-#ifdef PSXBIOS_LOG
+static void psxBios_FlushCache() { // 44
PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
-#endif
- psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
- psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
- pc0 = ra;
+ FlushCache();
+ mips_return_void();
}
void psxBios_GPU_dw() { // 0x46
}
/* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
-void psxBios_get_cd_status(void) //a6
+static void psxBios_get_cd_status() // a6
{
+ PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
v0 = 1;
pc0 = ra;
}
-void psxBios__card_info() { // ab
-#ifdef PSXBIOS_LOG
+static void psxBios__card_info() { // ab
PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
-#endif
u32 ret, port;
- card_active_chan = a0;
- port = card_active_chan >> 4;
+ storeRam32(A_CARD_CHAN1, a0);
+ port = a0 >> 4;
switch (port) {
case 0x0:
ret = 0x0100;
break;
default:
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
-#endif
+ PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
ret = 0x0302;
break;
}
PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
#endif
- card_active_chan = a0;
+ storeRam32(A_CARD_CHAN1, a0);
// DeliverEvent(0xf0000011, 0x0004);
DeliverEvent(0xf4000001, 0x0004);
mips_return(ret);
}
-char ffile[64], *pfile;
-int nfile;
-
static void buopen(int mcd, char *ptr, char *cfg)
{
int i;
u32 *ram32 = (u32 *)psxM;
PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
- // (maybe) todo: early_card_irq, FlushCache etc
+ // (maybe) todo: early_card_irq, etc
ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
- mips_return_c(0, 300);
+ psxBios_FlushCache();
+ mips_return_c(0, 34+13+15+6);
}
void psxBios_StartCARD() { // 4b
v0 = 0; pc0 = ra;
return;
}
- card_active_chan = a0;
+ storeRam32(A_CARD_CHAN1, a0);
port = a0 >> 4;
if (pa2 != INVALID_PTR) {
v0 = 0; pc0 = ra;
return;
}
- card_active_chan = a0;
+ storeRam32(A_CARD_CHAN1, a0);
port = a0 >> 4;
if (pa2 != INVALID_PTR) {
mips_return_c(A_B0_TABLE, 3);
}
-void psxBios__card_chan() { // 0x58
-#ifdef PSXBIOS_LOG
+static void psxBios__card_chan() { // 0x58
+ u32 ret;
PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
-#endif
- v0 = card_active_chan;
- pc0 = ra;
+ // todo: should return active slot chan
+ // (active - which was last processed by irq code)
+ ret = loadRam32(A_CARD_CHAN1);
+ mips_return_c(ret, 8);
}
static void psxBios_ChangeClearPad() { // 5b
mips_return_c(ret, 6);
}
-void psxBios__card_status() { // 5c
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
-#endif
+static void psxBios__card_status() { // 5c
+ PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
- v0 = card_active_chan;
+ v0 = 1; // ready
pc0 = ra;
}
-void psxBios__card_wait() { // 5d
-#ifdef PSXBIOS_LOG
- PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
-#endif
+static void psxBios__card_wait() { // 5d
+ PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
- v0 = 1;
+ v0 = 1; // ready
pc0 = ra;
}
d[2] = SWAPu32(handler2);
// install the hle traps
- PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
- PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
+ if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
+ if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
}
static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
//************** THE END ***************************************
/**/
- heap_addr = NULL;
- heap_end = NULL;
- heap_size = 0;
memset(FDesc, 0, sizeof(FDesc));
- card_active_chan = 0;
// initial RNG seed
psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
len = 0x80000 - 0x69d68;
uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
+ // trap attempts to call bios directly
+ rom32[0x00000/4] = HLEOP(hleop_dummy);
+ rom32[0x00180/4] = HLEOP(hleop_dummy);
+ rom32[0x3fffc/4] = HLEOP(hleop_dummy);
+ rom32[0x65ffc/4] = HLEOP(hleop_dummy);
+ rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
+
/* 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 :
void psxBiosFreeze(int Mode) {
u32 base = 0x40000;
- bfreezepsxMptr(heap_addr, u32);
bfreezes(FDesc);
- bfreezel(&card_active_chan);
- bfreezel(&heap_size);
}