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 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.Status |= 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.Status |= 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.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
2000 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
2003 void psxBios_ResetEntryInt() { // 18
2005 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2012 void psxBios_HookEntryInt() { // 19
2014 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
2017 jmp_int = (u32*)Ra0;
2021 void psxBios_UnDeliverEvent() { // 0x20
2029 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2032 if (EventCB[ev][spec].status == EvStALREADY &&
2033 EventCB[ev][spec].mode == EvMdNOINTR)
2034 EventCB[ev][spec].status = EvStACTIVE;
2039 char ffile[64], *pfile;
2042 static void buopen(int mcd, char *ptr, char *cfg)
2045 char *mcd_data = ptr;
2047 strcpy(FDesc[1 + mcd].name, Ra0+5);
2048 FDesc[1 + mcd].offset = 0;
2049 FDesc[1 + mcd].mode = a1;
2051 for (i=1; i<16; i++) {
2052 const char *fptr = mcd_data + 128 * i;
2053 if ((*fptr & 0xF0) != 0x50) continue;
2054 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2055 FDesc[1 + mcd].mcfile = i;
2056 SysPrintf("open %s\n", fptr+0xa);
2060 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2061 for (i=1; i<16; i++) {
2062 int j, xor, nblk = a1 >> 16;
2064 char *fptr = mcd_data + 128 * i;
2066 if ((*fptr & 0xF0) != 0xa0) continue;
2068 FDesc[1 + mcd].mcfile = i;
2071 fptr[5] = 0x20 * nblk;
2074 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2075 pptr = fptr2 = fptr;
2076 for(j=2; j<=nblk; j++) {
2078 for(i++; i<16; i++) {
2081 memset(fptr2, 0, 128);
2082 fptr2[0] = j < nblk ? 0x52 : 0x53;
2085 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2090 /* shouldn't this return ENOSPC if i == 16? */
2092 pptr[8] = pptr[9] = 0xff;
2093 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2095 SysPrintf("openC %s %d\n", ptr, nblk);
2097 /* just go ahead and resave them all */
2098 SaveMcd(cfg, ptr, 128, 128 * 15);
2101 /* shouldn't this return ENOSPC if i == 16? */
2106 * int open(char *name , int mode);
2109 void psxBios_open() { // 0x32
2113 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2118 if (pa0 != INVALID_PTR) {
2119 if (!strncmp(pa0, "bu00", 4)) {
2120 buopen(1, Mcd1Data, Config.Mcd1);
2123 if (!strncmp(pa0, "bu10", 4)) {
2124 buopen(2, Mcd2Data, Config.Mcd2);
2132 * int lseek(int fd , int offset , int whence);
2135 void psxBios_lseek() { // 0x33
2137 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2142 FDesc[a0].offset = a1;
2144 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2145 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2149 FDesc[a0].offset+= a1;
2150 v0 = FDesc[a0].offset;
2159 * int read(int fd , void *buf , int nbytes);
2162 void psxBios_read() { // 0x34
2167 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2172 if (pa1 != INVALID_PTR) {
2174 case 2: buread(pa1, 1, a2); break;
2175 case 3: buread(pa1, 2, a2); break;
2183 * int write(int fd , void *buf , int nbytes);
2186 void psxBios_write() { // 0x35/0x03
2191 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2195 if (pa1 == INVALID_PTR) {
2200 if (a0 == 1) { // stdout
2205 SysPrintf("%c", *ptr++); a2--;
2211 case 2: buwrite(pa1, 1, a2); break;
2212 case 3: buwrite(pa1, 2, a2); break;
2218 static void psxBios_write_psxout() {
2219 if (a0 == 1) { // stdout
2220 const char *ptr = Ra1;
2223 if (ptr != INVALID_PTR)
2225 SysPrintf("%c", *ptr++);
2229 static void psxBios_putchar_psxout() { // 3d
2230 SysPrintf("%c", (char)a0);
2233 static void psxBios_puts_psxout() { // 3e/3f
2234 SysPrintf("%s", Ra0);
2238 * int close(int fd);
2241 void psxBios_close() { // 0x36
2243 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2250 void psxBios_putchar() { // 3d
2251 SysPrintf("%c", (char)a0);
2255 void psxBios_puts() { // 3e/3f
2256 SysPrintf("%s", Ra0);
2261 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2262 * We want to mimic the PSX's behaviour in this case for bufile. */
2263 static size_t strlen_internal(char* p)
2265 size_t size_of_array = 0;
2266 while (*p++) size_of_array++;
2267 return size_of_array;
2270 #define bufile(mcd) { \
2271 size_t size_of_name = strlen_internal(dir->name); \
2272 while (nfile < 16) { \
2275 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2277 if ((*ptr & 0xF0) != 0x50) continue; \
2278 /* Bug link files show up as free block. */ \
2279 if (!ptr[0xa]) continue; \
2281 if (pfile[0] == 0) { \
2282 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2283 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2284 } else for (i=0; i<20; i++) { \
2285 if (pfile[i] == ptr[i]) { \
2286 dir->name[i] = ptr[i]; continue; } \
2287 if (pfile[i] == '?') { \
2288 dir->name[i] = ptr[i]; continue; } \
2289 if (pfile[i] == '*') { \
2290 strcpy(dir->name+i, ptr+i); break; } \
2293 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2294 if (match == 0) { continue; } \
2302 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2305 void psxBios_firstfile() { // 42
2306 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2313 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2318 if (pa0 != INVALID_PTR) {
2322 if (!strncmp(pa0, "bu00", 4)) {
2323 // firstfile() calls _card_read() internally, so deliver it's event
2324 DeliverEvent(0x11, 0x2);
2326 } else if (!strncmp(pa0, "bu10", 4)) {
2327 // firstfile() calls _card_read() internally, so deliver it's event
2328 DeliverEvent(0x11, 0x2);
2337 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2340 void psxBios_nextfile() { // 43
2341 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2347 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2352 if (!strncmp(ffile, "bu00", 4)) {
2356 if (!strncmp(ffile, "bu10", 4)) {
2363 #define burename(mcd) { \
2364 for (i=1; i<16; i++) { \
2365 int namelen, j, xor = 0; \
2366 ptr = Mcd##mcd##Data + 128 * i; \
2367 if ((*ptr & 0xF0) != 0x50) continue; \
2368 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2369 namelen = strlen(Ra1+5); \
2370 memcpy(ptr+0xa, Ra1+5, namelen); \
2371 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2372 for (j=0; j<127; j++) xor^= ptr[j]; \
2374 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2381 * int rename(char *old, char *new);
2384 void psxBios_rename() { // 44
2391 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2396 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2397 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2401 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2410 #define budelete(mcd) { \
2411 for (i=1; i<16; i++) { \
2412 ptr = Mcd##mcd##Data + 128 * i; \
2413 if ((*ptr & 0xF0) != 0x50) continue; \
2414 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2415 *ptr = (*ptr & 0xf) | 0xA0; \
2416 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2417 SysPrintf("delete %s\n", ptr+0xa); \
2424 * int delete(char *name);
2427 void psxBios_delete() { // 45
2433 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2438 if (pa0 != INVALID_PTR) {
2439 if (!strncmp(pa0, "bu00", 4)) {
2443 if (!strncmp(pa0, "bu10", 4)) {
2451 void psxBios_InitCARD() { // 4a
2453 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2461 void psxBios_StartCARD() { // 4b
2463 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2466 if (CardState == 0) CardState = 1;
2471 void psxBios_StopCARD() { // 4c
2473 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2476 if (CardState == 1) CardState = 0;
2481 void psxBios__card_write() { // 0x4e
2486 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2489 Function also accepts sector 400h (a bug).
2490 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2494 /* Invalid sectors */
2498 card_active_chan = a0;
2501 if (pa2 != INVALID_PTR) {
2503 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2504 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2506 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2507 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2511 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2512 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2517 void psxBios__card_read() { // 0x4f
2522 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2525 Function also accepts sector 400h (a bug).
2526 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2530 /* Invalid sectors */
2534 card_active_chan = a0;
2537 if (pa2 != INVALID_PTR) {
2539 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2541 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2545 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2546 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2551 void psxBios__new_card() { // 0x50
2553 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2559 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2560 void psxBios__get_error(void) // 55
2566 void psxBios_Krom2RawAdd() { // 0x51
2569 const u32 table_8140[][2] = {
2570 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2571 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2572 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2573 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2574 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2575 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2576 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2577 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2578 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2582 const u32 table_889f[][2] = {
2583 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2584 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2585 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2586 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2587 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2588 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2589 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2590 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2594 if (a0 >= 0x8140 && a0 <= 0x84be) {
2595 while (table_8140[i][0] <= a0) i++;
2596 a0 -= table_8140[i - 1][0];
2597 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2598 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2599 while (table_889f[i][0] <= a0) i++;
2600 a0 -= table_889f[i - 1][0];
2601 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2609 void psxBios_GetC0Table() { // 56
2611 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2614 v0 = 0x674; pc0 = ra;
2617 void psxBios_GetB0Table() { // 57
2619 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2622 v0 = 0x874; pc0 = ra;
2625 void psxBios__card_chan() { // 0x58
2627 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2630 v0 = card_active_chan;
2634 void psxBios_ChangeClearPad() { // 5b
2636 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2642 void psxBios__card_status() { // 5c
2644 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2647 v0 = card_active_chan;
2651 void psxBios__card_wait() { // 5d
2653 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2660 /* System calls C0 */
2663 * int SysEnqIntRP(int index , long *queue);
2666 void psxBios_SysEnqIntRP() { // 02
2668 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2677 * int SysDeqIntRP(int index , long *queue);
2680 void psxBios_SysDeqIntRP() { // 03
2682 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2690 void psxBios_ChangeClearRCnt() { // 0a
2694 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2697 ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2701 // psxRegs.CP0.n.Status|= 0x404;
2705 void psxBios_dummy() {
2707 PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2712 void (*biosA0[256])();
2713 void (*biosB0[256])();
2714 void (*biosC0[256])();
2716 #include "sjisfont.h"
2718 void psxBiosInit() {
2724 for(i = 0; i < 256; i++) {
2729 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
2730 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
2731 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
2732 biosA0[0x3f] = psxBios_printf_psxout;
2734 if (!Config.HLE) return;
2736 for(i = 0; i < 256; i++) {
2737 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2738 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2739 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2742 biosA0[0x00] = psxBios_open;
2743 biosA0[0x01] = psxBios_lseek;
2744 biosA0[0x02] = psxBios_read;
2745 biosA0[0x03] = psxBios_write;
2746 biosA0[0x04] = psxBios_close;
2747 //biosA0[0x05] = psxBios_ioctl;
2748 //biosA0[0x06] = psxBios_exit;
2749 //biosA0[0x07] = psxBios_sys_a0_07;
2750 biosA0[0x08] = psxBios_getc;
2751 biosA0[0x09] = psxBios_putc;
2752 biosA0[0x0a] = psxBios_todigit;
2753 //biosA0[0x0b] = psxBios_atof;
2754 //biosA0[0x0c] = psxBios_strtoul;
2755 //biosA0[0x0d] = psxBios_strtol;
2756 biosA0[0x0e] = psxBios_abs;
2757 biosA0[0x0f] = psxBios_labs;
2758 biosA0[0x10] = psxBios_atoi;
2759 biosA0[0x11] = psxBios_atol;
2760 //biosA0[0x12] = psxBios_atob;
2761 biosA0[0x13] = psxBios_setjmp;
2762 biosA0[0x14] = psxBios_longjmp;
2763 biosA0[0x15] = psxBios_strcat;
2764 biosA0[0x16] = psxBios_strncat;
2765 biosA0[0x17] = psxBios_strcmp;
2766 biosA0[0x18] = psxBios_strncmp;
2767 biosA0[0x19] = psxBios_strcpy;
2768 biosA0[0x1a] = psxBios_strncpy;
2769 biosA0[0x1b] = psxBios_strlen;
2770 biosA0[0x1c] = psxBios_index;
2771 biosA0[0x1d] = psxBios_rindex;
2772 biosA0[0x1e] = psxBios_strchr;
2773 biosA0[0x1f] = psxBios_strrchr;
2774 biosA0[0x20] = psxBios_strpbrk;
2775 biosA0[0x21] = psxBios_strspn;
2776 biosA0[0x22] = psxBios_strcspn;
2777 biosA0[0x23] = psxBios_strtok;
2778 biosA0[0x24] = psxBios_strstr;
2779 biosA0[0x25] = psxBios_toupper;
2780 biosA0[0x26] = psxBios_tolower;
2781 biosA0[0x27] = psxBios_bcopy;
2782 biosA0[0x28] = psxBios_bzero;
2783 biosA0[0x29] = psxBios_bcmp;
2784 biosA0[0x2a] = psxBios_memcpy;
2785 biosA0[0x2b] = psxBios_memset;
2786 biosA0[0x2c] = psxBios_memmove;
2787 biosA0[0x2d] = psxBios_memcmp;
2788 biosA0[0x2e] = psxBios_memchr;
2789 biosA0[0x2f] = psxBios_rand;
2790 biosA0[0x30] = psxBios_srand;
2791 biosA0[0x31] = psxBios_qsort;
2792 //biosA0[0x32] = psxBios_strtod;
2793 biosA0[0x33] = psxBios_malloc;
2794 biosA0[0x34] = psxBios_free;
2795 //biosA0[0x35] = psxBios_lsearch;
2796 //biosA0[0x36] = psxBios_bsearch;
2797 biosA0[0x37] = psxBios_calloc;
2798 biosA0[0x38] = psxBios_realloc;
2799 biosA0[0x39] = psxBios_InitHeap;
2800 //biosA0[0x3a] = psxBios__exit;
2801 biosA0[0x3b] = psxBios_getchar;
2802 biosA0[0x3c] = psxBios_putchar;
2803 //biosA0[0x3d] = psxBios_gets;
2804 //biosA0[0x40] = psxBios_sys_a0_40;
2805 //biosA0[0x41] = psxBios_LoadTest;
2806 biosA0[0x42] = psxBios_Load;
2807 biosA0[0x43] = psxBios_Exec;
2808 biosA0[0x44] = psxBios_FlushCache;
2809 //biosA0[0x45] = psxBios_InstallInterruptHandler;
2810 biosA0[0x46] = psxBios_GPU_dw;
2811 biosA0[0x47] = psxBios_mem2vram;
2812 biosA0[0x48] = psxBios_SendGPU;
2813 biosA0[0x49] = psxBios_GPU_cw;
2814 biosA0[0x4a] = psxBios_GPU_cwb;
2815 biosA0[0x4b] = psxBios_GPU_SendPackets;
2816 biosA0[0x4c] = psxBios_sys_a0_4c;
2817 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2818 //biosA0[0x4e] = psxBios_GPU_sync;
2819 //biosA0[0x4f] = psxBios_sys_a0_4f;
2820 //biosA0[0x50] = psxBios_sys_a0_50;
2821 biosA0[0x51] = psxBios_LoadExec;
2822 //biosA0[0x52] = psxBios_GetSysSp;
2823 //biosA0[0x53] = psxBios_sys_a0_53;
2824 //biosA0[0x54] = psxBios__96_init_a54;
2825 //biosA0[0x55] = psxBios__bu_init_a55;
2826 //biosA0[0x56] = psxBios__96_remove_a56;
2827 //biosA0[0x57] = psxBios_sys_a0_57;
2828 //biosA0[0x58] = psxBios_sys_a0_58;
2829 //biosA0[0x59] = psxBios_sys_a0_59;
2830 //biosA0[0x5a] = psxBios_sys_a0_5a;
2831 //biosA0[0x5b] = psxBios_dev_tty_init;
2832 //biosA0[0x5c] = psxBios_dev_tty_open;
2833 //biosA0[0x5d] = psxBios_sys_a0_5d;
2834 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2835 //biosA0[0x5f] = psxBios_dev_cd_open;
2836 //biosA0[0x60] = psxBios_dev_cd_read;
2837 //biosA0[0x61] = psxBios_dev_cd_close;
2838 //biosA0[0x62] = psxBios_dev_cd_firstfile;
2839 //biosA0[0x63] = psxBios_dev_cd_nextfile;
2840 //biosA0[0x64] = psxBios_dev_cd_chdir;
2841 //biosA0[0x65] = psxBios_dev_card_open;
2842 //biosA0[0x66] = psxBios_dev_card_read;
2843 //biosA0[0x67] = psxBios_dev_card_write;
2844 //biosA0[0x68] = psxBios_dev_card_close;
2845 //biosA0[0x69] = psxBios_dev_card_firstfile;
2846 //biosA0[0x6a] = psxBios_dev_card_nextfile;
2847 //biosA0[0x6b] = psxBios_dev_card_erase;
2848 //biosA0[0x6c] = psxBios_dev_card_undelete;
2849 //biosA0[0x6d] = psxBios_dev_card_format;
2850 //biosA0[0x6e] = psxBios_dev_card_rename;
2851 //biosA0[0x6f] = psxBios_dev_card_6f;
2852 biosA0[0x70] = psxBios__bu_init;
2853 biosA0[0x71] = psxBios__96_init;
2854 biosA0[0x72] = psxBios__96_remove;
2855 //biosA0[0x73] = psxBios_sys_a0_73;
2856 //biosA0[0x74] = psxBios_sys_a0_74;
2857 //biosA0[0x75] = psxBios_sys_a0_75;
2858 //biosA0[0x76] = psxBios_sys_a0_76;
2859 //biosA0[0x77] = psxBios_sys_a0_77;
2860 //biosA0[0x78] = psxBios__96_CdSeekL;
2861 //biosA0[0x79] = psxBios_sys_a0_79;
2862 //biosA0[0x7a] = psxBios_sys_a0_7a;
2863 //biosA0[0x7b] = psxBios_sys_a0_7b;
2864 //biosA0[0x7c] = psxBios__96_CdGetStatus;
2865 //biosA0[0x7d] = psxBios_sys_a0_7d;
2866 //biosA0[0x7e] = psxBios__96_CdRead;
2867 //biosA0[0x7f] = psxBios_sys_a0_7f;
2868 //biosA0[0x80] = psxBios_sys_a0_80;
2869 //biosA0[0x81] = psxBios_sys_a0_81;
2870 //biosA0[0x82] = psxBios_sys_a0_82;
2871 //biosA0[0x83] = psxBios_sys_a0_83;
2872 //biosA0[0x84] = psxBios_sys_a0_84;
2873 //biosA0[0x85] = psxBios__96_CdStop;
2874 //biosA0[0x86] = psxBios_sys_a0_86;
2875 //biosA0[0x87] = psxBios_sys_a0_87;
2876 //biosA0[0x88] = psxBios_sys_a0_88;
2877 //biosA0[0x89] = psxBios_sys_a0_89;
2878 //biosA0[0x8a] = psxBios_sys_a0_8a;
2879 //biosA0[0x8b] = psxBios_sys_a0_8b;
2880 //biosA0[0x8c] = psxBios_sys_a0_8c;
2881 //biosA0[0x8d] = psxBios_sys_a0_8d;
2882 //biosA0[0x8e] = psxBios_sys_a0_8e;
2883 //biosA0[0x8f] = psxBios_sys_a0_8f;
2884 //biosA0[0x90] = psxBios_sys_a0_90;
2885 //biosA0[0x91] = psxBios_sys_a0_91;
2886 //biosA0[0x92] = psxBios_sys_a0_92;
2887 //biosA0[0x93] = psxBios_sys_a0_93;
2888 //biosA0[0x94] = psxBios_sys_a0_94;
2889 //biosA0[0x95] = psxBios_sys_a0_95;
2890 //biosA0[0x96] = psxBios_AddCDROMDevice;
2891 //biosA0[0x97] = psxBios_AddMemCardDevide;
2892 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2893 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2894 //biosA0[0x9a] = psxBios_sys_a0_9a;
2895 //biosA0[0x9b] = psxBios_sys_a0_9b;
2896 //biosA0[0x9c] = psxBios_SetConf;
2897 //biosA0[0x9d] = psxBios_GetConf;
2898 //biosA0[0x9e] = psxBios_sys_a0_9e;
2899 biosA0[0x9f] = psxBios_SetMem;
2900 //biosA0[0xa0] = psxBios__boot;
2901 //biosA0[0xa1] = psxBios_SystemError;
2902 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2903 //biosA0[0xa3] = psxBios_DequeueCdIntr;
2904 //biosA0[0xa4] = psxBios_sys_a0_a4;
2905 //biosA0[0xa5] = psxBios_ReadSector;
2906 biosA0[0xa6] = psxBios_get_cd_status;
2907 //biosA0[0xa7] = psxBios_bufs_cb_0;
2908 //biosA0[0xa8] = psxBios_bufs_cb_1;
2909 //biosA0[0xa9] = psxBios_bufs_cb_2;
2910 //biosA0[0xaa] = psxBios_bufs_cb_3;
2911 biosA0[0xab] = psxBios__card_info;
2912 biosA0[0xac] = psxBios__card_load;
2913 //biosA0[0axd] = psxBios__card_auto;
2914 //biosA0[0xae] = psxBios_bufs_cd_4;
2915 //biosA0[0xaf] = psxBios_sys_a0_af;
2916 //biosA0[0xb0] = psxBios_sys_a0_b0;
2917 //biosA0[0xb1] = psxBios_sys_a0_b1;
2918 //biosA0[0xb2] = psxBios_do_a_long_jmp
2919 //biosA0[0xb3] = psxBios_sys_a0_b3;
2920 //biosA0[0xb4] = psxBios_sub_function;
2921 //*******************B0 CALLS****************************
2922 //biosB0[0x00] = psxBios_SysMalloc;
2923 //biosB0[0x01] = psxBios_sys_b0_01;
2924 biosB0[0x02] = psxBios_SetRCnt;
2925 biosB0[0x03] = psxBios_GetRCnt;
2926 biosB0[0x04] = psxBios_StartRCnt;
2927 biosB0[0x05] = psxBios_StopRCnt;
2928 biosB0[0x06] = psxBios_ResetRCnt;
2929 biosB0[0x07] = psxBios_DeliverEvent;
2930 biosB0[0x08] = psxBios_OpenEvent;
2931 biosB0[0x09] = psxBios_CloseEvent;
2932 biosB0[0x0a] = psxBios_WaitEvent;
2933 biosB0[0x0b] = psxBios_TestEvent;
2934 biosB0[0x0c] = psxBios_EnableEvent;
2935 biosB0[0x0d] = psxBios_DisableEvent;
2936 biosB0[0x0e] = psxBios_OpenTh;
2937 biosB0[0x0f] = psxBios_CloseTh;
2938 biosB0[0x10] = psxBios_ChangeTh;
2939 //biosB0[0x11] = psxBios_psxBios_b0_11;
2940 biosB0[0x12] = psxBios_InitPAD;
2941 biosB0[0x13] = psxBios_StartPAD;
2942 biosB0[0x14] = psxBios_StopPAD;
2943 biosB0[0x15] = psxBios_PAD_init;
2944 biosB0[0x16] = psxBios_PAD_dr;
2945 biosB0[0x17] = psxBios_ReturnFromException;
2946 biosB0[0x18] = psxBios_ResetEntryInt;
2947 biosB0[0x19] = psxBios_HookEntryInt;
2948 //biosB0[0x1a] = psxBios_sys_b0_1a;
2949 //biosB0[0x1b] = psxBios_sys_b0_1b;
2950 //biosB0[0x1c] = psxBios_sys_b0_1c;
2951 //biosB0[0x1d] = psxBios_sys_b0_1d;
2952 //biosB0[0x1e] = psxBios_sys_b0_1e;
2953 //biosB0[0x1f] = psxBios_sys_b0_1f;
2954 biosB0[0x20] = psxBios_UnDeliverEvent;
2955 //biosB0[0x21] = psxBios_sys_b0_21;
2956 //biosB0[0x22] = psxBios_sys_b0_22;
2957 //biosB0[0x23] = psxBios_sys_b0_23;
2958 //biosB0[0x24] = psxBios_sys_b0_24;
2959 //biosB0[0x25] = psxBios_sys_b0_25;
2960 //biosB0[0x26] = psxBios_sys_b0_26;
2961 //biosB0[0x27] = psxBios_sys_b0_27;
2962 //biosB0[0x28] = psxBios_sys_b0_28;
2963 //biosB0[0x29] = psxBios_sys_b0_29;
2964 //biosB0[0x2a] = psxBios_sys_b0_2a;
2965 //biosB0[0x2b] = psxBios_sys_b0_2b;
2966 //biosB0[0x2c] = psxBios_sys_b0_2c;
2967 //biosB0[0x2d] = psxBios_sys_b0_2d;
2968 //biosB0[0x2e] = psxBios_sys_b0_2e;
2969 //biosB0[0x2f] = psxBios_sys_b0_2f;
2970 //biosB0[0x30] = psxBios_sys_b0_30;
2971 //biosB0[0x31] = psxBios_sys_b0_31;
2972 biosB0[0x32] = psxBios_open;
2973 biosB0[0x33] = psxBios_lseek;
2974 biosB0[0x34] = psxBios_read;
2975 biosB0[0x35] = psxBios_write;
2976 biosB0[0x36] = psxBios_close;
2977 //biosB0[0x37] = psxBios_ioctl;
2978 //biosB0[0x38] = psxBios_exit;
2979 //biosB0[0x39] = psxBios_sys_b0_39;
2980 //biosB0[0x3a] = psxBios_getc;
2981 //biosB0[0x3b] = psxBios_putc;
2982 biosB0[0x3c] = psxBios_getchar;
2983 //biosB0[0x3e] = psxBios_gets;
2984 //biosB0[0x40] = psxBios_cd;
2985 biosB0[0x41] = psxBios_format;
2986 biosB0[0x42] = psxBios_firstfile;
2987 biosB0[0x43] = psxBios_nextfile;
2988 biosB0[0x44] = psxBios_rename;
2989 biosB0[0x45] = psxBios_delete;
2990 //biosB0[0x46] = psxBios_undelete;
2991 //biosB0[0x47] = psxBios_AddDevice;
2992 //biosB0[0x48] = psxBios_RemoteDevice;
2993 //biosB0[0x49] = psxBios_PrintInstalledDevices;
2994 biosB0[0x4a] = psxBios_InitCARD;
2995 biosB0[0x4b] = psxBios_StartCARD;
2996 biosB0[0x4c] = psxBios_StopCARD;
2997 //biosB0[0x4d] = psxBios_sys_b0_4d;
2998 biosB0[0x4e] = psxBios__card_write;
2999 biosB0[0x4f] = psxBios__card_read;
3000 biosB0[0x50] = psxBios__new_card;
3001 biosB0[0x51] = psxBios_Krom2RawAdd;
3002 //biosB0[0x52] = psxBios_sys_b0_52;
3003 //biosB0[0x53] = psxBios_sys_b0_53;
3004 //biosB0[0x54] = psxBios__get_errno;
3005 biosB0[0x55] = psxBios__get_error;
3006 biosB0[0x56] = psxBios_GetC0Table;
3007 biosB0[0x57] = psxBios_GetB0Table;
3008 biosB0[0x58] = psxBios__card_chan;
3009 //biosB0[0x59] = psxBios_sys_b0_59;
3010 //biosB0[0x5a] = psxBios_sys_b0_5a;
3011 biosB0[0x5b] = psxBios_ChangeClearPad;
3012 biosB0[0x5c] = psxBios__card_status;
3013 biosB0[0x5d] = psxBios__card_wait;
3014 //*******************C0 CALLS****************************
3015 //biosC0[0x00] = psxBios_InitRCnt;
3016 //biosC0[0x01] = psxBios_InitException;
3017 biosC0[0x02] = psxBios_SysEnqIntRP;
3018 biosC0[0x03] = psxBios_SysDeqIntRP;
3019 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
3020 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3021 //biosC0[0x06] = psxBios_ExceptionHandler;
3022 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3023 //biosC0[0x08] = psxBios_SysInitMemory;
3024 //biosC0[0x09] = psxBios_SysInitKMem;
3025 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3026 //biosC0[0x0b] = psxBios_SystemError;
3027 //biosC0[0x0c] = psxBios_InitDefInt;
3028 //biosC0[0x0d] = psxBios_sys_c0_0d;
3029 //biosC0[0x0e] = psxBios_sys_c0_0e;
3030 //biosC0[0x0f] = psxBios_sys_c0_0f;
3031 //biosC0[0x10] = psxBios_sys_c0_10;
3032 //biosC0[0x11] = psxBios_sys_c0_11;
3033 //biosC0[0x12] = psxBios_InstallDevices;
3034 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3035 //biosC0[0x14] = psxBios_sys_c0_14;
3036 //biosC0[0x15] = psxBios__cdevinput;
3037 //biosC0[0x16] = psxBios__cdevscan;
3038 //biosC0[0x17] = psxBios__circgetc;
3039 //biosC0[0x18] = psxBios__circputc;
3040 //biosC0[0x19] = psxBios_ioabort;
3041 //biosC0[0x1a] = psxBios_sys_c0_1a
3042 //biosC0[0x1b] = psxBios_KernelRedirect;
3043 //biosC0[0x1c] = psxBios_PatchAOTable;
3044 //************** THE END ***************************************
3047 size = sizeof(EvCB) * 32;
3048 EventCB = (void *)&psxR[base]; base += size * 6;
3049 memset(EventCB, 0, size * 6);
3051 EvEV = EventCB + 32;
3052 RcEV = EventCB + 32 * 2;
3053 UeEV = EventCB + 32 * 3;
3054 SwEV = EventCB + 32 * 4;
3055 ThEV = EventCB + 32 * 5;
3057 ptr = (u32 *)&psxM[0x0874]; // b0 table
3058 ptr[0] = SWAPu32(0x4c54 - 0x884);
3060 ptr = (u32 *)&psxM[0x0674]; // c0 table
3061 ptr[6] = SWAPu32(0xc80);
3063 memset(SysIntRP, 0, sizeof(SysIntRP));
3064 memset(ThreadCB, 0, sizeof(ThreadCB));
3065 ThreadCB[0].status = 2; // main thread
3072 pad_buf1len = pad_buf2len = 0;
3078 memset(FDesc, 0, sizeof(FDesc));
3079 card_active_chan = 0;
3081 psxMu32ref(0x0150) = SWAPu32(0x160);
3082 psxMu32ref(0x0154) = SWAPu32(0x320);
3083 psxMu32ref(0x0160) = SWAPu32(0x248);
3084 strcpy((char *)&psxM[0x248], "bu");
3085 /* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3086 psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3087 psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3088 psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3089 psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3092 psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
3093 /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
3094 Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3095 //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
3096 psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3097 psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3098 psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3099 psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3100 psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3101 psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3102 psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3103 psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3105 // initial stack pointer for BIOS interrupt
3106 psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3109 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3112 len = 0x80000 - 0x66000;
3113 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3114 len = 0x80000 - 0x69d68;
3115 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3118 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3120 hleSoftCall = FALSE;
3122 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3123 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3124 Here are some examples of games not working with this fix in place :
3125 R-type won't get past the Irem logo if not implemented.
3126 Crash Team Racing will softlock after the Sony logo.
3129 psxMu32ref(0x0000) = SWAPu32(0x00000003);
3131 But overwritten by 00000003h after soon.
3132 psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3134 psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3135 psxMu32ref(0x0008) = SWAPu32(0x08000403);
3136 psxMu32ref(0x000C) = SWAPu32(0x00000000);
3139 void psxBiosShutdown() {
3142 #define psxBios_PADpoll(pad) { \
3143 PAD##pad##_startPoll(pad); \
3144 pad_buf##pad[0] = 0; \
3145 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3146 if (!(pad_buf##pad[1] & 0x0f)) { \
3149 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3151 PAD##pad##_poll(0); \
3153 while (bufcount--) { \
3154 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3158 void biosInterrupt() {
3161 // if (psxHu32(0x1070) & 0x1) { // Vsync
3162 if (pad_buf != NULL) {
3163 u32 *buf = (u32*)pad_buf;
3165 if (!Config.UseNet) {
3167 if (PAD1_poll(0x42) == 0x23) {
3169 *buf = PAD1_poll(0) << 8;
3170 *buf |= PAD1_poll(0);
3172 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3173 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3176 *buf = PAD1_poll(0) << 8;
3177 *buf|= PAD1_poll(0);
3181 if (PAD2_poll(0x42) == 0x23) {
3183 *buf |= PAD2_poll(0) << 24;
3184 *buf |= PAD2_poll(0) << 16;
3186 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3187 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3190 *buf |= PAD2_poll(0) << 24;
3191 *buf |= PAD2_poll(0) << 16;
3199 data = PAD1_poll(0) << 8;
3200 data |= PAD1_poll(0);
3202 if (NET_sendPadData(&data, 2) == -1)
3205 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3207 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3211 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3214 if (NET_sendPadData(pad_buf1, i) == -1)
3217 if (NET_recvPadData(pad_buf1, 1) == -1)
3219 if (NET_recvPadData(pad_buf2, 2) == -1)
3233 if (psxHu32(0x1070) & 0x1) { // Vsync
3234 if (RcEV[3][1].status == EvStACTIVE) {
3235 softCall(RcEV[3][1].fhandler);
3236 // hwWrite32(0x1f801070, ~(1));
3240 if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3243 for (i = 0; i < 3; i++) {
3244 if (psxHu32(0x1070) & (1 << (i + 4))) {
3245 if (RcEV[i][1].status == EvStACTIVE) {
3246 softCall(RcEV[i][1].fhandler);
3248 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3254 void psxBiosException() {
3257 switch (psxRegs.CP0.n.Cause & 0x3c) {
3258 case 0x00: // Interrupt
3259 interrupt_r26=psxRegs.CP0.n.EPC;
3261 // PSXCPU_LOG("interrupt\n");
3265 sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3269 for (i = 0; i < 8; i++) {
3271 u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3278 if (jmp_int != NULL) {
3281 psxHwWrite32(0x1f801070, 0xffffffff);
3286 for (i = 0; i < 8; i++) // s0-s7
3287 psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3294 psxHwWrite16(0x1f801070, 0);
3297 case 0x20: // Syscall
3299 PSXCPU_LOG("syscall exp %x\n", a0);
3302 case 1: // EnterCritical - disable irq's
3303 /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3304 v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3305 psxRegs.CP0.n.Status &= ~0x404;
3308 case 2: // ExitCritical - enable irq's
3309 psxRegs.CP0.n.Status |= 0x404;
3311 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3315 pc0 = psxRegs.CP0.n.EPC + 4;
3317 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3318 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3323 PSXCPU_LOG("unknown bios exception!\n");
3328 pc0 = psxRegs.CP0.n.EPC;
3329 if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3331 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3332 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3335 #define bfreeze(ptr, size) { \
3336 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3337 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3341 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3342 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3344 #define bfreezepsxMptr(ptr, type) { \
3346 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3347 else psxRu32ref(base) = 0; \
3349 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3350 else (ptr) = NULL; \
3352 base += sizeof(u32); \
3355 void psxBiosFreeze(int Mode) {
3358 bfreezepsxMptr(jmp_int, u32);
3359 bfreezepsxMptr(pad_buf, int);
3360 bfreezepsxMptr(pad_buf1, char);
3361 bfreezepsxMptr(pad_buf2, char);
3362 bfreezepsxMptr(heap_addr, u32);
3363 bfreezel(&pad_buf1len);
3364 bfreezel(&pad_buf2len);
3367 bfreezel(&CardState);
3369 bfreezel(&CurThread);
3371 bfreezel(&card_active_chan);
3372 bfreezel(&pad_stopped);
3373 bfreezel(&heap_size);