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_KMALLOC_PTR 0x7460
293 #define A_KMALLOC_SIZE 0x7464
294 #define A_KMALLOC_END 0x7468
295 #define A_EEXIT_PTR 0x75d0
296 #define A_EXC_STACK 0x85d8 // exception stack top
297 #define A_RCNT_VBL_ACK 0x8600
298 #define A_EXC_GP 0xf450
300 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
302 static u32 loadRam32(u32 addr)
304 assert(!(addr & 0x5f800000));
305 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
308 static void *castRam32ptr(u32 addr)
310 assert(!(addr & 0x5f800003));
311 return psxM + (addr & 0x1ffffc);
314 static void *loadRam32ptr(u32 addr)
316 return castRam32ptr(loadRam32(addr));
319 static void storeRam32(u32 addr, u32 d)
321 assert(!(addr & 0x5f800000));
322 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
325 static void mips_return(u32 val)
331 static void use_cycles(u32 cycle)
333 psxRegs.cycle += cycle * 2;
336 static void mips_return_c(u32 val, u32 cycle)
342 static void mips_return_void_c(u32 cycle)
348 static int returned_from_exception(void)
350 // 0x80000080 means it took another exception just after return
351 return pc0 == k0 || pc0 == 0x80000080;
354 static inline void softCall(u32 pc) {
356 u32 ssr = psxRegs.CP0.n.SR;
359 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
361 while (pc0 != 0x80001000)
362 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
365 psxRegs.CP0.n.SR = ssr;
368 static inline void softCallInException(u32 pc) {
373 while (!returned_from_exception() && pc0 != 0x80001000)
374 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
376 if (pc0 == 0x80001000)
380 static inline void DeliverEvent(u32 ev, u32 spec) {
381 if (EventCB[ev][spec].status != EvStACTIVE) return;
383 // EventCB[ev][spec].status = EvStALREADY;
384 if (EventCB[ev][spec].mode == EvMdINTR) {
385 softCall(EventCB[ev][spec].fhandler);
386 } else EventCB[ev][spec].status = EvStALREADY;
392 // System calls A0 */
395 #define buread(Ra1, mcd, length) { \
396 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); \
397 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
398 memcpy(Ra1, ptr, length); \
399 if (FDesc[1 + mcd].mode & 0x8000) { \
400 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
401 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
404 FDesc[1 + mcd].offset += v0; \
407 #define buwrite(Ra1, mcd, length) { \
408 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
409 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
410 ptr = Mcd##mcd##Data + offset; \
411 memcpy(ptr, Ra1, length); \
412 FDesc[1 + mcd].offset += length; \
413 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
414 if (FDesc[1 + mcd].mode & 0x8000) { \
415 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
416 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
422 //#define PSXBIOS_LOG printf
423 #define PSXBIOS_LOG(...)
426 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
427 /* For some strange reason, the returned character is sign-expanded; */
428 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
429 /* TODO FIX ME : Properly implement this behaviour */
430 void psxBios_getc(void) // 0x03, 0x35
435 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
439 if (pa1 != INVALID_PTR) {
441 case 2: buread(pa1, 1, 1); break;
442 case 3: buread(pa1, 2, 1); break;
449 /* Copy of psxBios_write, except size is 1. */
450 void psxBios_putc(void) // 0x09, 0x3B
455 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
458 if (pa1 == INVALID_PTR) {
463 if (a0 == 1) { // stdout
464 char *ptr = (char *)pa1;
468 printf("%c", *ptr++); a2--;
474 case 2: buwrite(pa1, 1, 1); break;
475 case 3: buwrite(pa1, 2, 1); break;
481 void psxBios_todigit(void) // 0x0a
485 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
488 if (c >= 0x30 && c < 0x3A) {
491 else if (c > 0x60 && c < 0x7B) {
494 else if (c > 0x40 && c < 0x5B) {
497 else if (c >= 0x80) {
508 void psxBios_abs() { // 0x0e
509 if ((s32)a0 < 0) v0 = -(s32)a0;
514 void psxBios_labs() { // 0x0f
518 void psxBios_atoi() { // 0x10
520 char *p = (char *)Ra0;
524 case ' ': case '\t': continue;
531 while (*p >= '0' && *p <= '9') {
532 n = n * 10 + *p++ - '0';
539 void psxBios_atol() { // 0x11
549 static void psxBios_setjmp() { // 0x13
550 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
553 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
555 jmp_buf->ra_ = SWAP32(ra);
556 jmp_buf->sp_ = SWAP32(sp);
557 jmp_buf->fp_ = SWAP32(fp);
558 for (i = 0; i < 8; i++) // s0-s7
559 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
560 jmp_buf->gp_ = SWAP32(gp);
562 mips_return_c(0, 15);
565 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
569 ra = SWAP32(jmp_buf->ra_);
570 sp = SWAP32(jmp_buf->sp_);
571 fp = SWAP32(jmp_buf->fp_);
572 for (i = 0; i < 8; i++) // s0-s7
573 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
574 gp = SWAP32(jmp_buf->gp_);;
577 void psxBios_longjmp() { // 0x14
578 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
580 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
581 longjmp_load(jmp_buf);
582 mips_return_c(a1, 15);
585 void psxBios_strcat() { // 0x15
586 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
589 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
591 if (a0 == 0 || a1 == 0)
599 while ((*p1++ = *p2++) != '\0');
604 void psxBios_strncat() { // 0x16
605 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
609 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
611 if (a0 == 0 || a1 == 0)
619 while ((*p1++ = *p2++) != '\0') {
629 void psxBios_strcmp() { // 0x17
630 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
632 if (a0 == 0 && a1 == 0)
638 else if (a0 == 0 && a1 != 0)
644 else if (a0 != 0 && a1 == 0)
651 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
654 while (*p1 == *p2++) {
673 void psxBios_strncmp() { // 0x18
674 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
676 if (a0 == 0 && a1 == 0)
682 else if (a0 == 0 && a1 != 0)
688 else if (a0 != 0 && a1 == 0)
695 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
698 while (--n >= 0 && *p1 == *p2++) {
702 v1 = a2 - ((a2-n) - 1);
710 v0 = (n < 0 ? 0 : *p1 - *--p2);
712 v1 = a2 - ((a2-n) - 1);
718 void psxBios_strcpy() { // 0x19
719 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
720 if (a0 == 0 || a1 == 0)
726 while ((*p1++ = *p2++) != '\0');
731 void psxBios_strncpy() { // 0x1a
732 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
734 if (a0 == 0 || a1 == 0)
740 for (i = 0; i < n; i++) {
741 if ((*p1++ = *p2++) == '\0') {
753 void psxBios_strlen() { // 0x1b
754 char *p = (char *)Ra0;
765 void psxBios_index() { // 0x1c
766 char *p = (char *)Ra0;
776 v0 = a0 + (p - (char *)Ra0);
780 } while (*p++ != '\0');
785 void psxBios_rindex() { // 0x1d
786 char *p = (char *)Ra0;
796 v0 = a0 + (p - (char *)Ra0);
797 } while (*p++ != '\0');
802 void psxBios_strchr() { // 0x1e
806 void psxBios_strrchr() { // 0x1f
810 void psxBios_strpbrk() { // 0x20
811 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
813 while ((c = *p1++) != '\0') {
814 for (scanp = p2; (sc = *scanp++) != '\0';) {
816 v0 = a0 + (p1 - 1 - (char *)Ra0);
823 // BUG: return a0 instead of NULL if not found
827 void psxBios_strspn() { // 0x21
830 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
831 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
832 if (*p2 == '\0') break;
835 v0 = p1 - (char *)Ra0; pc0 = ra;
838 void psxBios_strcspn() { // 0x22
841 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
842 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
843 if (*p2 != '\0') break;
846 v0 = p1 - (char *)Ra0; pc0 = ra;
849 void psxBios_strtok() { // 0x23
850 char *pcA0 = (char *)Ra0;
851 char *pcRet = strtok(pcA0, (char *)Ra1);
853 v0 = a0 + pcRet - pcA0;
859 void psxBios_strstr() { // 0x24
860 char *p = (char *)Ra0, *p1, *p2;
866 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
871 v0 = a0 + (p - (char *)Ra0);
882 void psxBios_toupper() { // 0x25
883 v0 = (s8)(a0 & 0xff);
884 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
888 void psxBios_tolower() { // 0x26
889 v0 = (s8)(a0 & 0xff);
890 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
894 void psxBios_bcopy() { // 0x27
895 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
897 if (a0 == 0 || a2 > 0x7FFFFFFF)
902 while ((s32)a2-- > 0) *p1++ = *p2++;
907 void psxBios_bzero() { // 0x28
908 char *p = (char *)Ra0;
910 /* Same as memset here (See memset below) */
911 if (a1 > 0x7FFFFFFF || a1 == 0)
922 while ((s32)a1-- > 0) *p++ = '\0';
927 void psxBios_bcmp() { // 0x29
928 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
930 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
932 while ((s32)a2-- > 0) {
933 if (*p1++ != *p2++) {
934 v0 = *p1 - *p2; // BUG: compare the NEXT byte
943 void psxBios_memcpy() { // 0x2a
944 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
946 if (a0 == 0 || a2 > 0x7FFFFFFF)
951 while ((s32)a2-- > 0) {
958 void psxBios_memset() { // 0x2b
959 char *p = (char *)Ra0;
961 if (a2 > 0x7FFFFFFF || a2 == 0)
972 while ((s32)a2-- > 0) *p++ = (char)a1;
977 void psxBios_memmove() { // 0x2c
978 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
980 if (a0 == 0 || a2 > 0x7FFFFFFF)
985 if (p2 <= p1 && p2 + a2 > p1) {
986 a2++; // BUG: copy one more byte here
989 while ((s32)a2-- > 0) *--p1 = *--p2;
991 while ((s32)a2-- > 0) *p1++ = *p2++;
996 void psxBios_memcmp() { // 0x2d
1000 void psxBios_memchr() { // 0x2e
1001 char *p = (char *)Ra0;
1003 if (a0 == 0 || a2 > 0x7FFFFFFF)
1009 while ((s32)a2-- > 0) {
1010 if (*p++ != (s8)a1) continue;
1011 v0 = a0 + (p - (char *)Ra0 - 1);
1019 void psxBios_rand() { // 0x2f
1020 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1021 v0 = (s >> 16) & 0x7fff;
1022 psxMu32ref(0x9010) = SWAPu32(s);
1026 void psxBios_srand() { // 0x30
1027 psxMu32ref(0x9010) = SWAPu32(a0);
1031 static u32 qscmpfunc, qswidth;
1033 static inline int qscmp(char *a, char *b) {
1036 a0 = sa0 + (a - (char *)PSXM(sa0));
1037 a1 = sa0 + (b - (char *)PSXM(sa0));
1039 softCall(qscmpfunc);
1045 static inline void qexchange(char *i, char *j) {
1056 static inline void q3exchange(char *i, char *j, char *k) {
1068 static void qsort_main(char *a, char *l) {
1069 char *i, *j, *lp, *hp;
1074 if ((n = l - a) <= qswidth)
1076 n = qswidth * (n / (2 * qswidth));
1082 if ((c = qscmp(i, lp)) == 0) {
1083 qexchange(i, lp -= qswidth);
1094 if ((c = qscmp(hp, j)) == 0) {
1095 qexchange(hp += qswidth, j);
1100 q3exchange(i, hp += qswidth, j);
1114 if (lp - a >= l - hp) {
1115 qsort_main(hp + qswidth, l);
1124 q3exchange(j, lp -= qswidth, i);
1129 void psxBios_qsort() { // 0x31
1132 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1137 void psxBios_malloc() { // 0x33
1138 u32 *chunk, *newchunk = NULL;
1139 unsigned int dsize = 0, csize, cstat;
1142 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1144 if (!a0 || (!heap_size || !heap_addr)) {
1150 // scan through heap and combine free chunks of space
1153 while(chunk < heap_end) {
1154 // get size and status of actual chunk
1155 csize = ((u32)*chunk) & 0xfffffffc;
1156 cstat = ((u32)*chunk) & 1;
1158 // most probably broken heap descriptor
1159 // this fixes Burning Road
1162 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1167 // it's a free chunk
1172 colflag = 1; // let's begin a new collection of free memory
1174 else dsize += (csize+4); // add the new size including header
1176 // not a free chunk: did we start a collection ?
1178 if(colflag == 1) { // collection is over
1180 *newchunk = SWAP32(dsize | 1);
1185 chunk = (u32*)((uptr)chunk + csize + 4);
1187 // if neccessary free memory on end of heap
1189 *newchunk = SWAP32(dsize | 1);
1192 csize = ((u32)*chunk) & 0xfffffffc;
1193 cstat = ((u32)*chunk) & 1;
1194 dsize = (a0 + 3) & 0xfffffffc;
1196 // exit on uninitialized heap
1197 if (chunk == NULL) {
1198 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1204 // search an unused chunk that is big enough until the end of the heap
1205 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1206 chunk = (u32*)((uptr)chunk + csize + 4);
1208 // catch out of memory
1209 if(chunk >= heap_end) {
1210 printf("malloc %x,%x: Out of memory error!\n",
1216 csize = ((u32)*chunk) & 0xfffffffc;
1217 cstat = ((u32)*chunk) & 1;
1221 if(dsize == csize) {
1222 // chunk has same size
1223 *chunk &= 0xfffffffc;
1224 } else if (dsize > csize) {
1229 *chunk = SWAP32(dsize);
1230 newchunk = (u32*)((uptr)chunk + dsize + 4);
1231 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1234 // return pointer to allocated memory
1235 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1237 //printf ("malloc %x,%x\n", v0, a0);
1241 void psxBios_free() { // 0x34
1244 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1247 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1250 *(u32*)(Ra0-4) |= 1; // set chunk to free
1254 void psxBios_calloc() { // 0x37
1257 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1267 void psxBios_realloc() { // 0x38
1271 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1275 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1280 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1285 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1286 /* Note that it is not quite implemented this way here. */
1296 /* InitHeap(void *block , int n) */
1297 void psxBios_InitHeap() { // 0x39
1301 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1304 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1309 heap_addr = (u32 *)Ra0;
1311 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1312 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1313 //*heap_addr = SWAP32(size | 1);
1315 SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1320 void psxBios_getchar() { //0x3b
1321 v0 = getchar(); pc0 = ra;
1324 static void psxBios_printf_psxout() { // 0x3f
1333 if (psp != INVALID_PTR) {
1334 memcpy(save, psp, 4 * 4);
1335 psxMu32ref(sp) = SWAP32((u32)a0);
1336 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1337 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1338 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1350 tmp2[j++] = Ra0[i]; goto _start;
1352 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1363 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1367 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1373 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1375 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1377 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1379 *ptmp++ = Ra0[i]; break;
1389 if (psp != INVALID_PTR)
1390 memcpy(psp, save, 4 * 4);
1392 SysPrintf("%s", tmp);
1395 void psxBios_printf() { // 0x3f
1396 psxBios_printf_psxout();
1400 void psxBios_format() { // 0x41
1401 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1403 CreateMcd(Config.Mcd1);
1404 LoadMcd(1, Config.Mcd1);
1407 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1409 CreateMcd(Config.Mcd2);
1410 LoadMcd(2, Config.Mcd2);
1420 static void psxBios_SystemErrorUnresolvedException() {
1421 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1422 SysPrintf("psxBios_%s\n", biosA0n[0x40]);
1423 storeRam32(0xfffc, 0x12345678);
1425 mips_return_void_c(1000);
1429 * long Load(char *name, struct EXEC *header);
1432 void psxBios_Load() { // 0x42
1437 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1438 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1441 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
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 static u32 psxBios_SysMalloc_(u32 size);
1734 static void psxBios_SysMalloc() { // B 00
1735 u32 ret = psxBios_SysMalloc_(a0);
1737 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1738 mips_return_c(ret, 33);
1741 void psxBios_SetRCnt() { // 02
1743 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1750 psxRcntWtarget(a0, a1);
1751 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1752 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1753 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1754 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1755 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1757 psxRcntWmode(a0, mode);
1762 void psxBios_GetRCnt() { // 03
1764 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1768 if (a0 != 3) v0 = psxRcntRcount(a0);
1773 void psxBios_StartRCnt() { // 04
1775 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1779 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1780 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1784 void psxBios_StopRCnt() { // 05
1786 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1790 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1791 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1795 void psxBios_ResetRCnt() { // 06
1797 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1802 psxRcntWmode(a0, 0);
1803 psxRcntWtarget(a0, 0);
1804 psxRcntWcount(a0, 0);
1810 /* gets ev for use with EventCB */
1812 ev = (a0 >> 24) & 0xf; \
1813 if (ev == 0xf) ev = 0x5; \
1817 /* gets spec for use with EventCB */
1821 case 0x0301: spec = 16; break; \
1822 case 0x0302: spec = 17; break; \
1824 for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1828 void psxBios_DeliverEvent() { // 07
1836 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1839 DeliverEvent(ev, spec);
1844 void psxBios_OpenEvent() { // 08
1852 PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1855 EventCB[ev][spec].status = EvStWAIT;
1856 EventCB[ev][spec].mode = a2;
1857 EventCB[ev][spec].fhandler = a3;
1859 v0 = ev | (spec << 8);
1863 void psxBios_CloseEvent() { // 09
1867 spec = (a0 >> 8) & 0xff;
1870 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1873 EventCB[ev][spec].status = EvStUNUSED;
1878 void psxBios_WaitEvent() { // 0a
1882 spec = (a0 >> 8) & 0xff;
1884 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1886 if (EventCB[ev][spec].status == EvStUNUSED)
1893 if (EventCB[ev][spec].status == EvStALREADY)
1895 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1896 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1906 void psxBios_TestEvent() { // 0b
1910 spec = (a0 >> 8) & 0xff;
1912 if (EventCB[ev][spec].status == EvStALREADY)
1914 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1923 PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1929 void psxBios_EnableEvent() { // 0c
1933 spec = (a0 >> 8) & 0xff;
1936 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1939 EventCB[ev][spec].status = EvStACTIVE;
1944 void psxBios_DisableEvent() { // 0d
1948 spec = (a0 >> 8) & 0xff;
1951 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1954 EventCB[ev][spec].status = EvStWAIT;
1960 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1963 void psxBios_OpenTh() { // 0e
1964 TCB *tcb = loadRam32ptr(A_TT_TCB);
1965 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
1968 for (th = 1; th < limit; th++)
1970 if (tcb[th].status != SWAP32(0x4000)) break;
1974 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1975 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1977 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1979 mips_return_c(0xffffffff, 20);
1982 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1984 tcb[th].status = SWAP32(0x4000);
1985 tcb[th].mode = SWAP32(0x1000);
1986 tcb[th].epc = SWAP32(a0);
1987 tcb[th].reg[30] = SWAP32(a1); // fp
1988 tcb[th].reg[29] = SWAP32(a1); // sp
1989 tcb[th].reg[28] = SWAP32(a2); // gp
1991 mips_return_c(0xff000000 + th, 34);
1995 * int CloseTh(long thread);
1998 void psxBios_CloseTh() { // 0f
1999 TCB *tcb = loadRam32ptr(A_TT_TCB);
2000 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2004 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2006 /* The return value is always 1 (even if the handle was already closed). */
2008 if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2009 tcb[th].status = SWAP32(0x1000);
2016 * int ChangeTh(long thread);
2019 void psxBios_ChangeTh() { // 10
2020 u32 tcbBase = loadRam32(A_TT_TCB);
2021 u32 th = a0 & 0xffff;
2024 // PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
2026 // without doing any argument checks, just issue a syscall
2027 // (like the real bios does)
2029 a1 = tcbBase + th * sizeof(TCB);
2034 void psxBios_InitPAD() { // 0x12
2036 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
2039 pad_buf1 = (char*)Ra0;
2041 pad_buf2 = (char*)Ra2;
2047 void psxBios_StartPAD() { // 13
2049 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2052 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
2053 psxRegs.CP0.n.SR |= 0x401;
2057 void psxBios_StopPAD() { // 14
2059 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2067 void psxBios_PAD_init() { // 15
2069 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2071 if (!(a0 == 0x20000000 || a0 == 0x20000001))
2077 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
2078 pad_buf = (int *)Ra1;
2080 psxRegs.CP0.n.SR |= 0x401;
2085 void psxBios_PAD_dr() { // 16
2087 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2093 static void psxBios_ReturnFromException() { // 17
2094 u32 tcbPtr = loadRam32(A_TT_PCB);
2095 const TCB *tcb = loadRam32ptr(tcbPtr);
2098 for (i = 1; i < 32; i++)
2099 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2100 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2101 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2102 psxRegs.CP0.n.SR = SWAP32(tcb->sr);
2104 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2105 pc0 = k0 = SWAP32(tcb->epc);
2107 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
2112 void psxBios_ResetEntryInt() { // 18
2113 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2115 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2116 mips_return_void_c(5);
2119 void psxBios_HookEntryInt() { // 19
2120 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2122 storeRam32(A_EEXIT_PTR, a0);
2123 mips_return_void_c(3);
2126 void psxBios_UnDeliverEvent() { // 0x20
2134 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2137 if (EventCB[ev][spec].status == EvStALREADY &&
2138 EventCB[ev][spec].mode == EvMdNOINTR)
2139 EventCB[ev][spec].status = EvStACTIVE;
2144 char ffile[64], *pfile;
2147 static void buopen(int mcd, char *ptr, char *cfg)
2150 char *mcd_data = ptr;
2152 strcpy(FDesc[1 + mcd].name, Ra0+5);
2153 FDesc[1 + mcd].offset = 0;
2154 FDesc[1 + mcd].mode = a1;
2156 for (i=1; i<16; i++) {
2157 const char *fptr = mcd_data + 128 * i;
2158 if ((*fptr & 0xF0) != 0x50) continue;
2159 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2160 FDesc[1 + mcd].mcfile = i;
2161 SysPrintf("open %s\n", fptr+0xa);
2165 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2166 for (i=1; i<16; i++) {
2167 int j, xor, nblk = a1 >> 16;
2169 char *fptr = mcd_data + 128 * i;
2171 if ((*fptr & 0xF0) != 0xa0) continue;
2173 FDesc[1 + mcd].mcfile = i;
2176 fptr[5] = 0x20 * nblk;
2179 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2180 pptr = fptr2 = fptr;
2181 for(j=2; j<=nblk; j++) {
2183 for(i++; i<16; i++) {
2186 memset(fptr2, 0, 128);
2187 fptr2[0] = j < nblk ? 0x52 : 0x53;
2190 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2195 /* shouldn't this return ENOSPC if i == 16? */
2197 pptr[8] = pptr[9] = 0xff;
2198 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2200 SysPrintf("openC %s %d\n", ptr, nblk);
2202 /* just go ahead and resave them all */
2203 SaveMcd(cfg, ptr, 128, 128 * 15);
2206 /* shouldn't this return ENOSPC if i == 16? */
2211 * int open(char *name , int mode);
2214 void psxBios_open() { // 0x32
2218 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2223 if (pa0 != INVALID_PTR) {
2224 if (!strncmp(pa0, "bu00", 4)) {
2225 buopen(1, Mcd1Data, Config.Mcd1);
2228 if (!strncmp(pa0, "bu10", 4)) {
2229 buopen(2, Mcd2Data, Config.Mcd2);
2237 * int lseek(int fd , int offset , int whence);
2240 void psxBios_lseek() { // 0x33
2242 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2247 FDesc[a0].offset = a1;
2249 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2250 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2254 FDesc[a0].offset+= a1;
2255 v0 = FDesc[a0].offset;
2264 * int read(int fd , void *buf , int nbytes);
2267 void psxBios_read() { // 0x34
2272 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2277 if (pa1 != INVALID_PTR) {
2279 case 2: buread(pa1, 1, a2); break;
2280 case 3: buread(pa1, 2, a2); break;
2288 * int write(int fd , void *buf , int nbytes);
2291 void psxBios_write() { // 0x35/0x03
2296 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2300 if (pa1 == INVALID_PTR) {
2305 if (a0 == 1) { // stdout
2310 SysPrintf("%c", *ptr++); a2--;
2316 case 2: buwrite(pa1, 1, a2); break;
2317 case 3: buwrite(pa1, 2, a2); break;
2323 static void psxBios_write_psxout() {
2324 if (a0 == 1) { // stdout
2325 const char *ptr = Ra1;
2328 if (ptr != INVALID_PTR)
2330 SysPrintf("%c", *ptr++);
2334 static void psxBios_putchar_psxout() { // 3d
2335 SysPrintf("%c", (char)a0);
2338 static void psxBios_puts_psxout() { // 3e/3f
2339 SysPrintf("%s", Ra0);
2343 * int close(int fd);
2346 void psxBios_close() { // 0x36
2348 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2355 void psxBios_putchar() { // 3d
2356 SysPrintf("%c", (char)a0);
2360 void psxBios_puts() { // 3e/3f
2361 SysPrintf("%s", Ra0);
2366 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2367 * We want to mimic the PSX's behaviour in this case for bufile. */
2368 static size_t strlen_internal(char* p)
2370 size_t size_of_array = 0;
2371 while (*p++) size_of_array++;
2372 return size_of_array;
2375 #define bufile(mcd) { \
2376 size_t size_of_name = strlen_internal(dir->name); \
2377 while (nfile < 16) { \
2380 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2382 if ((*ptr & 0xF0) != 0x50) continue; \
2383 /* Bug link files show up as free block. */ \
2384 if (!ptr[0xa]) continue; \
2386 if (pfile[0] == 0) { \
2387 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2388 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2389 } else for (i=0; i<20; i++) { \
2390 if (pfile[i] == ptr[i]) { \
2391 dir->name[i] = ptr[i]; continue; } \
2392 if (pfile[i] == '?') { \
2393 dir->name[i] = ptr[i]; continue; } \
2394 if (pfile[i] == '*') { \
2395 strcpy(dir->name+i, ptr+i); break; } \
2398 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2399 if (match == 0) { continue; } \
2407 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2410 void psxBios_firstfile() { // 42
2411 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2418 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2423 if (pa0 != INVALID_PTR) {
2427 if (!strncmp(pa0, "bu00", 4)) {
2428 // firstfile() calls _card_read() internally, so deliver it's event
2429 DeliverEvent(0x11, 0x2);
2431 } else if (!strncmp(pa0, "bu10", 4)) {
2432 // firstfile() calls _card_read() internally, so deliver it's event
2433 DeliverEvent(0x11, 0x2);
2442 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2445 void psxBios_nextfile() { // 43
2446 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2452 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2457 if (!strncmp(ffile, "bu00", 4)) {
2461 if (!strncmp(ffile, "bu10", 4)) {
2468 #define burename(mcd) { \
2469 for (i=1; i<16; i++) { \
2470 int namelen, j, xor = 0; \
2471 ptr = Mcd##mcd##Data + 128 * i; \
2472 if ((*ptr & 0xF0) != 0x50) continue; \
2473 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2474 namelen = strlen(Ra1+5); \
2475 memcpy(ptr+0xa, Ra1+5, namelen); \
2476 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2477 for (j=0; j<127; j++) xor^= ptr[j]; \
2479 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2486 * int rename(char *old, char *new);
2489 void psxBios_rename() { // 44
2496 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2501 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2502 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2506 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2515 #define budelete(mcd) { \
2516 for (i=1; i<16; i++) { \
2517 ptr = Mcd##mcd##Data + 128 * i; \
2518 if ((*ptr & 0xF0) != 0x50) continue; \
2519 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2520 *ptr = (*ptr & 0xf) | 0xA0; \
2521 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2522 SysPrintf("delete %s\n", ptr+0xa); \
2529 * int delete(char *name);
2532 void psxBios_delete() { // 45
2538 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2543 if (pa0 != INVALID_PTR) {
2544 if (!strncmp(pa0, "bu00", 4)) {
2548 if (!strncmp(pa0, "bu10", 4)) {
2556 void psxBios_InitCARD() { // 4a
2558 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2566 void psxBios_StartCARD() { // 4b
2568 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2571 if (CardState == 0) CardState = 1;
2576 void psxBios_StopCARD() { // 4c
2578 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2581 if (CardState == 1) CardState = 0;
2586 void psxBios__card_write() { // 0x4e
2591 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2594 Function also accepts sector 400h (a bug).
2595 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2599 /* Invalid sectors */
2603 card_active_chan = a0;
2606 if (pa2 != INVALID_PTR) {
2608 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2609 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2611 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2612 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2616 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2617 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2622 void psxBios__card_read() { // 0x4f
2627 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2630 Function also accepts sector 400h (a bug).
2631 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2635 /* Invalid sectors */
2639 card_active_chan = a0;
2642 if (pa2 != INVALID_PTR) {
2644 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2646 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2650 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2651 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2656 void psxBios__new_card() { // 0x50
2658 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2664 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2665 void psxBios__get_error(void) // 55
2667 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2672 void psxBios_Krom2RawAdd() { // 0x51
2675 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2676 const u32 table_8140[][2] = {
2677 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2678 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2679 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2680 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2681 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2682 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2683 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2684 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2685 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2689 const u32 table_889f[][2] = {
2690 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2691 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2692 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2693 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2694 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2695 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2696 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2697 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2701 if (a0 >= 0x8140 && a0 <= 0x84be) {
2702 while (table_8140[i][0] <= a0) i++;
2703 a0 -= table_8140[i - 1][0];
2704 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2705 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2706 while (table_889f[i][0] <= a0) i++;
2707 a0 -= table_889f[i - 1][0];
2708 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2716 void psxBios_GetC0Table() { // 56
2717 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2718 log_unhandled("GetC0Table @%08x\n", ra);
2720 mips_return_c(A_C0_TABLE, 3);
2723 void psxBios_GetB0Table() { // 57
2724 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2725 log_unhandled("GetB0Table @%08x\n", ra);
2727 mips_return_c(A_B0_TABLE, 3);
2730 void psxBios__card_chan() { // 0x58
2732 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2735 v0 = card_active_chan;
2739 void psxBios_ChangeClearPad() { // 5b
2741 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2747 void psxBios__card_status() { // 5c
2749 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2752 v0 = card_active_chan;
2756 void psxBios__card_wait() { // 5d
2758 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2765 /* System calls C0 */
2767 static void psxBios_SysEnqIntRP();
2769 static void psxBios_InitRCnt() { // 00
2771 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2772 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2773 for (i = 0; i < 3; i++) {
2774 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2775 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2776 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2779 psxBios_SysEnqIntRP();
2780 mips_return_c(0, 9);
2783 static void psxBios_InitException() { // 01
2784 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2786 psxBios_SysEnqIntRP();
2787 mips_return_c(0, 9);
2791 * int SysEnqIntRP(int index , long *queue);
2794 static void psxBios_SysEnqIntRP() { // 02
2795 u32 old, base = loadRam32(A_TT_ExCB);
2796 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2798 old = loadRam32(base + (a0 << 3));
2799 storeRam32(base + (a0 << 3), a1);
2800 storeRam32(a1, old);
2801 mips_return_c(0, 9);
2805 * int SysDeqIntRP(int index , long *queue);
2808 static void psxBios_SysDeqIntRP_() { // 03
2809 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2810 u32 lim = 0, ret = 0;
2812 // as in original: no arg checks of any kind, bug if a1 == 0
2813 ptr = loadRam32(base + (a0 << 3));
2815 next = loadRam32(ptr);
2817 storeRam32(base + (a0 << 3), next);
2822 while (next && next != a1 && lim++ < 100) {
2824 next = loadRam32(ptr);
2828 next = loadRam32(next);
2829 storeRam32(ptr, next);
2836 PSXBIOS_LOG("bad chain %u %x\n", a0, base);
2838 mips_return_c(ret, 12);
2841 static void psxBios_SysDeqIntRP() { // 03
2842 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2843 psxBios_SysDeqIntRP_();
2846 static void psxBios_SysInitMemory_(u32 base, u32 size) {
2847 storeRam32(base, 0);
2848 storeRam32(A_KMALLOC_PTR, base);
2849 storeRam32(A_KMALLOC_SIZE, size);
2850 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2853 // this should be much more complicated, but maybe that'll be enough
2854 static u32 psxBios_SysMalloc_(u32 size) {
2855 u32 ptr = loadRam32(A_KMALLOC_PTR);
2857 size = (size + 3) & ~3;
2858 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2859 storeRam32(ptr, size);
2863 static void psxBios_SysInitMemory() { // 08
2864 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2866 psxBios_SysInitMemory_(a0, a1);
2867 mips_return_void_c(12);
2870 static void psxBios_ChangeClearRCnt() { // 0a
2873 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2875 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
2876 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
2877 mips_return_c(ret, 8);
2880 static void psxBios_InitDefInt() { // 0c
2881 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
2882 // should also clear the autoack table
2884 psxBios_SysEnqIntRP();
2885 mips_return_c(0, 20 + 6*2);
2888 void psxBios_dummy() {
2889 u32 pc = (pc0 & 0x1fffff) - 4;
2890 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
2891 : pc == 0xc0 ? biosC0n : NULL;
2892 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
2893 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
2894 (void)pc; (void)ntab;
2895 mips_return_c(0, 100);
2898 void (*biosA0[256])();
2899 // C0 and B0 overlap (end of C0 is start of B0)
2900 void (*biosC0[256+128])();
2901 void (**biosB0)() = biosC0 + 128;
2903 #include "sjisfont.h"
2905 void setup_mips_code()
2908 ptr = (u32 *)&psxM[A_SYSCALL];
2909 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
2910 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
2911 ptr[0x08/4] = SWAPu32(0x00000000); // nop
2913 ptr = (u32 *)&psxM[A_EXCEPTION];
2914 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
2915 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
2916 ptr[0x14/4] = SWAPu32(0x00000000); // nop
2917 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
2918 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
2919 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
2920 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
2921 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
2922 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
2923 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
2925 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
2926 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
2927 ptr[0x68/4] = SWAPu32(0x24630004); // addiu $v1, $v1, 4
2928 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
2930 ptr[0xb0/4] = HLEOP(hleop_exception);
2933 static const struct {
2937 { 0xbfc050a4, hleop_exc0_0_1 },
2938 { 0xbfc04fbc, hleop_exc0_0_2 },
2939 { 0xbfc0506c, hleop_exc0_1_1 },
2940 { 0xbfc04dec, hleop_exc0_1_2 },
2941 { 0x1a00, hleop_exc0_2_2 },
2942 { 0x19c8, hleop_exc1_0_1 },
2943 { 0x18bc, hleop_exc1_0_2 },
2944 { 0x1990, hleop_exc1_1_1 },
2945 { 0x1858, hleop_exc1_1_2 },
2946 { 0x1958, hleop_exc1_2_1 },
2947 { 0x17f4, hleop_exc1_2_2 },
2948 { 0x1920, hleop_exc1_3_1 },
2949 { 0x1794, hleop_exc1_3_2 },
2950 { 0x2458, hleop_exc3_0_2 },
2953 static int chain_hle_op(u32 handler)
2957 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
2958 if (chainfns[i].addr == handler)
2959 return chainfns[i].op;
2963 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
2965 d[0] = SWAPu32(next);
2966 d[1] = SWAPu32(handler1);
2967 d[2] = SWAPu32(handler2);
2969 // install hle traps
2970 PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
2971 PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
2974 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
2976 u32 *ram32 = (u32 *)psxM;
2977 u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
2978 u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
2979 u32 p_excb, p_evcb, p_pcb, p_tcb;
2981 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
2982 psxBios_SysInitMemory_(0xa000e000, 0x2000);
2983 p_excb = psxBios_SysMalloc_(s_excb);
2984 p_evcb = psxBios_SysMalloc_(s_evcb);
2985 p_pcb = psxBios_SysMalloc_(s_pcb);
2986 p_tcb = psxBios_SysMalloc_(s_tcb);
2988 // "table of tables". Some games modify it
2989 assert(A_TT_ExCB == 0x0100);
2990 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
2991 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
2992 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
2993 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
2994 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
2995 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
2996 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
2997 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
2998 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
2999 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3000 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3001 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3003 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3004 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3005 storeRam32(p_excb + 4*4, 0x0000); // chain2
3006 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3008 storeRam32(p_pcb, p_tcb);
3009 storeRam32(p_tcb, 0x4000); // first TCB
3012 void psxBiosInit() {
3018 memset(psxM, 0, 0x10000);
3019 for(i = 0; i < 256; i++) {
3024 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3025 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3026 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3027 biosA0[0x3f] = psxBios_printf_psxout;
3029 if (!Config.HLE) return;
3031 for(i = 0; i < 256; i++) {
3032 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3033 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3034 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3037 biosA0[0x00] = psxBios_open;
3038 biosA0[0x01] = psxBios_lseek;
3039 biosA0[0x02] = psxBios_read;
3040 biosA0[0x03] = psxBios_write;
3041 biosA0[0x04] = psxBios_close;
3042 //biosA0[0x05] = psxBios_ioctl;
3043 //biosA0[0x06] = psxBios_exit;
3044 //biosA0[0x07] = psxBios_sys_a0_07;
3045 biosA0[0x08] = psxBios_getc;
3046 biosA0[0x09] = psxBios_putc;
3047 biosA0[0x0a] = psxBios_todigit;
3048 //biosA0[0x0b] = psxBios_atof;
3049 //biosA0[0x0c] = psxBios_strtoul;
3050 //biosA0[0x0d] = psxBios_strtol;
3051 biosA0[0x0e] = psxBios_abs;
3052 biosA0[0x0f] = psxBios_labs;
3053 biosA0[0x10] = psxBios_atoi;
3054 biosA0[0x11] = psxBios_atol;
3055 //biosA0[0x12] = psxBios_atob;
3056 biosA0[0x13] = psxBios_setjmp;
3057 biosA0[0x14] = psxBios_longjmp;
3058 biosA0[0x15] = psxBios_strcat;
3059 biosA0[0x16] = psxBios_strncat;
3060 biosA0[0x17] = psxBios_strcmp;
3061 biosA0[0x18] = psxBios_strncmp;
3062 biosA0[0x19] = psxBios_strcpy;
3063 biosA0[0x1a] = psxBios_strncpy;
3064 biosA0[0x1b] = psxBios_strlen;
3065 biosA0[0x1c] = psxBios_index;
3066 biosA0[0x1d] = psxBios_rindex;
3067 biosA0[0x1e] = psxBios_strchr;
3068 biosA0[0x1f] = psxBios_strrchr;
3069 biosA0[0x20] = psxBios_strpbrk;
3070 biosA0[0x21] = psxBios_strspn;
3071 biosA0[0x22] = psxBios_strcspn;
3072 biosA0[0x23] = psxBios_strtok;
3073 biosA0[0x24] = psxBios_strstr;
3074 biosA0[0x25] = psxBios_toupper;
3075 biosA0[0x26] = psxBios_tolower;
3076 biosA0[0x27] = psxBios_bcopy;
3077 biosA0[0x28] = psxBios_bzero;
3078 biosA0[0x29] = psxBios_bcmp;
3079 biosA0[0x2a] = psxBios_memcpy;
3080 biosA0[0x2b] = psxBios_memset;
3081 biosA0[0x2c] = psxBios_memmove;
3082 biosA0[0x2d] = psxBios_memcmp;
3083 biosA0[0x2e] = psxBios_memchr;
3084 biosA0[0x2f] = psxBios_rand;
3085 biosA0[0x30] = psxBios_srand;
3086 biosA0[0x31] = psxBios_qsort;
3087 //biosA0[0x32] = psxBios_strtod;
3088 biosA0[0x33] = psxBios_malloc;
3089 biosA0[0x34] = psxBios_free;
3090 //biosA0[0x35] = psxBios_lsearch;
3091 //biosA0[0x36] = psxBios_bsearch;
3092 biosA0[0x37] = psxBios_calloc;
3093 biosA0[0x38] = psxBios_realloc;
3094 biosA0[0x39] = psxBios_InitHeap;
3095 //biosA0[0x3a] = psxBios__exit;
3096 biosA0[0x3b] = psxBios_getchar;
3097 biosA0[0x3c] = psxBios_putchar;
3098 //biosA0[0x3d] = psxBios_gets;
3099 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3100 //biosA0[0x41] = psxBios_LoadTest;
3101 biosA0[0x42] = psxBios_Load;
3102 biosA0[0x43] = psxBios_Exec;
3103 biosA0[0x44] = psxBios_FlushCache;
3104 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3105 biosA0[0x46] = psxBios_GPU_dw;
3106 biosA0[0x47] = psxBios_mem2vram;
3107 biosA0[0x48] = psxBios_SendGPU;
3108 biosA0[0x49] = psxBios_GPU_cw;
3109 biosA0[0x4a] = psxBios_GPU_cwb;
3110 biosA0[0x4b] = psxBios_GPU_SendPackets;
3111 biosA0[0x4c] = psxBios_sys_a0_4c;
3112 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3113 //biosA0[0x4e] = psxBios_GPU_sync;
3114 //biosA0[0x4f] = psxBios_sys_a0_4f;
3115 //biosA0[0x50] = psxBios_sys_a0_50;
3116 biosA0[0x51] = psxBios_LoadExec;
3117 //biosA0[0x52] = psxBios_GetSysSp;
3118 //biosA0[0x53] = psxBios_sys_a0_53;
3119 //biosA0[0x54] = psxBios__96_init_a54;
3120 //biosA0[0x55] = psxBios__bu_init_a55;
3121 biosA0[0x56] = psxBios_CdRemove;
3122 //biosA0[0x57] = psxBios_sys_a0_57;
3123 //biosA0[0x58] = psxBios_sys_a0_58;
3124 //biosA0[0x59] = psxBios_sys_a0_59;
3125 //biosA0[0x5a] = psxBios_sys_a0_5a;
3126 //biosA0[0x5b] = psxBios_dev_tty_init;
3127 //biosA0[0x5c] = psxBios_dev_tty_open;
3128 //biosA0[0x5d] = psxBios_sys_a0_5d;
3129 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3130 //biosA0[0x5f] = psxBios_dev_cd_open;
3131 //biosA0[0x60] = psxBios_dev_cd_read;
3132 //biosA0[0x61] = psxBios_dev_cd_close;
3133 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3134 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3135 //biosA0[0x64] = psxBios_dev_cd_chdir;
3136 //biosA0[0x65] = psxBios_dev_card_open;
3137 //biosA0[0x66] = psxBios_dev_card_read;
3138 //biosA0[0x67] = psxBios_dev_card_write;
3139 //biosA0[0x68] = psxBios_dev_card_close;
3140 //biosA0[0x69] = psxBios_dev_card_firstfile;
3141 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3142 //biosA0[0x6b] = psxBios_dev_card_erase;
3143 //biosA0[0x6c] = psxBios_dev_card_undelete;
3144 //biosA0[0x6d] = psxBios_dev_card_format;
3145 //biosA0[0x6e] = psxBios_dev_card_rename;
3146 //biosA0[0x6f] = psxBios_dev_card_6f;
3147 biosA0[0x70] = psxBios__bu_init;
3148 biosA0[0x71] = psxBios__96_init;
3149 biosA0[0x72] = psxBios_CdRemove;
3150 //biosA0[0x73] = psxBios_sys_a0_73;
3151 //biosA0[0x74] = psxBios_sys_a0_74;
3152 //biosA0[0x75] = psxBios_sys_a0_75;
3153 //biosA0[0x76] = psxBios_sys_a0_76;
3154 //biosA0[0x77] = psxBios_sys_a0_77;
3155 //biosA0[0x78] = psxBios__96_CdSeekL;
3156 //biosA0[0x79] = psxBios_sys_a0_79;
3157 //biosA0[0x7a] = psxBios_sys_a0_7a;
3158 //biosA0[0x7b] = psxBios_sys_a0_7b;
3159 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3160 //biosA0[0x7d] = psxBios_sys_a0_7d;
3161 //biosA0[0x7e] = psxBios__96_CdRead;
3162 //biosA0[0x7f] = psxBios_sys_a0_7f;
3163 //biosA0[0x80] = psxBios_sys_a0_80;
3164 //biosA0[0x81] = psxBios_sys_a0_81;
3165 //biosA0[0x82] = psxBios_sys_a0_82;
3166 //biosA0[0x83] = psxBios_sys_a0_83;
3167 //biosA0[0x84] = psxBios_sys_a0_84;
3168 //biosA0[0x85] = psxBios__96_CdStop;
3169 //biosA0[0x86] = psxBios_sys_a0_86;
3170 //biosA0[0x87] = psxBios_sys_a0_87;
3171 //biosA0[0x88] = psxBios_sys_a0_88;
3172 //biosA0[0x89] = psxBios_sys_a0_89;
3173 //biosA0[0x8a] = psxBios_sys_a0_8a;
3174 //biosA0[0x8b] = psxBios_sys_a0_8b;
3175 //biosA0[0x8c] = psxBios_sys_a0_8c;
3176 //biosA0[0x8d] = psxBios_sys_a0_8d;
3177 //biosA0[0x8e] = psxBios_sys_a0_8e;
3178 //biosA0[0x8f] = psxBios_sys_a0_8f;
3179 biosA0[0x90] = hleExc0_1_2;
3180 biosA0[0x91] = hleExc0_0_2;
3181 biosA0[0x92] = hleExc0_1_1;
3182 biosA0[0x93] = hleExc0_0_1;
3183 //biosA0[0x94] = psxBios_sys_a0_94;
3184 //biosA0[0x95] = psxBios_sys_a0_95;
3185 //biosA0[0x96] = psxBios_AddCDROMDevice;
3186 //biosA0[0x97] = psxBios_AddMemCardDevide;
3187 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3188 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3189 //biosA0[0x9a] = psxBios_sys_a0_9a;
3190 //biosA0[0x9b] = psxBios_sys_a0_9b;
3191 //biosA0[0x9c] = psxBios_SetConf;
3192 //biosA0[0x9d] = psxBios_GetConf;
3193 //biosA0[0x9e] = psxBios_sys_a0_9e;
3194 biosA0[0x9f] = psxBios_SetMem;
3195 //biosA0[0xa0] = psxBios__boot;
3196 //biosA0[0xa1] = psxBios_SystemError;
3197 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3198 biosA0[0xa3] = psxBios_DequeueCdIntr;
3199 //biosA0[0xa4] = psxBios_sys_a0_a4;
3200 //biosA0[0xa5] = psxBios_ReadSector;
3201 biosA0[0xa6] = psxBios_get_cd_status;
3202 //biosA0[0xa7] = psxBios_bufs_cb_0;
3203 //biosA0[0xa8] = psxBios_bufs_cb_1;
3204 //biosA0[0xa9] = psxBios_bufs_cb_2;
3205 //biosA0[0xaa] = psxBios_bufs_cb_3;
3206 biosA0[0xab] = psxBios__card_info;
3207 biosA0[0xac] = psxBios__card_load;
3208 //biosA0[0axd] = psxBios__card_auto;
3209 //biosA0[0xae] = psxBios_bufs_cd_4;
3210 //biosA0[0xaf] = psxBios_sys_a0_af;
3211 //biosA0[0xb0] = psxBios_sys_a0_b0;
3212 //biosA0[0xb1] = psxBios_sys_a0_b1;
3213 //biosA0[0xb2] = psxBios_do_a_long_jmp
3214 //biosA0[0xb3] = psxBios_sys_a0_b3;
3215 //biosA0[0xb4] = psxBios_sub_function;
3216 //*******************B0 CALLS****************************
3217 biosB0[0x00] = psxBios_SysMalloc;
3218 //biosB0[0x01] = psxBios_sys_b0_01;
3219 biosB0[0x02] = psxBios_SetRCnt;
3220 biosB0[0x03] = psxBios_GetRCnt;
3221 biosB0[0x04] = psxBios_StartRCnt;
3222 biosB0[0x05] = psxBios_StopRCnt;
3223 biosB0[0x06] = psxBios_ResetRCnt;
3224 biosB0[0x07] = psxBios_DeliverEvent;
3225 biosB0[0x08] = psxBios_OpenEvent;
3226 biosB0[0x09] = psxBios_CloseEvent;
3227 biosB0[0x0a] = psxBios_WaitEvent;
3228 biosB0[0x0b] = psxBios_TestEvent;
3229 biosB0[0x0c] = psxBios_EnableEvent;
3230 biosB0[0x0d] = psxBios_DisableEvent;
3231 biosB0[0x0e] = psxBios_OpenTh;
3232 biosB0[0x0f] = psxBios_CloseTh;
3233 biosB0[0x10] = psxBios_ChangeTh;
3234 //biosB0[0x11] = psxBios_psxBios_b0_11;
3235 biosB0[0x12] = psxBios_InitPAD;
3236 biosB0[0x13] = psxBios_StartPAD;
3237 biosB0[0x14] = psxBios_StopPAD;
3238 biosB0[0x15] = psxBios_PAD_init;
3239 biosB0[0x16] = psxBios_PAD_dr;
3240 biosB0[0x17] = psxBios_ReturnFromException;
3241 biosB0[0x18] = psxBios_ResetEntryInt;
3242 biosB0[0x19] = psxBios_HookEntryInt;
3243 //biosB0[0x1a] = psxBios_sys_b0_1a;
3244 //biosB0[0x1b] = psxBios_sys_b0_1b;
3245 //biosB0[0x1c] = psxBios_sys_b0_1c;
3246 //biosB0[0x1d] = psxBios_sys_b0_1d;
3247 //biosB0[0x1e] = psxBios_sys_b0_1e;
3248 //biosB0[0x1f] = psxBios_sys_b0_1f;
3249 biosB0[0x20] = psxBios_UnDeliverEvent;
3250 //biosB0[0x21] = psxBios_sys_b0_21;
3251 //biosB0[0x22] = psxBios_sys_b0_22;
3252 //biosB0[0x23] = psxBios_sys_b0_23;
3253 //biosB0[0x24] = psxBios_sys_b0_24;
3254 //biosB0[0x25] = psxBios_sys_b0_25;
3255 //biosB0[0x26] = psxBios_sys_b0_26;
3256 //biosB0[0x27] = psxBios_sys_b0_27;
3257 //biosB0[0x28] = psxBios_sys_b0_28;
3258 //biosB0[0x29] = psxBios_sys_b0_29;
3259 //biosB0[0x2a] = psxBios_sys_b0_2a;
3260 //biosB0[0x2b] = psxBios_sys_b0_2b;
3261 //biosB0[0x2c] = psxBios_sys_b0_2c;
3262 //biosB0[0x2d] = psxBios_sys_b0_2d;
3263 //biosB0[0x2e] = psxBios_sys_b0_2e;
3264 //biosB0[0x2f] = psxBios_sys_b0_2f;
3265 //biosB0[0x30] = psxBios_sys_b0_30;
3266 //biosB0[0x31] = psxBios_sys_b0_31;
3267 biosB0[0x32] = psxBios_open;
3268 biosB0[0x33] = psxBios_lseek;
3269 biosB0[0x34] = psxBios_read;
3270 biosB0[0x35] = psxBios_write;
3271 biosB0[0x36] = psxBios_close;
3272 //biosB0[0x37] = psxBios_ioctl;
3273 //biosB0[0x38] = psxBios_exit;
3274 //biosB0[0x39] = psxBios_sys_b0_39;
3275 //biosB0[0x3a] = psxBios_getc;
3276 //biosB0[0x3b] = psxBios_putc;
3277 biosB0[0x3c] = psxBios_getchar;
3278 //biosB0[0x3e] = psxBios_gets;
3279 //biosB0[0x40] = psxBios_cd;
3280 biosB0[0x41] = psxBios_format;
3281 biosB0[0x42] = psxBios_firstfile;
3282 biosB0[0x43] = psxBios_nextfile;
3283 biosB0[0x44] = psxBios_rename;
3284 biosB0[0x45] = psxBios_delete;
3285 //biosB0[0x46] = psxBios_undelete;
3286 //biosB0[0x47] = psxBios_AddDevice;
3287 //biosB0[0x48] = psxBios_RemoteDevice;
3288 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3289 biosB0[0x4a] = psxBios_InitCARD;
3290 biosB0[0x4b] = psxBios_StartCARD;
3291 biosB0[0x4c] = psxBios_StopCARD;
3292 //biosB0[0x4d] = psxBios_sys_b0_4d;
3293 biosB0[0x4e] = psxBios__card_write;
3294 biosB0[0x4f] = psxBios__card_read;
3295 biosB0[0x50] = psxBios__new_card;
3296 biosB0[0x51] = psxBios_Krom2RawAdd;
3297 //biosB0[0x52] = psxBios_sys_b0_52;
3298 //biosB0[0x53] = psxBios_sys_b0_53;
3299 //biosB0[0x54] = psxBios__get_errno;
3300 biosB0[0x55] = psxBios__get_error;
3301 biosB0[0x56] = psxBios_GetC0Table;
3302 biosB0[0x57] = psxBios_GetB0Table;
3303 biosB0[0x58] = psxBios__card_chan;
3304 //biosB0[0x59] = psxBios_sys_b0_59;
3305 //biosB0[0x5a] = psxBios_sys_b0_5a;
3306 biosB0[0x5b] = psxBios_ChangeClearPad;
3307 biosB0[0x5c] = psxBios__card_status;
3308 biosB0[0x5d] = psxBios__card_wait;
3309 //*******************C0 CALLS****************************
3310 biosC0[0x00] = psxBios_InitRCnt;
3311 biosC0[0x01] = psxBios_InitException;
3312 biosC0[0x02] = psxBios_SysEnqIntRP;
3313 biosC0[0x03] = psxBios_SysDeqIntRP;
3314 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
3315 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3316 //biosC0[0x06] = psxBios_ExceptionHandler;
3317 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3318 biosC0[0x08] = psxBios_SysInitMemory;
3319 //biosC0[0x09] = psxBios_SysInitKMem;
3320 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3321 //biosC0[0x0b] = psxBios_SystemError;
3322 biosC0[0x0c] = psxBios_InitDefInt;
3323 //biosC0[0x0d] = psxBios_sys_c0_0d;
3324 //biosC0[0x0e] = psxBios_sys_c0_0e;
3325 //biosC0[0x0f] = psxBios_sys_c0_0f;
3326 //biosC0[0x10] = psxBios_sys_c0_10;
3327 //biosC0[0x11] = psxBios_sys_c0_11;
3328 //biosC0[0x12] = psxBios_InstallDevices;
3329 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3330 //biosC0[0x14] = psxBios_sys_c0_14;
3331 //biosC0[0x15] = psxBios__cdevinput;
3332 //biosC0[0x16] = psxBios__cdevscan;
3333 //biosC0[0x17] = psxBios__circgetc;
3334 //biosC0[0x18] = psxBios__circputc;
3335 //biosC0[0x19] = psxBios_ioabort;
3336 //biosC0[0x1a] = psxBios_sys_c0_1a
3337 //biosC0[0x1b] = psxBios_KernelRedirect;
3338 //biosC0[0x1c] = psxBios_PatchAOTable;
3339 //************** THE END ***************************************
3342 size = sizeof(EvCB) * 32;
3343 EventCB = (void *)&psxR[base]; base += size * 6;
3344 memset(EventCB, 0, size * 6);
3346 EvEV = EventCB + 32;
3347 RcEV = EventCB + 32 * 2;
3348 UeEV = EventCB + 32 * 3;
3349 SwEV = EventCB + 32 * 4;
3350 ThEV = EventCB + 32 * 5;
3356 pad_buf1len = pad_buf2len = 0;
3362 memset(FDesc, 0, sizeof(FDesc));
3363 card_active_chan = 0;
3366 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3369 len = 0x80000 - 0x66000;
3370 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3371 len = 0x80000 - 0x69d68;
3372 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3375 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3377 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3378 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3379 Here are some examples of games not working with this fix in place :
3380 R-type won't get past the Irem logo if not implemented.
3381 Crash Team Racing will softlock after the Sony logo.
3384 ram32 = (u32 *)psxM;
3385 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3386 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3387 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3388 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3390 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3391 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3393 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3394 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3395 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3396 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3398 ram32[0x00a0/4] = HLEOP(hleop_a0);
3399 ram32[0x00b0/4] = HLEOP(hleop_b0);
3400 ram32[0x00c0/4] = HLEOP(hleop_c0);
3404 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3405 strcpy((char *)&ram32[0xeff0/4], "bu");
3407 // default exception handler chains
3408 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3409 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3410 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3411 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3412 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3413 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3414 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3415 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3419 // fill the api jumptables with fake entries as some games patch them
3420 // (or rather the funcs listed there)
3421 ptr = (u32 *)&psxM[A_A0_TABLE];
3422 for (i = 0; i < 256; i++)
3423 ptr[i] = SWAP32(0x1000);
3425 ptr = (u32 *)&psxM[A_B0_TABLE];
3426 for (i = 0; i < 256; i++)
3427 ptr[i] = SWAP32(0x2000);
3428 // B(5b) is special because games patch (sometimes even jump to)
3429 // code at fixed offsets from it, nocash lists offsets:
3430 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3431 // call: +7a0=4b70, +884=4c54, +894=4c64
3432 ptr[0x5b] = SWAP32(0x43d0);
3433 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra
3434 ram32[0x4c54/4] = SWAP32(0x03e00008); // jr $ra
3435 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3437 ptr = (u32 *)&psxM[A_C0_TABLE];
3438 for (i = 0; i < 256/2; i++)
3439 ptr[i] = SWAP32(0x3000);
3440 ptr[6] = SWAP32(A_EXCEPTION);
3443 ram32[0x1000/4] = HLEOP(hleop_dummy);
3444 ram32[0x2000/4] = HLEOP(hleop_dummy);
3445 ram32[0x3000/4] = HLEOP(hleop_dummy);
3446 ram32[0x4c54/4] = HLEOP(hleop_dummy); // for B12_InitPad?
3447 ram32[0x8000/4] = HLEOP(hleop_execret);
3449 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3450 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3451 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3452 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3453 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3454 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3457 void psxBiosShutdown() {
3460 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3461 if (tcb_cnt != 4 || evcb_cnt != 16)
3462 setup_tt(tcb_cnt, evcb_cnt);
3465 #define psxBios_PADpoll(pad) { \
3466 PAD##pad##_startPoll(pad); \
3467 pad_buf##pad[0] = 0; \
3468 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3469 if (!(pad_buf##pad[1] & 0x0f)) { \
3472 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3474 PAD##pad##_poll(0); \
3476 while (bufcount--) { \
3477 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3481 static void biosPadHLE() {
3484 if (pad_buf != NULL) {
3485 u32 *buf = (u32*)pad_buf;
3488 if (PAD1_poll(0x42) == 0x23) {
3490 *buf = PAD1_poll(0) << 8;
3491 *buf |= PAD1_poll(0);
3493 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3494 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3497 *buf = PAD1_poll(0) << 8;
3498 *buf|= PAD1_poll(0);
3502 if (PAD2_poll(0x42) == 0x23) {
3504 *buf |= PAD2_poll(0) << 24;
3505 *buf |= PAD2_poll(0) << 16;
3507 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3508 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3511 *buf |= PAD2_poll(0) << 24;
3512 *buf |= PAD2_poll(0) << 16;
3526 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3530 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3531 psxBios_ReturnFromException();
3537 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3538 // so this is only partially implemented
3539 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3541 u32 cdrom_dma_ack_enable = 1; // a000b93c
3542 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3545 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3548 //PSXBIOS_LOG("%s\n", __func__);
3550 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3551 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3552 //if (--cdrom_irq_counter == 0) // 0xa0009180
3553 // DeliverEvent(); // 0xf0000003, 0x10
3557 mips_return_c(ret, 20);
3560 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3562 u32 cdrom_irq_ack_enable = 1; // a000b938
3563 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3566 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3569 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3570 PSXBIOS_LOG("%s TODO\n", __func__);
3573 mips_return_c(ret, 20);
3576 void hleExc0_2_2_syscall() // not in any A/B/C table
3578 u32 code = (psxRegs.CP0.n.Cause & 0x3c) >> 2;
3579 u32 tcbPtr = loadRam32(A_TT_PCB);
3580 TCB *tcb = loadRam32ptr(tcbPtr);
3582 if (code != R3000E_Syscall) {
3584 // DeliverEvent(); // 0xf0000010, 0x1000
3585 psxBios_SystemErrorUnresolvedException();
3587 mips_return_c(0, 17);
3591 //printf("%s c=%d a0=%d\n", __func__, code, a0);
3592 tcb->epc += SWAP32(4);
3597 case 1: { // EnterCritical - disable irqs
3598 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3599 tcb->reg[2] = SWAP32(was_enabled);
3600 tcb->sr &= SWAP32(~0x404);
3603 case 2: // ExitCritical - enable irqs
3604 tcb->sr |= SWAP32(0x404);
3607 case 3: { // ChangeThreadSubFunction
3608 u32 tcbPtr = loadRam32(A_TT_PCB);
3609 storeRam32(tcbPtr, a1);
3613 // DeliverEvent(); // 0xf0000010, 0x4000
3617 psxBios_ReturnFromException();
3620 void hleExc1_0_1(void)
3622 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3623 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3626 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3629 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3630 // DeliverEvent 0xf2000000 + ev_index, 2
3631 if (RcEV[ev_index][1].status == EvStACTIVE) {
3632 softCall(RcEV[ev_index][1].fhandler);
3636 mips_return_c(ret, 22);
3639 void hleExc1_0_2(void)
3641 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3644 void hleExc1_1_1(void)
3646 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3647 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3650 void hleExc1_1_2(void)
3652 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3655 void hleExc1_2_1(void)
3657 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3658 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3661 void hleExc1_2_2(void)
3663 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3666 void hleExc1_3_1(void)
3668 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3669 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3672 void hleExc1_3_2(void)
3674 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3677 void hleExc3_0_2_defint(void)
3679 static const struct {
3690 { 6, 6 }, // rcnt2 (bug)
3695 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3696 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3697 // DeliverEvent 0xf0000000 + ev, 0x1000
3702 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3705 void psxBiosException() {
3706 u32 tcbPtr = loadRam32(A_TT_PCB);
3707 u32 *chains = loadRam32ptr(A_TT_ExCB);
3708 TCB *tcb = loadRam32ptr(tcbPtr);
3714 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3715 for (i = 4; i < 32; i++) {
3718 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3720 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3721 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3722 tcb->epc = SWAP32(psxRegs.CP0.n.EPC);
3723 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3724 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3725 sp = fp = loadRam32(A_EXC_SP);
3729 // do the chains (always 4)
3730 for (c = lim = 0; c < 4; c++) {
3731 if (chains[c * 2] == 0)
3733 ptr = SWAP32(chains[c * 2]);
3734 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3735 chain = castRam32ptr(ptr);
3740 softCallInException(SWAP32(chain[2]));
3741 if (returned_from_exception())
3744 if (v0 == 0 || chain[1] == 0)
3746 softCallInException(SWAP32(chain[1]));
3747 if (returned_from_exception())
3753 // TODO make this a chain entry
3754 if (psxHu32(0x1070) & 1)
3757 // return from exception (custom or default)
3759 ptr = loadRam32(A_EEXIT_PTR);
3760 if (ptr != A_EEXIT_DEF) {
3761 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3762 longjmp_load(jmp_buf);
3767 psxBios_ReturnFromException();
3770 #define bfreeze(ptr, size) { \
3771 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3772 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3776 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3777 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3779 #define bfreezepsxMptr(ptr, type) { \
3781 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3782 else psxRu32ref(base) = 0; \
3784 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3785 else (ptr) = NULL; \
3787 base += sizeof(u32); \
3790 void psxBiosFreeze(int Mode) {
3793 bfreezepsxMptr(pad_buf, int);
3794 bfreezepsxMptr(pad_buf1, char);
3795 bfreezepsxMptr(pad_buf2, char);
3796 bfreezepsxMptr(heap_addr, u32);
3797 bfreezel(&pad_buf1len);
3798 bfreezel(&pad_buf2len);
3800 bfreezel(&CardState);
3801 bfreezel(&CurThread);
3803 bfreezel(&card_active_chan);
3804 bfreezel(&pad_stopped);
3805 bfreezel(&heap_size);