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.
39 #if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
40 #pragma GCC diagnostic ignored "-Wpointer-sign"
44 #define SysPrintf if (Config.PsxOut) printf
46 char *biosA0n[256] = {
48 "open", "lseek", "read", "write",
49 "close", "ioctl", "exit", "sys_a0_07",
50 "getc", "putc", "todigit", "atof",
51 "strtoul", "strtol", "abs", "labs",
53 "atoi", "atol", "atob", "setjmp",
54 "longjmp", "strcat", "strncat", "strcmp",
55 "strncmp", "strcpy", "strncpy", "strlen",
56 "index", "rindex", "strchr", "strrchr",
58 "strpbrk", "strspn", "strcspn", "strtok",
59 "strstr", "toupper", "tolower", "bcopy",
60 "bzero", "bcmp", "memcpy", "memset",
61 "memmove", "memcmp", "memchr", "rand",
63 "srand", "qsort", "strtod", "malloc",
64 "free", "lsearch", "bsearch", "calloc",
65 "realloc", "InitHeap", "_exit", "getchar",
66 "putchar", "gets", "puts", "printf",
68 "sys_a0_40", "LoadTest", "Load", "Exec",
69 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
70 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
71 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
73 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
74 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
75 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
76 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
78 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
79 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
80 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
81 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
83 "_bu_init", "_96_init", "_96_remove", "sys_a0_73",
84 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
85 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
86 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
88 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
89 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
90 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
91 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
93 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
94 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
95 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
96 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
98 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
99 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
100 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
101 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
103 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
107 char *biosB0n[256] = {
109 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
110 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
111 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
112 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
114 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
115 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
116 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
117 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
119 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
120 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
121 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
122 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
124 "sys_b0_30", "sys_b0_31", "open", "lseek",
125 "read", "write", "close", "ioctl",
126 "exit", "sys_b0_39", "getc", "putc",
127 "getchar", "putchar", "gets", "puts",
129 "cd", "format", "firstfile", "nextfile",
130 "rename", "delete", "undelete", "AddDevice",
131 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
132 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
134 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
135 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
136 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
137 "_card_status", "_card_wait",
140 char *biosC0n[256] = {
142 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
143 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
144 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
145 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
147 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
148 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
149 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
153 //#define r0 (psxRegs.GPR.n.r0)
154 #define at (psxRegs.GPR.n.at)
155 #define v0 (psxRegs.GPR.n.v0)
156 #define v1 (psxRegs.GPR.n.v1)
157 #define a0 (psxRegs.GPR.n.a0)
158 #define a1 (psxRegs.GPR.n.a1)
159 #define a2 (psxRegs.GPR.n.a2)
160 #define a3 (psxRegs.GPR.n.a3)
161 #define t0 (psxRegs.GPR.n.t0)
162 #define t1 (psxRegs.GPR.n.t1)
163 #define t2 (psxRegs.GPR.n.t2)
164 #define t3 (psxRegs.GPR.n.t3)
165 #define t4 (psxRegs.GPR.n.t4)
166 #define t5 (psxRegs.GPR.n.t5)
167 #define t6 (psxRegs.GPR.n.t6)
168 #define t7 (psxRegs.GPR.n.t7)
169 #define t8 (psxRegs.GPR.n.t8)
170 #define t9 (psxRegs.GPR.n.t9)
171 #define s0 (psxRegs.GPR.n.s0)
172 #define s1 (psxRegs.GPR.n.s1)
173 #define s2 (psxRegs.GPR.n.s2)
174 #define s3 (psxRegs.GPR.n.s3)
175 #define s4 (psxRegs.GPR.n.s4)
176 #define s5 (psxRegs.GPR.n.s5)
177 #define s6 (psxRegs.GPR.n.s6)
178 #define s7 (psxRegs.GPR.n.s7)
179 #define k0 (psxRegs.GPR.n.k0)
180 #define k1 (psxRegs.GPR.n.k1)
181 #define gp (psxRegs.GPR.n.gp)
182 #define sp (psxRegs.GPR.n.sp)
183 #define fp (psxRegs.GPR.n.s8)
184 #define ra (psxRegs.GPR.n.ra)
185 #define pc0 (psxRegs.pc)
187 #define Ra0 ((char *)PSXM(a0))
188 #define Ra1 ((char *)PSXM(a1))
189 #define Ra2 ((char *)PSXM(a2))
190 #define Ra3 ((char *)PSXM(a3))
191 #define Rv0 ((char *)PSXM(v0))
192 #define Rsp ((char *)PSXM(sp))
201 #define EvStUNUSED 0x0000
202 #define EvStWAIT 0x1000
203 #define EvStACTIVE 0x2000
204 #define EvStALREADY 0x4000
206 #define EvMdINTR 0x1000
207 #define EvMdNOINTR 0x2000
236 u32 _sp, _fp, _gp, ret, base;
256 static u32 *jmp_int = NULL;
257 static int *pad_buf = NULL;
258 static char *pad_buf1 = NULL, *pad_buf2 = NULL;
259 static int pad_buf1len, pad_buf2len;
260 static int pad_stopped = 0;
263 static EvCB *EventCB;
264 static EvCB *HwEV; // 0xf0
265 static EvCB *EvEV; // 0xf1
266 static EvCB *RcEV; // 0xf2
267 static EvCB *UeEV; // 0xf3
268 static EvCB *SwEV; // 0xf4
269 static EvCB *ThEV; // 0xff
270 static u32 heap_size = 0;
271 static u32 *heap_addr = NULL;
272 static u32 *heap_end = NULL;
273 static u32 SysIntRP[8];
274 static int CardState = -1;
275 static TCB ThreadCB[8];
276 static int CurThread = 0;
277 static FileDesc FDesc[32];
278 static u32 card_active_chan = 0;
280 boolean hleSoftCall = FALSE;
282 static inline void softCall(u32 pc) {
288 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
293 static inline void softCall2(u32 pc) {
300 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
306 static inline void DeliverEvent(u32 ev, u32 spec) {
307 if (EventCB[ev][spec].status != EvStACTIVE) return;
309 // EventCB[ev][spec].status = EvStALREADY;
310 if (EventCB[ev][spec].mode == EvMdINTR) {
311 softCall2(EventCB[ev][spec].fhandler);
312 } else EventCB[ev][spec].status = EvStALREADY;
315 static unsigned interrupt_r26=0x8004E8B0;
317 static inline void SaveRegs() {
318 memcpy(regs, psxRegs.GPR.r, 32*4);
319 regs[32] = psxRegs.GPR.n.lo;
320 regs[33] = psxRegs.GPR.n.hi;
321 regs[34] = psxRegs.pc;
324 static inline void LoadRegs() {
325 memcpy(psxRegs.GPR.r, regs, 32*4);
326 psxRegs.GPR.n.lo = regs[32];
327 psxRegs.GPR.n.hi = regs[33];
333 // System calls A0 */
336 #define buread(Ra1, mcd, length) { \
337 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); \
338 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
339 memcpy(Ra1, ptr, length); \
340 if (FDesc[1 + mcd].mode & 0x8000) { \
341 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
342 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
345 FDesc[1 + mcd].offset += v0; \
348 #define buwrite(Ra1, mcd, length) { \
349 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
350 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
351 ptr = Mcd##mcd##Data + offset; \
352 memcpy(ptr, Ra1, length); \
353 FDesc[1 + mcd].offset += length; \
354 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
355 if (FDesc[1 + mcd].mode & 0x8000) { \
356 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
357 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
363 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
364 /* For some strange reason, the returned character is sign-expanded; */
365 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
366 /* TODO FIX ME : Properly implement this behaviour */
367 void psxBios_getc(void) // 0x03, 0x35
372 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
376 if (pa1 != INVALID_PTR) {
378 case 2: buread(pa1, 1, 1); break;
379 case 3: buread(pa1, 2, 1); break;
386 /* Copy of psxBios_write, except size is 1. */
387 void psxBios_putc(void) // 0x09, 0x3B
392 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
395 if (pa1 == INVALID_PTR) {
400 if (a0 == 1) { // stdout
401 char *ptr = (char *)pa1;
405 printf("%c", *ptr++); a2--;
411 case 2: buwrite(pa1, 1, 1); break;
412 case 3: buwrite(pa1, 2, 1); break;
418 void psxBios_todigit(void) // 0x0a
422 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
425 if (c >= 0x30 && c < 0x3A) {
428 else if (c > 0x60 && c < 0x7B) {
431 else if (c > 0x40 && c < 0x5B) {
434 else if (c >= 0x80) {
445 void psxBios_abs() { // 0x0e
446 if ((s32)a0 < 0) v0 = -(s32)a0;
451 void psxBios_labs() { // 0x0f
455 void psxBios_atoi() { // 0x10
457 char *p = (char *)Ra0;
461 case ' ': case '\t': continue;
468 while (*p >= '0' && *p <= '9') {
469 n = n * 10 + *p++ - '0';
476 void psxBios_atol() { // 0x11
480 void psxBios_setjmp() { // 0x13
481 u32 *jmp_buf = (u32 *)Ra0;
485 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x13]);
491 for (i = 0; i < 8; i++) // s0-s7
492 jmp_buf[3 + i] = psxRegs.GPR.r[16 + i];
498 void psxBios_longjmp() { // 0x14
499 u32 *jmp_buf = (u32 *)Ra0;
503 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
506 ra = jmp_buf[0]; /* ra */
507 sp = jmp_buf[1]; /* sp */
508 fp = jmp_buf[2]; /* fp */
509 for (i = 0; i < 8; i++) // s0-s7
510 psxRegs.GPR.r[16 + i] = jmp_buf[3 + i];
511 gp = jmp_buf[11]; /* gp */
516 void psxBios_strcat() { // 0x15
517 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
520 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
522 if (a0 == 0 || a1 == 0)
530 while ((*p1++ = *p2++) != '\0');
535 void psxBios_strncat() { // 0x16
536 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
540 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
542 if (a0 == 0 || a1 == 0)
550 while ((*p1++ = *p2++) != '\0') {
560 void psxBios_strcmp() { // 0x17
561 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
563 if (a0 == 0 && a1 == 0)
569 else if (a0 == 0 && a1 != 0)
575 else if (a0 != 0 && a1 == 0)
582 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
585 while (*p1 == *p2++) {
604 void psxBios_strncmp() { // 0x18
605 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
607 if (a0 == 0 && a1 == 0)
613 else if (a0 == 0 && a1 != 0)
619 else if (a0 != 0 && a1 == 0)
626 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
629 while (--n >= 0 && *p1 == *p2++) {
633 v1 = a2 - ((a2-n) - 1);
641 v0 = (n < 0 ? 0 : *p1 - *--p2);
643 v1 = a2 - ((a2-n) - 1);
649 void psxBios_strcpy() { // 0x19
650 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
651 if (a0 == 0 || a1 == 0)
657 while ((*p1++ = *p2++) != '\0');
662 void psxBios_strncpy() { // 0x1a
663 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
665 if (a0 == 0 || a1 == 0)
671 for (i = 0; i < n; i++) {
672 if ((*p1++ = *p2++) == '\0') {
684 void psxBios_strlen() { // 0x1b
685 char *p = (char *)Ra0;
696 void psxBios_index() { // 0x1c
697 char *p = (char *)Ra0;
707 v0 = a0 + (p - (char *)Ra0);
711 } while (*p++ != '\0');
716 void psxBios_rindex() { // 0x1d
717 char *p = (char *)Ra0;
727 v0 = a0 + (p - (char *)Ra0);
728 } while (*p++ != '\0');
733 void psxBios_strchr() { // 0x1e
737 void psxBios_strrchr() { // 0x1f
741 void psxBios_strpbrk() { // 0x20
742 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
744 while ((c = *p1++) != '\0') {
745 for (scanp = p2; (sc = *scanp++) != '\0';) {
747 v0 = a0 + (p1 - 1 - (char *)Ra0);
754 // BUG: return a0 instead of NULL if not found
758 void psxBios_strspn() { // 0x21
761 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
762 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
763 if (*p2 == '\0') break;
766 v0 = p1 - (char *)Ra0; pc0 = ra;
769 void psxBios_strcspn() { // 0x22
772 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
773 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
774 if (*p2 != '\0') break;
777 v0 = p1 - (char *)Ra0; pc0 = ra;
780 void psxBios_strtok() { // 0x23
781 char *pcA0 = (char *)Ra0;
782 char *pcRet = strtok(pcA0, (char *)Ra1);
784 v0 = a0 + pcRet - pcA0;
790 void psxBios_strstr() { // 0x24
791 char *p = (char *)Ra0, *p1, *p2;
797 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
802 v0 = a0 + (p - (char *)Ra0);
813 void psxBios_toupper() { // 0x25
814 v0 = (s8)(a0 & 0xff);
815 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
819 void psxBios_tolower() { // 0x26
820 v0 = (s8)(a0 & 0xff);
821 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
825 void psxBios_bcopy() { // 0x27
826 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
828 if (a0 == 0 || a2 > 0x7FFFFFFF)
833 while ((s32)a2-- > 0) *p1++ = *p2++;
838 void psxBios_bzero() { // 0x28
839 char *p = (char *)Ra0;
841 /* Same as memset here (See memset below) */
842 if (a1 > 0x7FFFFFFF || a1 == 0)
853 while ((s32)a1-- > 0) *p++ = '\0';
858 void psxBios_bcmp() { // 0x29
859 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
861 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
863 while ((s32)a2-- > 0) {
864 if (*p1++ != *p2++) {
865 v0 = *p1 - *p2; // BUG: compare the NEXT byte
874 void psxBios_memcpy() { // 0x2a
875 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
877 if (a0 == 0 || a2 > 0x7FFFFFFF)
882 while ((s32)a2-- > 0) {
889 void psxBios_memset() { // 0x2b
890 char *p = (char *)Ra0;
892 if (a2 > 0x7FFFFFFF || a2 == 0)
903 while ((s32)a2-- > 0) *p++ = (char)a1;
908 void psxBios_memmove() { // 0x2c
909 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
911 if (a0 == 0 || a2 > 0x7FFFFFFF)
916 if (p2 <= p1 && p2 + a2 > p1) {
917 a2++; // BUG: copy one more byte here
920 while ((s32)a2-- > 0) *--p1 = *--p2;
922 while ((s32)a2-- > 0) *p1++ = *p2++;
927 void psxBios_memcmp() { // 0x2d
931 void psxBios_memchr() { // 0x2e
932 char *p = (char *)Ra0;
934 if (a0 == 0 || a2 > 0x7FFFFFFF)
940 while ((s32)a2-- > 0) {
941 if (*p++ != (s8)a1) continue;
942 v0 = a0 + (p - (char *)Ra0 - 1);
950 void psxBios_rand() { // 0x2f
951 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
952 v0 = (s >> 16) & 0x7fff;
953 psxMu32ref(0x9010) = SWAPu32(s);
957 void psxBios_srand() { // 0x30
958 psxMu32ref(0x9010) = SWAPu32(a0);
962 static u32 qscmpfunc, qswidth;
964 static inline int qscmp(char *a, char *b) {
967 a0 = sa0 + (a - (char *)PSXM(sa0));
968 a1 = sa0 + (b - (char *)PSXM(sa0));
970 softCall2(qscmpfunc);
976 static inline void qexchange(char *i, char *j) {
987 static inline void q3exchange(char *i, char *j, char *k) {
999 static void qsort_main(char *a, char *l) {
1000 char *i, *j, *lp, *hp;
1005 if ((n = l - a) <= qswidth)
1007 n = qswidth * (n / (2 * qswidth));
1013 if ((c = qscmp(i, lp)) == 0) {
1014 qexchange(i, lp -= qswidth);
1025 if ((c = qscmp(hp, j)) == 0) {
1026 qexchange(hp += qswidth, j);
1031 q3exchange(i, hp += qswidth, j);
1045 if (lp - a >= l - hp) {
1046 qsort_main(hp + qswidth, l);
1055 q3exchange(j, lp -= qswidth, i);
1060 void psxBios_qsort() { // 0x31
1063 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1068 void psxBios_malloc() { // 0x33
1069 u32 *chunk, *newchunk = NULL;
1070 unsigned int dsize = 0, csize, cstat;
1073 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1075 if (!a0 || (!heap_size || !heap_addr)) {
1081 // scan through heap and combine free chunks of space
1084 while(chunk < heap_end) {
1085 // get size and status of actual chunk
1086 csize = ((u32)*chunk) & 0xfffffffc;
1087 cstat = ((u32)*chunk) & 1;
1089 // most probably broken heap descriptor
1090 // this fixes Burning Road
1093 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1098 // it's a free chunk
1103 colflag = 1; // let's begin a new collection of free memory
1105 else dsize += (csize+4); // add the new size including header
1107 // not a free chunk: did we start a collection ?
1109 if(colflag == 1) { // collection is over
1111 *newchunk = SWAP32(dsize | 1);
1116 chunk = (u32*)((uptr)chunk + csize + 4);
1118 // if neccessary free memory on end of heap
1120 *newchunk = SWAP32(dsize | 1);
1123 csize = ((u32)*chunk) & 0xfffffffc;
1124 cstat = ((u32)*chunk) & 1;
1125 dsize = (a0 + 3) & 0xfffffffc;
1127 // exit on uninitialized heap
1128 if (chunk == NULL) {
1129 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1135 // search an unused chunk that is big enough until the end of the heap
1136 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1137 chunk = (u32*)((uptr)chunk + csize + 4);
1139 // catch out of memory
1140 if(chunk >= heap_end) {
1141 printf("malloc %x,%x: Out of memory error!\n",
1147 csize = ((u32)*chunk) & 0xfffffffc;
1148 cstat = ((u32)*chunk) & 1;
1152 if(dsize == csize) {
1153 // chunk has same size
1154 *chunk &= 0xfffffffc;
1155 } else if (dsize > csize) {
1160 *chunk = SWAP32(dsize);
1161 newchunk = (u32*)((uptr)chunk + dsize + 4);
1162 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1165 // return pointer to allocated memory
1166 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1168 //printf ("malloc %x,%x\n", v0, a0);
1172 void psxBios_free() { // 0x34
1175 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1178 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1181 *(u32*)(Ra0-4) |= 1; // set chunk to free
1185 void psxBios_calloc() { // 0x37
1188 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1198 void psxBios_realloc() { // 0x38
1202 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1206 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1211 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1216 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1217 /* Note that it is not quite implemented this way here. */
1227 /* InitHeap(void *block , int n) */
1228 void psxBios_InitHeap() { // 0x39
1232 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1235 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1240 heap_addr = (u32 *)Ra0;
1242 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1243 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1244 //*heap_addr = SWAP32(size | 1);
1246 SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1251 void psxBios_getchar() { //0x3b
1252 v0 = getchar(); pc0 = ra;
1255 void psxBios_printf() { // 0x3f
1264 if (psp != INVALID_PTR) {
1265 memcpy(save, psp, 4 * 4);
1266 psxMu32ref(sp) = SWAP32((u32)a0);
1267 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1268 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1269 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1281 tmp2[j++] = Ra0[i]; goto _start;
1283 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1294 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1298 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1304 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1306 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1308 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1310 *ptmp++ = Ra0[i]; break;
1321 memcpy(psp, save, 4 * 4);
1323 SysPrintf("%s", tmp);
1328 void psxBios_format() { // 0x41
1329 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1331 CreateMcd(Config.Mcd1);
1332 LoadMcd(1, Config.Mcd1);
1335 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1337 CreateMcd(Config.Mcd2);
1338 LoadMcd(2, Config.Mcd2);
1349 * long Load(char *name, struct EXEC *header);
1352 void psxBios_Load() { // 0x42
1357 PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1);
1361 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1362 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1370 * int Exec(struct EXEC *header , int argc , char **argv);
1373 void psxBios_Exec() { // 43
1374 EXEC *header = (EXEC*)Ra0;
1378 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1388 if (header->S_addr != 0) {
1389 tmp = header->S_addr + header->s_size;
1405 void psxBios_FlushCache() { // 44
1407 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1409 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1410 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1414 void psxBios_GPU_dw() { // 0x46
1419 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1422 GPU_writeData(0xa0000000);
1423 GPU_writeData((a1<<0x10)|(a0&0xffff));
1424 GPU_writeData((a3<<0x10)|(a2&0xffff));
1426 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1429 GPU_writeData(SWAPu32(*ptr++));
1435 void psxBios_mem2vram() { // 0x47
1438 GPU_writeData(0xa0000000);
1439 GPU_writeData((a1<<0x10)|(a0&0xffff));
1440 GPU_writeData((a3<<0x10)|(a2&0xffff));
1441 size = ((((a2 * a3) / 2) >> 4) << 16);
1442 GPU_writeStatus(0x04000002);
1443 psxHwWrite32(0x1f8010f4,0);
1444 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1445 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1446 psxHwWrite32(0x1f8010a4, size | 0x10);
1447 psxHwWrite32(0x1f8010a8,0x01000201);
1452 void psxBios_SendGPU() { // 0x48
1453 GPU_writeStatus(a0);
1458 void psxBios_GPU_cw() { // 0x49
1465 void psxBios_GPU_cwb() { // 0x4a
1466 u32 *ptr = (u32*)Ra0;
1471 GPU_writeData(SWAPu32(*ptr++));
1477 void psxBios_GPU_SendPackets() { //4b:
1479 GPU_writeStatus(0x04000002);
1480 psxHwWrite32(0x1f8010f4,0);
1481 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1482 psxHwWrite32(0x1f8010a0,a0);
1483 psxHwWrite32(0x1f8010a4,0);
1484 psxHwWrite32(0x1f8010a8,0x010000401);
1488 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1489 psxHwWrite32(0x1f8010a8,0x00000401);
1490 GPU_writeData(0x0400000);
1491 GPU_writeData(0x0200000);
1492 GPU_writeData(0x0100000);
1497 void psxBios_GPU_GetGPUStatus() { // 0x4d
1498 v0 = GPU_readStatus();
1504 void psxBios_LoadExec() { // 51
1505 EXEC *header = (EXEC*)PSXM(0xf000);
1509 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1511 s_addr = a1; s_size = a2;
1516 header->S_addr = s_addr;
1517 header->s_size = s_size;
1519 a0 = 0xf000; a1 = 0; a2 = 0;
1523 void psxBios__bu_init() { // 70
1525 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1528 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1529 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1534 void psxBios__96_init() { // 71
1536 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1542 void psxBios__96_remove() { // 72
1544 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1550 void psxBios_SetMem() { // 9f
1551 u32 new = psxHu32(0x1060);
1554 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1559 psxHu32ref(0x1060) = SWAP32(new);
1560 psxMu32ref(0x060) = a0;
1561 SysPrintf("Change effective memory : %d MBytes\n",a0);
1565 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1566 psxMu32ref(0x060) = a0;
1567 SysPrintf("Change effective memory : %d MBytes\n",a0);
1570 SysPrintf("Effective memory must be 2/8 MBytes\n");
1577 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1578 void psxBios_get_cd_status(void) //a6
1584 void psxBios__card_info() { // ab
1586 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1589 card_active_chan = a0;
1590 port = card_active_chan >> 4;
1596 if (McdDisable[port & 1])
1601 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1607 if (McdDisable[0] && McdDisable[1])
1610 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1611 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1612 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
1616 void psxBios__card_load() { // ac
1618 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1621 card_active_chan = a0;
1623 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1624 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1629 /* System calls B0 */
1631 void psxBios_SetRCnt() { // 02
1633 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1640 psxRcntWtarget(a0, a1);
1641 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1642 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1643 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1644 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1645 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1647 psxRcntWmode(a0, mode);
1652 void psxBios_GetRCnt() { // 03
1654 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1658 if (a0 != 3) v0 = psxRcntRcount(a0);
1663 void psxBios_StartRCnt() { // 04
1665 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1669 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1670 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1674 void psxBios_StopRCnt() { // 05
1676 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1680 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1681 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1685 void psxBios_ResetRCnt() { // 06
1687 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1692 psxRcntWmode(a0, 0);
1693 psxRcntWtarget(a0, 0);
1694 psxRcntWcount(a0, 0);
1700 /* gets ev for use with EventCB */
1702 ev = (a0 >> 24) & 0xf; \
1703 if (ev == 0xf) ev = 0x5; \
1707 /* gets spec for use with EventCB */
1711 case 0x0301: spec = 16; break; \
1712 case 0x0302: spec = 17; break; \
1714 for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1718 void psxBios_DeliverEvent() { // 07
1726 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1729 DeliverEvent(ev, spec);
1734 void psxBios_OpenEvent() { // 08
1742 PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1745 EventCB[ev][spec].status = EvStWAIT;
1746 EventCB[ev][spec].mode = a2;
1747 EventCB[ev][spec].fhandler = a3;
1749 v0 = ev | (spec << 8);
1753 void psxBios_CloseEvent() { // 09
1757 spec = (a0 >> 8) & 0xff;
1760 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1763 EventCB[ev][spec].status = EvStUNUSED;
1768 void psxBios_WaitEvent() { // 0a
1772 spec = (a0 >> 8) & 0xff;
1774 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1776 if (EventCB[ev][spec].status == EvStUNUSED)
1783 if (EventCB[ev][spec].status == EvStALREADY)
1785 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1786 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1796 void psxBios_TestEvent() { // 0b
1800 spec = (a0 >> 8) & 0xff;
1802 if (EventCB[ev][spec].status == EvStALREADY)
1804 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1813 PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1819 void psxBios_EnableEvent() { // 0c
1823 spec = (a0 >> 8) & 0xff;
1826 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1829 EventCB[ev][spec].status = EvStACTIVE;
1834 void psxBios_DisableEvent() { // 0d
1838 spec = (a0 >> 8) & 0xff;
1841 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1844 EventCB[ev][spec].status = EvStWAIT;
1850 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1853 void psxBios_OpenTh() { // 0e
1856 for (th=1; th<8; th++)
1858 if (ThreadCB[th].status == 0) break;
1862 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1863 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1865 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1872 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1875 ThreadCB[th].status = 1;
1876 ThreadCB[th].func = a0;
1877 ThreadCB[th].reg[29] = a1;
1878 ThreadCB[th].reg[28] = a2;
1884 * int CloseTh(long thread);
1887 void psxBios_CloseTh() { // 0f
1891 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
1893 /* The return value is always 1 (even if the handle was already closed). */
1895 if (ThreadCB[th].status != 0) {
1896 ThreadCB[th].status = 0;
1903 * int ChangeTh(long thread);
1906 void psxBios_ChangeTh() { // 10
1910 // PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
1912 /* The return value is always 1. */
1914 if (ThreadCB[th].status == 0 || CurThread == th) {
1917 if (ThreadCB[CurThread].status == 2) {
1918 ThreadCB[CurThread].status = 1;
1919 ThreadCB[CurThread].func = ra;
1920 memcpy(ThreadCB[CurThread].reg, psxRegs.GPR.r, 32*4);
1923 memcpy(psxRegs.GPR.r, ThreadCB[th].reg, 32*4);
1924 pc0 = ThreadCB[th].func;
1925 ThreadCB[th].status = 2;
1930 void psxBios_InitPAD() { // 0x12
1932 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
1935 pad_buf1 = (char*)Ra0;
1937 pad_buf2 = (char*)Ra2;
1943 void psxBios_StartPAD() { // 13
1945 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
1948 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
1949 psxRegs.CP0.n.Status |= 0x401;
1953 void psxBios_StopPAD() { // 14
1955 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
1963 void psxBios_PAD_init() { // 15
1965 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
1967 if (!(a0 == 0x20000000 || a0 == 0x20000001))
1973 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
1974 pad_buf = (int *)Ra1;
1976 psxRegs.CP0.n.Status |= 0x401;
1981 void psxBios_PAD_dr() { // 16
1983 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
1989 void psxBios_ReturnFromException() { // 17
1992 pc0 = psxRegs.CP0.n.EPC;
1994 if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;
1996 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
1997 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
2000 void psxBios_ResetEntryInt() { // 18
2002 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2009 void psxBios_HookEntryInt() { // 19
2011 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
2014 jmp_int = (u32*)Ra0;
2018 void psxBios_UnDeliverEvent() { // 0x20
2026 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2029 if (EventCB[ev][spec].status == EvStALREADY &&
2030 EventCB[ev][spec].mode == EvMdNOINTR)
2031 EventCB[ev][spec].status = EvStACTIVE;
2036 char ffile[64], *pfile;
2039 static void buopen(int mcd, char *ptr, char *cfg)
2042 char *mcd_data = ptr;
2044 strcpy(FDesc[1 + mcd].name, Ra0+5);
2045 FDesc[1 + mcd].offset = 0;
2046 FDesc[1 + mcd].mode = a1;
2048 for (i=1; i<16; i++) {
2049 const char *fptr = mcd_data + 128 * i;
2050 if ((*fptr & 0xF0) != 0x50) continue;
2051 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2052 FDesc[1 + mcd].mcfile = i;
2053 SysPrintf("open %s\n", fptr+0xa);
2057 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2058 for (i=1; i<16; i++) {
2059 int j, xor, nblk = a1 >> 16;
2061 char *fptr = mcd_data + 128 * i;
2063 if ((*fptr & 0xF0) != 0xa0) continue;
2065 FDesc[1 + mcd].mcfile = i;
2068 fptr[5] = 0x20 * nblk;
2071 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2072 pptr = fptr2 = fptr;
2073 for(j=2; j<=nblk; j++) {
2075 for(i++; i<16; i++) {
2078 memset(fptr2, 0, 128);
2079 fptr2[0] = j < nblk ? 0x52 : 0x53;
2082 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2087 /* shouldn't this return ENOSPC if i == 16? */
2089 pptr[8] = pptr[9] = 0xff;
2090 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2092 SysPrintf("openC %s %d\n", ptr, nblk);
2094 /* just go ahead and resave them all */
2095 SaveMcd(cfg, ptr, 128, 128 * 15);
2098 /* shouldn't this return ENOSPC if i == 16? */
2103 * int open(char *name , int mode);
2106 void psxBios_open() { // 0x32
2110 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2115 if (pa0 != INVALID_PTR) {
2116 if (!strncmp(pa0, "bu00", 4)) {
2117 buopen(1, Mcd1Data, Config.Mcd1);
2120 if (!strncmp(pa0, "bu10", 4)) {
2121 buopen(2, Mcd2Data, Config.Mcd2);
2129 * int lseek(int fd , int offset , int whence);
2132 void psxBios_lseek() { // 0x33
2134 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2139 FDesc[a0].offset = a1;
2141 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2142 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2146 FDesc[a0].offset+= a1;
2147 v0 = FDesc[a0].offset;
2156 * int read(int fd , void *buf , int nbytes);
2159 void psxBios_read() { // 0x34
2164 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2169 if (pa1 != INVALID_PTR) {
2171 case 2: buread(pa1, 1, a2); break;
2172 case 3: buread(pa1, 2, a2); break;
2180 * int write(int fd , void *buf , int nbytes);
2183 void psxBios_write() { // 0x35/0x03
2188 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2192 if (pa1 == INVALID_PTR) {
2197 if (a0 == 1) { // stdout
2202 SysPrintf("%c", *ptr++); a2--;
2208 case 2: buwrite(pa1, 1, a2); break;
2209 case 3: buwrite(pa1, 2, a2); break;
2216 * int close(int fd);
2219 void psxBios_close() { // 0x36
2221 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2228 void psxBios_putchar() { // 3d
2229 SysPrintf("%c", (char)a0);
2233 void psxBios_puts() { // 3e/3f
2234 SysPrintf("%s", Ra0);
2239 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2240 * We want to mimic the PSX's behaviour in this case for bufile. */
2241 static size_t strlen_internal(char* p)
2243 size_t size_of_array = 0;
2244 while (*p++) size_of_array++;
2245 return size_of_array;
2248 #define bufile(mcd) { \
2249 size_t size_of_name = strlen_internal(dir->name); \
2250 while (nfile < 16) { \
2253 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2255 if ((*ptr & 0xF0) != 0x50) continue; \
2256 /* Bug link files show up as free block. */ \
2257 if (!ptr[0xa]) continue; \
2259 if (pfile[0] == 0) { \
2260 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2261 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2262 } else for (i=0; i<20; i++) { \
2263 if (pfile[i] == ptr[i]) { \
2264 dir->name[i] = ptr[i]; continue; } \
2265 if (pfile[i] == '?') { \
2266 dir->name[i] = ptr[i]; continue; } \
2267 if (pfile[i] == '*') { \
2268 strcpy(dir->name+i, ptr+i); break; } \
2271 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2272 if (match == 0) { continue; } \
2280 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2283 void psxBios_firstfile() { // 42
2284 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2291 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2296 if (pa0 != INVALID_PTR) {
2300 if (!strncmp(pa0, "bu00", 4)) {
2301 // firstfile() calls _card_read() internally, so deliver it's event
2302 DeliverEvent(0x11, 0x2);
2304 } else if (!strncmp(pa0, "bu10", 4)) {
2305 // firstfile() calls _card_read() internally, so deliver it's event
2306 DeliverEvent(0x11, 0x2);
2315 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2318 void psxBios_nextfile() { // 43
2319 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2325 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2330 if (!strncmp(ffile, "bu00", 4)) {
2334 if (!strncmp(ffile, "bu10", 4)) {
2341 #define burename(mcd) { \
2342 for (i=1; i<16; i++) { \
2343 int namelen, j, xor = 0; \
2344 ptr = Mcd##mcd##Data + 128 * i; \
2345 if ((*ptr & 0xF0) != 0x50) continue; \
2346 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2347 namelen = strlen(Ra1+5); \
2348 memcpy(ptr+0xa, Ra1+5, namelen); \
2349 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2350 for (j=0; j<127; j++) xor^= ptr[j]; \
2352 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2359 * int rename(char *old, char *new);
2362 void psxBios_rename() { // 44
2369 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2374 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2375 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2379 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2388 #define budelete(mcd) { \
2389 for (i=1; i<16; i++) { \
2390 ptr = Mcd##mcd##Data + 128 * i; \
2391 if ((*ptr & 0xF0) != 0x50) continue; \
2392 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2393 *ptr = (*ptr & 0xf) | 0xA0; \
2394 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2395 SysPrintf("delete %s\n", ptr+0xa); \
2402 * int delete(char *name);
2405 void psxBios_delete() { // 45
2411 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2416 if (pa0 != INVALID_PTR) {
2417 if (!strncmp(pa0, "bu00", 4)) {
2421 if (!strncmp(pa0, "bu10", 4)) {
2429 void psxBios_InitCARD() { // 4a
2431 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2439 void psxBios_StartCARD() { // 4b
2441 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2444 if (CardState == 0) CardState = 1;
2449 void psxBios_StopCARD() { // 4c
2451 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2454 if (CardState == 1) CardState = 0;
2459 void psxBios__card_write() { // 0x4e
2464 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2467 Function also accepts sector 400h (a bug).
2468 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2472 /* Invalid sectors */
2476 card_active_chan = a0;
2479 if (pa2 != INVALID_PTR) {
2481 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2482 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2484 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2485 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2489 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2490 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2495 void psxBios__card_read() { // 0x4f
2500 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2503 Function also accepts sector 400h (a bug).
2504 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2508 /* Invalid sectors */
2512 card_active_chan = a0;
2515 if (pa2 != INVALID_PTR) {
2517 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2519 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2523 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2524 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2529 void psxBios__new_card() { // 0x50
2531 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2537 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2538 void psxBios__get_error(void) // 55
2544 void psxBios_Krom2RawAdd() { // 0x51
2547 const u32 table_8140[][2] = {
2548 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2549 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2550 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2551 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2552 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2553 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2554 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2555 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2556 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2560 const u32 table_889f[][2] = {
2561 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2562 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2563 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2564 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2565 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2566 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2567 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2568 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2572 if (a0 >= 0x8140 && a0 <= 0x84be) {
2573 while (table_8140[i][0] <= a0) i++;
2574 a0 -= table_8140[i - 1][0];
2575 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2576 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2577 while (table_889f[i][0] <= a0) i++;
2578 a0 -= table_889f[i - 1][0];
2579 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2587 void psxBios_GetC0Table() { // 56
2589 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2592 v0 = 0x674; pc0 = ra;
2595 void psxBios_GetB0Table() { // 57
2597 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2600 v0 = 0x874; pc0 = ra;
2603 void psxBios__card_chan() { // 0x58
2605 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2608 v0 = card_active_chan;
2612 void psxBios_ChangeClearPad() { // 5b
2614 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2620 void psxBios__card_status() { // 5c
2622 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2625 v0 = card_active_chan;
2629 void psxBios__card_wait() { // 5d
2631 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2638 /* System calls C0 */
2641 * int SysEnqIntRP(int index , long *queue);
2644 void psxBios_SysEnqIntRP() { // 02
2646 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2655 * int SysDeqIntRP(int index , long *queue);
2658 void psxBios_SysDeqIntRP() { // 03
2660 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2668 void psxBios_ChangeClearRCnt() { // 0a
2672 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2675 ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2679 // psxRegs.CP0.n.Status|= 0x404;
2683 void psxBios_dummy() {
2685 PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2690 void (*biosA0[256])();
2691 void (*biosB0[256])();
2692 void (*biosC0[256])();
2694 #include "sjisfont.h"
2696 void psxBiosInit() {
2702 for(i = 0; i < 256; i++) {
2707 biosA0[0x3e] = psxBios_puts;
2708 biosA0[0x3f] = psxBios_printf;
2710 biosB0[0x3d] = psxBios_putchar;
2711 biosB0[0x3f] = psxBios_puts;
2713 if (!Config.HLE) return;
2715 for(i = 0; i < 256; i++) {
2716 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2717 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2718 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2721 biosA0[0x00] = psxBios_open;
2722 biosA0[0x01] = psxBios_lseek;
2723 biosA0[0x02] = psxBios_read;
2724 biosA0[0x03] = psxBios_write;
2725 biosA0[0x04] = psxBios_close;
2726 //biosA0[0x05] = psxBios_ioctl;
2727 //biosA0[0x06] = psxBios_exit;
2728 //biosA0[0x07] = psxBios_sys_a0_07;
2729 biosA0[0x08] = psxBios_getc;
2730 biosA0[0x09] = psxBios_putc;
2731 biosA0[0x0a] = psxBios_todigit;
2732 //biosA0[0x0b] = psxBios_atof;
2733 //biosA0[0x0c] = psxBios_strtoul;
2734 //biosA0[0x0d] = psxBios_strtol;
2735 biosA0[0x0e] = psxBios_abs;
2736 biosA0[0x0f] = psxBios_labs;
2737 biosA0[0x10] = psxBios_atoi;
2738 biosA0[0x11] = psxBios_atol;
2739 //biosA0[0x12] = psxBios_atob;
2740 biosA0[0x13] = psxBios_setjmp;
2741 biosA0[0x14] = psxBios_longjmp;
2742 biosA0[0x15] = psxBios_strcat;
2743 biosA0[0x16] = psxBios_strncat;
2744 biosA0[0x17] = psxBios_strcmp;
2745 biosA0[0x18] = psxBios_strncmp;
2746 biosA0[0x19] = psxBios_strcpy;
2747 biosA0[0x1a] = psxBios_strncpy;
2748 biosA0[0x1b] = psxBios_strlen;
2749 biosA0[0x1c] = psxBios_index;
2750 biosA0[0x1d] = psxBios_rindex;
2751 biosA0[0x1e] = psxBios_strchr;
2752 biosA0[0x1f] = psxBios_strrchr;
2753 biosA0[0x20] = psxBios_strpbrk;
2754 biosA0[0x21] = psxBios_strspn;
2755 biosA0[0x22] = psxBios_strcspn;
2756 biosA0[0x23] = psxBios_strtok;
2757 biosA0[0x24] = psxBios_strstr;
2758 biosA0[0x25] = psxBios_toupper;
2759 biosA0[0x26] = psxBios_tolower;
2760 biosA0[0x27] = psxBios_bcopy;
2761 biosA0[0x28] = psxBios_bzero;
2762 biosA0[0x29] = psxBios_bcmp;
2763 biosA0[0x2a] = psxBios_memcpy;
2764 biosA0[0x2b] = psxBios_memset;
2765 biosA0[0x2c] = psxBios_memmove;
2766 biosA0[0x2d] = psxBios_memcmp;
2767 biosA0[0x2e] = psxBios_memchr;
2768 biosA0[0x2f] = psxBios_rand;
2769 biosA0[0x30] = psxBios_srand;
2770 biosA0[0x31] = psxBios_qsort;
2771 //biosA0[0x32] = psxBios_strtod;
2772 biosA0[0x33] = psxBios_malloc;
2773 biosA0[0x34] = psxBios_free;
2774 //biosA0[0x35] = psxBios_lsearch;
2775 //biosA0[0x36] = psxBios_bsearch;
2776 biosA0[0x37] = psxBios_calloc;
2777 biosA0[0x38] = psxBios_realloc;
2778 biosA0[0x39] = psxBios_InitHeap;
2779 //biosA0[0x3a] = psxBios__exit;
2780 biosA0[0x3b] = psxBios_getchar;
2781 biosA0[0x3c] = psxBios_putchar;
2782 //biosA0[0x3d] = psxBios_gets;
2783 //biosA0[0x40] = psxBios_sys_a0_40;
2784 //biosA0[0x41] = psxBios_LoadTest;
2785 biosA0[0x42] = psxBios_Load;
2786 biosA0[0x43] = psxBios_Exec;
2787 biosA0[0x44] = psxBios_FlushCache;
2788 //biosA0[0x45] = psxBios_InstallInterruptHandler;
2789 biosA0[0x46] = psxBios_GPU_dw;
2790 biosA0[0x47] = psxBios_mem2vram;
2791 biosA0[0x48] = psxBios_SendGPU;
2792 biosA0[0x49] = psxBios_GPU_cw;
2793 biosA0[0x4a] = psxBios_GPU_cwb;
2794 biosA0[0x4b] = psxBios_GPU_SendPackets;
2795 biosA0[0x4c] = psxBios_sys_a0_4c;
2796 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2797 //biosA0[0x4e] = psxBios_GPU_sync;
2798 //biosA0[0x4f] = psxBios_sys_a0_4f;
2799 //biosA0[0x50] = psxBios_sys_a0_50;
2800 biosA0[0x51] = psxBios_LoadExec;
2801 //biosA0[0x52] = psxBios_GetSysSp;
2802 //biosA0[0x53] = psxBios_sys_a0_53;
2803 //biosA0[0x54] = psxBios__96_init_a54;
2804 //biosA0[0x55] = psxBios__bu_init_a55;
2805 //biosA0[0x56] = psxBios__96_remove_a56;
2806 //biosA0[0x57] = psxBios_sys_a0_57;
2807 //biosA0[0x58] = psxBios_sys_a0_58;
2808 //biosA0[0x59] = psxBios_sys_a0_59;
2809 //biosA0[0x5a] = psxBios_sys_a0_5a;
2810 //biosA0[0x5b] = psxBios_dev_tty_init;
2811 //biosA0[0x5c] = psxBios_dev_tty_open;
2812 //biosA0[0x5d] = psxBios_sys_a0_5d;
2813 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2814 //biosA0[0x5f] = psxBios_dev_cd_open;
2815 //biosA0[0x60] = psxBios_dev_cd_read;
2816 //biosA0[0x61] = psxBios_dev_cd_close;
2817 //biosA0[0x62] = psxBios_dev_cd_firstfile;
2818 //biosA0[0x63] = psxBios_dev_cd_nextfile;
2819 //biosA0[0x64] = psxBios_dev_cd_chdir;
2820 //biosA0[0x65] = psxBios_dev_card_open;
2821 //biosA0[0x66] = psxBios_dev_card_read;
2822 //biosA0[0x67] = psxBios_dev_card_write;
2823 //biosA0[0x68] = psxBios_dev_card_close;
2824 //biosA0[0x69] = psxBios_dev_card_firstfile;
2825 //biosA0[0x6a] = psxBios_dev_card_nextfile;
2826 //biosA0[0x6b] = psxBios_dev_card_erase;
2827 //biosA0[0x6c] = psxBios_dev_card_undelete;
2828 //biosA0[0x6d] = psxBios_dev_card_format;
2829 //biosA0[0x6e] = psxBios_dev_card_rename;
2830 //biosA0[0x6f] = psxBios_dev_card_6f;
2831 biosA0[0x70] = psxBios__bu_init;
2832 biosA0[0x71] = psxBios__96_init;
2833 biosA0[0x72] = psxBios__96_remove;
2834 //biosA0[0x73] = psxBios_sys_a0_73;
2835 //biosA0[0x74] = psxBios_sys_a0_74;
2836 //biosA0[0x75] = psxBios_sys_a0_75;
2837 //biosA0[0x76] = psxBios_sys_a0_76;
2838 //biosA0[0x77] = psxBios_sys_a0_77;
2839 //biosA0[0x78] = psxBios__96_CdSeekL;
2840 //biosA0[0x79] = psxBios_sys_a0_79;
2841 //biosA0[0x7a] = psxBios_sys_a0_7a;
2842 //biosA0[0x7b] = psxBios_sys_a0_7b;
2843 //biosA0[0x7c] = psxBios__96_CdGetStatus;
2844 //biosA0[0x7d] = psxBios_sys_a0_7d;
2845 //biosA0[0x7e] = psxBios__96_CdRead;
2846 //biosA0[0x7f] = psxBios_sys_a0_7f;
2847 //biosA0[0x80] = psxBios_sys_a0_80;
2848 //biosA0[0x81] = psxBios_sys_a0_81;
2849 //biosA0[0x82] = psxBios_sys_a0_82;
2850 //biosA0[0x83] = psxBios_sys_a0_83;
2851 //biosA0[0x84] = psxBios_sys_a0_84;
2852 //biosA0[0x85] = psxBios__96_CdStop;
2853 //biosA0[0x86] = psxBios_sys_a0_86;
2854 //biosA0[0x87] = psxBios_sys_a0_87;
2855 //biosA0[0x88] = psxBios_sys_a0_88;
2856 //biosA0[0x89] = psxBios_sys_a0_89;
2857 //biosA0[0x8a] = psxBios_sys_a0_8a;
2858 //biosA0[0x8b] = psxBios_sys_a0_8b;
2859 //biosA0[0x8c] = psxBios_sys_a0_8c;
2860 //biosA0[0x8d] = psxBios_sys_a0_8d;
2861 //biosA0[0x8e] = psxBios_sys_a0_8e;
2862 //biosA0[0x8f] = psxBios_sys_a0_8f;
2863 //biosA0[0x90] = psxBios_sys_a0_90;
2864 //biosA0[0x91] = psxBios_sys_a0_91;
2865 //biosA0[0x92] = psxBios_sys_a0_92;
2866 //biosA0[0x93] = psxBios_sys_a0_93;
2867 //biosA0[0x94] = psxBios_sys_a0_94;
2868 //biosA0[0x95] = psxBios_sys_a0_95;
2869 //biosA0[0x96] = psxBios_AddCDROMDevice;
2870 //biosA0[0x97] = psxBios_AddMemCardDevide;
2871 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2872 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2873 //biosA0[0x9a] = psxBios_sys_a0_9a;
2874 //biosA0[0x9b] = psxBios_sys_a0_9b;
2875 //biosA0[0x9c] = psxBios_SetConf;
2876 //biosA0[0x9d] = psxBios_GetConf;
2877 //biosA0[0x9e] = psxBios_sys_a0_9e;
2878 biosA0[0x9f] = psxBios_SetMem;
2879 //biosA0[0xa0] = psxBios__boot;
2880 //biosA0[0xa1] = psxBios_SystemError;
2881 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2882 //biosA0[0xa3] = psxBios_DequeueCdIntr;
2883 //biosA0[0xa4] = psxBios_sys_a0_a4;
2884 //biosA0[0xa5] = psxBios_ReadSector;
2885 biosA0[0xa6] = psxBios_get_cd_status;
2886 //biosA0[0xa7] = psxBios_bufs_cb_0;
2887 //biosA0[0xa8] = psxBios_bufs_cb_1;
2888 //biosA0[0xa9] = psxBios_bufs_cb_2;
2889 //biosA0[0xaa] = psxBios_bufs_cb_3;
2890 biosA0[0xab] = psxBios__card_info;
2891 biosA0[0xac] = psxBios__card_load;
2892 //biosA0[0axd] = psxBios__card_auto;
2893 //biosA0[0xae] = psxBios_bufs_cd_4;
2894 //biosA0[0xaf] = psxBios_sys_a0_af;
2895 //biosA0[0xb0] = psxBios_sys_a0_b0;
2896 //biosA0[0xb1] = psxBios_sys_a0_b1;
2897 //biosA0[0xb2] = psxBios_do_a_long_jmp
2898 //biosA0[0xb3] = psxBios_sys_a0_b3;
2899 //biosA0[0xb4] = psxBios_sub_function;
2900 //*******************B0 CALLS****************************
2901 //biosB0[0x00] = psxBios_SysMalloc;
2902 //biosB0[0x01] = psxBios_sys_b0_01;
2903 biosB0[0x02] = psxBios_SetRCnt;
2904 biosB0[0x03] = psxBios_GetRCnt;
2905 biosB0[0x04] = psxBios_StartRCnt;
2906 biosB0[0x05] = psxBios_StopRCnt;
2907 biosB0[0x06] = psxBios_ResetRCnt;
2908 biosB0[0x07] = psxBios_DeliverEvent;
2909 biosB0[0x08] = psxBios_OpenEvent;
2910 biosB0[0x09] = psxBios_CloseEvent;
2911 biosB0[0x0a] = psxBios_WaitEvent;
2912 biosB0[0x0b] = psxBios_TestEvent;
2913 biosB0[0x0c] = psxBios_EnableEvent;
2914 biosB0[0x0d] = psxBios_DisableEvent;
2915 biosB0[0x0e] = psxBios_OpenTh;
2916 biosB0[0x0f] = psxBios_CloseTh;
2917 biosB0[0x10] = psxBios_ChangeTh;
2918 //biosB0[0x11] = psxBios_psxBios_b0_11;
2919 biosB0[0x12] = psxBios_InitPAD;
2920 biosB0[0x13] = psxBios_StartPAD;
2921 biosB0[0x14] = psxBios_StopPAD;
2922 biosB0[0x15] = psxBios_PAD_init;
2923 biosB0[0x16] = psxBios_PAD_dr;
2924 biosB0[0x17] = psxBios_ReturnFromException;
2925 biosB0[0x18] = psxBios_ResetEntryInt;
2926 biosB0[0x19] = psxBios_HookEntryInt;
2927 //biosB0[0x1a] = psxBios_sys_b0_1a;
2928 //biosB0[0x1b] = psxBios_sys_b0_1b;
2929 //biosB0[0x1c] = psxBios_sys_b0_1c;
2930 //biosB0[0x1d] = psxBios_sys_b0_1d;
2931 //biosB0[0x1e] = psxBios_sys_b0_1e;
2932 //biosB0[0x1f] = psxBios_sys_b0_1f;
2933 biosB0[0x20] = psxBios_UnDeliverEvent;
2934 //biosB0[0x21] = psxBios_sys_b0_21;
2935 //biosB0[0x22] = psxBios_sys_b0_22;
2936 //biosB0[0x23] = psxBios_sys_b0_23;
2937 //biosB0[0x24] = psxBios_sys_b0_24;
2938 //biosB0[0x25] = psxBios_sys_b0_25;
2939 //biosB0[0x26] = psxBios_sys_b0_26;
2940 //biosB0[0x27] = psxBios_sys_b0_27;
2941 //biosB0[0x28] = psxBios_sys_b0_28;
2942 //biosB0[0x29] = psxBios_sys_b0_29;
2943 //biosB0[0x2a] = psxBios_sys_b0_2a;
2944 //biosB0[0x2b] = psxBios_sys_b0_2b;
2945 //biosB0[0x2c] = psxBios_sys_b0_2c;
2946 //biosB0[0x2d] = psxBios_sys_b0_2d;
2947 //biosB0[0x2e] = psxBios_sys_b0_2e;
2948 //biosB0[0x2f] = psxBios_sys_b0_2f;
2949 //biosB0[0x30] = psxBios_sys_b0_30;
2950 //biosB0[0x31] = psxBios_sys_b0_31;
2951 biosB0[0x32] = psxBios_open;
2952 biosB0[0x33] = psxBios_lseek;
2953 biosB0[0x34] = psxBios_read;
2954 biosB0[0x35] = psxBios_write;
2955 biosB0[0x36] = psxBios_close;
2956 //biosB0[0x37] = psxBios_ioctl;
2957 //biosB0[0x38] = psxBios_exit;
2958 //biosB0[0x39] = psxBios_sys_b0_39;
2959 //biosB0[0x3a] = psxBios_getc;
2960 //biosB0[0x3b] = psxBios_putc;
2961 biosB0[0x3c] = psxBios_getchar;
2962 //biosB0[0x3e] = psxBios_gets;
2963 //biosB0[0x40] = psxBios_cd;
2964 biosB0[0x41] = psxBios_format;
2965 biosB0[0x42] = psxBios_firstfile;
2966 biosB0[0x43] = psxBios_nextfile;
2967 biosB0[0x44] = psxBios_rename;
2968 biosB0[0x45] = psxBios_delete;
2969 //biosB0[0x46] = psxBios_undelete;
2970 //biosB0[0x47] = psxBios_AddDevice;
2971 //biosB0[0x48] = psxBios_RemoteDevice;
2972 //biosB0[0x49] = psxBios_PrintInstalledDevices;
2973 biosB0[0x4a] = psxBios_InitCARD;
2974 biosB0[0x4b] = psxBios_StartCARD;
2975 biosB0[0x4c] = psxBios_StopCARD;
2976 //biosB0[0x4d] = psxBios_sys_b0_4d;
2977 biosB0[0x4e] = psxBios__card_write;
2978 biosB0[0x4f] = psxBios__card_read;
2979 biosB0[0x50] = psxBios__new_card;
2980 biosB0[0x51] = psxBios_Krom2RawAdd;
2981 //biosB0[0x52] = psxBios_sys_b0_52;
2982 //biosB0[0x53] = psxBios_sys_b0_53;
2983 //biosB0[0x54] = psxBios__get_errno;
2984 biosB0[0x55] = psxBios__get_error;
2985 biosB0[0x56] = psxBios_GetC0Table;
2986 biosB0[0x57] = psxBios_GetB0Table;
2987 biosB0[0x58] = psxBios__card_chan;
2988 //biosB0[0x59] = psxBios_sys_b0_59;
2989 //biosB0[0x5a] = psxBios_sys_b0_5a;
2990 biosB0[0x5b] = psxBios_ChangeClearPad;
2991 biosB0[0x5c] = psxBios__card_status;
2992 biosB0[0x5d] = psxBios__card_wait;
2993 //*******************C0 CALLS****************************
2994 //biosC0[0x00] = psxBios_InitRCnt;
2995 //biosC0[0x01] = psxBios_InitException;
2996 biosC0[0x02] = psxBios_SysEnqIntRP;
2997 biosC0[0x03] = psxBios_SysDeqIntRP;
2998 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
2999 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3000 //biosC0[0x06] = psxBios_ExceptionHandler;
3001 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3002 //biosC0[0x08] = psxBios_SysInitMemory;
3003 //biosC0[0x09] = psxBios_SysInitKMem;
3004 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3005 //biosC0[0x0b] = psxBios_SystemError;
3006 //biosC0[0x0c] = psxBios_InitDefInt;
3007 //biosC0[0x0d] = psxBios_sys_c0_0d;
3008 //biosC0[0x0e] = psxBios_sys_c0_0e;
3009 //biosC0[0x0f] = psxBios_sys_c0_0f;
3010 //biosC0[0x10] = psxBios_sys_c0_10;
3011 //biosC0[0x11] = psxBios_sys_c0_11;
3012 //biosC0[0x12] = psxBios_InstallDevices;
3013 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3014 //biosC0[0x14] = psxBios_sys_c0_14;
3015 //biosC0[0x15] = psxBios__cdevinput;
3016 //biosC0[0x16] = psxBios__cdevscan;
3017 //biosC0[0x17] = psxBios__circgetc;
3018 //biosC0[0x18] = psxBios__circputc;
3019 //biosC0[0x19] = psxBios_ioabort;
3020 //biosC0[0x1a] = psxBios_sys_c0_1a
3021 //biosC0[0x1b] = psxBios_KernelRedirect;
3022 //biosC0[0x1c] = psxBios_PatchAOTable;
3023 //************** THE END ***************************************
3026 size = sizeof(EvCB) * 32;
3027 EventCB = (void *)&psxR[base]; base += size * 6;
3028 memset(EventCB, 0, size * 6);
3030 EvEV = EventCB + 32;
3031 RcEV = EventCB + 32 * 2;
3032 UeEV = EventCB + 32 * 3;
3033 SwEV = EventCB + 32 * 4;
3034 ThEV = EventCB + 32 * 5;
3036 ptr = (u32 *)&psxM[0x0874]; // b0 table
3037 ptr[0] = SWAPu32(0x4c54 - 0x884);
3039 ptr = (u32 *)&psxM[0x0674]; // c0 table
3040 ptr[6] = SWAPu32(0xc80);
3042 memset(SysIntRP, 0, sizeof(SysIntRP));
3043 memset(ThreadCB, 0, sizeof(ThreadCB));
3044 ThreadCB[0].status = 2; // main thread
3051 pad_buf1len = pad_buf2len = 0;
3057 memset(FDesc, 0, sizeof(FDesc));
3058 card_active_chan = 0;
3060 psxMu32ref(0x0150) = SWAPu32(0x160);
3061 psxMu32ref(0x0154) = SWAPu32(0x320);
3062 psxMu32ref(0x0160) = SWAPu32(0x248);
3063 strcpy((char *)&psxM[0x248], "bu");
3064 /* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3065 psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3066 psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3067 psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3068 psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3071 psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
3072 /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
3073 Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3074 //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
3075 psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3076 psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3077 psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3078 psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3079 psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3080 psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3081 psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3082 psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3084 // initial stack pointer for BIOS interrupt
3085 psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3088 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3091 len = 0x80000 - 0x66000;
3092 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3093 len = 0x80000 - 0x69d68;
3094 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3097 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3099 hleSoftCall = FALSE;
3101 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3102 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3103 Here are some examples of games not working with this fix in place :
3104 R-type won't get past the Irem logo if not implemented.
3105 Crash Team Racing will softlock after the Sony logo.
3108 psxMu32ref(0x0000) = SWAPu32(0x00000003);
3110 But overwritten by 00000003h after soon.
3111 psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3113 psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3114 psxMu32ref(0x0008) = SWAPu32(0x08000403);
3115 psxMu32ref(0x000C) = SWAPu32(0x00000000);
3118 void psxBiosShutdown() {
3121 #define psxBios_PADpoll(pad) { \
3122 PAD##pad##_startPoll(pad); \
3123 pad_buf##pad[0] = 0; \
3124 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3125 if (!(pad_buf##pad[1] & 0x0f)) { \
3128 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3130 PAD##pad##_poll(0); \
3132 while (bufcount--) { \
3133 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3137 void biosInterrupt() {
3140 // if (psxHu32(0x1070) & 0x1) { // Vsync
3141 if (pad_buf != NULL) {
3142 u32 *buf = (u32*)pad_buf;
3144 if (!Config.UseNet) {
3146 if (PAD1_poll(0x42) == 0x23) {
3148 *buf = PAD1_poll(0) << 8;
3149 *buf |= PAD1_poll(0);
3151 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3152 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3155 *buf = PAD1_poll(0) << 8;
3156 *buf|= PAD1_poll(0);
3160 if (PAD2_poll(0x42) == 0x23) {
3162 *buf |= PAD2_poll(0) << 24;
3163 *buf |= PAD2_poll(0) << 16;
3165 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3166 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3169 *buf |= PAD2_poll(0) << 24;
3170 *buf |= PAD2_poll(0) << 16;
3178 data = PAD1_poll(0) << 8;
3179 data |= PAD1_poll(0);
3181 if (NET_sendPadData(&data, 2) == -1)
3184 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3186 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3190 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3193 if (NET_sendPadData(pad_buf1, i) == -1)
3196 if (NET_recvPadData(pad_buf1, 1) == -1)
3198 if (NET_recvPadData(pad_buf2, 2) == -1)
3212 if (psxHu32(0x1070) & 0x1) { // Vsync
3213 if (RcEV[3][1].status == EvStACTIVE) {
3214 softCall(RcEV[3][1].fhandler);
3215 // hwWrite32(0x1f801070, ~(1));
3219 if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3222 for (i = 0; i < 3; i++) {
3223 if (psxHu32(0x1070) & (1 << (i + 4))) {
3224 if (RcEV[i][1].status == EvStACTIVE) {
3225 softCall(RcEV[i][1].fhandler);
3227 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3233 void psxBiosException() {
3236 switch (psxRegs.CP0.n.Cause & 0x3c) {
3237 case 0x00: // Interrupt
3238 interrupt_r26=psxRegs.CP0.n.EPC;
3240 // PSXCPU_LOG("interrupt\n");
3244 sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3248 for (i = 0; i < 8; i++) {
3250 u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3257 if (jmp_int != NULL) {
3260 psxHwWrite32(0x1f801070, 0xffffffff);
3265 for (i = 0; i < 8; i++) // s0-s7
3266 psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3273 psxHwWrite16(0x1f801070, 0);
3276 case 0x20: // Syscall
3278 PSXCPU_LOG("syscall exp %x\n", a0);
3281 case 1: // EnterCritical - disable irq's
3282 /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3283 v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3284 psxRegs.CP0.n.Status &= ~0x404;
3287 case 2: // ExitCritical - enable irq's
3288 psxRegs.CP0.n.Status |= 0x404;
3290 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3294 pc0 = psxRegs.CP0.n.EPC + 4;
3296 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3297 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3302 PSXCPU_LOG("unknown bios exception!\n");
3307 pc0 = psxRegs.CP0.n.EPC;
3308 if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3310 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3311 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3314 #define bfreeze(ptr, size) { \
3315 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3316 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3320 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3321 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3323 #define bfreezepsxMptr(ptr, type) { \
3325 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3326 else psxRu32ref(base) = 0; \
3328 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3329 else (ptr) = NULL; \
3331 base += sizeof(u32); \
3334 void psxBiosFreeze(int Mode) {
3337 bfreezepsxMptr(jmp_int, u32);
3338 bfreezepsxMptr(pad_buf, int);
3339 bfreezepsxMptr(pad_buf1, char);
3340 bfreezepsxMptr(pad_buf2, char);
3341 bfreezepsxMptr(heap_addr, u32);
3342 bfreezel(&pad_buf1len);
3343 bfreezel(&pad_buf2len);
3346 bfreezel(&CardState);
3348 bfreezel(&CurThread);
3350 bfreezel(&card_active_chan);
3351 bfreezel(&pad_stopped);
3352 bfreezel(&heap_size);