1 /***************************************************************************
2 * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3 * dmitrysmagin, senquack *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
19 ***************************************************************************/
21 /* Gameblabla 2018-2019 :
22 * Numerous changes to bios calls as well as improvements in order to conform to nocash's findings
23 * for the PSX bios calls. Thanks senquack for helping out with some of the changes
24 * and helping to spot issues and refine my patches.
28 * Internal simulated HLE BIOS.
31 // TODO: implement all system calls, count the exact CPU cycles of system calls.
40 #if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
41 #pragma GCC diagnostic ignored "-Wpointer-sign"
45 #define SysPrintf if (Config.PsxOut) printf
47 char *biosA0n[256] = {
49 "open", "lseek", "read", "write",
50 "close", "ioctl", "exit", "sys_a0_07",
51 "getc", "putc", "todigit", "atof",
52 "strtoul", "strtol", "abs", "labs",
54 "atoi", "atol", "atob", "setjmp",
55 "longjmp", "strcat", "strncat", "strcmp",
56 "strncmp", "strcpy", "strncpy", "strlen",
57 "index", "rindex", "strchr", "strrchr",
59 "strpbrk", "strspn", "strcspn", "strtok",
60 "strstr", "toupper", "tolower", "bcopy",
61 "bzero", "bcmp", "memcpy", "memset",
62 "memmove", "memcmp", "memchr", "rand",
64 "srand", "qsort", "strtod", "malloc",
65 "free", "lsearch", "bsearch", "calloc",
66 "realloc", "InitHeap", "_exit", "getchar",
67 "putchar", "gets", "puts", "printf",
69 "sys_a0_40", "LoadTest", "Load", "Exec",
70 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
71 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
72 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
74 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
75 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
76 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
77 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
79 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
80 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
81 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
82 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
84 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
85 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
86 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
87 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
89 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
90 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
91 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
92 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
94 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
95 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
96 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
97 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
99 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
100 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
101 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
102 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
104 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
108 char *biosB0n[256] = {
110 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
111 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
112 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
113 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
115 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
116 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
117 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
118 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
120 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
121 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
122 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
123 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
125 "sys_b0_30", "sys_b0_31", "open", "lseek",
126 "read", "write", "close", "ioctl",
127 "exit", "sys_b0_39", "getc", "putc",
128 "getchar", "putchar", "gets", "puts",
130 "cd", "format", "firstfile", "nextfile",
131 "rename", "delete", "undelete", "AddDevice",
132 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
133 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
135 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
136 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
137 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
138 "_card_status", "_card_wait",
141 char *biosC0n[256] = {
143 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
144 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
145 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
146 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
148 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
149 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
150 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
154 //#define r0 (psxRegs.GPR.n.r0)
155 #define at (psxRegs.GPR.n.at)
156 #define v0 (psxRegs.GPR.n.v0)
157 #define v1 (psxRegs.GPR.n.v1)
158 #define a0 (psxRegs.GPR.n.a0)
159 #define a1 (psxRegs.GPR.n.a1)
160 #define a2 (psxRegs.GPR.n.a2)
161 #define a3 (psxRegs.GPR.n.a3)
162 #define t0 (psxRegs.GPR.n.t0)
163 #define t1 (psxRegs.GPR.n.t1)
164 #define t2 (psxRegs.GPR.n.t2)
165 #define t3 (psxRegs.GPR.n.t3)
166 #define t4 (psxRegs.GPR.n.t4)
167 #define t5 (psxRegs.GPR.n.t5)
168 #define t6 (psxRegs.GPR.n.t6)
169 #define t7 (psxRegs.GPR.n.t7)
170 #define t8 (psxRegs.GPR.n.t8)
171 #define t9 (psxRegs.GPR.n.t9)
172 #define s0 (psxRegs.GPR.n.s0)
173 #define s1 (psxRegs.GPR.n.s1)
174 #define s2 (psxRegs.GPR.n.s2)
175 #define s3 (psxRegs.GPR.n.s3)
176 #define s4 (psxRegs.GPR.n.s4)
177 #define s5 (psxRegs.GPR.n.s5)
178 #define s6 (psxRegs.GPR.n.s6)
179 #define s7 (psxRegs.GPR.n.s7)
180 #define k0 (psxRegs.GPR.n.k0)
181 #define k1 (psxRegs.GPR.n.k1)
182 #define gp (psxRegs.GPR.n.gp)
183 #define sp (psxRegs.GPR.n.sp)
184 #define fp (psxRegs.GPR.n.s8)
185 #define ra (psxRegs.GPR.n.ra)
186 #define pc0 (psxRegs.pc)
188 #define Ra0 ((char *)PSXM(a0))
189 #define Ra1 ((char *)PSXM(a1))
190 #define Ra2 ((char *)PSXM(a2))
191 #define Ra3 ((char *)PSXM(a3))
192 #define Rv0 ((char *)PSXM(v0))
193 #define Rsp ((char *)PSXM(sp))
202 #define EvStUNUSED 0x0000
203 #define EvStWAIT 0x1000
204 #define EvStACTIVE 0x2000
205 #define EvStALREADY 0x4000
207 #define EvMdINTR 0x1000
208 #define EvMdNOINTR 0x2000
240 u32 _sp, _fp, _gp, ret, base;
260 static int *pad_buf = NULL;
261 static char *pad_buf1 = NULL, *pad_buf2 = NULL;
262 static int pad_buf1len, pad_buf2len;
263 static int pad_stopped = 0;
266 static EvCB *EventCB;
267 static EvCB *HwEV; // 0xf0
268 static EvCB *EvEV; // 0xf1
269 static EvCB *RcEV; // 0xf2
270 static EvCB *UeEV; // 0xf3
271 static EvCB *SwEV; // 0xf4
272 static EvCB *ThEV; // 0xff
273 static u32 heap_size = 0;
274 static u32 *heap_addr = NULL;
275 static u32 *heap_end = NULL;
276 static int CardState = -1;
277 static int CurThread = 0;
278 static FileDesc FDesc[32];
279 static u32 card_active_chan = 0;
281 // fixed RAM offsets, SCPH1001 compatible
282 #define A_TT_ExCB 0x0100
283 #define A_TT_PCB 0x0108
284 #define A_TT_TCB 0x0110
285 #define A_A0_TABLE 0x0200
286 #define A_B0_TABLE 0x0874
287 #define A_C0_TABLE 0x0674
288 #define A_SYSCALL 0x0650
289 #define A_EXCEPTION 0x0c80
290 #define A_EXC_SP 0x6cf0
291 #define A_EEXIT_DEF 0x6cf4
292 #define A_EEXIT_PTR 0x75d0
293 #define A_EXC_STACK 0x85d8 // exception stack top
294 #define A_RCNT_VBL_ACK 0x8600
295 #define A_EXC_GP 0xf450
297 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
299 static u32 loadRam32(u32 addr)
301 assert(!(addr & 0x5f800000));
302 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
305 static void *castRam32ptr(u32 addr)
307 assert(!(addr & 0x5f800003));
308 return psxM + (addr & 0x1ffffc);
311 static void *loadRam32ptr(u32 addr)
313 return castRam32ptr(loadRam32(addr));
316 static void storeRam32(u32 addr, u32 d)
318 assert(!(addr & 0x5f800000));
319 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
322 static void mips_return(u32 val)
328 static void use_cycles(u32 cycle)
330 psxRegs.cycle += cycle * 2;
333 static void mips_return_c(u32 val, u32 cycle)
339 static void mips_return_void_c(u32 cycle)
345 static int returned_from_exception(void)
347 // 0x80000080 means it took another exception just after return
348 return pc0 == k0 || pc0 == 0x80000080;
351 static inline void softCall(u32 pc) {
353 u32 ssr = psxRegs.CP0.n.SR;
356 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
358 while (pc0 != 0x80001000)
359 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
362 psxRegs.CP0.n.SR = ssr;
365 static inline void softCallInException(u32 pc) {
370 while (!returned_from_exception() && pc0 != 0x80001000)
371 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
373 if (pc0 == 0x80001000)
377 static inline void DeliverEvent(u32 ev, u32 spec) {
378 if (EventCB[ev][spec].status != EvStACTIVE) return;
380 // EventCB[ev][spec].status = EvStALREADY;
381 if (EventCB[ev][spec].mode == EvMdINTR) {
382 softCall(EventCB[ev][spec].fhandler);
383 } else EventCB[ev][spec].status = EvStALREADY;
389 // System calls A0 */
392 #define buread(Ra1, mcd, length) { \
393 SysPrintf("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
394 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
395 memcpy(Ra1, ptr, length); \
396 if (FDesc[1 + mcd].mode & 0x8000) { \
397 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
398 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
401 FDesc[1 + mcd].offset += v0; \
404 #define buwrite(Ra1, mcd, length) { \
405 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
406 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
407 ptr = Mcd##mcd##Data + offset; \
408 memcpy(ptr, Ra1, length); \
409 FDesc[1 + mcd].offset += length; \
410 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
411 if (FDesc[1 + mcd].mode & 0x8000) { \
412 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
413 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
419 //#define PSXBIOS_LOG printf
420 #define PSXBIOS_LOG(...)
423 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
424 /* For some strange reason, the returned character is sign-expanded; */
425 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
426 /* TODO FIX ME : Properly implement this behaviour */
427 void psxBios_getc(void) // 0x03, 0x35
432 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
436 if (pa1 != INVALID_PTR) {
438 case 2: buread(pa1, 1, 1); break;
439 case 3: buread(pa1, 2, 1); break;
446 /* Copy of psxBios_write, except size is 1. */
447 void psxBios_putc(void) // 0x09, 0x3B
452 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
455 if (pa1 == INVALID_PTR) {
460 if (a0 == 1) { // stdout
461 char *ptr = (char *)pa1;
465 printf("%c", *ptr++); a2--;
471 case 2: buwrite(pa1, 1, 1); break;
472 case 3: buwrite(pa1, 2, 1); break;
478 void psxBios_todigit(void) // 0x0a
482 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
485 if (c >= 0x30 && c < 0x3A) {
488 else if (c > 0x60 && c < 0x7B) {
491 else if (c > 0x40 && c < 0x5B) {
494 else if (c >= 0x80) {
505 void psxBios_abs() { // 0x0e
506 if ((s32)a0 < 0) v0 = -(s32)a0;
511 void psxBios_labs() { // 0x0f
515 void psxBios_atoi() { // 0x10
517 char *p = (char *)Ra0;
521 case ' ': case '\t': continue;
528 while (*p >= '0' && *p <= '9') {
529 n = n * 10 + *p++ - '0';
536 void psxBios_atol() { // 0x11
546 static void psxBios_setjmp() { // 0x13
547 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
550 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
552 jmp_buf->ra_ = SWAP32(ra);
553 jmp_buf->sp_ = SWAP32(sp);
554 jmp_buf->fp_ = SWAP32(fp);
555 for (i = 0; i < 8; i++) // s0-s7
556 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
557 jmp_buf->gp_ = SWAP32(gp);
559 mips_return_c(0, 15);
562 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
566 ra = SWAP32(jmp_buf->ra_);
567 sp = SWAP32(jmp_buf->sp_);
568 fp = SWAP32(jmp_buf->fp_);
569 for (i = 0; i < 8; i++) // s0-s7
570 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
571 gp = SWAP32(jmp_buf->gp_);;
574 void psxBios_longjmp() { // 0x14
575 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
577 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
578 longjmp_load(jmp_buf);
579 mips_return_c(a1, 15);
582 void psxBios_strcat() { // 0x15
583 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
586 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
588 if (a0 == 0 || a1 == 0)
596 while ((*p1++ = *p2++) != '\0');
601 void psxBios_strncat() { // 0x16
602 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
606 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
608 if (a0 == 0 || a1 == 0)
616 while ((*p1++ = *p2++) != '\0') {
626 void psxBios_strcmp() { // 0x17
627 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
629 if (a0 == 0 && a1 == 0)
635 else if (a0 == 0 && a1 != 0)
641 else if (a0 != 0 && a1 == 0)
648 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
651 while (*p1 == *p2++) {
670 void psxBios_strncmp() { // 0x18
671 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
673 if (a0 == 0 && a1 == 0)
679 else if (a0 == 0 && a1 != 0)
685 else if (a0 != 0 && a1 == 0)
692 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
695 while (--n >= 0 && *p1 == *p2++) {
699 v1 = a2 - ((a2-n) - 1);
707 v0 = (n < 0 ? 0 : *p1 - *--p2);
709 v1 = a2 - ((a2-n) - 1);
715 void psxBios_strcpy() { // 0x19
716 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
717 if (a0 == 0 || a1 == 0)
723 while ((*p1++ = *p2++) != '\0');
728 void psxBios_strncpy() { // 0x1a
729 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
731 if (a0 == 0 || a1 == 0)
737 for (i = 0; i < n; i++) {
738 if ((*p1++ = *p2++) == '\0') {
750 void psxBios_strlen() { // 0x1b
751 char *p = (char *)Ra0;
762 void psxBios_index() { // 0x1c
763 char *p = (char *)Ra0;
773 v0 = a0 + (p - (char *)Ra0);
777 } while (*p++ != '\0');
782 void psxBios_rindex() { // 0x1d
783 char *p = (char *)Ra0;
793 v0 = a0 + (p - (char *)Ra0);
794 } while (*p++ != '\0');
799 void psxBios_strchr() { // 0x1e
803 void psxBios_strrchr() { // 0x1f
807 void psxBios_strpbrk() { // 0x20
808 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
810 while ((c = *p1++) != '\0') {
811 for (scanp = p2; (sc = *scanp++) != '\0';) {
813 v0 = a0 + (p1 - 1 - (char *)Ra0);
820 // BUG: return a0 instead of NULL if not found
824 void psxBios_strspn() { // 0x21
827 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
828 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
829 if (*p2 == '\0') break;
832 v0 = p1 - (char *)Ra0; pc0 = ra;
835 void psxBios_strcspn() { // 0x22
838 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
839 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
840 if (*p2 != '\0') break;
843 v0 = p1 - (char *)Ra0; pc0 = ra;
846 void psxBios_strtok() { // 0x23
847 char *pcA0 = (char *)Ra0;
848 char *pcRet = strtok(pcA0, (char *)Ra1);
850 v0 = a0 + pcRet - pcA0;
856 void psxBios_strstr() { // 0x24
857 char *p = (char *)Ra0, *p1, *p2;
863 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
868 v0 = a0 + (p - (char *)Ra0);
879 void psxBios_toupper() { // 0x25
880 v0 = (s8)(a0 & 0xff);
881 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
885 void psxBios_tolower() { // 0x26
886 v0 = (s8)(a0 & 0xff);
887 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
891 void psxBios_bcopy() { // 0x27
892 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
894 if (a0 == 0 || a2 > 0x7FFFFFFF)
899 while ((s32)a2-- > 0) *p1++ = *p2++;
904 void psxBios_bzero() { // 0x28
905 char *p = (char *)Ra0;
907 /* Same as memset here (See memset below) */
908 if (a1 > 0x7FFFFFFF || a1 == 0)
919 while ((s32)a1-- > 0) *p++ = '\0';
924 void psxBios_bcmp() { // 0x29
925 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
927 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
929 while ((s32)a2-- > 0) {
930 if (*p1++ != *p2++) {
931 v0 = *p1 - *p2; // BUG: compare the NEXT byte
940 void psxBios_memcpy() { // 0x2a
941 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
943 if (a0 == 0 || a2 > 0x7FFFFFFF)
948 while ((s32)a2-- > 0) {
955 void psxBios_memset() { // 0x2b
956 char *p = (char *)Ra0;
958 if (a2 > 0x7FFFFFFF || a2 == 0)
969 while ((s32)a2-- > 0) *p++ = (char)a1;
974 void psxBios_memmove() { // 0x2c
975 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
977 if (a0 == 0 || a2 > 0x7FFFFFFF)
982 if (p2 <= p1 && p2 + a2 > p1) {
983 a2++; // BUG: copy one more byte here
986 while ((s32)a2-- > 0) *--p1 = *--p2;
988 while ((s32)a2-- > 0) *p1++ = *p2++;
993 void psxBios_memcmp() { // 0x2d
997 void psxBios_memchr() { // 0x2e
998 char *p = (char *)Ra0;
1000 if (a0 == 0 || a2 > 0x7FFFFFFF)
1006 while ((s32)a2-- > 0) {
1007 if (*p++ != (s8)a1) continue;
1008 v0 = a0 + (p - (char *)Ra0 - 1);
1016 void psxBios_rand() { // 0x2f
1017 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1018 v0 = (s >> 16) & 0x7fff;
1019 psxMu32ref(0x9010) = SWAPu32(s);
1023 void psxBios_srand() { // 0x30
1024 psxMu32ref(0x9010) = SWAPu32(a0);
1028 static u32 qscmpfunc, qswidth;
1030 static inline int qscmp(char *a, char *b) {
1033 a0 = sa0 + (a - (char *)PSXM(sa0));
1034 a1 = sa0 + (b - (char *)PSXM(sa0));
1036 softCall(qscmpfunc);
1042 static inline void qexchange(char *i, char *j) {
1053 static inline void q3exchange(char *i, char *j, char *k) {
1065 static void qsort_main(char *a, char *l) {
1066 char *i, *j, *lp, *hp;
1071 if ((n = l - a) <= qswidth)
1073 n = qswidth * (n / (2 * qswidth));
1079 if ((c = qscmp(i, lp)) == 0) {
1080 qexchange(i, lp -= qswidth);
1091 if ((c = qscmp(hp, j)) == 0) {
1092 qexchange(hp += qswidth, j);
1097 q3exchange(i, hp += qswidth, j);
1111 if (lp - a >= l - hp) {
1112 qsort_main(hp + qswidth, l);
1121 q3exchange(j, lp -= qswidth, i);
1126 void psxBios_qsort() { // 0x31
1129 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1134 void psxBios_malloc() { // 0x33
1135 u32 *chunk, *newchunk = NULL;
1136 unsigned int dsize = 0, csize, cstat;
1139 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1141 if (!a0 || (!heap_size || !heap_addr)) {
1147 // scan through heap and combine free chunks of space
1150 while(chunk < heap_end) {
1151 // get size and status of actual chunk
1152 csize = ((u32)*chunk) & 0xfffffffc;
1153 cstat = ((u32)*chunk) & 1;
1155 // most probably broken heap descriptor
1156 // this fixes Burning Road
1159 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1164 // it's a free chunk
1169 colflag = 1; // let's begin a new collection of free memory
1171 else dsize += (csize+4); // add the new size including header
1173 // not a free chunk: did we start a collection ?
1175 if(colflag == 1) { // collection is over
1177 *newchunk = SWAP32(dsize | 1);
1182 chunk = (u32*)((uptr)chunk + csize + 4);
1184 // if neccessary free memory on end of heap
1186 *newchunk = SWAP32(dsize | 1);
1189 csize = ((u32)*chunk) & 0xfffffffc;
1190 cstat = ((u32)*chunk) & 1;
1191 dsize = (a0 + 3) & 0xfffffffc;
1193 // exit on uninitialized heap
1194 if (chunk == NULL) {
1195 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1201 // search an unused chunk that is big enough until the end of the heap
1202 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1203 chunk = (u32*)((uptr)chunk + csize + 4);
1205 // catch out of memory
1206 if(chunk >= heap_end) {
1207 printf("malloc %x,%x: Out of memory error!\n",
1213 csize = ((u32)*chunk) & 0xfffffffc;
1214 cstat = ((u32)*chunk) & 1;
1218 if(dsize == csize) {
1219 // chunk has same size
1220 *chunk &= 0xfffffffc;
1221 } else if (dsize > csize) {
1226 *chunk = SWAP32(dsize);
1227 newchunk = (u32*)((uptr)chunk + dsize + 4);
1228 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1231 // return pointer to allocated memory
1232 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1234 //printf ("malloc %x,%x\n", v0, a0);
1238 void psxBios_free() { // 0x34
1241 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1244 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1247 *(u32*)(Ra0-4) |= 1; // set chunk to free
1251 void psxBios_calloc() { // 0x37
1254 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1264 void psxBios_realloc() { // 0x38
1268 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1272 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1277 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1282 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1283 /* Note that it is not quite implemented this way here. */
1293 /* InitHeap(void *block , int n) */
1294 void psxBios_InitHeap() { // 0x39
1298 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1301 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1306 heap_addr = (u32 *)Ra0;
1308 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1309 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1310 //*heap_addr = SWAP32(size | 1);
1312 SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1317 void psxBios_getchar() { //0x3b
1318 v0 = getchar(); pc0 = ra;
1321 static void psxBios_printf_psxout() { // 0x3f
1330 if (psp != INVALID_PTR) {
1331 memcpy(save, psp, 4 * 4);
1332 psxMu32ref(sp) = SWAP32((u32)a0);
1333 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1334 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1335 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1347 tmp2[j++] = Ra0[i]; goto _start;
1349 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1360 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1364 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1370 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1372 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1374 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1376 *ptmp++ = Ra0[i]; break;
1386 if (psp != INVALID_PTR)
1387 memcpy(psp, save, 4 * 4);
1389 SysPrintf("%s", tmp);
1392 void psxBios_printf() { // 0x3f
1393 psxBios_printf_psxout();
1397 void psxBios_format() { // 0x41
1398 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1400 CreateMcd(Config.Mcd1);
1401 LoadMcd(1, Config.Mcd1);
1404 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1406 CreateMcd(Config.Mcd2);
1407 LoadMcd(2, Config.Mcd2);
1417 static void psxBios_SystemErrorUnresolvedException() {
1418 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1419 SysPrintf("psxBios_%s\n", biosA0n[0x40]);
1420 storeRam32(0xfffc, 0x12345678);
1422 mips_return_void_c(1000);
1426 * long Load(char *name, struct EXEC *header);
1429 void psxBios_Load() { // 0x42
1434 PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1);
1438 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1439 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1447 * int Exec(struct EXEC *header , int argc , char **argv);
1450 void psxBios_Exec() { // 43
1451 EXEC *header = (EXEC*)Ra0;
1455 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1465 if (header->S_addr != 0) {
1466 tmp = header->S_addr + header->s_size;
1482 void psxBios_FlushCache() { // 44
1484 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1486 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1487 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1491 void psxBios_GPU_dw() { // 0x46
1496 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1499 GPU_writeData(0xa0000000);
1500 GPU_writeData((a1<<0x10)|(a0&0xffff));
1501 GPU_writeData((a3<<0x10)|(a2&0xffff));
1503 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1506 GPU_writeData(SWAPu32(*ptr++));
1512 void psxBios_mem2vram() { // 0x47
1515 GPU_writeData(0xa0000000);
1516 GPU_writeData((a1<<0x10)|(a0&0xffff));
1517 GPU_writeData((a3<<0x10)|(a2&0xffff));
1518 size = ((((a2 * a3) / 2) >> 4) << 16);
1519 GPU_writeStatus(0x04000002);
1520 psxHwWrite32(0x1f8010f4,0);
1521 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1522 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1523 psxHwWrite32(0x1f8010a4, size | 0x10);
1524 psxHwWrite32(0x1f8010a8,0x01000201);
1529 void psxBios_SendGPU() { // 0x48
1530 GPU_writeStatus(a0);
1535 void psxBios_GPU_cw() { // 0x49
1542 void psxBios_GPU_cwb() { // 0x4a
1543 u32 *ptr = (u32*)Ra0;
1548 GPU_writeData(SWAPu32(*ptr++));
1554 void psxBios_GPU_SendPackets() { //4b:
1556 GPU_writeStatus(0x04000002);
1557 psxHwWrite32(0x1f8010f4,0);
1558 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1559 psxHwWrite32(0x1f8010a0,a0);
1560 psxHwWrite32(0x1f8010a4,0);
1561 psxHwWrite32(0x1f8010a8,0x010000401);
1565 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1566 psxHwWrite32(0x1f8010a8,0x00000401);
1567 GPU_writeData(0x0400000);
1568 GPU_writeData(0x0200000);
1569 GPU_writeData(0x0100000);
1574 void psxBios_GPU_GetGPUStatus() { // 0x4d
1575 v0 = GPU_readStatus();
1581 void psxBios_LoadExec() { // 51
1582 EXEC *header = (EXEC*)PSXM(0xf000);
1586 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1588 s_addr = a1; s_size = a2;
1593 header->S_addr = s_addr;
1594 header->s_size = s_size;
1596 a0 = 0xf000; a1 = 0; a2 = 0;
1600 void psxBios__bu_init() { // 70
1602 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1605 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1606 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1611 void psxBios__96_init() { // 71
1613 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1619 static void psxBios_SysDeqIntRP_();
1621 static void psxBios_DequeueCdIntr_() {
1622 a0 = 0; a1 = 0x91d0;
1623 psxBios_SysDeqIntRP_();
1624 a0 = 0; a1 = 0x91e0;
1625 psxBios_SysDeqIntRP_();
1629 static void psxBios_DequeueCdIntr() { // a3
1630 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1631 psxBios_DequeueCdIntr_();
1634 static void psxBios_CdRemove() { // 56, 72
1635 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1637 // CloseEvent 0xf1000000
1638 // CloseEvent 0xf1000001
1639 // CloseEvent 0xf1000002
1640 // CloseEvent 0xf1000003
1641 // CloseEvent 0xf1000004
1642 psxBios_DequeueCdIntr_();
1644 // EnterCriticalSection - should be done at the beginning,
1645 // but this way is much easier to implement
1651 void psxBios_SetMem() { // 9f
1652 u32 new = psxHu32(0x1060);
1655 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1660 psxHu32ref(0x1060) = SWAP32(new);
1661 psxMu32ref(0x060) = a0;
1662 SysPrintf("Change effective memory : %d MBytes\n",a0);
1666 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1667 psxMu32ref(0x060) = a0;
1668 SysPrintf("Change effective memory : %d MBytes\n",a0);
1671 SysPrintf("Effective memory must be 2/8 MBytes\n");
1678 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1679 void psxBios_get_cd_status(void) //a6
1685 void psxBios__card_info() { // ab
1687 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1690 card_active_chan = a0;
1691 port = card_active_chan >> 4;
1697 if (McdDisable[port & 1])
1702 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1708 if (McdDisable[0] && McdDisable[1])
1711 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1712 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1713 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
1717 void psxBios__card_load() { // ac
1719 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1722 card_active_chan = a0;
1724 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1725 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1730 /* System calls B0 */
1732 void psxBios_SetRCnt() { // 02
1734 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1741 psxRcntWtarget(a0, a1);
1742 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1743 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1744 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1745 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1746 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1748 psxRcntWmode(a0, mode);
1753 void psxBios_GetRCnt() { // 03
1755 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1759 if (a0 != 3) v0 = psxRcntRcount(a0);
1764 void psxBios_StartRCnt() { // 04
1766 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1770 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1771 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1775 void psxBios_StopRCnt() { // 05
1777 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1781 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1782 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1786 void psxBios_ResetRCnt() { // 06
1788 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1793 psxRcntWmode(a0, 0);
1794 psxRcntWtarget(a0, 0);
1795 psxRcntWcount(a0, 0);
1801 /* gets ev for use with EventCB */
1803 ev = (a0 >> 24) & 0xf; \
1804 if (ev == 0xf) ev = 0x5; \
1808 /* gets spec for use with EventCB */
1812 case 0x0301: spec = 16; break; \
1813 case 0x0302: spec = 17; break; \
1815 for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1819 void psxBios_DeliverEvent() { // 07
1827 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1830 DeliverEvent(ev, spec);
1835 void psxBios_OpenEvent() { // 08
1843 PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1846 EventCB[ev][spec].status = EvStWAIT;
1847 EventCB[ev][spec].mode = a2;
1848 EventCB[ev][spec].fhandler = a3;
1850 v0 = ev | (spec << 8);
1854 void psxBios_CloseEvent() { // 09
1858 spec = (a0 >> 8) & 0xff;
1861 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1864 EventCB[ev][spec].status = EvStUNUSED;
1869 void psxBios_WaitEvent() { // 0a
1873 spec = (a0 >> 8) & 0xff;
1875 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1877 if (EventCB[ev][spec].status == EvStUNUSED)
1884 if (EventCB[ev][spec].status == EvStALREADY)
1886 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1887 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1897 void psxBios_TestEvent() { // 0b
1901 spec = (a0 >> 8) & 0xff;
1903 if (EventCB[ev][spec].status == EvStALREADY)
1905 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1914 PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1920 void psxBios_EnableEvent() { // 0c
1924 spec = (a0 >> 8) & 0xff;
1927 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1930 EventCB[ev][spec].status = EvStACTIVE;
1935 void psxBios_DisableEvent() { // 0d
1939 spec = (a0 >> 8) & 0xff;
1942 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1945 EventCB[ev][spec].status = EvStWAIT;
1951 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1954 void psxBios_OpenTh() { // 0e
1955 TCB *tcb = loadRam32ptr(A_TT_TCB);
1956 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
1959 for (th = 1; th < limit; th++)
1961 if (tcb[th].status != SWAP32(0x4000)) break;
1965 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1966 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1968 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1970 mips_return_c(0xffffffff, 20);
1973 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1975 tcb[th].status = SWAP32(0x4000);
1976 tcb[th].mode = SWAP32(0x1000);
1977 tcb[th].epc = SWAP32(a0);
1978 tcb[th].reg[30] = SWAP32(a1); // fp
1979 tcb[th].reg[29] = SWAP32(a1); // sp
1980 tcb[th].reg[28] = SWAP32(a2); // gp
1982 mips_return_c(0xff000000 + th, 34);
1986 * int CloseTh(long thread);
1989 void psxBios_CloseTh() { // 0f
1990 TCB *tcb = loadRam32ptr(A_TT_TCB);
1991 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
1995 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
1997 /* The return value is always 1 (even if the handle was already closed). */
1999 if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2000 tcb[th].status = SWAP32(0x1000);
2007 * int ChangeTh(long thread);
2010 void psxBios_ChangeTh() { // 10
2011 u32 tcbBase = loadRam32(A_TT_TCB);
2012 u32 th = a0 & 0xffff;
2015 // PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
2017 // without doing any argument checks, just issue a syscall
2018 // (like the real bios does)
2020 a1 = tcbBase + th * sizeof(TCB);
2025 void psxBios_InitPAD() { // 0x12
2027 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
2030 pad_buf1 = (char*)Ra0;
2032 pad_buf2 = (char*)Ra2;
2038 void psxBios_StartPAD() { // 13
2040 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2043 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
2044 psxRegs.CP0.n.SR |= 0x401;
2048 void psxBios_StopPAD() { // 14
2050 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2058 void psxBios_PAD_init() { // 15
2060 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2062 if (!(a0 == 0x20000000 || a0 == 0x20000001))
2068 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
2069 pad_buf = (int *)Ra1;
2071 psxRegs.CP0.n.SR |= 0x401;
2076 void psxBios_PAD_dr() { // 16
2078 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2084 static void psxBios_ReturnFromException() { // 17
2085 u32 tcbPtr = loadRam32(A_TT_PCB);
2086 const TCB *tcb = loadRam32ptr(tcbPtr);
2089 for (i = 1; i < 32; i++)
2090 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2091 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2092 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2093 psxRegs.CP0.n.SR = SWAP32(tcb->sr);
2095 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2096 pc0 = k0 = SWAP32(tcb->epc);
2098 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
2103 void psxBios_ResetEntryInt() { // 18
2104 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2106 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2107 mips_return_void_c(5);
2110 void psxBios_HookEntryInt() { // 19
2111 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2113 storeRam32(A_EEXIT_PTR, a0);
2114 mips_return_void_c(3);
2117 void psxBios_UnDeliverEvent() { // 0x20
2125 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2128 if (EventCB[ev][spec].status == EvStALREADY &&
2129 EventCB[ev][spec].mode == EvMdNOINTR)
2130 EventCB[ev][spec].status = EvStACTIVE;
2135 char ffile[64], *pfile;
2138 static void buopen(int mcd, char *ptr, char *cfg)
2141 char *mcd_data = ptr;
2143 strcpy(FDesc[1 + mcd].name, Ra0+5);
2144 FDesc[1 + mcd].offset = 0;
2145 FDesc[1 + mcd].mode = a1;
2147 for (i=1; i<16; i++) {
2148 const char *fptr = mcd_data + 128 * i;
2149 if ((*fptr & 0xF0) != 0x50) continue;
2150 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2151 FDesc[1 + mcd].mcfile = i;
2152 SysPrintf("open %s\n", fptr+0xa);
2156 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2157 for (i=1; i<16; i++) {
2158 int j, xor, nblk = a1 >> 16;
2160 char *fptr = mcd_data + 128 * i;
2162 if ((*fptr & 0xF0) != 0xa0) continue;
2164 FDesc[1 + mcd].mcfile = i;
2167 fptr[5] = 0x20 * nblk;
2170 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2171 pptr = fptr2 = fptr;
2172 for(j=2; j<=nblk; j++) {
2174 for(i++; i<16; i++) {
2177 memset(fptr2, 0, 128);
2178 fptr2[0] = j < nblk ? 0x52 : 0x53;
2181 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2186 /* shouldn't this return ENOSPC if i == 16? */
2188 pptr[8] = pptr[9] = 0xff;
2189 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2191 SysPrintf("openC %s %d\n", ptr, nblk);
2193 /* just go ahead and resave them all */
2194 SaveMcd(cfg, ptr, 128, 128 * 15);
2197 /* shouldn't this return ENOSPC if i == 16? */
2202 * int open(char *name , int mode);
2205 void psxBios_open() { // 0x32
2209 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2214 if (pa0 != INVALID_PTR) {
2215 if (!strncmp(pa0, "bu00", 4)) {
2216 buopen(1, Mcd1Data, Config.Mcd1);
2219 if (!strncmp(pa0, "bu10", 4)) {
2220 buopen(2, Mcd2Data, Config.Mcd2);
2228 * int lseek(int fd , int offset , int whence);
2231 void psxBios_lseek() { // 0x33
2233 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2238 FDesc[a0].offset = a1;
2240 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2241 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2245 FDesc[a0].offset+= a1;
2246 v0 = FDesc[a0].offset;
2255 * int read(int fd , void *buf , int nbytes);
2258 void psxBios_read() { // 0x34
2263 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2268 if (pa1 != INVALID_PTR) {
2270 case 2: buread(pa1, 1, a2); break;
2271 case 3: buread(pa1, 2, a2); break;
2279 * int write(int fd , void *buf , int nbytes);
2282 void psxBios_write() { // 0x35/0x03
2287 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2291 if (pa1 == INVALID_PTR) {
2296 if (a0 == 1) { // stdout
2301 SysPrintf("%c", *ptr++); a2--;
2307 case 2: buwrite(pa1, 1, a2); break;
2308 case 3: buwrite(pa1, 2, a2); break;
2314 static void psxBios_write_psxout() {
2315 if (a0 == 1) { // stdout
2316 const char *ptr = Ra1;
2319 if (ptr != INVALID_PTR)
2321 SysPrintf("%c", *ptr++);
2325 static void psxBios_putchar_psxout() { // 3d
2326 SysPrintf("%c", (char)a0);
2329 static void psxBios_puts_psxout() { // 3e/3f
2330 SysPrintf("%s", Ra0);
2334 * int close(int fd);
2337 void psxBios_close() { // 0x36
2339 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2346 void psxBios_putchar() { // 3d
2347 SysPrintf("%c", (char)a0);
2351 void psxBios_puts() { // 3e/3f
2352 SysPrintf("%s", Ra0);
2357 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2358 * We want to mimic the PSX's behaviour in this case for bufile. */
2359 static size_t strlen_internal(char* p)
2361 size_t size_of_array = 0;
2362 while (*p++) size_of_array++;
2363 return size_of_array;
2366 #define bufile(mcd) { \
2367 size_t size_of_name = strlen_internal(dir->name); \
2368 while (nfile < 16) { \
2371 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2373 if ((*ptr & 0xF0) != 0x50) continue; \
2374 /* Bug link files show up as free block. */ \
2375 if (!ptr[0xa]) continue; \
2377 if (pfile[0] == 0) { \
2378 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2379 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2380 } else for (i=0; i<20; i++) { \
2381 if (pfile[i] == ptr[i]) { \
2382 dir->name[i] = ptr[i]; continue; } \
2383 if (pfile[i] == '?') { \
2384 dir->name[i] = ptr[i]; continue; } \
2385 if (pfile[i] == '*') { \
2386 strcpy(dir->name+i, ptr+i); break; } \
2389 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2390 if (match == 0) { continue; } \
2398 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2401 void psxBios_firstfile() { // 42
2402 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2409 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2414 if (pa0 != INVALID_PTR) {
2418 if (!strncmp(pa0, "bu00", 4)) {
2419 // firstfile() calls _card_read() internally, so deliver it's event
2420 DeliverEvent(0x11, 0x2);
2422 } else if (!strncmp(pa0, "bu10", 4)) {
2423 // firstfile() calls _card_read() internally, so deliver it's event
2424 DeliverEvent(0x11, 0x2);
2433 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2436 void psxBios_nextfile() { // 43
2437 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2443 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2448 if (!strncmp(ffile, "bu00", 4)) {
2452 if (!strncmp(ffile, "bu10", 4)) {
2459 #define burename(mcd) { \
2460 for (i=1; i<16; i++) { \
2461 int namelen, j, xor = 0; \
2462 ptr = Mcd##mcd##Data + 128 * i; \
2463 if ((*ptr & 0xF0) != 0x50) continue; \
2464 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2465 namelen = strlen(Ra1+5); \
2466 memcpy(ptr+0xa, Ra1+5, namelen); \
2467 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2468 for (j=0; j<127; j++) xor^= ptr[j]; \
2470 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2477 * int rename(char *old, char *new);
2480 void psxBios_rename() { // 44
2487 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2492 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2493 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2497 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2506 #define budelete(mcd) { \
2507 for (i=1; i<16; i++) { \
2508 ptr = Mcd##mcd##Data + 128 * i; \
2509 if ((*ptr & 0xF0) != 0x50) continue; \
2510 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2511 *ptr = (*ptr & 0xf) | 0xA0; \
2512 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2513 SysPrintf("delete %s\n", ptr+0xa); \
2520 * int delete(char *name);
2523 void psxBios_delete() { // 45
2529 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2534 if (pa0 != INVALID_PTR) {
2535 if (!strncmp(pa0, "bu00", 4)) {
2539 if (!strncmp(pa0, "bu10", 4)) {
2547 void psxBios_InitCARD() { // 4a
2549 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2557 void psxBios_StartCARD() { // 4b
2559 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2562 if (CardState == 0) CardState = 1;
2567 void psxBios_StopCARD() { // 4c
2569 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2572 if (CardState == 1) CardState = 0;
2577 void psxBios__card_write() { // 0x4e
2582 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2585 Function also accepts sector 400h (a bug).
2586 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2590 /* Invalid sectors */
2594 card_active_chan = a0;
2597 if (pa2 != INVALID_PTR) {
2599 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2600 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2602 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2603 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2607 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2608 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2613 void psxBios__card_read() { // 0x4f
2618 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2621 Function also accepts sector 400h (a bug).
2622 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2626 /* Invalid sectors */
2630 card_active_chan = a0;
2633 if (pa2 != INVALID_PTR) {
2635 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2637 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2641 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2642 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2647 void psxBios__new_card() { // 0x50
2649 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2655 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2656 void psxBios__get_error(void) // 55
2658 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2663 void psxBios_Krom2RawAdd() { // 0x51
2666 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2667 const u32 table_8140[][2] = {
2668 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2669 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2670 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2671 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2672 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2673 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2674 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2675 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2676 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2680 const u32 table_889f[][2] = {
2681 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2682 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2683 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2684 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2685 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2686 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2687 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2688 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2692 if (a0 >= 0x8140 && a0 <= 0x84be) {
2693 while (table_8140[i][0] <= a0) i++;
2694 a0 -= table_8140[i - 1][0];
2695 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2696 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2697 while (table_889f[i][0] <= a0) i++;
2698 a0 -= table_889f[i - 1][0];
2699 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2707 void psxBios_GetC0Table() { // 56
2708 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2709 log_unhandled("GetC0Table @%08x\n", ra);
2711 mips_return_c(A_C0_TABLE, 3);
2714 void psxBios_GetB0Table() { // 57
2715 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2716 log_unhandled("GetB0Table @%08x\n", ra);
2718 mips_return_c(A_B0_TABLE, 3);
2721 void psxBios__card_chan() { // 0x58
2723 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2726 v0 = card_active_chan;
2730 void psxBios_ChangeClearPad() { // 5b
2732 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2738 void psxBios__card_status() { // 5c
2740 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2743 v0 = card_active_chan;
2747 void psxBios__card_wait() { // 5d
2749 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2756 /* System calls C0 */
2759 * int SysEnqIntRP(int index , long *queue);
2762 void psxBios_SysEnqIntRP() { // 02
2763 u32 old, base = loadRam32(A_TT_ExCB);
2764 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2766 old = loadRam32(base + (a0 << 3));
2767 storeRam32(base + (a0 << 3), a1);
2768 storeRam32(a1, old);
2769 mips_return_c(0, 9);
2773 * int SysDeqIntRP(int index , long *queue);
2776 static void psxBios_SysDeqIntRP_() { // 03
2777 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2778 u32 lim = 0, ret = 0;
2780 // as in original: no arg checks of any kind, bug if a1 == 0
2781 ptr = loadRam32(base + (a0 << 3));
2783 next = loadRam32(ptr);
2785 storeRam32(base + (a0 << 3), next);
2790 while (next && next != a1 && lim++ < 100) {
2792 next = loadRam32(ptr);
2796 next = loadRam32(next);
2797 storeRam32(ptr, next);
2804 PSXBIOS_LOG("bad chain %u %x\n", a0, base);
2806 mips_return_c(ret, 12);
2809 static void psxBios_SysDeqIntRP() { // 03
2810 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2811 psxBios_SysDeqIntRP_();
2814 void psxBios_ChangeClearRCnt() { // 0a
2817 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2819 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
2820 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
2821 mips_return_c(ret, 8);
2824 void psxBios_dummy() {
2825 u32 pc = (pc0 & 0x1fffff) - 4;
2826 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
2827 : pc == 0xc0 ? biosC0n : NULL;
2828 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
2829 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
2830 (void)pc; (void)ntab;
2831 mips_return_c(0, 100);
2834 void (*biosA0[256])();
2835 // C0 and B0 overlap (end of C0 is start of B0)
2836 void (*biosC0[256+128])();
2837 void (**biosB0)() = biosC0 + 128;
2839 #include "sjisfont.h"
2841 void setup_mips_code()
2844 ptr = (u32 *)&psxM[A_SYSCALL];
2845 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
2846 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
2847 ptr[0x08/4] = SWAPu32(0x00000000); // nop
2849 ptr = (u32 *)&psxM[A_EXCEPTION];
2850 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
2851 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
2852 ptr[0x14/4] = SWAPu32(0x00000000); // nop
2853 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
2854 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
2855 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
2856 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
2857 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
2858 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
2859 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
2861 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
2862 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
2863 ptr[0x68/4] = SWAPu32(0x24630004); // addiu $v1, $v1, 4
2864 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
2866 ptr[0xb0/4] = HLEOP(hleop_exception);
2869 static const struct {
2873 { 0xbfc050a4, hleop_exc0_0_1 },
2874 { 0xbfc04fbc, hleop_exc0_0_2 },
2875 { 0xbfc0506c, hleop_exc0_1_1 },
2876 { 0xbfc04dec, hleop_exc0_1_2 },
2877 { 0x1a00, hleop_exc0_2_2 },
2878 { 0x19c8, hleop_exc1_0_1 },
2879 { 0x18bc, hleop_exc1_0_2 },
2880 { 0x1990, hleop_exc1_1_1 },
2881 { 0x1858, hleop_exc1_1_2 },
2882 { 0x1958, hleop_exc1_2_1 },
2883 { 0x17f4, hleop_exc1_2_2 },
2884 { 0x1920, hleop_exc1_3_1 },
2885 { 0x1794, hleop_exc1_3_2 },
2886 { 0x2458, hleop_exc3_0_2 },
2889 static int chain_hle_op(u32 handler)
2893 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
2894 if (chainfns[i].addr == handler)
2895 return chainfns[i].op;
2899 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
2901 d[0] = SWAPu32(next);
2902 d[1] = SWAPu32(handler1);
2903 d[2] = SWAPu32(handler2);
2905 // install hle traps
2906 PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
2907 PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
2910 void psxBiosInit() {
2916 memset(psxM, 0, 0x10000);
2917 for(i = 0; i < 256; i++) {
2922 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
2923 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
2924 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
2925 biosA0[0x3f] = psxBios_printf_psxout;
2927 if (!Config.HLE) return;
2929 for(i = 0; i < 256; i++) {
2930 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2931 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2932 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2935 biosA0[0x00] = psxBios_open;
2936 biosA0[0x01] = psxBios_lseek;
2937 biosA0[0x02] = psxBios_read;
2938 biosA0[0x03] = psxBios_write;
2939 biosA0[0x04] = psxBios_close;
2940 //biosA0[0x05] = psxBios_ioctl;
2941 //biosA0[0x06] = psxBios_exit;
2942 //biosA0[0x07] = psxBios_sys_a0_07;
2943 biosA0[0x08] = psxBios_getc;
2944 biosA0[0x09] = psxBios_putc;
2945 biosA0[0x0a] = psxBios_todigit;
2946 //biosA0[0x0b] = psxBios_atof;
2947 //biosA0[0x0c] = psxBios_strtoul;
2948 //biosA0[0x0d] = psxBios_strtol;
2949 biosA0[0x0e] = psxBios_abs;
2950 biosA0[0x0f] = psxBios_labs;
2951 biosA0[0x10] = psxBios_atoi;
2952 biosA0[0x11] = psxBios_atol;
2953 //biosA0[0x12] = psxBios_atob;
2954 biosA0[0x13] = psxBios_setjmp;
2955 biosA0[0x14] = psxBios_longjmp;
2956 biosA0[0x15] = psxBios_strcat;
2957 biosA0[0x16] = psxBios_strncat;
2958 biosA0[0x17] = psxBios_strcmp;
2959 biosA0[0x18] = psxBios_strncmp;
2960 biosA0[0x19] = psxBios_strcpy;
2961 biosA0[0x1a] = psxBios_strncpy;
2962 biosA0[0x1b] = psxBios_strlen;
2963 biosA0[0x1c] = psxBios_index;
2964 biosA0[0x1d] = psxBios_rindex;
2965 biosA0[0x1e] = psxBios_strchr;
2966 biosA0[0x1f] = psxBios_strrchr;
2967 biosA0[0x20] = psxBios_strpbrk;
2968 biosA0[0x21] = psxBios_strspn;
2969 biosA0[0x22] = psxBios_strcspn;
2970 biosA0[0x23] = psxBios_strtok;
2971 biosA0[0x24] = psxBios_strstr;
2972 biosA0[0x25] = psxBios_toupper;
2973 biosA0[0x26] = psxBios_tolower;
2974 biosA0[0x27] = psxBios_bcopy;
2975 biosA0[0x28] = psxBios_bzero;
2976 biosA0[0x29] = psxBios_bcmp;
2977 biosA0[0x2a] = psxBios_memcpy;
2978 biosA0[0x2b] = psxBios_memset;
2979 biosA0[0x2c] = psxBios_memmove;
2980 biosA0[0x2d] = psxBios_memcmp;
2981 biosA0[0x2e] = psxBios_memchr;
2982 biosA0[0x2f] = psxBios_rand;
2983 biosA0[0x30] = psxBios_srand;
2984 biosA0[0x31] = psxBios_qsort;
2985 //biosA0[0x32] = psxBios_strtod;
2986 biosA0[0x33] = psxBios_malloc;
2987 biosA0[0x34] = psxBios_free;
2988 //biosA0[0x35] = psxBios_lsearch;
2989 //biosA0[0x36] = psxBios_bsearch;
2990 biosA0[0x37] = psxBios_calloc;
2991 biosA0[0x38] = psxBios_realloc;
2992 biosA0[0x39] = psxBios_InitHeap;
2993 //biosA0[0x3a] = psxBios__exit;
2994 biosA0[0x3b] = psxBios_getchar;
2995 biosA0[0x3c] = psxBios_putchar;
2996 //biosA0[0x3d] = psxBios_gets;
2997 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
2998 //biosA0[0x41] = psxBios_LoadTest;
2999 biosA0[0x42] = psxBios_Load;
3000 biosA0[0x43] = psxBios_Exec;
3001 biosA0[0x44] = psxBios_FlushCache;
3002 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3003 biosA0[0x46] = psxBios_GPU_dw;
3004 biosA0[0x47] = psxBios_mem2vram;
3005 biosA0[0x48] = psxBios_SendGPU;
3006 biosA0[0x49] = psxBios_GPU_cw;
3007 biosA0[0x4a] = psxBios_GPU_cwb;
3008 biosA0[0x4b] = psxBios_GPU_SendPackets;
3009 biosA0[0x4c] = psxBios_sys_a0_4c;
3010 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3011 //biosA0[0x4e] = psxBios_GPU_sync;
3012 //biosA0[0x4f] = psxBios_sys_a0_4f;
3013 //biosA0[0x50] = psxBios_sys_a0_50;
3014 biosA0[0x51] = psxBios_LoadExec;
3015 //biosA0[0x52] = psxBios_GetSysSp;
3016 //biosA0[0x53] = psxBios_sys_a0_53;
3017 //biosA0[0x54] = psxBios__96_init_a54;
3018 //biosA0[0x55] = psxBios__bu_init_a55;
3019 biosA0[0x56] = psxBios_CdRemove;
3020 //biosA0[0x57] = psxBios_sys_a0_57;
3021 //biosA0[0x58] = psxBios_sys_a0_58;
3022 //biosA0[0x59] = psxBios_sys_a0_59;
3023 //biosA0[0x5a] = psxBios_sys_a0_5a;
3024 //biosA0[0x5b] = psxBios_dev_tty_init;
3025 //biosA0[0x5c] = psxBios_dev_tty_open;
3026 //biosA0[0x5d] = psxBios_sys_a0_5d;
3027 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3028 //biosA0[0x5f] = psxBios_dev_cd_open;
3029 //biosA0[0x60] = psxBios_dev_cd_read;
3030 //biosA0[0x61] = psxBios_dev_cd_close;
3031 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3032 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3033 //biosA0[0x64] = psxBios_dev_cd_chdir;
3034 //biosA0[0x65] = psxBios_dev_card_open;
3035 //biosA0[0x66] = psxBios_dev_card_read;
3036 //biosA0[0x67] = psxBios_dev_card_write;
3037 //biosA0[0x68] = psxBios_dev_card_close;
3038 //biosA0[0x69] = psxBios_dev_card_firstfile;
3039 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3040 //biosA0[0x6b] = psxBios_dev_card_erase;
3041 //biosA0[0x6c] = psxBios_dev_card_undelete;
3042 //biosA0[0x6d] = psxBios_dev_card_format;
3043 //biosA0[0x6e] = psxBios_dev_card_rename;
3044 //biosA0[0x6f] = psxBios_dev_card_6f;
3045 biosA0[0x70] = psxBios__bu_init;
3046 biosA0[0x71] = psxBios__96_init;
3047 biosA0[0x72] = psxBios_CdRemove;
3048 //biosA0[0x73] = psxBios_sys_a0_73;
3049 //biosA0[0x74] = psxBios_sys_a0_74;
3050 //biosA0[0x75] = psxBios_sys_a0_75;
3051 //biosA0[0x76] = psxBios_sys_a0_76;
3052 //biosA0[0x77] = psxBios_sys_a0_77;
3053 //biosA0[0x78] = psxBios__96_CdSeekL;
3054 //biosA0[0x79] = psxBios_sys_a0_79;
3055 //biosA0[0x7a] = psxBios_sys_a0_7a;
3056 //biosA0[0x7b] = psxBios_sys_a0_7b;
3057 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3058 //biosA0[0x7d] = psxBios_sys_a0_7d;
3059 //biosA0[0x7e] = psxBios__96_CdRead;
3060 //biosA0[0x7f] = psxBios_sys_a0_7f;
3061 //biosA0[0x80] = psxBios_sys_a0_80;
3062 //biosA0[0x81] = psxBios_sys_a0_81;
3063 //biosA0[0x82] = psxBios_sys_a0_82;
3064 //biosA0[0x83] = psxBios_sys_a0_83;
3065 //biosA0[0x84] = psxBios_sys_a0_84;
3066 //biosA0[0x85] = psxBios__96_CdStop;
3067 //biosA0[0x86] = psxBios_sys_a0_86;
3068 //biosA0[0x87] = psxBios_sys_a0_87;
3069 //biosA0[0x88] = psxBios_sys_a0_88;
3070 //biosA0[0x89] = psxBios_sys_a0_89;
3071 //biosA0[0x8a] = psxBios_sys_a0_8a;
3072 //biosA0[0x8b] = psxBios_sys_a0_8b;
3073 //biosA0[0x8c] = psxBios_sys_a0_8c;
3074 //biosA0[0x8d] = psxBios_sys_a0_8d;
3075 //biosA0[0x8e] = psxBios_sys_a0_8e;
3076 //biosA0[0x8f] = psxBios_sys_a0_8f;
3077 biosA0[0x90] = hleExc0_1_2;
3078 biosA0[0x91] = hleExc0_0_2;
3079 biosA0[0x92] = hleExc0_1_1;
3080 biosA0[0x93] = hleExc0_0_1;
3081 //biosA0[0x94] = psxBios_sys_a0_94;
3082 //biosA0[0x95] = psxBios_sys_a0_95;
3083 //biosA0[0x96] = psxBios_AddCDROMDevice;
3084 //biosA0[0x97] = psxBios_AddMemCardDevide;
3085 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3086 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3087 //biosA0[0x9a] = psxBios_sys_a0_9a;
3088 //biosA0[0x9b] = psxBios_sys_a0_9b;
3089 //biosA0[0x9c] = psxBios_SetConf;
3090 //biosA0[0x9d] = psxBios_GetConf;
3091 //biosA0[0x9e] = psxBios_sys_a0_9e;
3092 biosA0[0x9f] = psxBios_SetMem;
3093 //biosA0[0xa0] = psxBios__boot;
3094 //biosA0[0xa1] = psxBios_SystemError;
3095 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3096 biosA0[0xa3] = psxBios_DequeueCdIntr;
3097 //biosA0[0xa4] = psxBios_sys_a0_a4;
3098 //biosA0[0xa5] = psxBios_ReadSector;
3099 biosA0[0xa6] = psxBios_get_cd_status;
3100 //biosA0[0xa7] = psxBios_bufs_cb_0;
3101 //biosA0[0xa8] = psxBios_bufs_cb_1;
3102 //biosA0[0xa9] = psxBios_bufs_cb_2;
3103 //biosA0[0xaa] = psxBios_bufs_cb_3;
3104 biosA0[0xab] = psxBios__card_info;
3105 biosA0[0xac] = psxBios__card_load;
3106 //biosA0[0axd] = psxBios__card_auto;
3107 //biosA0[0xae] = psxBios_bufs_cd_4;
3108 //biosA0[0xaf] = psxBios_sys_a0_af;
3109 //biosA0[0xb0] = psxBios_sys_a0_b0;
3110 //biosA0[0xb1] = psxBios_sys_a0_b1;
3111 //biosA0[0xb2] = psxBios_do_a_long_jmp
3112 //biosA0[0xb3] = psxBios_sys_a0_b3;
3113 //biosA0[0xb4] = psxBios_sub_function;
3114 //*******************B0 CALLS****************************
3115 //biosB0[0x00] = psxBios_SysMalloc;
3116 //biosB0[0x01] = psxBios_sys_b0_01;
3117 biosB0[0x02] = psxBios_SetRCnt;
3118 biosB0[0x03] = psxBios_GetRCnt;
3119 biosB0[0x04] = psxBios_StartRCnt;
3120 biosB0[0x05] = psxBios_StopRCnt;
3121 biosB0[0x06] = psxBios_ResetRCnt;
3122 biosB0[0x07] = psxBios_DeliverEvent;
3123 biosB0[0x08] = psxBios_OpenEvent;
3124 biosB0[0x09] = psxBios_CloseEvent;
3125 biosB0[0x0a] = psxBios_WaitEvent;
3126 biosB0[0x0b] = psxBios_TestEvent;
3127 biosB0[0x0c] = psxBios_EnableEvent;
3128 biosB0[0x0d] = psxBios_DisableEvent;
3129 biosB0[0x0e] = psxBios_OpenTh;
3130 biosB0[0x0f] = psxBios_CloseTh;
3131 biosB0[0x10] = psxBios_ChangeTh;
3132 //biosB0[0x11] = psxBios_psxBios_b0_11;
3133 biosB0[0x12] = psxBios_InitPAD;
3134 biosB0[0x13] = psxBios_StartPAD;
3135 biosB0[0x14] = psxBios_StopPAD;
3136 biosB0[0x15] = psxBios_PAD_init;
3137 biosB0[0x16] = psxBios_PAD_dr;
3138 biosB0[0x17] = psxBios_ReturnFromException;
3139 biosB0[0x18] = psxBios_ResetEntryInt;
3140 biosB0[0x19] = psxBios_HookEntryInt;
3141 //biosB0[0x1a] = psxBios_sys_b0_1a;
3142 //biosB0[0x1b] = psxBios_sys_b0_1b;
3143 //biosB0[0x1c] = psxBios_sys_b0_1c;
3144 //biosB0[0x1d] = psxBios_sys_b0_1d;
3145 //biosB0[0x1e] = psxBios_sys_b0_1e;
3146 //biosB0[0x1f] = psxBios_sys_b0_1f;
3147 biosB0[0x20] = psxBios_UnDeliverEvent;
3148 //biosB0[0x21] = psxBios_sys_b0_21;
3149 //biosB0[0x22] = psxBios_sys_b0_22;
3150 //biosB0[0x23] = psxBios_sys_b0_23;
3151 //biosB0[0x24] = psxBios_sys_b0_24;
3152 //biosB0[0x25] = psxBios_sys_b0_25;
3153 //biosB0[0x26] = psxBios_sys_b0_26;
3154 //biosB0[0x27] = psxBios_sys_b0_27;
3155 //biosB0[0x28] = psxBios_sys_b0_28;
3156 //biosB0[0x29] = psxBios_sys_b0_29;
3157 //biosB0[0x2a] = psxBios_sys_b0_2a;
3158 //biosB0[0x2b] = psxBios_sys_b0_2b;
3159 //biosB0[0x2c] = psxBios_sys_b0_2c;
3160 //biosB0[0x2d] = psxBios_sys_b0_2d;
3161 //biosB0[0x2e] = psxBios_sys_b0_2e;
3162 //biosB0[0x2f] = psxBios_sys_b0_2f;
3163 //biosB0[0x30] = psxBios_sys_b0_30;
3164 //biosB0[0x31] = psxBios_sys_b0_31;
3165 biosB0[0x32] = psxBios_open;
3166 biosB0[0x33] = psxBios_lseek;
3167 biosB0[0x34] = psxBios_read;
3168 biosB0[0x35] = psxBios_write;
3169 biosB0[0x36] = psxBios_close;
3170 //biosB0[0x37] = psxBios_ioctl;
3171 //biosB0[0x38] = psxBios_exit;
3172 //biosB0[0x39] = psxBios_sys_b0_39;
3173 //biosB0[0x3a] = psxBios_getc;
3174 //biosB0[0x3b] = psxBios_putc;
3175 biosB0[0x3c] = psxBios_getchar;
3176 //biosB0[0x3e] = psxBios_gets;
3177 //biosB0[0x40] = psxBios_cd;
3178 biosB0[0x41] = psxBios_format;
3179 biosB0[0x42] = psxBios_firstfile;
3180 biosB0[0x43] = psxBios_nextfile;
3181 biosB0[0x44] = psxBios_rename;
3182 biosB0[0x45] = psxBios_delete;
3183 //biosB0[0x46] = psxBios_undelete;
3184 //biosB0[0x47] = psxBios_AddDevice;
3185 //biosB0[0x48] = psxBios_RemoteDevice;
3186 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3187 biosB0[0x4a] = psxBios_InitCARD;
3188 biosB0[0x4b] = psxBios_StartCARD;
3189 biosB0[0x4c] = psxBios_StopCARD;
3190 //biosB0[0x4d] = psxBios_sys_b0_4d;
3191 biosB0[0x4e] = psxBios__card_write;
3192 biosB0[0x4f] = psxBios__card_read;
3193 biosB0[0x50] = psxBios__new_card;
3194 biosB0[0x51] = psxBios_Krom2RawAdd;
3195 //biosB0[0x52] = psxBios_sys_b0_52;
3196 //biosB0[0x53] = psxBios_sys_b0_53;
3197 //biosB0[0x54] = psxBios__get_errno;
3198 biosB0[0x55] = psxBios__get_error;
3199 biosB0[0x56] = psxBios_GetC0Table;
3200 biosB0[0x57] = psxBios_GetB0Table;
3201 biosB0[0x58] = psxBios__card_chan;
3202 //biosB0[0x59] = psxBios_sys_b0_59;
3203 //biosB0[0x5a] = psxBios_sys_b0_5a;
3204 biosB0[0x5b] = psxBios_ChangeClearPad;
3205 biosB0[0x5c] = psxBios__card_status;
3206 biosB0[0x5d] = psxBios__card_wait;
3207 //*******************C0 CALLS****************************
3208 //biosC0[0x00] = psxBios_InitRCnt;
3209 //biosC0[0x01] = psxBios_InitException;
3210 biosC0[0x02] = psxBios_SysEnqIntRP;
3211 biosC0[0x03] = psxBios_SysDeqIntRP;
3212 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
3213 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3214 //biosC0[0x06] = psxBios_ExceptionHandler;
3215 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3216 //biosC0[0x08] = psxBios_SysInitMemory;
3217 //biosC0[0x09] = psxBios_SysInitKMem;
3218 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3219 //biosC0[0x0b] = psxBios_SystemError;
3220 //biosC0[0x0c] = psxBios_InitDefInt;
3221 //biosC0[0x0d] = psxBios_sys_c0_0d;
3222 //biosC0[0x0e] = psxBios_sys_c0_0e;
3223 //biosC0[0x0f] = psxBios_sys_c0_0f;
3224 //biosC0[0x10] = psxBios_sys_c0_10;
3225 //biosC0[0x11] = psxBios_sys_c0_11;
3226 //biosC0[0x12] = psxBios_InstallDevices;
3227 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3228 //biosC0[0x14] = psxBios_sys_c0_14;
3229 //biosC0[0x15] = psxBios__cdevinput;
3230 //biosC0[0x16] = psxBios__cdevscan;
3231 //biosC0[0x17] = psxBios__circgetc;
3232 //biosC0[0x18] = psxBios__circputc;
3233 //biosC0[0x19] = psxBios_ioabort;
3234 //biosC0[0x1a] = psxBios_sys_c0_1a
3235 //biosC0[0x1b] = psxBios_KernelRedirect;
3236 //biosC0[0x1c] = psxBios_PatchAOTable;
3237 //************** THE END ***************************************
3240 size = sizeof(EvCB) * 32;
3241 EventCB = (void *)&psxR[base]; base += size * 6;
3242 memset(EventCB, 0, size * 6);
3244 EvEV = EventCB + 32;
3245 RcEV = EventCB + 32 * 2;
3246 UeEV = EventCB + 32 * 3;
3247 SwEV = EventCB + 32 * 4;
3248 ThEV = EventCB + 32 * 5;
3254 pad_buf1len = pad_buf2len = 0;
3260 memset(FDesc, 0, sizeof(FDesc));
3261 card_active_chan = 0;
3264 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3267 len = 0x80000 - 0x66000;
3268 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3269 len = 0x80000 - 0x69d68;
3270 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3273 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3275 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3276 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3277 Here are some examples of games not working with this fix in place :
3278 R-type won't get past the Irem logo if not implemented.
3279 Crash Team Racing will softlock after the Sony logo.
3282 ram32 = (u32 *)psxM;
3283 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3284 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3285 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3286 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3288 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3289 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3291 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3292 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3293 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3294 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3296 ram32[0x00a0/4] = HLEOP(hleop_a0);
3297 ram32[0x00b0/4] = HLEOP(hleop_b0);
3298 ram32[0x00c0/4] = HLEOP(hleop_c0);
3300 // "table of tables". Some games modify it
3301 assert(A_TT_ExCB == 0x0100);
3302 ram32[0x0100/4] = SWAPu32(0x0000e004); // ExCB - exception chains
3303 ram32[0x0104/4] = SWAPu32(0x00000020); // ExCB size
3304 ram32[0x0108/4] = SWAPu32(0x0000e1ec); // PCB - process control
3305 ram32[0x010c/4] = SWAPu32(0x00000004); // PCB size
3306 ram32[0x0110/4] = SWAPu32(0x0000e1f4); // TCB - thread control
3307 ram32[0x0114/4] = SWAPu32(0x00000300); // TCB size
3308 ram32[0x0120/4] = SWAPu32(0x0000e028); // EvCB - event control
3309 ram32[0x0124/4] = SWAPu32(0x000001c0); // EvCB size
3310 ram32[0x0140/4] = SWAPu32(0x00008648); // FCB - file control
3311 ram32[0x0144/4] = SWAPu32(0x000002c0); // FCB size
3312 ram32[0x0150/4] = SWAPu32(0x00006ee0); // DCB - device control
3313 ram32[0x0154/4] = SWAPu32(0x00000320); // DCB size
3315 ram32[0xe000/4] = SWAPu32(0x00000020); // SysMalloc block size
3316 ram32[0xe004/4] = SWAPu32(0x000091e0); // chain0
3317 ram32[0xe00c/4] = SWAPu32(0x00006d88); // chain1
3318 ram32[0xe014/4] = SWAPu32(0x00000000); // chain2
3319 ram32[0xe01c/4] = SWAPu32(0x00006d98); // chain3
3321 ram32[0xe1ec/4] = SWAPu32(0x0000e1f4); // TCB
3322 ram32[0xe1f0/4] = SWAPu32(0x00000300); // SysMalloc block size
3323 ram32[0xe1f4/4] = SWAPu32(0x00004000); // first TCB
3325 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3326 strcpy((char *)&ram32[0xeff0/4], "bu");
3328 // default exception handler chains
3329 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3330 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3331 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3332 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3333 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3334 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3335 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3336 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3340 // fill the api jumptables with fake entries as some games patch them
3341 // (or rather the funcs listed there)
3342 ptr = (u32 *)&psxM[A_A0_TABLE];
3343 for (i = 0; i < 256; i++)
3344 ptr[i] = SWAP32(0x1000);
3346 ptr = (u32 *)&psxM[A_B0_TABLE];
3347 for (i = 0; i < 256; i++)
3348 ptr[i] = SWAP32(0x2000);
3349 // B(5b) is special because games patch (sometimes even jump to)
3350 // code at fixed offsets from it, nocash lists offsets:
3351 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3352 // call: +7a0=4b70, +884=4c54, +894=4c64
3353 ptr[0x5b] = SWAP32(0x43d0);
3354 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra
3355 ram32[0x4c54/4] = SWAP32(0x03e00008); // jr $ra
3356 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3358 ptr = (u32 *)&psxM[A_C0_TABLE];
3359 for (i = 0; i < 256/2; i++)
3360 ptr[i] = SWAP32(0x3000);
3361 ptr[6] = SWAP32(A_EXCEPTION);
3364 ram32[0x1000/4] = HLEOP(hleop_dummy);
3365 ram32[0x2000/4] = HLEOP(hleop_dummy);
3366 ram32[0x3000/4] = HLEOP(hleop_dummy);
3367 ram32[0x4c54/4] = HLEOP(hleop_dummy); // for B12_InitPad?
3368 ram32[0x8000/4] = HLEOP(hleop_execret);
3370 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3371 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3372 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3373 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3374 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3375 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3377 psxRegs.CP0.n.SR &= ~0x400000; // use ram vector
3380 void psxBiosShutdown() {
3383 void psxBiosCnfLoaded(u32 tcbs, u32 events) {
3385 log_unhandled("FIXME: TCB = %x\n", tcbs);
3387 log_unhandled("FIXME: EVENT = %x\n", tcbs);
3390 #define psxBios_PADpoll(pad) { \
3391 PAD##pad##_startPoll(pad); \
3392 pad_buf##pad[0] = 0; \
3393 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3394 if (!(pad_buf##pad[1] & 0x0f)) { \
3397 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3399 PAD##pad##_poll(0); \
3401 while (bufcount--) { \
3402 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3406 static void biosPadHLE() {
3409 if (pad_buf != NULL) {
3410 u32 *buf = (u32*)pad_buf;
3413 if (PAD1_poll(0x42) == 0x23) {
3415 *buf = PAD1_poll(0) << 8;
3416 *buf |= PAD1_poll(0);
3418 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3419 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3422 *buf = PAD1_poll(0) << 8;
3423 *buf|= PAD1_poll(0);
3427 if (PAD2_poll(0x42) == 0x23) {
3429 *buf |= PAD2_poll(0) << 24;
3430 *buf |= PAD2_poll(0) << 16;
3432 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3433 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3436 *buf |= PAD2_poll(0) << 24;
3437 *buf |= PAD2_poll(0) << 16;
3451 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3455 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3456 psxBios_ReturnFromException();
3462 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3463 // so this is only partially implemented
3464 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3466 u32 cdrom_dma_ack_enable = 1; // a000b93c
3467 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3470 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3473 //PSXBIOS_LOG("%s\n", __func__);
3475 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3476 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3477 //if (--cdrom_irq_counter == 0) // 0xa0009180
3478 // DeliverEvent(); // 0xf0000003, 0x10
3482 mips_return_c(ret, 20);
3485 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3487 u32 cdrom_irq_ack_enable = 1; // a000b938
3488 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3491 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3494 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3495 PSXBIOS_LOG("%s TODO\n", __func__);
3498 mips_return_c(ret, 20);
3501 void hleExc0_2_2_syscall() // not in any A/B/C table
3503 u32 code = (psxRegs.CP0.n.Cause & 0x3c) >> 2;
3504 u32 tcbPtr = loadRam32(A_TT_PCB);
3505 TCB *tcb = loadRam32ptr(tcbPtr);
3507 if (code != R3000E_Syscall) {
3509 // DeliverEvent(); // 0xf0000010, 0x1000
3510 psxBios_SystemErrorUnresolvedException();
3512 mips_return_c(0, 17);
3516 //printf("%s c=%d a0=%d\n", __func__, code, a0);
3517 tcb->epc += SWAP32(4);
3522 case 1: { // EnterCritical - disable irqs
3523 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3524 tcb->reg[2] = SWAP32(was_enabled);
3525 tcb->sr &= SWAP32(~0x404);
3528 case 2: // ExitCritical - enable irqs
3529 tcb->sr |= SWAP32(0x404);
3532 case 3: { // ChangeThreadSubFunction
3533 u32 tcbPtr = loadRam32(A_TT_PCB);
3534 storeRam32(tcbPtr, a1);
3538 // DeliverEvent(); // 0xf0000010, 0x4000
3542 psxBios_ReturnFromException();
3545 void hleExc1_0_1(void)
3547 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3548 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3551 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3554 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3555 // DeliverEvent 0xf2000000 + ev_index, 2
3556 if (RcEV[ev_index][1].status == EvStACTIVE) {
3557 softCall(RcEV[ev_index][1].fhandler);
3561 mips_return_c(ret, 22);
3564 void hleExc1_0_2(void)
3566 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3569 void hleExc1_1_1(void)
3571 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3572 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3575 void hleExc1_1_2(void)
3577 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3580 void hleExc1_2_1(void)
3582 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3583 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3586 void hleExc1_2_2(void)
3588 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3591 void hleExc1_3_1(void)
3593 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3594 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3597 void hleExc1_3_2(void)
3599 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3602 void hleExc3_0_2_defint(void)
3604 static const struct {
3615 { 6, 6 }, // rcnt2 (bug)
3620 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3621 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3622 // DeliverEvent 0xf0000000 + ev, 0x1000
3627 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3630 void psxBiosException() {
3631 u32 tcbPtr = loadRam32(A_TT_PCB);
3632 u32 *chains = loadRam32ptr(A_TT_ExCB);
3633 TCB *tcb = loadRam32ptr(tcbPtr);
3639 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3640 for (i = 4; i < 32; i++) {
3643 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3645 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3646 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3647 tcb->epc = SWAP32(psxRegs.CP0.n.EPC);
3648 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3649 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3650 sp = fp = loadRam32(A_EXC_SP);
3654 // do the chains (always 4)
3655 for (c = lim = 0; c < 4; c++) {
3656 if (chains[c * 2] == 0)
3658 ptr = SWAP32(chains[c * 2]);
3659 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3660 chain = castRam32ptr(ptr);
3665 softCallInException(SWAP32(chain[2]));
3666 if (returned_from_exception())
3669 if (v0 == 0 || chain[1] == 0)
3671 softCallInException(SWAP32(chain[1]));
3672 if (returned_from_exception())
3678 // TODO make this a chain entry
3679 if (psxHu32(0x1070) & 1)
3682 // return from exception (custom or default)
3684 ptr = loadRam32(A_EEXIT_PTR);
3685 if (ptr != A_EEXIT_DEF) {
3686 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3687 longjmp_load(jmp_buf);
3692 psxBios_ReturnFromException();
3695 #define bfreeze(ptr, size) { \
3696 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3697 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3701 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3702 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3704 #define bfreezepsxMptr(ptr, type) { \
3706 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3707 else psxRu32ref(base) = 0; \
3709 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3710 else (ptr) = NULL; \
3712 base += sizeof(u32); \
3715 void psxBiosFreeze(int Mode) {
3718 bfreezepsxMptr(pad_buf, int);
3719 bfreezepsxMptr(pad_buf1, char);
3720 bfreezepsxMptr(pad_buf2, char);
3721 bfreezepsxMptr(heap_addr, u32);
3722 bfreezel(&pad_buf1len);
3723 bfreezel(&pad_buf2len);
3725 bfreezel(&CardState);
3726 bfreezel(&CurThread);
3728 bfreezel(&card_active_chan);
3729 bfreezel(&pad_stopped);
3730 bfreezel(&heap_size);