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(EXEC_CALLER_HLE);
293 static inline void softCall2(u32 pc) {
300 while (pc0 != 0x80001000) psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
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 static void psxBios_printf_psxout() { // 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;
1320 if (psp != INVALID_PTR)
1321 memcpy(psp, save, 4 * 4);
1323 SysPrintf("%s", tmp);
1326 void psxBios_printf() { // 0x3f
1327 psxBios_printf_psxout();
1331 void psxBios_format() { // 0x41
1332 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1334 CreateMcd(Config.Mcd1);
1335 LoadMcd(1, Config.Mcd1);
1338 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1340 CreateMcd(Config.Mcd2);
1341 LoadMcd(2, Config.Mcd2);
1352 * long Load(char *name, struct EXEC *header);
1355 void psxBios_Load() { // 0x42
1360 PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1);
1364 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1365 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1373 * int Exec(struct EXEC *header , int argc , char **argv);
1376 void psxBios_Exec() { // 43
1377 EXEC *header = (EXEC*)Ra0;
1381 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1391 if (header->S_addr != 0) {
1392 tmp = header->S_addr + header->s_size;
1408 void psxBios_FlushCache() { // 44
1410 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1412 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1413 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1417 void psxBios_GPU_dw() { // 0x46
1422 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1425 GPU_writeData(0xa0000000);
1426 GPU_writeData((a1<<0x10)|(a0&0xffff));
1427 GPU_writeData((a3<<0x10)|(a2&0xffff));
1429 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1432 GPU_writeData(SWAPu32(*ptr++));
1438 void psxBios_mem2vram() { // 0x47
1441 GPU_writeData(0xa0000000);
1442 GPU_writeData((a1<<0x10)|(a0&0xffff));
1443 GPU_writeData((a3<<0x10)|(a2&0xffff));
1444 size = ((((a2 * a3) / 2) >> 4) << 16);
1445 GPU_writeStatus(0x04000002);
1446 psxHwWrite32(0x1f8010f4,0);
1447 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1448 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1449 psxHwWrite32(0x1f8010a4, size | 0x10);
1450 psxHwWrite32(0x1f8010a8,0x01000201);
1455 void psxBios_SendGPU() { // 0x48
1456 GPU_writeStatus(a0);
1461 void psxBios_GPU_cw() { // 0x49
1468 void psxBios_GPU_cwb() { // 0x4a
1469 u32 *ptr = (u32*)Ra0;
1474 GPU_writeData(SWAPu32(*ptr++));
1480 void psxBios_GPU_SendPackets() { //4b:
1482 GPU_writeStatus(0x04000002);
1483 psxHwWrite32(0x1f8010f4,0);
1484 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1485 psxHwWrite32(0x1f8010a0,a0);
1486 psxHwWrite32(0x1f8010a4,0);
1487 psxHwWrite32(0x1f8010a8,0x010000401);
1491 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1492 psxHwWrite32(0x1f8010a8,0x00000401);
1493 GPU_writeData(0x0400000);
1494 GPU_writeData(0x0200000);
1495 GPU_writeData(0x0100000);
1500 void psxBios_GPU_GetGPUStatus() { // 0x4d
1501 v0 = GPU_readStatus();
1507 void psxBios_LoadExec() { // 51
1508 EXEC *header = (EXEC*)PSXM(0xf000);
1512 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1514 s_addr = a1; s_size = a2;
1519 header->S_addr = s_addr;
1520 header->s_size = s_size;
1522 a0 = 0xf000; a1 = 0; a2 = 0;
1526 void psxBios__bu_init() { // 70
1528 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1531 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1532 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1537 void psxBios__96_init() { // 71
1539 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1545 void psxBios__96_remove() { // 72
1547 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1553 void psxBios_SetMem() { // 9f
1554 u32 new = psxHu32(0x1060);
1557 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1562 psxHu32ref(0x1060) = SWAP32(new);
1563 psxMu32ref(0x060) = a0;
1564 SysPrintf("Change effective memory : %d MBytes\n",a0);
1568 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1569 psxMu32ref(0x060) = a0;
1570 SysPrintf("Change effective memory : %d MBytes\n",a0);
1573 SysPrintf("Effective memory must be 2/8 MBytes\n");
1580 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1581 void psxBios_get_cd_status(void) //a6
1587 void psxBios__card_info() { // ab
1589 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1592 card_active_chan = a0;
1593 port = card_active_chan >> 4;
1599 if (McdDisable[port & 1])
1604 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1610 if (McdDisable[0] && McdDisable[1])
1613 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1614 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1615 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
1619 void psxBios__card_load() { // ac
1621 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1624 card_active_chan = a0;
1626 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1627 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1632 /* System calls B0 */
1634 void psxBios_SetRCnt() { // 02
1636 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1643 psxRcntWtarget(a0, a1);
1644 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1645 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1646 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1647 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1648 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1650 psxRcntWmode(a0, mode);
1655 void psxBios_GetRCnt() { // 03
1657 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1661 if (a0 != 3) v0 = psxRcntRcount(a0);
1666 void psxBios_StartRCnt() { // 04
1668 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1672 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1673 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1677 void psxBios_StopRCnt() { // 05
1679 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1683 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1684 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1688 void psxBios_ResetRCnt() { // 06
1690 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1695 psxRcntWmode(a0, 0);
1696 psxRcntWtarget(a0, 0);
1697 psxRcntWcount(a0, 0);
1703 /* gets ev for use with EventCB */
1705 ev = (a0 >> 24) & 0xf; \
1706 if (ev == 0xf) ev = 0x5; \
1710 /* gets spec for use with EventCB */
1714 case 0x0301: spec = 16; break; \
1715 case 0x0302: spec = 17; break; \
1717 for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1721 void psxBios_DeliverEvent() { // 07
1729 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1732 DeliverEvent(ev, spec);
1737 void psxBios_OpenEvent() { // 08
1745 PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1748 EventCB[ev][spec].status = EvStWAIT;
1749 EventCB[ev][spec].mode = a2;
1750 EventCB[ev][spec].fhandler = a3;
1752 v0 = ev | (spec << 8);
1756 void psxBios_CloseEvent() { // 09
1760 spec = (a0 >> 8) & 0xff;
1763 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1766 EventCB[ev][spec].status = EvStUNUSED;
1771 void psxBios_WaitEvent() { // 0a
1775 spec = (a0 >> 8) & 0xff;
1777 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1779 if (EventCB[ev][spec].status == EvStUNUSED)
1786 if (EventCB[ev][spec].status == EvStALREADY)
1788 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1789 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1799 void psxBios_TestEvent() { // 0b
1803 spec = (a0 >> 8) & 0xff;
1805 if (EventCB[ev][spec].status == EvStALREADY)
1807 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1816 PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1822 void psxBios_EnableEvent() { // 0c
1826 spec = (a0 >> 8) & 0xff;
1829 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1832 EventCB[ev][spec].status = EvStACTIVE;
1837 void psxBios_DisableEvent() { // 0d
1841 spec = (a0 >> 8) & 0xff;
1844 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1847 EventCB[ev][spec].status = EvStWAIT;
1853 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1856 void psxBios_OpenTh() { // 0e
1859 for (th=1; th<8; th++)
1861 if (ThreadCB[th].status == 0) break;
1865 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1866 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1868 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1875 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1878 ThreadCB[th].status = 1;
1879 ThreadCB[th].func = a0;
1880 ThreadCB[th].reg[29] = a1;
1881 ThreadCB[th].reg[28] = a2;
1887 * int CloseTh(long thread);
1890 void psxBios_CloseTh() { // 0f
1894 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
1896 /* The return value is always 1 (even if the handle was already closed). */
1898 if (ThreadCB[th].status != 0) {
1899 ThreadCB[th].status = 0;
1906 * int ChangeTh(long thread);
1909 void psxBios_ChangeTh() { // 10
1913 // PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
1915 /* The return value is always 1. */
1917 if (ThreadCB[th].status == 0 || CurThread == th) {
1920 if (ThreadCB[CurThread].status == 2) {
1921 ThreadCB[CurThread].status = 1;
1922 ThreadCB[CurThread].func = ra;
1923 memcpy(ThreadCB[CurThread].reg, psxRegs.GPR.r, 32*4);
1926 memcpy(psxRegs.GPR.r, ThreadCB[th].reg, 32*4);
1927 pc0 = ThreadCB[th].func;
1928 ThreadCB[th].status = 2;
1933 void psxBios_InitPAD() { // 0x12
1935 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
1938 pad_buf1 = (char*)Ra0;
1940 pad_buf2 = (char*)Ra2;
1946 void psxBios_StartPAD() { // 13
1948 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
1951 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
1952 psxRegs.CP0.n.SR |= 0x401;
1956 void psxBios_StopPAD() { // 14
1958 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
1966 void psxBios_PAD_init() { // 15
1968 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
1970 if (!(a0 == 0x20000000 || a0 == 0x20000001))
1976 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
1977 pad_buf = (int *)Ra1;
1979 psxRegs.CP0.n.SR |= 0x401;
1984 void psxBios_PAD_dr() { // 16
1986 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
1992 void psxBios_ReturnFromException() { // 17
1995 pc0 = psxRegs.CP0.n.EPC;
1997 if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;
1999 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
2002 void psxBios_ResetEntryInt() { // 18
2004 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2011 void psxBios_HookEntryInt() { // 19
2013 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
2016 jmp_int = (u32*)Ra0;
2020 void psxBios_UnDeliverEvent() { // 0x20
2028 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2031 if (EventCB[ev][spec].status == EvStALREADY &&
2032 EventCB[ev][spec].mode == EvMdNOINTR)
2033 EventCB[ev][spec].status = EvStACTIVE;
2038 char ffile[64], *pfile;
2041 static void buopen(int mcd, char *ptr, char *cfg)
2044 char *mcd_data = ptr;
2046 strcpy(FDesc[1 + mcd].name, Ra0+5);
2047 FDesc[1 + mcd].offset = 0;
2048 FDesc[1 + mcd].mode = a1;
2050 for (i=1; i<16; i++) {
2051 const char *fptr = mcd_data + 128 * i;
2052 if ((*fptr & 0xF0) != 0x50) continue;
2053 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2054 FDesc[1 + mcd].mcfile = i;
2055 SysPrintf("open %s\n", fptr+0xa);
2059 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2060 for (i=1; i<16; i++) {
2061 int j, xor, nblk = a1 >> 16;
2063 char *fptr = mcd_data + 128 * i;
2065 if ((*fptr & 0xF0) != 0xa0) continue;
2067 FDesc[1 + mcd].mcfile = i;
2070 fptr[5] = 0x20 * nblk;
2073 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2074 pptr = fptr2 = fptr;
2075 for(j=2; j<=nblk; j++) {
2077 for(i++; i<16; i++) {
2080 memset(fptr2, 0, 128);
2081 fptr2[0] = j < nblk ? 0x52 : 0x53;
2084 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2089 /* shouldn't this return ENOSPC if i == 16? */
2091 pptr[8] = pptr[9] = 0xff;
2092 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2094 SysPrintf("openC %s %d\n", ptr, nblk);
2096 /* just go ahead and resave them all */
2097 SaveMcd(cfg, ptr, 128, 128 * 15);
2100 /* shouldn't this return ENOSPC if i == 16? */
2105 * int open(char *name , int mode);
2108 void psxBios_open() { // 0x32
2112 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2117 if (pa0 != INVALID_PTR) {
2118 if (!strncmp(pa0, "bu00", 4)) {
2119 buopen(1, Mcd1Data, Config.Mcd1);
2122 if (!strncmp(pa0, "bu10", 4)) {
2123 buopen(2, Mcd2Data, Config.Mcd2);
2131 * int lseek(int fd , int offset , int whence);
2134 void psxBios_lseek() { // 0x33
2136 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2141 FDesc[a0].offset = a1;
2143 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2144 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2148 FDesc[a0].offset+= a1;
2149 v0 = FDesc[a0].offset;
2158 * int read(int fd , void *buf , int nbytes);
2161 void psxBios_read() { // 0x34
2166 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2171 if (pa1 != INVALID_PTR) {
2173 case 2: buread(pa1, 1, a2); break;
2174 case 3: buread(pa1, 2, a2); break;
2182 * int write(int fd , void *buf , int nbytes);
2185 void psxBios_write() { // 0x35/0x03
2190 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2194 if (pa1 == INVALID_PTR) {
2199 if (a0 == 1) { // stdout
2204 SysPrintf("%c", *ptr++); a2--;
2210 case 2: buwrite(pa1, 1, a2); break;
2211 case 3: buwrite(pa1, 2, a2); break;
2217 static void psxBios_write_psxout() {
2218 if (a0 == 1) { // stdout
2219 const char *ptr = Ra1;
2222 if (ptr != INVALID_PTR)
2224 SysPrintf("%c", *ptr++);
2228 static void psxBios_putchar_psxout() { // 3d
2229 SysPrintf("%c", (char)a0);
2232 static void psxBios_puts_psxout() { // 3e/3f
2233 SysPrintf("%s", Ra0);
2237 * int close(int fd);
2240 void psxBios_close() { // 0x36
2242 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2249 void psxBios_putchar() { // 3d
2250 SysPrintf("%c", (char)a0);
2254 void psxBios_puts() { // 3e/3f
2255 SysPrintf("%s", Ra0);
2260 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2261 * We want to mimic the PSX's behaviour in this case for bufile. */
2262 static size_t strlen_internal(char* p)
2264 size_t size_of_array = 0;
2265 while (*p++) size_of_array++;
2266 return size_of_array;
2269 #define bufile(mcd) { \
2270 size_t size_of_name = strlen_internal(dir->name); \
2271 while (nfile < 16) { \
2274 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2276 if ((*ptr & 0xF0) != 0x50) continue; \
2277 /* Bug link files show up as free block. */ \
2278 if (!ptr[0xa]) continue; \
2280 if (pfile[0] == 0) { \
2281 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2282 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2283 } else for (i=0; i<20; i++) { \
2284 if (pfile[i] == ptr[i]) { \
2285 dir->name[i] = ptr[i]; continue; } \
2286 if (pfile[i] == '?') { \
2287 dir->name[i] = ptr[i]; continue; } \
2288 if (pfile[i] == '*') { \
2289 strcpy(dir->name+i, ptr+i); break; } \
2292 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2293 if (match == 0) { continue; } \
2301 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2304 void psxBios_firstfile() { // 42
2305 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2312 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2317 if (pa0 != INVALID_PTR) {
2321 if (!strncmp(pa0, "bu00", 4)) {
2322 // firstfile() calls _card_read() internally, so deliver it's event
2323 DeliverEvent(0x11, 0x2);
2325 } else if (!strncmp(pa0, "bu10", 4)) {
2326 // firstfile() calls _card_read() internally, so deliver it's event
2327 DeliverEvent(0x11, 0x2);
2336 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2339 void psxBios_nextfile() { // 43
2340 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2346 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2351 if (!strncmp(ffile, "bu00", 4)) {
2355 if (!strncmp(ffile, "bu10", 4)) {
2362 #define burename(mcd) { \
2363 for (i=1; i<16; i++) { \
2364 int namelen, j, xor = 0; \
2365 ptr = Mcd##mcd##Data + 128 * i; \
2366 if ((*ptr & 0xF0) != 0x50) continue; \
2367 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2368 namelen = strlen(Ra1+5); \
2369 memcpy(ptr+0xa, Ra1+5, namelen); \
2370 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2371 for (j=0; j<127; j++) xor^= ptr[j]; \
2373 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2380 * int rename(char *old, char *new);
2383 void psxBios_rename() { // 44
2390 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2395 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2396 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2400 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2409 #define budelete(mcd) { \
2410 for (i=1; i<16; i++) { \
2411 ptr = Mcd##mcd##Data + 128 * i; \
2412 if ((*ptr & 0xF0) != 0x50) continue; \
2413 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2414 *ptr = (*ptr & 0xf) | 0xA0; \
2415 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2416 SysPrintf("delete %s\n", ptr+0xa); \
2423 * int delete(char *name);
2426 void psxBios_delete() { // 45
2432 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2437 if (pa0 != INVALID_PTR) {
2438 if (!strncmp(pa0, "bu00", 4)) {
2442 if (!strncmp(pa0, "bu10", 4)) {
2450 void psxBios_InitCARD() { // 4a
2452 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2460 void psxBios_StartCARD() { // 4b
2462 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2465 if (CardState == 0) CardState = 1;
2470 void psxBios_StopCARD() { // 4c
2472 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2475 if (CardState == 1) CardState = 0;
2480 void psxBios__card_write() { // 0x4e
2485 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2488 Function also accepts sector 400h (a bug).
2489 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2493 /* Invalid sectors */
2497 card_active_chan = a0;
2500 if (pa2 != INVALID_PTR) {
2502 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2503 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2505 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2506 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2510 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2511 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2516 void psxBios__card_read() { // 0x4f
2521 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2524 Function also accepts sector 400h (a bug).
2525 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2529 /* Invalid sectors */
2533 card_active_chan = a0;
2536 if (pa2 != INVALID_PTR) {
2538 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2540 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2544 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2545 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2550 void psxBios__new_card() { // 0x50
2552 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2558 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2559 void psxBios__get_error(void) // 55
2565 void psxBios_Krom2RawAdd() { // 0x51
2568 const u32 table_8140[][2] = {
2569 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2570 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2571 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2572 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2573 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2574 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2575 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2576 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2577 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2581 const u32 table_889f[][2] = {
2582 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2583 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2584 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2585 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2586 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2587 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2588 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2589 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2593 if (a0 >= 0x8140 && a0 <= 0x84be) {
2594 while (table_8140[i][0] <= a0) i++;
2595 a0 -= table_8140[i - 1][0];
2596 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2597 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2598 while (table_889f[i][0] <= a0) i++;
2599 a0 -= table_889f[i - 1][0];
2600 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2608 void psxBios_GetC0Table() { // 56
2610 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2613 v0 = 0x674; pc0 = ra;
2616 void psxBios_GetB0Table() { // 57
2618 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2621 v0 = 0x874; pc0 = ra;
2624 void psxBios__card_chan() { // 0x58
2626 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2629 v0 = card_active_chan;
2633 void psxBios_ChangeClearPad() { // 5b
2635 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2641 void psxBios__card_status() { // 5c
2643 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2646 v0 = card_active_chan;
2650 void psxBios__card_wait() { // 5d
2652 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2659 /* System calls C0 */
2662 * int SysEnqIntRP(int index , long *queue);
2665 void psxBios_SysEnqIntRP() { // 02
2667 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2676 * int SysDeqIntRP(int index , long *queue);
2679 void psxBios_SysDeqIntRP() { // 03
2681 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2689 void psxBios_ChangeClearRCnt() { // 0a
2693 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2696 ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2700 // psxRegs.CP0.n.SR|= 0x404;
2704 void psxBios_dummy() {
2706 PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2711 void (*biosA0[256])();
2712 void (*biosB0[256])();
2713 void (*biosC0[256])();
2715 #include "sjisfont.h"
2717 void psxBiosInit() {
2723 for(i = 0; i < 256; i++) {
2728 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
2729 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
2730 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
2731 biosA0[0x3f] = psxBios_printf_psxout;
2733 if (!Config.HLE) return;
2735 for(i = 0; i < 256; i++) {
2736 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2737 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2738 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2741 biosA0[0x00] = psxBios_open;
2742 biosA0[0x01] = psxBios_lseek;
2743 biosA0[0x02] = psxBios_read;
2744 biosA0[0x03] = psxBios_write;
2745 biosA0[0x04] = psxBios_close;
2746 //biosA0[0x05] = psxBios_ioctl;
2747 //biosA0[0x06] = psxBios_exit;
2748 //biosA0[0x07] = psxBios_sys_a0_07;
2749 biosA0[0x08] = psxBios_getc;
2750 biosA0[0x09] = psxBios_putc;
2751 biosA0[0x0a] = psxBios_todigit;
2752 //biosA0[0x0b] = psxBios_atof;
2753 //biosA0[0x0c] = psxBios_strtoul;
2754 //biosA0[0x0d] = psxBios_strtol;
2755 biosA0[0x0e] = psxBios_abs;
2756 biosA0[0x0f] = psxBios_labs;
2757 biosA0[0x10] = psxBios_atoi;
2758 biosA0[0x11] = psxBios_atol;
2759 //biosA0[0x12] = psxBios_atob;
2760 biosA0[0x13] = psxBios_setjmp;
2761 biosA0[0x14] = psxBios_longjmp;
2762 biosA0[0x15] = psxBios_strcat;
2763 biosA0[0x16] = psxBios_strncat;
2764 biosA0[0x17] = psxBios_strcmp;
2765 biosA0[0x18] = psxBios_strncmp;
2766 biosA0[0x19] = psxBios_strcpy;
2767 biosA0[0x1a] = psxBios_strncpy;
2768 biosA0[0x1b] = psxBios_strlen;
2769 biosA0[0x1c] = psxBios_index;
2770 biosA0[0x1d] = psxBios_rindex;
2771 biosA0[0x1e] = psxBios_strchr;
2772 biosA0[0x1f] = psxBios_strrchr;
2773 biosA0[0x20] = psxBios_strpbrk;
2774 biosA0[0x21] = psxBios_strspn;
2775 biosA0[0x22] = psxBios_strcspn;
2776 biosA0[0x23] = psxBios_strtok;
2777 biosA0[0x24] = psxBios_strstr;
2778 biosA0[0x25] = psxBios_toupper;
2779 biosA0[0x26] = psxBios_tolower;
2780 biosA0[0x27] = psxBios_bcopy;
2781 biosA0[0x28] = psxBios_bzero;
2782 biosA0[0x29] = psxBios_bcmp;
2783 biosA0[0x2a] = psxBios_memcpy;
2784 biosA0[0x2b] = psxBios_memset;
2785 biosA0[0x2c] = psxBios_memmove;
2786 biosA0[0x2d] = psxBios_memcmp;
2787 biosA0[0x2e] = psxBios_memchr;
2788 biosA0[0x2f] = psxBios_rand;
2789 biosA0[0x30] = psxBios_srand;
2790 biosA0[0x31] = psxBios_qsort;
2791 //biosA0[0x32] = psxBios_strtod;
2792 biosA0[0x33] = psxBios_malloc;
2793 biosA0[0x34] = psxBios_free;
2794 //biosA0[0x35] = psxBios_lsearch;
2795 //biosA0[0x36] = psxBios_bsearch;
2796 biosA0[0x37] = psxBios_calloc;
2797 biosA0[0x38] = psxBios_realloc;
2798 biosA0[0x39] = psxBios_InitHeap;
2799 //biosA0[0x3a] = psxBios__exit;
2800 biosA0[0x3b] = psxBios_getchar;
2801 biosA0[0x3c] = psxBios_putchar;
2802 //biosA0[0x3d] = psxBios_gets;
2803 //biosA0[0x40] = psxBios_sys_a0_40;
2804 //biosA0[0x41] = psxBios_LoadTest;
2805 biosA0[0x42] = psxBios_Load;
2806 biosA0[0x43] = psxBios_Exec;
2807 biosA0[0x44] = psxBios_FlushCache;
2808 //biosA0[0x45] = psxBios_InstallInterruptHandler;
2809 biosA0[0x46] = psxBios_GPU_dw;
2810 biosA0[0x47] = psxBios_mem2vram;
2811 biosA0[0x48] = psxBios_SendGPU;
2812 biosA0[0x49] = psxBios_GPU_cw;
2813 biosA0[0x4a] = psxBios_GPU_cwb;
2814 biosA0[0x4b] = psxBios_GPU_SendPackets;
2815 biosA0[0x4c] = psxBios_sys_a0_4c;
2816 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2817 //biosA0[0x4e] = psxBios_GPU_sync;
2818 //biosA0[0x4f] = psxBios_sys_a0_4f;
2819 //biosA0[0x50] = psxBios_sys_a0_50;
2820 biosA0[0x51] = psxBios_LoadExec;
2821 //biosA0[0x52] = psxBios_GetSysSp;
2822 //biosA0[0x53] = psxBios_sys_a0_53;
2823 //biosA0[0x54] = psxBios__96_init_a54;
2824 //biosA0[0x55] = psxBios__bu_init_a55;
2825 //biosA0[0x56] = psxBios__96_remove_a56;
2826 //biosA0[0x57] = psxBios_sys_a0_57;
2827 //biosA0[0x58] = psxBios_sys_a0_58;
2828 //biosA0[0x59] = psxBios_sys_a0_59;
2829 //biosA0[0x5a] = psxBios_sys_a0_5a;
2830 //biosA0[0x5b] = psxBios_dev_tty_init;
2831 //biosA0[0x5c] = psxBios_dev_tty_open;
2832 //biosA0[0x5d] = psxBios_sys_a0_5d;
2833 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2834 //biosA0[0x5f] = psxBios_dev_cd_open;
2835 //biosA0[0x60] = psxBios_dev_cd_read;
2836 //biosA0[0x61] = psxBios_dev_cd_close;
2837 //biosA0[0x62] = psxBios_dev_cd_firstfile;
2838 //biosA0[0x63] = psxBios_dev_cd_nextfile;
2839 //biosA0[0x64] = psxBios_dev_cd_chdir;
2840 //biosA0[0x65] = psxBios_dev_card_open;
2841 //biosA0[0x66] = psxBios_dev_card_read;
2842 //biosA0[0x67] = psxBios_dev_card_write;
2843 //biosA0[0x68] = psxBios_dev_card_close;
2844 //biosA0[0x69] = psxBios_dev_card_firstfile;
2845 //biosA0[0x6a] = psxBios_dev_card_nextfile;
2846 //biosA0[0x6b] = psxBios_dev_card_erase;
2847 //biosA0[0x6c] = psxBios_dev_card_undelete;
2848 //biosA0[0x6d] = psxBios_dev_card_format;
2849 //biosA0[0x6e] = psxBios_dev_card_rename;
2850 //biosA0[0x6f] = psxBios_dev_card_6f;
2851 biosA0[0x70] = psxBios__bu_init;
2852 biosA0[0x71] = psxBios__96_init;
2853 biosA0[0x72] = psxBios__96_remove;
2854 //biosA0[0x73] = psxBios_sys_a0_73;
2855 //biosA0[0x74] = psxBios_sys_a0_74;
2856 //biosA0[0x75] = psxBios_sys_a0_75;
2857 //biosA0[0x76] = psxBios_sys_a0_76;
2858 //biosA0[0x77] = psxBios_sys_a0_77;
2859 //biosA0[0x78] = psxBios__96_CdSeekL;
2860 //biosA0[0x79] = psxBios_sys_a0_79;
2861 //biosA0[0x7a] = psxBios_sys_a0_7a;
2862 //biosA0[0x7b] = psxBios_sys_a0_7b;
2863 //biosA0[0x7c] = psxBios__96_CdGetStatus;
2864 //biosA0[0x7d] = psxBios_sys_a0_7d;
2865 //biosA0[0x7e] = psxBios__96_CdRead;
2866 //biosA0[0x7f] = psxBios_sys_a0_7f;
2867 //biosA0[0x80] = psxBios_sys_a0_80;
2868 //biosA0[0x81] = psxBios_sys_a0_81;
2869 //biosA0[0x82] = psxBios_sys_a0_82;
2870 //biosA0[0x83] = psxBios_sys_a0_83;
2871 //biosA0[0x84] = psxBios_sys_a0_84;
2872 //biosA0[0x85] = psxBios__96_CdStop;
2873 //biosA0[0x86] = psxBios_sys_a0_86;
2874 //biosA0[0x87] = psxBios_sys_a0_87;
2875 //biosA0[0x88] = psxBios_sys_a0_88;
2876 //biosA0[0x89] = psxBios_sys_a0_89;
2877 //biosA0[0x8a] = psxBios_sys_a0_8a;
2878 //biosA0[0x8b] = psxBios_sys_a0_8b;
2879 //biosA0[0x8c] = psxBios_sys_a0_8c;
2880 //biosA0[0x8d] = psxBios_sys_a0_8d;
2881 //biosA0[0x8e] = psxBios_sys_a0_8e;
2882 //biosA0[0x8f] = psxBios_sys_a0_8f;
2883 //biosA0[0x90] = psxBios_sys_a0_90;
2884 //biosA0[0x91] = psxBios_sys_a0_91;
2885 //biosA0[0x92] = psxBios_sys_a0_92;
2886 //biosA0[0x93] = psxBios_sys_a0_93;
2887 //biosA0[0x94] = psxBios_sys_a0_94;
2888 //biosA0[0x95] = psxBios_sys_a0_95;
2889 //biosA0[0x96] = psxBios_AddCDROMDevice;
2890 //biosA0[0x97] = psxBios_AddMemCardDevide;
2891 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2892 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2893 //biosA0[0x9a] = psxBios_sys_a0_9a;
2894 //biosA0[0x9b] = psxBios_sys_a0_9b;
2895 //biosA0[0x9c] = psxBios_SetConf;
2896 //biosA0[0x9d] = psxBios_GetConf;
2897 //biosA0[0x9e] = psxBios_sys_a0_9e;
2898 biosA0[0x9f] = psxBios_SetMem;
2899 //biosA0[0xa0] = psxBios__boot;
2900 //biosA0[0xa1] = psxBios_SystemError;
2901 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2902 //biosA0[0xa3] = psxBios_DequeueCdIntr;
2903 //biosA0[0xa4] = psxBios_sys_a0_a4;
2904 //biosA0[0xa5] = psxBios_ReadSector;
2905 biosA0[0xa6] = psxBios_get_cd_status;
2906 //biosA0[0xa7] = psxBios_bufs_cb_0;
2907 //biosA0[0xa8] = psxBios_bufs_cb_1;
2908 //biosA0[0xa9] = psxBios_bufs_cb_2;
2909 //biosA0[0xaa] = psxBios_bufs_cb_3;
2910 biosA0[0xab] = psxBios__card_info;
2911 biosA0[0xac] = psxBios__card_load;
2912 //biosA0[0axd] = psxBios__card_auto;
2913 //biosA0[0xae] = psxBios_bufs_cd_4;
2914 //biosA0[0xaf] = psxBios_sys_a0_af;
2915 //biosA0[0xb0] = psxBios_sys_a0_b0;
2916 //biosA0[0xb1] = psxBios_sys_a0_b1;
2917 //biosA0[0xb2] = psxBios_do_a_long_jmp
2918 //biosA0[0xb3] = psxBios_sys_a0_b3;
2919 //biosA0[0xb4] = psxBios_sub_function;
2920 //*******************B0 CALLS****************************
2921 //biosB0[0x00] = psxBios_SysMalloc;
2922 //biosB0[0x01] = psxBios_sys_b0_01;
2923 biosB0[0x02] = psxBios_SetRCnt;
2924 biosB0[0x03] = psxBios_GetRCnt;
2925 biosB0[0x04] = psxBios_StartRCnt;
2926 biosB0[0x05] = psxBios_StopRCnt;
2927 biosB0[0x06] = psxBios_ResetRCnt;
2928 biosB0[0x07] = psxBios_DeliverEvent;
2929 biosB0[0x08] = psxBios_OpenEvent;
2930 biosB0[0x09] = psxBios_CloseEvent;
2931 biosB0[0x0a] = psxBios_WaitEvent;
2932 biosB0[0x0b] = psxBios_TestEvent;
2933 biosB0[0x0c] = psxBios_EnableEvent;
2934 biosB0[0x0d] = psxBios_DisableEvent;
2935 biosB0[0x0e] = psxBios_OpenTh;
2936 biosB0[0x0f] = psxBios_CloseTh;
2937 biosB0[0x10] = psxBios_ChangeTh;
2938 //biosB0[0x11] = psxBios_psxBios_b0_11;
2939 biosB0[0x12] = psxBios_InitPAD;
2940 biosB0[0x13] = psxBios_StartPAD;
2941 biosB0[0x14] = psxBios_StopPAD;
2942 biosB0[0x15] = psxBios_PAD_init;
2943 biosB0[0x16] = psxBios_PAD_dr;
2944 biosB0[0x17] = psxBios_ReturnFromException;
2945 biosB0[0x18] = psxBios_ResetEntryInt;
2946 biosB0[0x19] = psxBios_HookEntryInt;
2947 //biosB0[0x1a] = psxBios_sys_b0_1a;
2948 //biosB0[0x1b] = psxBios_sys_b0_1b;
2949 //biosB0[0x1c] = psxBios_sys_b0_1c;
2950 //biosB0[0x1d] = psxBios_sys_b0_1d;
2951 //biosB0[0x1e] = psxBios_sys_b0_1e;
2952 //biosB0[0x1f] = psxBios_sys_b0_1f;
2953 biosB0[0x20] = psxBios_UnDeliverEvent;
2954 //biosB0[0x21] = psxBios_sys_b0_21;
2955 //biosB0[0x22] = psxBios_sys_b0_22;
2956 //biosB0[0x23] = psxBios_sys_b0_23;
2957 //biosB0[0x24] = psxBios_sys_b0_24;
2958 //biosB0[0x25] = psxBios_sys_b0_25;
2959 //biosB0[0x26] = psxBios_sys_b0_26;
2960 //biosB0[0x27] = psxBios_sys_b0_27;
2961 //biosB0[0x28] = psxBios_sys_b0_28;
2962 //biosB0[0x29] = psxBios_sys_b0_29;
2963 //biosB0[0x2a] = psxBios_sys_b0_2a;
2964 //biosB0[0x2b] = psxBios_sys_b0_2b;
2965 //biosB0[0x2c] = psxBios_sys_b0_2c;
2966 //biosB0[0x2d] = psxBios_sys_b0_2d;
2967 //biosB0[0x2e] = psxBios_sys_b0_2e;
2968 //biosB0[0x2f] = psxBios_sys_b0_2f;
2969 //biosB0[0x30] = psxBios_sys_b0_30;
2970 //biosB0[0x31] = psxBios_sys_b0_31;
2971 biosB0[0x32] = psxBios_open;
2972 biosB0[0x33] = psxBios_lseek;
2973 biosB0[0x34] = psxBios_read;
2974 biosB0[0x35] = psxBios_write;
2975 biosB0[0x36] = psxBios_close;
2976 //biosB0[0x37] = psxBios_ioctl;
2977 //biosB0[0x38] = psxBios_exit;
2978 //biosB0[0x39] = psxBios_sys_b0_39;
2979 //biosB0[0x3a] = psxBios_getc;
2980 //biosB0[0x3b] = psxBios_putc;
2981 biosB0[0x3c] = psxBios_getchar;
2982 //biosB0[0x3e] = psxBios_gets;
2983 //biosB0[0x40] = psxBios_cd;
2984 biosB0[0x41] = psxBios_format;
2985 biosB0[0x42] = psxBios_firstfile;
2986 biosB0[0x43] = psxBios_nextfile;
2987 biosB0[0x44] = psxBios_rename;
2988 biosB0[0x45] = psxBios_delete;
2989 //biosB0[0x46] = psxBios_undelete;
2990 //biosB0[0x47] = psxBios_AddDevice;
2991 //biosB0[0x48] = psxBios_RemoteDevice;
2992 //biosB0[0x49] = psxBios_PrintInstalledDevices;
2993 biosB0[0x4a] = psxBios_InitCARD;
2994 biosB0[0x4b] = psxBios_StartCARD;
2995 biosB0[0x4c] = psxBios_StopCARD;
2996 //biosB0[0x4d] = psxBios_sys_b0_4d;
2997 biosB0[0x4e] = psxBios__card_write;
2998 biosB0[0x4f] = psxBios__card_read;
2999 biosB0[0x50] = psxBios__new_card;
3000 biosB0[0x51] = psxBios_Krom2RawAdd;
3001 //biosB0[0x52] = psxBios_sys_b0_52;
3002 //biosB0[0x53] = psxBios_sys_b0_53;
3003 //biosB0[0x54] = psxBios__get_errno;
3004 biosB0[0x55] = psxBios__get_error;
3005 biosB0[0x56] = psxBios_GetC0Table;
3006 biosB0[0x57] = psxBios_GetB0Table;
3007 biosB0[0x58] = psxBios__card_chan;
3008 //biosB0[0x59] = psxBios_sys_b0_59;
3009 //biosB0[0x5a] = psxBios_sys_b0_5a;
3010 biosB0[0x5b] = psxBios_ChangeClearPad;
3011 biosB0[0x5c] = psxBios__card_status;
3012 biosB0[0x5d] = psxBios__card_wait;
3013 //*******************C0 CALLS****************************
3014 //biosC0[0x00] = psxBios_InitRCnt;
3015 //biosC0[0x01] = psxBios_InitException;
3016 biosC0[0x02] = psxBios_SysEnqIntRP;
3017 biosC0[0x03] = psxBios_SysDeqIntRP;
3018 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
3019 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3020 //biosC0[0x06] = psxBios_ExceptionHandler;
3021 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3022 //biosC0[0x08] = psxBios_SysInitMemory;
3023 //biosC0[0x09] = psxBios_SysInitKMem;
3024 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3025 //biosC0[0x0b] = psxBios_SystemError;
3026 //biosC0[0x0c] = psxBios_InitDefInt;
3027 //biosC0[0x0d] = psxBios_sys_c0_0d;
3028 //biosC0[0x0e] = psxBios_sys_c0_0e;
3029 //biosC0[0x0f] = psxBios_sys_c0_0f;
3030 //biosC0[0x10] = psxBios_sys_c0_10;
3031 //biosC0[0x11] = psxBios_sys_c0_11;
3032 //biosC0[0x12] = psxBios_InstallDevices;
3033 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3034 //biosC0[0x14] = psxBios_sys_c0_14;
3035 //biosC0[0x15] = psxBios__cdevinput;
3036 //biosC0[0x16] = psxBios__cdevscan;
3037 //biosC0[0x17] = psxBios__circgetc;
3038 //biosC0[0x18] = psxBios__circputc;
3039 //biosC0[0x19] = psxBios_ioabort;
3040 //biosC0[0x1a] = psxBios_sys_c0_1a
3041 //biosC0[0x1b] = psxBios_KernelRedirect;
3042 //biosC0[0x1c] = psxBios_PatchAOTable;
3043 //************** THE END ***************************************
3046 size = sizeof(EvCB) * 32;
3047 EventCB = (void *)&psxR[base]; base += size * 6;
3048 memset(EventCB, 0, size * 6);
3050 EvEV = EventCB + 32;
3051 RcEV = EventCB + 32 * 2;
3052 UeEV = EventCB + 32 * 3;
3053 SwEV = EventCB + 32 * 4;
3054 ThEV = EventCB + 32 * 5;
3056 ptr = (u32 *)&psxM[0x0874]; // b0 table
3057 ptr[0] = SWAPu32(0x4c54 - 0x884);
3059 ptr = (u32 *)&psxM[0x0674]; // c0 table
3060 ptr[6] = SWAPu32(0xc80);
3062 memset(SysIntRP, 0, sizeof(SysIntRP));
3063 memset(ThreadCB, 0, sizeof(ThreadCB));
3064 ThreadCB[0].status = 2; // main thread
3071 pad_buf1len = pad_buf2len = 0;
3077 memset(FDesc, 0, sizeof(FDesc));
3078 card_active_chan = 0;
3080 psxMu32ref(0x0150) = SWAPu32(0x160);
3081 psxMu32ref(0x0154) = SWAPu32(0x320);
3082 psxMu32ref(0x0160) = SWAPu32(0x248);
3083 strcpy((char *)&psxM[0x248], "bu");
3084 /* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3085 psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3086 psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3087 psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3088 psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3091 psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
3092 /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
3093 Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3094 //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
3095 psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3096 psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3097 psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3098 psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3099 psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3100 psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3101 psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3102 psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3104 // initial stack pointer for BIOS interrupt
3105 psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3108 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3111 len = 0x80000 - 0x66000;
3112 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3113 len = 0x80000 - 0x69d68;
3114 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3117 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3119 hleSoftCall = FALSE;
3121 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3122 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3123 Here are some examples of games not working with this fix in place :
3124 R-type won't get past the Irem logo if not implemented.
3125 Crash Team Racing will softlock after the Sony logo.
3128 psxMu32ref(0x0000) = SWAPu32(0x00000003);
3130 But overwritten by 00000003h after soon.
3131 psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3133 psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3134 psxMu32ref(0x0008) = SWAPu32(0x08000403);
3135 psxMu32ref(0x000C) = SWAPu32(0x00000000);
3138 void psxBiosShutdown() {
3141 #define psxBios_PADpoll(pad) { \
3142 PAD##pad##_startPoll(pad); \
3143 pad_buf##pad[0] = 0; \
3144 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3145 if (!(pad_buf##pad[1] & 0x0f)) { \
3148 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3150 PAD##pad##_poll(0); \
3152 while (bufcount--) { \
3153 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3157 void biosInterrupt() {
3160 // if (psxHu32(0x1070) & 0x1) { // Vsync
3161 if (pad_buf != NULL) {
3162 u32 *buf = (u32*)pad_buf;
3164 if (!Config.UseNet) {
3166 if (PAD1_poll(0x42) == 0x23) {
3168 *buf = PAD1_poll(0) << 8;
3169 *buf |= PAD1_poll(0);
3171 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3172 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3175 *buf = PAD1_poll(0) << 8;
3176 *buf|= PAD1_poll(0);
3180 if (PAD2_poll(0x42) == 0x23) {
3182 *buf |= PAD2_poll(0) << 24;
3183 *buf |= PAD2_poll(0) << 16;
3185 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3186 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3189 *buf |= PAD2_poll(0) << 24;
3190 *buf |= PAD2_poll(0) << 16;
3198 data = PAD1_poll(0) << 8;
3199 data |= PAD1_poll(0);
3201 if (NET_sendPadData(&data, 2) == -1)
3204 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3206 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3210 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3213 if (NET_sendPadData(pad_buf1, i) == -1)
3216 if (NET_recvPadData(pad_buf1, 1) == -1)
3218 if (NET_recvPadData(pad_buf2, 2) == -1)
3232 if (psxHu32(0x1070) & 0x1) { // Vsync
3233 if (RcEV[3][1].status == EvStACTIVE) {
3234 softCall(RcEV[3][1].fhandler);
3235 // hwWrite32(0x1f801070, ~(1));
3239 if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3242 for (i = 0; i < 3; i++) {
3243 if (psxHu32(0x1070) & (1 << (i + 4))) {
3244 if (RcEV[i][1].status == EvStACTIVE) {
3245 softCall(RcEV[i][1].fhandler);
3247 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3253 void psxBiosException() {
3256 switch (psxRegs.CP0.n.Cause & 0x3c) {
3257 case 0x00: // Interrupt
3258 interrupt_r26=psxRegs.CP0.n.EPC;
3260 // PSXCPU_LOG("interrupt\n");
3264 sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3268 for (i = 0; i < 8; i++) {
3270 u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3277 if (jmp_int != NULL) {
3280 psxHwWrite32(0x1f801070, 0xffffffff);
3285 for (i = 0; i < 8; i++) // s0-s7
3286 psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3293 psxHwWrite16(0x1f801070, 0);
3296 case 0x20: // Syscall
3298 PSXCPU_LOG("syscall exp %x\n", a0);
3301 case 1: // EnterCritical - disable irq's
3302 /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3303 v0 = (psxRegs.CP0.n.SR & 0x404) == 0x404;
3304 psxRegs.CP0.n.SR &= ~0x404;
3307 case 2: // ExitCritical - enable irq's
3308 psxRegs.CP0.n.SR |= 0x404;
3310 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3314 pc0 = psxRegs.CP0.n.EPC + 4;
3316 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
3321 PSXCPU_LOG("unknown bios exception!\n");
3326 pc0 = psxRegs.CP0.n.EPC;
3327 if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3329 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
3332 #define bfreeze(ptr, size) { \
3333 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3334 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3338 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3339 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3341 #define bfreezepsxMptr(ptr, type) { \
3343 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3344 else psxRu32ref(base) = 0; \
3346 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3347 else (ptr) = NULL; \
3349 base += sizeof(u32); \
3352 void psxBiosFreeze(int Mode) {
3355 bfreezepsxMptr(jmp_int, u32);
3356 bfreezepsxMptr(pad_buf, int);
3357 bfreezepsxMptr(pad_buf1, char);
3358 bfreezepsxMptr(pad_buf2, char);
3359 bfreezepsxMptr(heap_addr, u32);
3360 bfreezel(&pad_buf1len);
3361 bfreezel(&pad_buf2len);
3364 bfreezel(&CardState);
3366 bfreezel(&CurThread);
3368 bfreezel(&card_active_chan);
3369 bfreezel(&pad_stopped);
3370 bfreezel(&heap_size);