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))
204 #define EvStUNUSED 0x0000
205 #define EvStDISABLED 0x1000
206 #define EvStACTIVE 0x2000
207 #define EvStALREADY 0x4000
209 #define EvMdCALL 0x1000
210 #define EvMdMARK 0x2000
233 u32 _sp, _fp, _gp, ret, base;
253 static int *pad_buf = NULL;
254 static char *pad_buf1 = NULL, *pad_buf2 = NULL;
255 static int pad_buf1len, pad_buf2len;
256 static int pad_stopped = 0;
257 static u32 heap_size = 0;
258 static u32 *heap_addr = NULL;
259 static u32 *heap_end = NULL;
260 static FileDesc FDesc[32];
261 static u32 card_active_chan = 0;
263 // fixed RAM offsets, SCPH1001 compatible
264 #define A_TT_ExCB 0x0100
265 #define A_TT_PCB 0x0108
266 #define A_TT_TCB 0x0110
267 #define A_TT_EvCB 0x0120
268 #define A_A0_TABLE 0x0200
269 #define A_B0_TABLE 0x0874
270 #define A_C0_TABLE 0x0674
271 #define A_SYSCALL 0x0650
272 #define A_EXCEPTION 0x0c80
273 #define A_EXC_SP 0x6cf0
274 #define A_EEXIT_DEF 0x6cf4
275 #define A_KMALLOC_PTR 0x7460
276 #define A_KMALLOC_SIZE 0x7464
277 #define A_KMALLOC_END 0x7468
278 #define A_EEXIT_PTR 0x75d0
279 #define A_EXC_STACK 0x85d8 // exception stack top
280 #define A_RCNT_VBL_ACK 0x8600
281 #define A_CD_EVENTS 0xb9b8
282 #define A_EXC_GP 0xf450
284 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
286 static u32 loadRam32(u32 addr)
288 assert(!(addr & 0x5f800000));
289 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
292 static void *castRam32ptr(u32 addr)
294 assert(!(addr & 0x5f800003));
295 return psxM + (addr & 0x1ffffc);
298 static void *loadRam32ptr(u32 addr)
300 return castRam32ptr(loadRam32(addr));
303 static void storeRam32(u32 addr, u32 d)
305 assert(!(addr & 0x5f800000));
306 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
309 static void mips_return(u32 val)
315 static void use_cycles(u32 cycle)
317 psxRegs.cycle += cycle * 2;
320 static void mips_return_c(u32 val, u32 cycle)
326 static void mips_return_void_c(u32 cycle)
332 static int returned_from_exception(void)
334 // 0x80000080 means it took another exception just after return
335 return pc0 == k0 || pc0 == 0x80000080;
338 static inline void softCall(u32 pc) {
340 u32 ssr = psxRegs.CP0.n.SR;
343 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
345 while (pc0 != 0x80001000)
346 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
349 psxRegs.CP0.n.SR = ssr;
352 static inline void softCallInException(u32 pc) {
357 while (!returned_from_exception() && pc0 != 0x80001000)
358 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
360 if (pc0 == 0x80001000)
364 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
365 static u32 DeliverEvent(u32 class, u32 spec);
366 static u32 UnDeliverEvent(u32 class, u32 spec);
367 static void CloseEvent(u32 ev);
372 // System calls A0 */
375 #define buread(Ra1, mcd, length) { \
376 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); \
377 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
378 memcpy(Ra1, ptr, length); \
379 if (FDesc[1 + mcd].mode & 0x8000) { \
380 DeliverEvent(0xf0000011, 0x0004); \
381 DeliverEvent(0xf4000001, 0x0004); \
384 FDesc[1 + mcd].offset += v0; \
387 #define buwrite(Ra1, mcd, length) { \
388 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
389 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
390 ptr = Mcd##mcd##Data + offset; \
391 memcpy(ptr, Ra1, length); \
392 FDesc[1 + mcd].offset += length; \
393 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
394 if (FDesc[1 + mcd].mode & 0x8000) { \
395 DeliverEvent(0xf0000011, 0x0004); \
396 DeliverEvent(0xf4000001, 0x0004); \
402 //#define PSXBIOS_LOG printf
403 #define PSXBIOS_LOG(...)
406 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
407 /* For some strange reason, the returned character is sign-expanded; */
408 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
409 /* TODO FIX ME : Properly implement this behaviour */
410 void psxBios_getc(void) // 0x03, 0x35
415 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
419 if (pa1 != INVALID_PTR) {
421 case 2: buread(pa1, 1, 1); break;
422 case 3: buread(pa1, 2, 1); break;
429 /* Copy of psxBios_write, except size is 1. */
430 void psxBios_putc(void) // 0x09, 0x3B
435 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
438 if (pa1 == INVALID_PTR) {
443 if (a0 == 1) { // stdout
444 char *ptr = (char *)pa1;
448 printf("%c", *ptr++); a2--;
454 case 2: buwrite(pa1, 1, 1); break;
455 case 3: buwrite(pa1, 2, 1); break;
461 void psxBios_todigit(void) // 0x0a
465 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
468 if (c >= 0x30 && c < 0x3A) {
471 else if (c > 0x60 && c < 0x7B) {
474 else if (c > 0x40 && c < 0x5B) {
477 else if (c >= 0x80) {
488 void psxBios_abs() { // 0x0e
489 if ((s32)a0 < 0) v0 = -(s32)a0;
494 void psxBios_labs() { // 0x0f
498 void psxBios_atoi() { // 0x10
500 char *p = (char *)Ra0;
504 case ' ': case '\t': continue;
511 while (*p >= '0' && *p <= '9') {
512 n = n * 10 + *p++ - '0';
519 void psxBios_atol() { // 0x11
529 static void psxBios_setjmp() { // 0x13
530 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
533 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
535 jmp_buf->ra_ = SWAP32(ra);
536 jmp_buf->sp_ = SWAP32(sp);
537 jmp_buf->fp_ = SWAP32(fp);
538 for (i = 0; i < 8; i++) // s0-s7
539 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
540 jmp_buf->gp_ = SWAP32(gp);
542 mips_return_c(0, 15);
545 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
549 ra = SWAP32(jmp_buf->ra_);
550 sp = SWAP32(jmp_buf->sp_);
551 fp = SWAP32(jmp_buf->fp_);
552 for (i = 0; i < 8; i++) // s0-s7
553 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
554 gp = SWAP32(jmp_buf->gp_);;
557 void psxBios_longjmp() { // 0x14
558 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
560 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
561 longjmp_load(jmp_buf);
562 mips_return_c(a1, 15);
565 void psxBios_strcat() { // 0x15
566 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
569 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
571 if (a0 == 0 || a1 == 0)
579 while ((*p1++ = *p2++) != '\0');
584 void psxBios_strncat() { // 0x16
585 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
589 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
591 if (a0 == 0 || a1 == 0)
599 while ((*p1++ = *p2++) != '\0') {
609 void psxBios_strcmp() { // 0x17
610 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
612 if (a0 == 0 && a1 == 0)
618 else if (a0 == 0 && a1 != 0)
624 else if (a0 != 0 && a1 == 0)
631 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
634 while (*p1 == *p2++) {
653 void psxBios_strncmp() { // 0x18
654 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
656 if (a0 == 0 && a1 == 0)
662 else if (a0 == 0 && a1 != 0)
668 else if (a0 != 0 && a1 == 0)
675 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
678 while (--n >= 0 && *p1 == *p2++) {
682 v1 = a2 - ((a2-n) - 1);
690 v0 = (n < 0 ? 0 : *p1 - *--p2);
692 v1 = a2 - ((a2-n) - 1);
698 void psxBios_strcpy() { // 0x19
699 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
700 if (a0 == 0 || a1 == 0)
706 while ((*p1++ = *p2++) != '\0');
711 void psxBios_strncpy() { // 0x1a
712 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
714 if (a0 == 0 || a1 == 0)
720 for (i = 0; i < n; i++) {
721 if ((*p1++ = *p2++) == '\0') {
733 void psxBios_strlen() { // 0x1b
734 char *p = (char *)Ra0;
745 void psxBios_index() { // 0x1c
746 char *p = (char *)Ra0;
756 v0 = a0 + (p - (char *)Ra0);
760 } while (*p++ != '\0');
765 void psxBios_rindex() { // 0x1d
766 char *p = (char *)Ra0;
776 v0 = a0 + (p - (char *)Ra0);
777 } while (*p++ != '\0');
782 void psxBios_strchr() { // 0x1e
786 void psxBios_strrchr() { // 0x1f
790 void psxBios_strpbrk() { // 0x20
791 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
793 while ((c = *p1++) != '\0') {
794 for (scanp = p2; (sc = *scanp++) != '\0';) {
796 v0 = a0 + (p1 - 1 - (char *)Ra0);
803 // BUG: return a0 instead of NULL if not found
807 void psxBios_strspn() { // 0x21
810 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
811 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
812 if (*p2 == '\0') break;
815 v0 = p1 - (char *)Ra0; pc0 = ra;
818 void psxBios_strcspn() { // 0x22
821 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
822 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
823 if (*p2 != '\0') break;
826 v0 = p1 - (char *)Ra0; pc0 = ra;
829 void psxBios_strtok() { // 0x23
830 char *pcA0 = (char *)Ra0;
831 char *pcRet = strtok(pcA0, (char *)Ra1);
833 v0 = a0 + pcRet - pcA0;
839 void psxBios_strstr() { // 0x24
840 char *p = (char *)Ra0, *p1, *p2;
846 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
851 v0 = a0 + (p - (char *)Ra0);
862 void psxBios_toupper() { // 0x25
863 v0 = (s8)(a0 & 0xff);
864 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
868 void psxBios_tolower() { // 0x26
869 v0 = (s8)(a0 & 0xff);
870 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
874 void psxBios_bcopy() { // 0x27
875 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
877 if (a0 == 0 || a2 > 0x7FFFFFFF)
882 while ((s32)a2-- > 0) *p1++ = *p2++;
887 void psxBios_bzero() { // 0x28
888 char *p = (char *)Ra0;
890 /* Same as memset here (See memset below) */
891 if (a1 > 0x7FFFFFFF || a1 == 0)
902 while ((s32)a1-- > 0) *p++ = '\0';
907 void psxBios_bcmp() { // 0x29
908 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
910 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
912 while ((s32)a2-- > 0) {
913 if (*p1++ != *p2++) {
914 v0 = *p1 - *p2; // BUG: compare the NEXT byte
923 void psxBios_memcpy() { // 0x2a
924 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
926 if (a0 == 0 || a2 > 0x7FFFFFFF)
931 while ((s32)a2-- > 0) {
938 void psxBios_memset() { // 0x2b
939 char *p = (char *)Ra0;
941 if (a2 > 0x7FFFFFFF || a2 == 0)
952 while ((s32)a2-- > 0) *p++ = (char)a1;
957 void psxBios_memmove() { // 0x2c
958 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
960 if (a0 == 0 || a2 > 0x7FFFFFFF)
965 if (p2 <= p1 && p2 + a2 > p1) {
966 a2++; // BUG: copy one more byte here
969 while ((s32)a2-- > 0) *--p1 = *--p2;
971 while ((s32)a2-- > 0) *p1++ = *p2++;
976 void psxBios_memcmp() { // 0x2d
980 void psxBios_memchr() { // 0x2e
981 char *p = (char *)Ra0;
983 if (a0 == 0 || a2 > 0x7FFFFFFF)
989 while ((s32)a2-- > 0) {
990 if (*p++ != (s8)a1) continue;
991 v0 = a0 + (p - (char *)Ra0 - 1);
999 void psxBios_rand() { // 0x2f
1000 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1001 v0 = (s >> 16) & 0x7fff;
1002 psxMu32ref(0x9010) = SWAPu32(s);
1006 void psxBios_srand() { // 0x30
1007 psxMu32ref(0x9010) = SWAPu32(a0);
1011 static u32 qscmpfunc, qswidth;
1013 static inline int qscmp(char *a, char *b) {
1016 a0 = sa0 + (a - (char *)PSXM(sa0));
1017 a1 = sa0 + (b - (char *)PSXM(sa0));
1019 softCall(qscmpfunc);
1025 static inline void qexchange(char *i, char *j) {
1036 static inline void q3exchange(char *i, char *j, char *k) {
1048 static void qsort_main(char *a, char *l) {
1049 char *i, *j, *lp, *hp;
1054 if ((n = l - a) <= qswidth)
1056 n = qswidth * (n / (2 * qswidth));
1062 if ((c = qscmp(i, lp)) == 0) {
1063 qexchange(i, lp -= qswidth);
1074 if ((c = qscmp(hp, j)) == 0) {
1075 qexchange(hp += qswidth, j);
1080 q3exchange(i, hp += qswidth, j);
1094 if (lp - a >= l - hp) {
1095 qsort_main(hp + qswidth, l);
1104 q3exchange(j, lp -= qswidth, i);
1109 void psxBios_qsort() { // 0x31
1112 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1117 void psxBios_malloc() { // 0x33
1118 u32 *chunk, *newchunk = NULL;
1119 unsigned int dsize = 0, csize, cstat;
1122 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1124 if (!a0 || (!heap_size || !heap_addr)) {
1130 // scan through heap and combine free chunks of space
1133 while(chunk < heap_end) {
1134 // get size and status of actual chunk
1135 csize = ((u32)*chunk) & 0xfffffffc;
1136 cstat = ((u32)*chunk) & 1;
1138 // most probably broken heap descriptor
1139 // this fixes Burning Road
1142 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1147 // it's a free chunk
1152 colflag = 1; // let's begin a new collection of free memory
1154 else dsize += (csize+4); // add the new size including header
1156 // not a free chunk: did we start a collection ?
1158 if(colflag == 1) { // collection is over
1160 *newchunk = SWAP32(dsize | 1);
1165 chunk = (u32*)((uptr)chunk + csize + 4);
1167 // if neccessary free memory on end of heap
1169 *newchunk = SWAP32(dsize | 1);
1172 csize = ((u32)*chunk) & 0xfffffffc;
1173 cstat = ((u32)*chunk) & 1;
1174 dsize = (a0 + 3) & 0xfffffffc;
1176 // exit on uninitialized heap
1177 if (chunk == NULL) {
1178 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1184 // search an unused chunk that is big enough until the end of the heap
1185 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1186 chunk = (u32*)((uptr)chunk + csize + 4);
1188 // catch out of memory
1189 if(chunk >= heap_end) {
1190 printf("malloc %x,%x: Out of memory error!\n",
1196 csize = ((u32)*chunk) & 0xfffffffc;
1197 cstat = ((u32)*chunk) & 1;
1201 if(dsize == csize) {
1202 // chunk has same size
1203 *chunk &= 0xfffffffc;
1204 } else if (dsize > csize) {
1209 *chunk = SWAP32(dsize);
1210 newchunk = (u32*)((uptr)chunk + dsize + 4);
1211 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1214 // return pointer to allocated memory
1215 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1217 //printf ("malloc %x,%x\n", v0, a0);
1221 void psxBios_free() { // 0x34
1224 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1227 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1230 *(u32*)(Ra0-4) |= 1; // set chunk to free
1234 void psxBios_calloc() { // 0x37
1237 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1247 void psxBios_realloc() { // 0x38
1251 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1255 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1260 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1265 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1266 /* Note that it is not quite implemented this way here. */
1276 /* InitHeap(void *block , int n) */
1277 void psxBios_InitHeap() { // 0x39
1281 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1284 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1289 heap_addr = (u32 *)Ra0;
1291 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1292 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1293 //*heap_addr = SWAP32(size | 1);
1295 SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1300 void psxBios_getchar() { //0x3b
1301 v0 = getchar(); pc0 = ra;
1304 static void psxBios_printf_psxout() { // 0x3f
1313 if (psp != INVALID_PTR) {
1314 memcpy(save, psp, 4 * 4);
1315 psxMu32ref(sp) = SWAP32((u32)a0);
1316 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1317 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1318 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1330 tmp2[j++] = Ra0[i]; goto _start;
1332 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1343 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1347 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1353 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1355 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1357 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1359 *ptmp++ = Ra0[i]; break;
1369 if (psp != INVALID_PTR)
1370 memcpy(psp, save, 4 * 4);
1372 SysPrintf("%s", tmp);
1375 void psxBios_printf() { // 0x3f
1376 psxBios_printf_psxout();
1380 void psxBios_format() { // 0x41
1381 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1383 CreateMcd(Config.Mcd1);
1384 LoadMcd(1, Config.Mcd1);
1387 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1389 CreateMcd(Config.Mcd2);
1390 LoadMcd(2, Config.Mcd2);
1400 static void psxBios_SystemErrorUnresolvedException() {
1401 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1402 SysPrintf("psxBios_%s\n", biosA0n[0x40]);
1403 storeRam32(0xfffc, 0x12345678);
1405 mips_return_void_c(1000);
1409 * long Load(char *name, struct EXEC *header);
1412 void psxBios_Load() { // 0x42
1417 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1418 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1421 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1427 * int Exec(struct EXEC *header , int argc , char **argv);
1430 void psxBios_Exec() { // 43
1431 EXEC *header = (EXEC*)Ra0;
1435 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1445 if (header->S_addr != 0) {
1446 tmp = header->S_addr + header->s_size;
1462 void psxBios_FlushCache() { // 44
1464 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1466 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1467 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1471 void psxBios_GPU_dw() { // 0x46
1476 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1479 GPU_writeData(0xa0000000);
1480 GPU_writeData((a1<<0x10)|(a0&0xffff));
1481 GPU_writeData((a3<<0x10)|(a2&0xffff));
1483 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1486 GPU_writeData(SWAPu32(*ptr++));
1492 void psxBios_mem2vram() { // 0x47
1495 GPU_writeData(0xa0000000);
1496 GPU_writeData((a1<<0x10)|(a0&0xffff));
1497 GPU_writeData((a3<<0x10)|(a2&0xffff));
1498 size = ((((a2 * a3) / 2) >> 4) << 16);
1499 GPU_writeStatus(0x04000002);
1500 psxHwWrite32(0x1f8010f4,0);
1501 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1502 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1503 psxHwWrite32(0x1f8010a4, size | 0x10);
1504 psxHwWrite32(0x1f8010a8,0x01000201);
1509 void psxBios_SendGPU() { // 0x48
1510 GPU_writeStatus(a0);
1515 void psxBios_GPU_cw() { // 0x49
1522 void psxBios_GPU_cwb() { // 0x4a
1523 u32 *ptr = (u32*)Ra0;
1528 GPU_writeData(SWAPu32(*ptr++));
1534 void psxBios_GPU_SendPackets() { //4b:
1536 GPU_writeStatus(0x04000002);
1537 psxHwWrite32(0x1f8010f4,0);
1538 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1539 psxHwWrite32(0x1f8010a0,a0);
1540 psxHwWrite32(0x1f8010a4,0);
1541 psxHwWrite32(0x1f8010a8,0x010000401);
1545 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1546 psxHwWrite32(0x1f8010a8,0x00000401);
1547 GPU_writeData(0x0400000);
1548 GPU_writeData(0x0200000);
1549 GPU_writeData(0x0100000);
1554 void psxBios_GPU_GetGPUStatus() { // 0x4d
1555 v0 = GPU_readStatus();
1561 void psxBios_LoadExec() { // 51
1562 EXEC *header = (EXEC*)PSXM(0xf000);
1566 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1568 s_addr = a1; s_size = a2;
1573 header->S_addr = s_addr;
1574 header->s_size = s_size;
1576 a0 = 0xf000; a1 = 0; a2 = 0;
1580 void psxBios__bu_init() { // 70
1582 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1585 DeliverEvent(0xf0000011, 0x0004);
1586 DeliverEvent(0xf4000001, 0x0004);
1591 void psxBios__96_init() { // 71
1593 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1599 static void psxBios_SysDeqIntRP_();
1601 static void psxBios_DequeueCdIntr_() {
1602 a0 = 0; a1 = 0x91d0;
1603 psxBios_SysDeqIntRP_();
1604 a0 = 0; a1 = 0x91e0;
1605 psxBios_SysDeqIntRP_();
1609 static void psxBios_DequeueCdIntr() { // a3
1610 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1611 psxBios_DequeueCdIntr_();
1614 static void psxBios_CdRemove() { // 56, 72
1615 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1617 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1618 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1619 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1620 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1621 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1622 psxBios_DequeueCdIntr_();
1624 // EnterCriticalSection - should be done at the beginning,
1625 // but this way is much easier to implement
1631 void psxBios_SetMem() { // 9f
1632 u32 new = psxHu32(0x1060);
1635 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1640 psxHu32ref(0x1060) = SWAP32(new);
1641 psxMu32ref(0x060) = a0;
1642 SysPrintf("Change effective memory : %d MBytes\n",a0);
1646 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1647 psxMu32ref(0x060) = a0;
1648 SysPrintf("Change effective memory : %d MBytes\n",a0);
1651 SysPrintf("Effective memory must be 2/8 MBytes\n");
1658 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1659 void psxBios_get_cd_status(void) //a6
1665 void psxBios__card_info() { // ab
1667 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1670 card_active_chan = a0;
1671 port = card_active_chan >> 4;
1677 if (McdDisable[port & 1])
1682 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1688 if (McdDisable[0] && McdDisable[1])
1691 DeliverEvent(0xf0000011, 0x0004);
1692 // DeliverEvent(0xf4000001, 0x0004);
1693 DeliverEvent(0xf4000001, ret);
1697 void psxBios__card_load() { // ac
1699 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1702 card_active_chan = a0;
1704 // DeliverEvent(0xf0000011, 0x0004);
1705 DeliverEvent(0xf4000001, 0x0004);
1710 /* System calls B0 */
1712 static u32 psxBios_SysMalloc_(u32 size);
1714 static void psxBios_SysMalloc() { // B 00
1715 u32 ret = psxBios_SysMalloc_(a0);
1717 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1718 mips_return_c(ret, 33);
1721 void psxBios_SetRCnt() { // 02
1723 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1730 psxRcntWtarget(a0, a1);
1731 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1732 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1733 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1734 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1735 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1737 psxRcntWmode(a0, mode);
1742 void psxBios_GetRCnt() { // 03
1744 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1748 if (a0 != 3) v0 = psxRcntRcount(a0);
1753 void psxBios_StartRCnt() { // 04
1755 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1759 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1760 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1764 void psxBios_StopRCnt() { // 05
1766 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1770 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1771 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1775 void psxBios_ResetRCnt() { // 06
1777 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1782 psxRcntWmode(a0, 0);
1783 psxRcntWtarget(a0, 0);
1784 psxRcntWcount(a0, 0);
1789 static u32 DeliverEvent(u32 class, u32 spec) {
1790 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1791 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1792 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1793 u32 i, lim = evcb_len / 0x1c;
1795 for (i = 0; i < lim; i++, ev++) {
1797 if (SWAP32(ev->status) != EvStACTIVE)
1800 if (SWAP32(ev->class) != class)
1803 if (SWAP32(ev->spec) != spec)
1806 ret = SWAP32(ev->mode);
1807 if (ret == EvMdMARK) {
1808 ev->status = SWAP32(EvStALREADY);
1812 if (ret == EvMdCALL) {
1813 ret = SWAP32(ev->fhandler);
1825 static u32 UnDeliverEvent(u32 class, u32 spec) {
1826 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1827 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1828 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1829 u32 i, lim = evcb_len / 0x1c;
1831 for (i = 0; i < lim; i++, ev++) {
1833 if (SWAP32(ev->status) != EvStALREADY)
1836 if (SWAP32(ev->class) != class)
1839 if (SWAP32(ev->spec) != spec)
1842 if (SWAP32(ev->mode) == EvMdMARK)
1843 ev->status = SWAP32(EvStACTIVE);
1849 static void psxBios_DeliverEvent() { // 07
1851 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1853 ret = DeliverEvent(a0, a1);
1857 static s32 get_free_EvCB_slot() {
1858 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1859 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1862 for (i = 0; i < lim; i++, ev++) {
1864 if (ev->status == SWAP32(EvStUNUSED))
1870 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
1871 u32 ret = get_free_EvCB_slot();
1872 if ((s32)ret >= 0) {
1873 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
1874 ev->class = SWAP32(class);
1875 ev->status = SWAP32(EvStDISABLED);
1876 ev->spec = SWAP32(spec);
1877 ev->mode = SWAP32(mode);
1878 ev->fhandler = SWAP32(func);
1884 static void psxBios_OpenEvent() { // 08
1885 u32 ret = OpenEvent(a0, a1, a2, a3);
1886 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
1887 biosB0n[0x08], a0, a1, a2, a3, ret);
1888 mips_return_c(ret, 36);
1891 static void CloseEvent(u32 ev)
1893 u32 base = loadRam32(A_TT_EvCB);
1894 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
1897 static void psxBios_CloseEvent() { // 09
1898 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
1899 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
1901 mips_return_c(1, 10);
1904 static void psxBios_WaitEvent() { // 0a
1905 u32 base = loadRam32(A_TT_EvCB);
1906 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1907 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
1910 if (status == EvStALREADY) {
1911 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1915 if (status != EvStACTIVE)
1917 mips_return_c(0, 2);
1921 // retrigger this hlecall after the next emulation event
1923 if ((s32)(next_interupt - psxRegs.cycle) > 0)
1924 psxRegs.cycle = next_interupt;
1928 static void psxBios_TestEvent() { // 0b
1929 u32 base = loadRam32(A_TT_EvCB);
1930 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1932 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
1933 if (status == EvStALREADY) {
1934 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1938 mips_return_c(ret, 15);
1941 static void psxBios_EnableEvent() { // 0c
1942 u32 base = loadRam32(A_TT_EvCB);
1943 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1944 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
1945 if (status != EvStUNUSED)
1946 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1948 mips_return_c(1, 15);
1951 static void psxBios_DisableEvent() { // 0d
1952 u32 base = loadRam32(A_TT_EvCB);
1953 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1954 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
1955 if (status != EvStUNUSED)
1956 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
1958 mips_return_c(1, 15);
1962 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1965 void psxBios_OpenTh() { // 0e
1966 TCB *tcb = loadRam32ptr(A_TT_TCB);
1967 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
1970 for (th = 1; th < limit; th++)
1972 if (tcb[th].status != SWAP32(0x4000)) break;
1976 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1977 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1979 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1981 mips_return_c(0xffffffff, 20);
1984 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1986 tcb[th].status = SWAP32(0x4000);
1987 tcb[th].mode = SWAP32(0x1000);
1988 tcb[th].epc = SWAP32(a0);
1989 tcb[th].reg[30] = SWAP32(a1); // fp
1990 tcb[th].reg[29] = SWAP32(a1); // sp
1991 tcb[th].reg[28] = SWAP32(a2); // gp
1993 mips_return_c(0xff000000 + th, 34);
1997 * int CloseTh(long thread);
2000 void psxBios_CloseTh() { // 0f
2001 TCB *tcb = loadRam32ptr(A_TT_TCB);
2002 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2006 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2008 /* The return value is always 1 (even if the handle was already closed). */
2010 if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2011 tcb[th].status = SWAP32(0x1000);
2018 * int ChangeTh(long thread);
2021 void psxBios_ChangeTh() { // 10
2022 u32 tcbBase = loadRam32(A_TT_TCB);
2023 u32 th = a0 & 0xffff;
2026 // PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
2028 // without doing any argument checks, just issue a syscall
2029 // (like the real bios does)
2031 a1 = tcbBase + th * sizeof(TCB);
2036 void psxBios_InitPAD() { // 0x12
2038 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
2041 pad_buf1 = (char*)Ra0;
2043 pad_buf2 = (char*)Ra2;
2049 void psxBios_StartPAD() { // 13
2051 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2054 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
2055 psxRegs.CP0.n.SR |= 0x401;
2059 void psxBios_StopPAD() { // 14
2061 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2069 void psxBios_PAD_init() { // 15
2071 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2073 if (!(a0 == 0x20000000 || a0 == 0x20000001))
2079 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
2080 pad_buf = (int *)Ra1;
2082 psxRegs.CP0.n.SR |= 0x401;
2087 void psxBios_PAD_dr() { // 16
2089 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2095 static void psxBios_ReturnFromException() { // 17
2096 u32 tcbPtr = loadRam32(A_TT_PCB);
2097 const TCB *tcb = loadRam32ptr(tcbPtr);
2100 for (i = 1; i < 32; i++)
2101 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2102 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2103 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2104 psxRegs.CP0.n.SR = SWAP32(tcb->sr);
2106 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2107 pc0 = k0 = SWAP32(tcb->epc);
2109 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
2114 void psxBios_ResetEntryInt() { // 18
2115 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2117 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2118 mips_return_void_c(5);
2121 void psxBios_HookEntryInt() { // 19
2122 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2124 storeRam32(A_EEXIT_PTR, a0);
2125 mips_return_void_c(3);
2128 static void psxBios_UnDeliverEvent() { // 0x20
2130 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2132 ret = UnDeliverEvent(a0, a1);
2136 char ffile[64], *pfile;
2139 static void buopen(int mcd, char *ptr, char *cfg)
2142 char *mcd_data = ptr;
2144 strcpy(FDesc[1 + mcd].name, Ra0+5);
2145 FDesc[1 + mcd].offset = 0;
2146 FDesc[1 + mcd].mode = a1;
2148 for (i=1; i<16; i++) {
2149 const char *fptr = mcd_data + 128 * i;
2150 if ((*fptr & 0xF0) != 0x50) continue;
2151 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2152 FDesc[1 + mcd].mcfile = i;
2153 SysPrintf("open %s\n", fptr+0xa);
2157 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2158 for (i=1; i<16; i++) {
2159 int j, xor, nblk = a1 >> 16;
2161 char *fptr = mcd_data + 128 * i;
2163 if ((*fptr & 0xF0) != 0xa0) continue;
2165 FDesc[1 + mcd].mcfile = i;
2168 fptr[5] = 0x20 * nblk;
2171 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2172 pptr = fptr2 = fptr;
2173 for(j=2; j<=nblk; j++) {
2175 for(i++; i<16; i++) {
2178 memset(fptr2, 0, 128);
2179 fptr2[0] = j < nblk ? 0x52 : 0x53;
2182 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2187 /* shouldn't this return ENOSPC if i == 16? */
2189 pptr[8] = pptr[9] = 0xff;
2190 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2192 SysPrintf("openC %s %d\n", ptr, nblk);
2194 /* just go ahead and resave them all */
2195 SaveMcd(cfg, ptr, 128, 128 * 15);
2198 /* shouldn't this return ENOSPC if i == 16? */
2203 * int open(char *name , int mode);
2206 void psxBios_open() { // 0x32
2210 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2215 if (pa0 != INVALID_PTR) {
2216 if (!strncmp(pa0, "bu00", 4)) {
2217 buopen(1, Mcd1Data, Config.Mcd1);
2220 if (!strncmp(pa0, "bu10", 4)) {
2221 buopen(2, Mcd2Data, Config.Mcd2);
2229 * int lseek(int fd , int offset , int whence);
2232 void psxBios_lseek() { // 0x33
2234 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2239 FDesc[a0].offset = a1;
2241 // DeliverEvent(0xf0000011, 0x0004);
2242 // DeliverEvent(0xf4000001, 0x0004);
2246 FDesc[a0].offset+= a1;
2247 v0 = FDesc[a0].offset;
2256 * int read(int fd , void *buf , int nbytes);
2259 void psxBios_read() { // 0x34
2264 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2269 if (pa1 != INVALID_PTR) {
2271 case 2: buread(pa1, 1, a2); break;
2272 case 3: buread(pa1, 2, a2); break;
2280 * int write(int fd , void *buf , int nbytes);
2283 void psxBios_write() { // 0x35/0x03
2288 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2292 if (pa1 == INVALID_PTR) {
2297 if (a0 == 1) { // stdout
2302 SysPrintf("%c", *ptr++); a2--;
2308 case 2: buwrite(pa1, 1, a2); break;
2309 case 3: buwrite(pa1, 2, a2); break;
2315 static void psxBios_write_psxout() {
2316 if (a0 == 1) { // stdout
2317 const char *ptr = Ra1;
2320 if (ptr != INVALID_PTR)
2322 SysPrintf("%c", *ptr++);
2326 static void psxBios_putchar_psxout() { // 3d
2327 SysPrintf("%c", (char)a0);
2330 static void psxBios_puts_psxout() { // 3e/3f
2331 SysPrintf("%s", Ra0);
2335 * int close(int fd);
2338 void psxBios_close() { // 0x36
2340 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2347 void psxBios_putchar() { // 3d
2348 SysPrintf("%c", (char)a0);
2352 void psxBios_puts() { // 3e/3f
2353 SysPrintf("%s", Ra0);
2358 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2359 * We want to mimic the PSX's behaviour in this case for bufile. */
2360 static size_t strlen_internal(char* p)
2362 size_t size_of_array = 0;
2363 while (*p++) size_of_array++;
2364 return size_of_array;
2367 #define bufile(mcd) { \
2368 size_t size_of_name = strlen_internal(dir->name); \
2369 while (nfile < 16) { \
2372 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2374 if ((*ptr & 0xF0) != 0x50) continue; \
2375 /* Bug link files show up as free block. */ \
2376 if (!ptr[0xa]) continue; \
2378 if (pfile[0] == 0) { \
2379 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2380 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2381 } else for (i=0; i<20; i++) { \
2382 if (pfile[i] == ptr[i]) { \
2383 dir->name[i] = ptr[i]; continue; } \
2384 if (pfile[i] == '?') { \
2385 dir->name[i] = ptr[i]; continue; } \
2386 if (pfile[i] == '*') { \
2387 strcpy(dir->name+i, ptr+i); break; } \
2390 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2391 if (match == 0) { continue; } \
2399 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2402 void psxBios_firstfile() { // 42
2403 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2410 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2415 if (pa0 != INVALID_PTR) {
2419 if (!strncmp(pa0, "bu00", 4)) {
2420 // firstfile() calls _card_read() internally, so deliver it's event
2421 DeliverEvent(0xf0000011, 0x0004);
2423 } else if (!strncmp(pa0, "bu10", 4)) {
2424 // firstfile() calls _card_read() internally, so deliver it's event
2425 DeliverEvent(0xf0000011, 0x0004);
2434 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2437 void psxBios_nextfile() { // 43
2438 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2444 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2449 if (!strncmp(ffile, "bu00", 4)) {
2453 if (!strncmp(ffile, "bu10", 4)) {
2460 #define burename(mcd) { \
2461 for (i=1; i<16; i++) { \
2462 int namelen, j, xor = 0; \
2463 ptr = Mcd##mcd##Data + 128 * i; \
2464 if ((*ptr & 0xF0) != 0x50) continue; \
2465 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2466 namelen = strlen(Ra1+5); \
2467 memcpy(ptr+0xa, Ra1+5, namelen); \
2468 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2469 for (j=0; j<127; j++) xor^= ptr[j]; \
2471 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2478 * int rename(char *old, char *new);
2481 void psxBios_rename() { // 44
2488 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2493 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2494 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2498 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2507 #define budelete(mcd) { \
2508 for (i=1; i<16; i++) { \
2509 ptr = Mcd##mcd##Data + 128 * i; \
2510 if ((*ptr & 0xF0) != 0x50) continue; \
2511 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2512 *ptr = (*ptr & 0xf) | 0xA0; \
2513 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2514 SysPrintf("delete %s\n", ptr+0xa); \
2521 * int delete(char *name);
2524 void psxBios_delete() { // 45
2530 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2535 if (pa0 != INVALID_PTR) {
2536 if (!strncmp(pa0, "bu00", 4)) {
2540 if (!strncmp(pa0, "bu10", 4)) {
2548 void psxBios_InitCARD() { // 4a
2550 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2556 void psxBios_StartCARD() { // 4b
2558 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2564 void psxBios_StopCARD() { // 4c
2566 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2572 void psxBios__card_write() { // 0x4e
2577 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2580 Function also accepts sector 400h (a bug).
2581 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2585 /* Invalid sectors */
2589 card_active_chan = a0;
2592 if (pa2 != INVALID_PTR) {
2594 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2595 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2597 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2598 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2602 DeliverEvent(0xf0000011, 0x0004);
2603 // DeliverEvent(0xf4000001, 0x0004);
2608 void psxBios__card_read() { // 0x4f
2613 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2616 Function also accepts sector 400h (a bug).
2617 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2621 /* Invalid sectors */
2625 card_active_chan = a0;
2628 if (pa2 != INVALID_PTR) {
2630 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2632 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2636 DeliverEvent(0xf0000011, 0x0004);
2637 // DeliverEvent(0xf4000001, 0x0004);
2642 void psxBios__new_card() { // 0x50
2644 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2650 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2651 void psxBios__get_error(void) // 55
2653 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2658 void psxBios_Krom2RawAdd() { // 0x51
2661 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2662 const u32 table_8140[][2] = {
2663 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2664 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2665 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2666 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2667 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2668 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2669 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2670 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2671 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2675 const u32 table_889f[][2] = {
2676 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2677 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2678 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2679 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2680 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2681 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2682 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2683 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2687 if (a0 >= 0x8140 && a0 <= 0x84be) {
2688 while (table_8140[i][0] <= a0) i++;
2689 a0 -= table_8140[i - 1][0];
2690 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2691 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2692 while (table_889f[i][0] <= a0) i++;
2693 a0 -= table_889f[i - 1][0];
2694 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2702 void psxBios_GetC0Table() { // 56
2703 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2704 log_unhandled("GetC0Table @%08x\n", ra);
2706 mips_return_c(A_C0_TABLE, 3);
2709 void psxBios_GetB0Table() { // 57
2710 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2711 log_unhandled("GetB0Table @%08x\n", ra);
2713 mips_return_c(A_B0_TABLE, 3);
2716 void psxBios__card_chan() { // 0x58
2718 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2721 v0 = card_active_chan;
2725 void psxBios_ChangeClearPad() { // 5b
2727 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2733 void psxBios__card_status() { // 5c
2735 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2738 v0 = card_active_chan;
2742 void psxBios__card_wait() { // 5d
2744 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2751 /* System calls C0 */
2753 static void psxBios_SysEnqIntRP();
2755 static void psxBios_InitRCnt() { // 00
2757 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2758 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2759 for (i = 0; i < 3; i++) {
2760 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2761 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2762 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2765 psxBios_SysEnqIntRP();
2766 mips_return_c(0, 9);
2769 static void psxBios_InitException() { // 01
2770 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2772 psxBios_SysEnqIntRP();
2773 mips_return_c(0, 9);
2777 * int SysEnqIntRP(int index , long *queue);
2780 static void psxBios_SysEnqIntRP() { // 02
2781 u32 old, base = loadRam32(A_TT_ExCB);
2782 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2784 old = loadRam32(base + (a0 << 3));
2785 storeRam32(base + (a0 << 3), a1);
2786 storeRam32(a1, old);
2787 mips_return_c(0, 9);
2791 * int SysDeqIntRP(int index , long *queue);
2794 static void psxBios_SysDeqIntRP_() { // 03
2795 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2796 u32 lim = 0, ret = 0;
2798 // as in original: no arg checks of any kind, bug if a1 == 0
2799 ptr = loadRam32(base + (a0 << 3));
2801 next = loadRam32(ptr);
2803 storeRam32(base + (a0 << 3), next);
2808 while (next && next != a1 && lim++ < 100) {
2810 next = loadRam32(ptr);
2814 next = loadRam32(next);
2815 storeRam32(ptr, next);
2822 PSXBIOS_LOG("bad chain %u %x\n", a0, base);
2824 mips_return_c(ret, 12);
2827 static void psxBios_SysDeqIntRP() { // 03
2828 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2829 psxBios_SysDeqIntRP_();
2832 static void psxBios_get_free_EvCB_slot() { // 04
2833 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
2834 s32 ret = get_free_EvCB_slot();
2835 mips_return_c(ret, 0);
2838 static void psxBios_SysInitMemory_(u32 base, u32 size) {
2839 storeRam32(base, 0);
2840 storeRam32(A_KMALLOC_PTR, base);
2841 storeRam32(A_KMALLOC_SIZE, size);
2842 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2845 // this should be much more complicated, but maybe that'll be enough
2846 static u32 psxBios_SysMalloc_(u32 size) {
2847 u32 ptr = loadRam32(A_KMALLOC_PTR);
2849 size = (size + 3) & ~3;
2850 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2851 storeRam32(ptr, size);
2855 static void psxBios_SysInitMemory() { // 08
2856 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2858 psxBios_SysInitMemory_(a0, a1);
2859 mips_return_void_c(12);
2862 static void psxBios_ChangeClearRCnt() { // 0a
2865 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2867 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
2868 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
2869 mips_return_c(ret, 8);
2872 static void psxBios_InitDefInt() { // 0c
2873 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
2874 // should also clear the autoack table
2876 psxBios_SysEnqIntRP();
2877 mips_return_c(0, 20 + 6*2);
2880 void psxBios_dummy() {
2881 u32 pc = (pc0 & 0x1fffff) - 4;
2882 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
2883 : pc == 0xc0 ? biosC0n : NULL;
2884 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
2885 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
2886 (void)pc; (void)ntab;
2887 mips_return_c(0, 100);
2890 void (*biosA0[256])();
2891 // C0 and B0 overlap (end of C0 is start of B0)
2892 void (*biosC0[256+128])();
2893 void (**biosB0)() = biosC0 + 128;
2895 #include "sjisfont.h"
2897 void setup_mips_code()
2900 ptr = (u32 *)&psxM[A_SYSCALL];
2901 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
2902 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
2903 ptr[0x08/4] = SWAPu32(0x00000000); // nop
2905 ptr = (u32 *)&psxM[A_EXCEPTION];
2906 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
2907 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
2908 ptr[0x14/4] = SWAPu32(0x00000000); // nop
2909 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
2910 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
2911 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
2912 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
2913 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
2914 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
2915 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
2917 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
2918 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
2919 ptr[0x68/4] = SWAPu32(0x24630004); // addiu $v1, $v1, 4
2920 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
2922 ptr[0xb0/4] = HLEOP(hleop_exception);
2925 static const struct {
2929 { 0xbfc050a4, hleop_exc0_0_1 },
2930 { 0xbfc04fbc, hleop_exc0_0_2 },
2931 { 0xbfc0506c, hleop_exc0_1_1 },
2932 { 0xbfc04dec, hleop_exc0_1_2 },
2933 { 0x1a00, hleop_exc0_2_2 },
2934 { 0x19c8, hleop_exc1_0_1 },
2935 { 0x18bc, hleop_exc1_0_2 },
2936 { 0x1990, hleop_exc1_1_1 },
2937 { 0x1858, hleop_exc1_1_2 },
2938 { 0x1958, hleop_exc1_2_1 },
2939 { 0x17f4, hleop_exc1_2_2 },
2940 { 0x1920, hleop_exc1_3_1 },
2941 { 0x1794, hleop_exc1_3_2 },
2942 { 0x2458, hleop_exc3_0_2 },
2945 static int chain_hle_op(u32 handler)
2949 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
2950 if (chainfns[i].addr == handler)
2951 return chainfns[i].op;
2955 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
2957 d[0] = SWAPu32(next);
2958 d[1] = SWAPu32(handler1);
2959 d[2] = SWAPu32(handler2);
2961 // install hle traps
2962 PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
2963 PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
2966 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
2968 u32 *ram32 = (u32 *)psxM;
2969 u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
2970 u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
2971 u32 p_excb, p_evcb, p_pcb, p_tcb;
2973 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
2974 psxBios_SysInitMemory_(0xa000e000, 0x2000);
2975 p_excb = psxBios_SysMalloc_(s_excb);
2976 p_evcb = psxBios_SysMalloc_(s_evcb);
2977 p_pcb = psxBios_SysMalloc_(s_pcb);
2978 p_tcb = psxBios_SysMalloc_(s_tcb);
2980 // "table of tables". Some games modify it
2981 assert(A_TT_ExCB == 0x0100);
2982 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
2983 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
2984 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
2985 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
2986 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
2987 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
2988 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
2989 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
2990 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
2991 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
2992 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
2993 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
2995 storeRam32(p_excb + 0*4, 0x91e0); // chain0
2996 storeRam32(p_excb + 2*4, 0x6d88); // chain1
2997 storeRam32(p_excb + 4*4, 0x0000); // chain2
2998 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3000 storeRam32(p_pcb, p_tcb);
3001 storeRam32(p_tcb, 0x4000); // first TCB
3004 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3005 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3006 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3007 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3008 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3009 DeliverEvent(0xf0000003, 0x0010);
3012 void psxBiosInit() {
3013 u32 *ptr, *ram32, *rom32;
3017 memset(psxM, 0, 0x10000);
3018 for(i = 0; i < 256; i++) {
3023 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3024 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3025 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3026 biosA0[0x3f] = psxBios_printf_psxout;
3028 if (!Config.HLE) return;
3030 for(i = 0; i < 256; i++) {
3031 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3032 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3033 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3036 biosA0[0x00] = psxBios_open;
3037 biosA0[0x01] = psxBios_lseek;
3038 biosA0[0x02] = psxBios_read;
3039 biosA0[0x03] = psxBios_write;
3040 biosA0[0x04] = psxBios_close;
3041 //biosA0[0x05] = psxBios_ioctl;
3042 //biosA0[0x06] = psxBios_exit;
3043 //biosA0[0x07] = psxBios_sys_a0_07;
3044 biosA0[0x08] = psxBios_getc;
3045 biosA0[0x09] = psxBios_putc;
3046 biosA0[0x0a] = psxBios_todigit;
3047 //biosA0[0x0b] = psxBios_atof;
3048 //biosA0[0x0c] = psxBios_strtoul;
3049 //biosA0[0x0d] = psxBios_strtol;
3050 biosA0[0x0e] = psxBios_abs;
3051 biosA0[0x0f] = psxBios_labs;
3052 biosA0[0x10] = psxBios_atoi;
3053 biosA0[0x11] = psxBios_atol;
3054 //biosA0[0x12] = psxBios_atob;
3055 biosA0[0x13] = psxBios_setjmp;
3056 biosA0[0x14] = psxBios_longjmp;
3057 biosA0[0x15] = psxBios_strcat;
3058 biosA0[0x16] = psxBios_strncat;
3059 biosA0[0x17] = psxBios_strcmp;
3060 biosA0[0x18] = psxBios_strncmp;
3061 biosA0[0x19] = psxBios_strcpy;
3062 biosA0[0x1a] = psxBios_strncpy;
3063 biosA0[0x1b] = psxBios_strlen;
3064 biosA0[0x1c] = psxBios_index;
3065 biosA0[0x1d] = psxBios_rindex;
3066 biosA0[0x1e] = psxBios_strchr;
3067 biosA0[0x1f] = psxBios_strrchr;
3068 biosA0[0x20] = psxBios_strpbrk;
3069 biosA0[0x21] = psxBios_strspn;
3070 biosA0[0x22] = psxBios_strcspn;
3071 biosA0[0x23] = psxBios_strtok;
3072 biosA0[0x24] = psxBios_strstr;
3073 biosA0[0x25] = psxBios_toupper;
3074 biosA0[0x26] = psxBios_tolower;
3075 biosA0[0x27] = psxBios_bcopy;
3076 biosA0[0x28] = psxBios_bzero;
3077 biosA0[0x29] = psxBios_bcmp;
3078 biosA0[0x2a] = psxBios_memcpy;
3079 biosA0[0x2b] = psxBios_memset;
3080 biosA0[0x2c] = psxBios_memmove;
3081 biosA0[0x2d] = psxBios_memcmp;
3082 biosA0[0x2e] = psxBios_memchr;
3083 biosA0[0x2f] = psxBios_rand;
3084 biosA0[0x30] = psxBios_srand;
3085 biosA0[0x31] = psxBios_qsort;
3086 //biosA0[0x32] = psxBios_strtod;
3087 biosA0[0x33] = psxBios_malloc;
3088 biosA0[0x34] = psxBios_free;
3089 //biosA0[0x35] = psxBios_lsearch;
3090 //biosA0[0x36] = psxBios_bsearch;
3091 biosA0[0x37] = psxBios_calloc;
3092 biosA0[0x38] = psxBios_realloc;
3093 biosA0[0x39] = psxBios_InitHeap;
3094 //biosA0[0x3a] = psxBios__exit;
3095 biosA0[0x3b] = psxBios_getchar;
3096 biosA0[0x3c] = psxBios_putchar;
3097 //biosA0[0x3d] = psxBios_gets;
3098 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3099 //biosA0[0x41] = psxBios_LoadTest;
3100 biosA0[0x42] = psxBios_Load;
3101 biosA0[0x43] = psxBios_Exec;
3102 biosA0[0x44] = psxBios_FlushCache;
3103 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3104 biosA0[0x46] = psxBios_GPU_dw;
3105 biosA0[0x47] = psxBios_mem2vram;
3106 biosA0[0x48] = psxBios_SendGPU;
3107 biosA0[0x49] = psxBios_GPU_cw;
3108 biosA0[0x4a] = psxBios_GPU_cwb;
3109 biosA0[0x4b] = psxBios_GPU_SendPackets;
3110 biosA0[0x4c] = psxBios_sys_a0_4c;
3111 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3112 //biosA0[0x4e] = psxBios_GPU_sync;
3113 //biosA0[0x4f] = psxBios_sys_a0_4f;
3114 //biosA0[0x50] = psxBios_sys_a0_50;
3115 biosA0[0x51] = psxBios_LoadExec;
3116 //biosA0[0x52] = psxBios_GetSysSp;
3117 //biosA0[0x53] = psxBios_sys_a0_53;
3118 //biosA0[0x54] = psxBios__96_init_a54;
3119 //biosA0[0x55] = psxBios__bu_init_a55;
3120 biosA0[0x56] = psxBios_CdRemove;
3121 //biosA0[0x57] = psxBios_sys_a0_57;
3122 //biosA0[0x58] = psxBios_sys_a0_58;
3123 //biosA0[0x59] = psxBios_sys_a0_59;
3124 //biosA0[0x5a] = psxBios_sys_a0_5a;
3125 //biosA0[0x5b] = psxBios_dev_tty_init;
3126 //biosA0[0x5c] = psxBios_dev_tty_open;
3127 //biosA0[0x5d] = psxBios_sys_a0_5d;
3128 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3129 //biosA0[0x5f] = psxBios_dev_cd_open;
3130 //biosA0[0x60] = psxBios_dev_cd_read;
3131 //biosA0[0x61] = psxBios_dev_cd_close;
3132 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3133 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3134 //biosA0[0x64] = psxBios_dev_cd_chdir;
3135 //biosA0[0x65] = psxBios_dev_card_open;
3136 //biosA0[0x66] = psxBios_dev_card_read;
3137 //biosA0[0x67] = psxBios_dev_card_write;
3138 //biosA0[0x68] = psxBios_dev_card_close;
3139 //biosA0[0x69] = psxBios_dev_card_firstfile;
3140 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3141 //biosA0[0x6b] = psxBios_dev_card_erase;
3142 //biosA0[0x6c] = psxBios_dev_card_undelete;
3143 //biosA0[0x6d] = psxBios_dev_card_format;
3144 //biosA0[0x6e] = psxBios_dev_card_rename;
3145 //biosA0[0x6f] = psxBios_dev_card_6f;
3146 biosA0[0x70] = psxBios__bu_init;
3147 biosA0[0x71] = psxBios__96_init;
3148 biosA0[0x72] = psxBios_CdRemove;
3149 //biosA0[0x73] = psxBios_sys_a0_73;
3150 //biosA0[0x74] = psxBios_sys_a0_74;
3151 //biosA0[0x75] = psxBios_sys_a0_75;
3152 //biosA0[0x76] = psxBios_sys_a0_76;
3153 //biosA0[0x77] = psxBios_sys_a0_77;
3154 //biosA0[0x78] = psxBios__96_CdSeekL;
3155 //biosA0[0x79] = psxBios_sys_a0_79;
3156 //biosA0[0x7a] = psxBios_sys_a0_7a;
3157 //biosA0[0x7b] = psxBios_sys_a0_7b;
3158 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3159 //biosA0[0x7d] = psxBios_sys_a0_7d;
3160 //biosA0[0x7e] = psxBios__96_CdRead;
3161 //biosA0[0x7f] = psxBios_sys_a0_7f;
3162 //biosA0[0x80] = psxBios_sys_a0_80;
3163 //biosA0[0x81] = psxBios_sys_a0_81;
3164 //biosA0[0x82] = psxBios_sys_a0_82;
3165 //biosA0[0x83] = psxBios_sys_a0_83;
3166 //biosA0[0x84] = psxBios_sys_a0_84;
3167 //biosA0[0x85] = psxBios__96_CdStop;
3168 //biosA0[0x86] = psxBios_sys_a0_86;
3169 //biosA0[0x87] = psxBios_sys_a0_87;
3170 //biosA0[0x88] = psxBios_sys_a0_88;
3171 //biosA0[0x89] = psxBios_sys_a0_89;
3172 //biosA0[0x8a] = psxBios_sys_a0_8a;
3173 //biosA0[0x8b] = psxBios_sys_a0_8b;
3174 //biosA0[0x8c] = psxBios_sys_a0_8c;
3175 //biosA0[0x8d] = psxBios_sys_a0_8d;
3176 //biosA0[0x8e] = psxBios_sys_a0_8e;
3177 //biosA0[0x8f] = psxBios_sys_a0_8f;
3178 biosA0[0x90] = hleExc0_1_2;
3179 biosA0[0x91] = hleExc0_0_2;
3180 biosA0[0x92] = hleExc0_1_1;
3181 biosA0[0x93] = hleExc0_0_1;
3182 //biosA0[0x94] = psxBios_sys_a0_94;
3183 //biosA0[0x95] = psxBios_sys_a0_95;
3184 //biosA0[0x96] = psxBios_AddCDROMDevice;
3185 //biosA0[0x97] = psxBios_AddMemCardDevide;
3186 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3187 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3188 //biosA0[0x9a] = psxBios_sys_a0_9a;
3189 //biosA0[0x9b] = psxBios_sys_a0_9b;
3190 //biosA0[0x9c] = psxBios_SetConf;
3191 //biosA0[0x9d] = psxBios_GetConf;
3192 //biosA0[0x9e] = psxBios_sys_a0_9e;
3193 biosA0[0x9f] = psxBios_SetMem;
3194 //biosA0[0xa0] = psxBios__boot;
3195 //biosA0[0xa1] = psxBios_SystemError;
3196 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3197 biosA0[0xa3] = psxBios_DequeueCdIntr;
3198 //biosA0[0xa4] = psxBios_sys_a0_a4;
3199 //biosA0[0xa5] = psxBios_ReadSector;
3200 biosA0[0xa6] = psxBios_get_cd_status;
3201 //biosA0[0xa7] = psxBios_bufs_cb_0;
3202 //biosA0[0xa8] = psxBios_bufs_cb_1;
3203 //biosA0[0xa9] = psxBios_bufs_cb_2;
3204 //biosA0[0xaa] = psxBios_bufs_cb_3;
3205 biosA0[0xab] = psxBios__card_info;
3206 biosA0[0xac] = psxBios__card_load;
3207 //biosA0[0axd] = psxBios__card_auto;
3208 //biosA0[0xae] = psxBios_bufs_cd_4;
3209 //biosA0[0xaf] = psxBios_sys_a0_af;
3210 //biosA0[0xb0] = psxBios_sys_a0_b0;
3211 //biosA0[0xb1] = psxBios_sys_a0_b1;
3212 //biosA0[0xb2] = psxBios_do_a_long_jmp
3213 //biosA0[0xb3] = psxBios_sys_a0_b3;
3214 //biosA0[0xb4] = psxBios_sub_function;
3215 //*******************B0 CALLS****************************
3216 biosB0[0x00] = psxBios_SysMalloc;
3217 //biosB0[0x01] = psxBios_sys_b0_01;
3218 biosB0[0x02] = psxBios_SetRCnt;
3219 biosB0[0x03] = psxBios_GetRCnt;
3220 biosB0[0x04] = psxBios_StartRCnt;
3221 biosB0[0x05] = psxBios_StopRCnt;
3222 biosB0[0x06] = psxBios_ResetRCnt;
3223 biosB0[0x07] = psxBios_DeliverEvent;
3224 biosB0[0x08] = psxBios_OpenEvent;
3225 biosB0[0x09] = psxBios_CloseEvent;
3226 biosB0[0x0a] = psxBios_WaitEvent;
3227 biosB0[0x0b] = psxBios_TestEvent;
3228 biosB0[0x0c] = psxBios_EnableEvent;
3229 biosB0[0x0d] = psxBios_DisableEvent;
3230 biosB0[0x0e] = psxBios_OpenTh;
3231 biosB0[0x0f] = psxBios_CloseTh;
3232 biosB0[0x10] = psxBios_ChangeTh;
3233 //biosB0[0x11] = psxBios_psxBios_b0_11;
3234 biosB0[0x12] = psxBios_InitPAD;
3235 biosB0[0x13] = psxBios_StartPAD;
3236 biosB0[0x14] = psxBios_StopPAD;
3237 biosB0[0x15] = psxBios_PAD_init;
3238 biosB0[0x16] = psxBios_PAD_dr;
3239 biosB0[0x17] = psxBios_ReturnFromException;
3240 biosB0[0x18] = psxBios_ResetEntryInt;
3241 biosB0[0x19] = psxBios_HookEntryInt;
3242 //biosB0[0x1a] = psxBios_sys_b0_1a;
3243 //biosB0[0x1b] = psxBios_sys_b0_1b;
3244 //biosB0[0x1c] = psxBios_sys_b0_1c;
3245 //biosB0[0x1d] = psxBios_sys_b0_1d;
3246 //biosB0[0x1e] = psxBios_sys_b0_1e;
3247 //biosB0[0x1f] = psxBios_sys_b0_1f;
3248 biosB0[0x20] = psxBios_UnDeliverEvent;
3249 //biosB0[0x21] = psxBios_sys_b0_21;
3250 //biosB0[0x22] = psxBios_sys_b0_22;
3251 //biosB0[0x23] = psxBios_sys_b0_23;
3252 //biosB0[0x24] = psxBios_sys_b0_24;
3253 //biosB0[0x25] = psxBios_sys_b0_25;
3254 //biosB0[0x26] = psxBios_sys_b0_26;
3255 //biosB0[0x27] = psxBios_sys_b0_27;
3256 //biosB0[0x28] = psxBios_sys_b0_28;
3257 //biosB0[0x29] = psxBios_sys_b0_29;
3258 //biosB0[0x2a] = psxBios_sys_b0_2a;
3259 //biosB0[0x2b] = psxBios_sys_b0_2b;
3260 //biosB0[0x2c] = psxBios_sys_b0_2c;
3261 //biosB0[0x2d] = psxBios_sys_b0_2d;
3262 //biosB0[0x2e] = psxBios_sys_b0_2e;
3263 //biosB0[0x2f] = psxBios_sys_b0_2f;
3264 //biosB0[0x30] = psxBios_sys_b0_30;
3265 //biosB0[0x31] = psxBios_sys_b0_31;
3266 biosB0[0x32] = psxBios_open;
3267 biosB0[0x33] = psxBios_lseek;
3268 biosB0[0x34] = psxBios_read;
3269 biosB0[0x35] = psxBios_write;
3270 biosB0[0x36] = psxBios_close;
3271 //biosB0[0x37] = psxBios_ioctl;
3272 //biosB0[0x38] = psxBios_exit;
3273 //biosB0[0x39] = psxBios_sys_b0_39;
3274 //biosB0[0x3a] = psxBios_getc;
3275 //biosB0[0x3b] = psxBios_putc;
3276 biosB0[0x3c] = psxBios_getchar;
3277 //biosB0[0x3e] = psxBios_gets;
3278 //biosB0[0x40] = psxBios_cd;
3279 biosB0[0x41] = psxBios_format;
3280 biosB0[0x42] = psxBios_firstfile;
3281 biosB0[0x43] = psxBios_nextfile;
3282 biosB0[0x44] = psxBios_rename;
3283 biosB0[0x45] = psxBios_delete;
3284 //biosB0[0x46] = psxBios_undelete;
3285 //biosB0[0x47] = psxBios_AddDevice;
3286 //biosB0[0x48] = psxBios_RemoteDevice;
3287 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3288 biosB0[0x4a] = psxBios_InitCARD;
3289 biosB0[0x4b] = psxBios_StartCARD;
3290 biosB0[0x4c] = psxBios_StopCARD;
3291 //biosB0[0x4d] = psxBios_sys_b0_4d;
3292 biosB0[0x4e] = psxBios__card_write;
3293 biosB0[0x4f] = psxBios__card_read;
3294 biosB0[0x50] = psxBios__new_card;
3295 biosB0[0x51] = psxBios_Krom2RawAdd;
3296 //biosB0[0x52] = psxBios_sys_b0_52;
3297 //biosB0[0x53] = psxBios_sys_b0_53;
3298 //biosB0[0x54] = psxBios__get_errno;
3299 biosB0[0x55] = psxBios__get_error;
3300 biosB0[0x56] = psxBios_GetC0Table;
3301 biosB0[0x57] = psxBios_GetB0Table;
3302 biosB0[0x58] = psxBios__card_chan;
3303 //biosB0[0x59] = psxBios_sys_b0_59;
3304 //biosB0[0x5a] = psxBios_sys_b0_5a;
3305 biosB0[0x5b] = psxBios_ChangeClearPad;
3306 biosB0[0x5c] = psxBios__card_status;
3307 biosB0[0x5d] = psxBios__card_wait;
3308 //*******************C0 CALLS****************************
3309 biosC0[0x00] = psxBios_InitRCnt;
3310 biosC0[0x01] = psxBios_InitException;
3311 biosC0[0x02] = psxBios_SysEnqIntRP;
3312 biosC0[0x03] = psxBios_SysDeqIntRP;
3313 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3314 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3315 //biosC0[0x06] = psxBios_ExceptionHandler;
3316 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3317 biosC0[0x08] = psxBios_SysInitMemory;
3318 //biosC0[0x09] = psxBios_SysInitKMem;
3319 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3320 //biosC0[0x0b] = psxBios_SystemError;
3321 biosC0[0x0c] = psxBios_InitDefInt;
3322 //biosC0[0x0d] = psxBios_sys_c0_0d;
3323 //biosC0[0x0e] = psxBios_sys_c0_0e;
3324 //biosC0[0x0f] = psxBios_sys_c0_0f;
3325 //biosC0[0x10] = psxBios_sys_c0_10;
3326 //biosC0[0x11] = psxBios_sys_c0_11;
3327 //biosC0[0x12] = psxBios_InstallDevices;
3328 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3329 //biosC0[0x14] = psxBios_sys_c0_14;
3330 //biosC0[0x15] = psxBios__cdevinput;
3331 //biosC0[0x16] = psxBios__cdevscan;
3332 //biosC0[0x17] = psxBios__circgetc;
3333 //biosC0[0x18] = psxBios__circputc;
3334 //biosC0[0x19] = psxBios_ioabort;
3335 //biosC0[0x1a] = psxBios_sys_c0_1a
3336 //biosC0[0x1b] = psxBios_KernelRedirect;
3337 //biosC0[0x1c] = psxBios_PatchAOTable;
3338 //************** THE END ***************************************
3345 pad_buf1len = pad_buf2len = 0;
3349 memset(FDesc, 0, sizeof(FDesc));
3350 card_active_chan = 0;
3353 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3355 rom32 = (u32 *)psxR;
3356 rom32[0x100/4] = SWAP32(0x19951204);
3357 rom32[0x104/4] = SWAP32(3);
3358 strcpy(psxR + 0x108, "PCSX authors");
3359 strcpy(psxR + 0x12c, "PCSX HLE");
3362 len = 0x80000 - 0x66000;
3363 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3364 len = 0x80000 - 0x69d68;
3365 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3368 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3370 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3371 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3372 Here are some examples of games not working with this fix in place :
3373 R-type won't get past the Irem logo if not implemented.
3374 Crash Team Racing will softlock after the Sony logo.
3377 ram32 = (u32 *)psxM;
3378 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3379 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3380 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3381 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3383 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3384 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3386 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3387 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3388 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3389 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3391 ram32[0x00a0/4] = HLEOP(hleop_a0);
3392 ram32[0x00b0/4] = HLEOP(hleop_b0);
3393 ram32[0x00c0/4] = HLEOP(hleop_c0);
3397 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3398 strcpy((char *)&ram32[0xeff0/4], "bu");
3400 // default exception handler chains
3401 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3402 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3403 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3404 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3405 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3406 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3407 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3408 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3412 // fill the api jumptables with fake entries as some games patch them
3413 // (or rather the funcs listed there)
3414 ptr = (u32 *)&psxM[A_A0_TABLE];
3415 for (i = 0; i < 256; i++)
3416 ptr[i] = SWAP32(0x1000);
3418 ptr = (u32 *)&psxM[A_B0_TABLE];
3419 for (i = 0; i < 256; i++)
3420 ptr[i] = SWAP32(0x2000);
3421 // B(5b) is special because games patch (sometimes even jump to)
3422 // code at fixed offsets from it, nocash lists offsets:
3423 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3424 // call: +7a0=4b70, +884=4c54, +894=4c64
3425 ptr[0x5b] = SWAP32(0x43d0);
3426 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra
3427 ram32[0x4c54/4] = SWAP32(0x03e00008); // jr $ra
3428 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3430 ptr = (u32 *)&psxM[A_C0_TABLE];
3431 for (i = 0; i < 256/2; i++)
3432 ptr[i] = SWAP32(0x3000);
3433 ptr[6] = SWAP32(A_EXCEPTION);
3436 ram32[0x1000/4] = HLEOP(hleop_dummy);
3437 ram32[0x2000/4] = HLEOP(hleop_dummy);
3438 ram32[0x3000/4] = HLEOP(hleop_dummy);
3439 ram32[0x4c54/4] = HLEOP(hleop_dummy); // for B12_InitPad?
3440 ram32[0x8000/4] = HLEOP(hleop_execret);
3442 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3443 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3444 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3445 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3446 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3447 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3450 void psxBiosShutdown() {
3453 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3454 if (tcb_cnt != 4 || evcb_cnt != 16)
3455 setup_tt(tcb_cnt, evcb_cnt);
3458 #define psxBios_PADpoll(pad) { \
3459 PAD##pad##_startPoll(pad); \
3460 pad_buf##pad[0] = 0; \
3461 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3462 if (!(pad_buf##pad[1] & 0x0f)) { \
3465 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3467 PAD##pad##_poll(0); \
3469 while (bufcount--) { \
3470 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3474 static void biosPadHLE() {
3477 if (pad_buf != NULL) {
3478 u32 *buf = (u32*)pad_buf;
3481 if (PAD1_poll(0x42) == 0x23) {
3483 *buf = PAD1_poll(0) << 8;
3484 *buf |= PAD1_poll(0);
3486 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3487 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3490 *buf = PAD1_poll(0) << 8;
3491 *buf|= PAD1_poll(0);
3495 if (PAD2_poll(0x42) == 0x23) {
3497 *buf |= PAD2_poll(0) << 24;
3498 *buf |= PAD2_poll(0) << 16;
3500 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3501 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3504 *buf |= PAD2_poll(0) << 24;
3505 *buf |= PAD2_poll(0) << 16;
3519 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3523 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3524 psxBios_ReturnFromException();
3530 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3531 // so this is only partially implemented
3532 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3534 u32 cdrom_dma_ack_enable = 1; // a000b93c
3535 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3538 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3541 //PSXBIOS_LOG("%s\n", __func__);
3543 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3544 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3545 //if (--cdrom_irq_counter == 0) // 0xa0009180
3546 // DeliverEvent(0xf0000003, 0x10);
3550 mips_return_c(ret, 20);
3553 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3555 u32 cdrom_irq_ack_enable = 1; // a000b938
3556 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3559 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3562 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3563 PSXBIOS_LOG("%s TODO\n", __func__);
3566 mips_return_c(ret, 20);
3569 void hleExc0_2_2_syscall() // not in any A/B/C table
3571 u32 code = (psxRegs.CP0.n.Cause & 0x3c) >> 2;
3572 u32 tcbPtr = loadRam32(A_TT_PCB);
3573 TCB *tcb = loadRam32ptr(tcbPtr);
3575 if (code != R3000E_Syscall) {
3577 DeliverEvent(0xf0000010, 0x1000);
3578 psxBios_SystemErrorUnresolvedException();
3580 mips_return_c(0, 17);
3584 //printf("%s c=%d a0=%d\n", __func__, code, a0);
3585 tcb->epc += SWAP32(4);
3590 case 1: { // EnterCritical - disable irqs
3591 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3592 tcb->reg[2] = SWAP32(was_enabled);
3593 tcb->sr &= SWAP32(~0x404);
3596 case 2: // ExitCritical - enable irqs
3597 tcb->sr |= SWAP32(0x404);
3600 case 3: { // ChangeThreadSubFunction
3601 u32 tcbPtr = loadRam32(A_TT_PCB);
3602 storeRam32(tcbPtr, a1);
3606 DeliverEvent(0xf0000010, 0x4000);
3610 psxBios_ReturnFromException();
3613 void hleExc1_0_1(void)
3615 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3616 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3619 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3622 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3623 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3626 mips_return_c(ret, 22);
3629 void hleExc1_0_2(void)
3631 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3634 void hleExc1_1_1(void)
3636 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3637 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3640 void hleExc1_1_2(void)
3642 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3645 void hleExc1_2_1(void)
3647 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3648 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3651 void hleExc1_2_2(void)
3653 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3656 void hleExc1_3_1(void)
3658 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3659 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3662 void hleExc1_3_2(void)
3664 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3667 void hleExc3_0_2_defint(void)
3669 static const struct {
3680 { 6, 6 }, // rcnt2 (bug)
3685 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3686 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3687 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3692 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3695 void psxBiosException() {
3696 u32 tcbPtr = loadRam32(A_TT_PCB);
3697 u32 *chains = loadRam32ptr(A_TT_ExCB);
3698 TCB *tcb = loadRam32ptr(tcbPtr);
3704 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3705 for (i = 4; i < 32; i++) {
3708 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3710 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3711 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3712 tcb->epc = SWAP32(psxRegs.CP0.n.EPC);
3713 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3714 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3715 sp = fp = loadRam32(A_EXC_SP);
3719 // do the chains (always 4)
3720 for (c = lim = 0; c < 4; c++) {
3721 if (chains[c * 2] == 0)
3723 ptr = SWAP32(chains[c * 2]);
3724 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3725 chain = castRam32ptr(ptr);
3730 softCallInException(SWAP32(chain[2]));
3731 if (returned_from_exception())
3734 if (v0 == 0 || chain[1] == 0)
3736 softCallInException(SWAP32(chain[1]));
3737 if (returned_from_exception())
3743 // TODO make this a chain entry
3744 if (psxHu32(0x1070) & 1)
3747 // return from exception (custom or default)
3749 ptr = loadRam32(A_EEXIT_PTR);
3750 if (ptr != A_EEXIT_DEF) {
3751 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3752 longjmp_load(jmp_buf);
3757 psxBios_ReturnFromException();
3760 #define bfreeze(ptr, size) { \
3761 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3762 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3766 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3767 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3769 #define bfreezepsxMptr(ptr, type) { \
3771 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3772 else psxRu32ref(base) = 0; \
3774 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3775 else (ptr) = NULL; \
3777 base += sizeof(u32); \
3780 void psxBiosFreeze(int Mode) {
3783 bfreezepsxMptr(pad_buf, int);
3784 bfreezepsxMptr(pad_buf1, char);
3785 bfreezepsxMptr(pad_buf2, char);
3786 bfreezepsxMptr(heap_addr, u32);
3788 bfreezel(&card_active_chan);
3789 bfreezel(&pad_stopped);
3790 bfreezel(&heap_size);