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 #define SysPrintf if (Config.PsxOut) printf
41 char *biosA0n[256] = {
43 "open", "lseek", "read", "write",
44 "close", "ioctl", "exit", "sys_a0_07",
45 "getc", "putc", "todigit", "atof",
46 "strtoul", "strtol", "abs", "labs",
48 "atoi", "atol", "atob", "setjmp",
49 "longjmp", "strcat", "strncat", "strcmp",
50 "strncmp", "strcpy", "strncpy", "strlen",
51 "index", "rindex", "strchr", "strrchr",
53 "strpbrk", "strspn", "strcspn", "strtok",
54 "strstr", "toupper", "tolower", "bcopy",
55 "bzero", "bcmp", "memcpy", "memset",
56 "memmove", "memcmp", "memchr", "rand",
58 "srand", "qsort", "strtod", "malloc",
59 "free", "lsearch", "bsearch", "calloc",
60 "realloc", "InitHeap", "_exit", "getchar",
61 "putchar", "gets", "puts", "printf",
63 "sys_a0_40", "LoadTest", "Load", "Exec",
64 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
65 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
66 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
68 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
69 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
70 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
71 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
73 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
74 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
75 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
76 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
78 "_bu_init", "_96_init", "_96_remove", "sys_a0_73",
79 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
80 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
81 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
83 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
84 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
85 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
86 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
88 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
89 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
90 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
91 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
93 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
94 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
95 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
96 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
98 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
102 char *biosB0n[256] = {
104 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
105 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
106 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
107 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
109 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
110 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
111 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
112 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
114 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
115 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
116 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
117 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
119 "sys_b0_30", "sys_b0_31", "open", "lseek",
120 "read", "write", "close", "ioctl",
121 "exit", "sys_b0_39", "getc", "putc",
122 "getchar", "putchar", "gets", "puts",
124 "cd", "format", "firstfile", "nextfile",
125 "rename", "delete", "undelete", "AddDevice",
126 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
127 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
129 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
130 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
131 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
132 "_card_status", "_card_wait",
135 char *biosC0n[256] = {
137 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
138 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
139 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
140 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
142 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
143 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
144 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
148 //#define r0 (psxRegs.GPR.n.r0)
149 #define at (psxRegs.GPR.n.at)
150 #define v0 (psxRegs.GPR.n.v0)
151 #define v1 (psxRegs.GPR.n.v1)
152 #define a0 (psxRegs.GPR.n.a0)
153 #define a1 (psxRegs.GPR.n.a1)
154 #define a2 (psxRegs.GPR.n.a2)
155 #define a3 (psxRegs.GPR.n.a3)
156 #define t0 (psxRegs.GPR.n.t0)
157 #define t1 (psxRegs.GPR.n.t1)
158 #define t2 (psxRegs.GPR.n.t2)
159 #define t3 (psxRegs.GPR.n.t3)
160 #define t4 (psxRegs.GPR.n.t4)
161 #define t5 (psxRegs.GPR.n.t5)
162 #define t6 (psxRegs.GPR.n.t6)
163 #define t7 (psxRegs.GPR.n.t7)
164 #define t8 (psxRegs.GPR.n.t8)
165 #define t9 (psxRegs.GPR.n.t9)
166 #define s0 (psxRegs.GPR.n.s0)
167 #define s1 (psxRegs.GPR.n.s1)
168 #define s2 (psxRegs.GPR.n.s2)
169 #define s3 (psxRegs.GPR.n.s3)
170 #define s4 (psxRegs.GPR.n.s4)
171 #define s5 (psxRegs.GPR.n.s5)
172 #define s6 (psxRegs.GPR.n.s6)
173 #define s7 (psxRegs.GPR.n.s7)
174 #define k0 (psxRegs.GPR.n.k0)
175 #define k1 (psxRegs.GPR.n.k1)
176 #define gp (psxRegs.GPR.n.gp)
177 #define sp (psxRegs.GPR.n.sp)
178 #define fp (psxRegs.GPR.n.s8)
179 #define ra (psxRegs.GPR.n.ra)
180 #define pc0 (psxRegs.pc)
182 #define Ra0 ((char *)PSXM(a0))
183 #define Ra1 ((char *)PSXM(a1))
184 #define Ra2 ((char *)PSXM(a2))
185 #define Ra3 ((char *)PSXM(a3))
186 #define Rv0 ((char *)PSXM(v0))
187 #define Rsp ((char *)PSXM(sp))
196 #define EvStUNUSED 0x0000
197 #define EvStWAIT 0x1000
198 #define EvStACTIVE 0x2000
199 #define EvStALREADY 0x4000
201 #define EvMdINTR 0x1000
202 #define EvMdNOINTR 0x2000
231 u32 _sp, _fp, _gp, ret, base;
251 static u32 *jmp_int = NULL;
252 static int *pad_buf = NULL;
253 static char *pad_buf1 = NULL, *pad_buf2 = NULL;
254 static int pad_buf1len, pad_buf2len;
255 static int pad_stopped = 0;
259 static EvCB *HwEV; // 0xf0
260 static EvCB *EvEV; // 0xf1
261 static EvCB *RcEV; // 0xf2
262 static EvCB *UeEV; // 0xf3
263 static EvCB *SwEV; // 0xf4
264 static EvCB *ThEV; // 0xff
265 static u32 heap_size = 0;
266 static u32 *heap_addr = NULL;
267 static u32 *heap_end = NULL;
268 static u32 SysIntRP[8];
269 static int CardState = -1;
270 static TCB Thread[8];
271 static int CurThread = 0;
272 static FileDesc FDesc[32];
273 static u32 card_active_chan;
275 boolean hleSoftCall = FALSE;
277 static inline void softCall(u32 pc) {
283 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
288 static inline void softCall2(u32 pc) {
295 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
301 static inline void DeliverEvent(u32 ev, u32 spec) {
302 if (Event[ev][spec].status != EvStACTIVE) return;
304 // Event[ev][spec].status = EvStALREADY;
305 if (Event[ev][spec].mode == EvMdINTR) {
306 softCall2(Event[ev][spec].fhandler);
307 } else Event[ev][spec].status = EvStALREADY;
310 static unsigned interrupt_r26=0x8004E8B0;
312 static inline void SaveRegs() {
313 memcpy(regs, psxRegs.GPR.r, 32*4);
314 regs[32] = psxRegs.GPR.n.lo;
315 regs[33] = psxRegs.GPR.n.hi;
316 regs[34] = psxRegs.pc;
319 static inline void LoadRegs() {
320 memcpy(psxRegs.GPR.r, regs, 32*4);
321 psxRegs.GPR.n.lo = regs[32];
322 psxRegs.GPR.n.hi = regs[33];
328 // System calls A0 */
331 #define buread(Ra1, mcd, length) { \
332 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); \
333 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
334 memcpy(Ra1, ptr, length); \
335 if (FDesc[1 + mcd].mode & 0x8000) { \
336 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
337 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
340 FDesc[1 + mcd].offset += v0; \
343 #define buwrite(Ra1, mcd, length) { \
344 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
345 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
346 ptr = Mcd##mcd##Data + offset; \
347 memcpy(ptr, Ra1, length); \
348 FDesc[1 + mcd].offset += length; \
349 if (FDesc[1 + mcd].mode & 0x8000) { \
350 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
351 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
357 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
358 /* For some strange reason, the returned character is sign-expanded; */
359 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
360 /* TODO FIX ME : Properly implement this behaviour */
361 void psxBios_getc(void) // 0x03, 0x35
366 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
372 case 2: buread(pa1, 1, 1); break;
373 case 3: buread(pa1, 2, 1); break;
380 /* Copy of psxBios_write, except size is 1. */
381 void psxBios_putc(void) // 0x09, 0x3B
386 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
394 if (a0 == 1) { // stdout
395 char *ptr = (char *)pa1;
399 printf("%c", *ptr++); a2--;
405 case 2: buwrite(pa1, 1, 1); break;
406 case 3: buwrite(pa1, 2, 1); break;
412 void psxBios_todigit(void) // 0x0a
416 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
419 if (c >= 0x30 && c < 0x3A) {
422 else if (c > 0x60 && c < 0x7B) {
425 else if (c > 0x40 && c < 0x5B) {
428 else if (c >= 0x80) {
439 void psxBios_abs() { // 0x0e
440 if ((s32)a0 < 0) v0 = -(s32)a0;
445 void psxBios_labs() { // 0x0f
449 void psxBios_atoi() { // 0x10
451 char *p = (char *)Ra0;
455 case ' ': case '\t': continue;
462 while (*p >= '0' && *p <= '9') {
463 n = n * 10 + *p++ - '0';
470 void psxBios_atol() { // 0x11
474 void psxBios_setjmp() { // 0x13
475 u32 *jmp_buf = (u32 *)Ra0;
479 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x13]);
485 for (i = 0; i < 8; i++) // s0-s7
486 jmp_buf[3 + i] = psxRegs.GPR.r[16 + i];
492 void psxBios_longjmp() { // 0x14
493 u32 *jmp_buf = (u32 *)Ra0;
497 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
500 ra = jmp_buf[0]; /* ra */
501 sp = jmp_buf[1]; /* sp */
502 fp = jmp_buf[2]; /* fp */
503 for (i = 0; i < 8; i++) // s0-s7
504 psxRegs.GPR.r[16 + i] = jmp_buf[3 + i];
505 gp = jmp_buf[11]; /* gp */
510 void psxBios_strcat() { // 0x15
511 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
514 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
516 if (a0 == 0 || a1 == 0)
524 while ((*p1++ = *p2++) != '\0');
529 void psxBios_strncat() { // 0x16
530 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
534 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
536 if (a0 == 0 || a1 == 0)
544 while ((*p1++ = *p2++) != '\0') {
554 void psxBios_strcmp() { // 0x17
555 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
557 if (a0 == 0 && a1 == 0)
563 else if (a0 == 0 && a1 != 0)
569 else if (a0 != 0 && a1 == 0)
576 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
579 while (*p1 == *p2++) {
598 void psxBios_strncmp() { // 0x18
599 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
601 if (a0 == 0 && a1 == 0)
607 else if (a0 == 0 && a1 != 0)
613 else if (a0 != 0 && a1 == 0)
620 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
623 while (--n >= 0 && *p1 == *p2++) {
627 v1 = a2 - ((a2-n) - 1);
635 v0 = (n < 0 ? 0 : *p1 - *--p2);
637 v1 = a2 - ((a2-n) - 1);
643 void psxBios_strcpy() { // 0x19
644 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
645 if (a0 == 0 || a1 == 0)
651 while ((*p1++ = *p2++) != '\0');
656 void psxBios_strncpy() { // 0x1a
657 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
659 if (a0 == 0 || a1 == 0)
665 for (i = 0; i < n; i++) {
666 if ((*p1++ = *p2++) == '\0') {
678 void psxBios_strlen() { // 0x1b
679 char *p = (char *)Ra0;
690 void psxBios_index() { // 0x1c
691 char *p = (char *)Ra0;
701 v0 = a0 + (p - (char *)Ra0);
705 } while (*p++ != '\0');
710 void psxBios_rindex() { // 0x1d
711 char *p = (char *)Ra0;
721 v0 = a0 + (p - (char *)Ra0);
722 } while (*p++ != '\0');
727 void psxBios_strchr() { // 0x1e
731 void psxBios_strrchr() { // 0x1f
735 void psxBios_strpbrk() { // 0x20
736 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
738 while ((c = *p1++) != '\0') {
739 for (scanp = p2; (sc = *scanp++) != '\0';) {
741 v0 = a0 + (p1 - 1 - (char *)Ra0);
748 // BUG: return a0 instead of NULL if not found
752 void psxBios_strspn() { // 0x21
755 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
756 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
757 if (*p2 == '\0') break;
760 v0 = p1 - (char *)Ra0; pc0 = ra;
763 void psxBios_strcspn() { // 0x22
766 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
767 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
768 if (*p2 != '\0') break;
771 v0 = p1 - (char *)Ra0; pc0 = ra;
774 void psxBios_strtok() { // 0x23
775 char *pcA0 = (char *)Ra0;
776 char *pcRet = strtok(pcA0, (char *)Ra1);
778 v0 = a0 + pcRet - pcA0;
784 void psxBios_strstr() { // 0x24
785 char *p = (char *)Ra0, *p1, *p2;
791 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
796 v0 = a0 + (p - (char *)Ra0);
807 void psxBios_toupper() { // 0x25
808 v0 = (s8)(a0 & 0xff);
809 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
813 void psxBios_tolower() { // 0x26
814 v0 = (s8)(a0 & 0xff);
815 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
819 void psxBios_bcopy() { // 0x27
820 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
822 if (a0 == 0 || a2 > 0x7FFFFFFF)
827 while ((s32)a2-- > 0) *p1++ = *p2++;
832 void psxBios_bzero() { // 0x28
833 char *p = (char *)Ra0;
835 /* Same as memset here (See memset below) */
836 if (a1 > 0x7FFFFFFF || a1 == 0)
847 while ((s32)a1-- > 0) *p++ = '\0';
852 void psxBios_bcmp() { // 0x29
853 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
855 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
857 while ((s32)a2-- > 0) {
858 if (*p1++ != *p2++) {
859 v0 = *p1 - *p2; // BUG: compare the NEXT byte
868 void psxBios_memcpy() { // 0x2a
869 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
871 if (a0 == 0 || a2 > 0x7FFFFFFF)
876 while ((s32)a2-- > 0) {
883 void psxBios_memset() { // 0x2b
884 char *p = (char *)Ra0;
886 if (a2 > 0x7FFFFFFF || a2 == 0)
897 while ((s32)a2-- > 0) *p++ = (char)a1;
902 void psxBios_memmove() { // 0x2c
903 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
905 if (a0 == 0 || a2 > 0x7FFFFFFF)
910 if (p2 <= p1 && p2 + a2 > p1) {
911 a2++; // BUG: copy one more byte here
914 while ((s32)a2-- > 0) *--p1 = *--p2;
916 while ((s32)a2-- > 0) *p1++ = *p2++;
921 void psxBios_memcmp() { // 0x2d
925 void psxBios_memchr() { // 0x2e
926 char *p = (char *)Ra0;
928 if (a0 == 0 || a2 > 0x7FFFFFFF)
934 while ((s32)a2-- > 0) {
935 if (*p++ != (s8)a1) continue;
936 v0 = a0 + (p - (char *)Ra0 - 1);
944 void psxBios_rand() { // 0x2f
945 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
946 v0 = (s >> 16) & 0x7fff;
947 psxMu32ref(0x9010) = SWAPu32(s);
951 void psxBios_srand() { // 0x30
952 psxMu32ref(0x9010) = SWAPu32(a0);
956 static u32 qscmpfunc, qswidth;
958 static inline int qscmp(char *a, char *b) {
961 a0 = sa0 + (a - (char *)PSXM(sa0));
962 a1 = sa0 + (b - (char *)PSXM(sa0));
964 softCall2(qscmpfunc);
970 static inline void qexchange(char *i, char *j) {
981 static inline void q3exchange(char *i, char *j, char *k) {
993 static void qsort_main(char *a, char *l) {
994 char *i, *j, *lp, *hp;
999 if ((n = l - a) <= qswidth)
1001 n = qswidth * (n / (2 * qswidth));
1007 if ((c = qscmp(i, lp)) == 0) {
1008 qexchange(i, lp -= qswidth);
1019 if ((c = qscmp(hp, j)) == 0) {
1020 qexchange(hp += qswidth, j);
1025 q3exchange(i, hp += qswidth, j);
1039 if (lp - a >= l - hp) {
1040 qsort_main(hp + qswidth, l);
1049 q3exchange(j, lp -= qswidth, i);
1054 void psxBios_qsort() { // 0x31
1057 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1062 void psxBios_malloc() { // 0x33
1063 unsigned int *chunk, *newchunk = NULL;
1064 unsigned int dsize = 0, csize, cstat;
1067 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1069 if (!a0 || (!heap_size || !heap_addr)) {
1075 // scan through heap and combine free chunks of space
1078 while(chunk < heap_end) {
1079 // get size and status of actual chunk
1080 csize = ((u32)*chunk) & 0xfffffffc;
1081 cstat = ((u32)*chunk) & 1;
1083 // most probably broken heap descriptor
1084 // this fixes Burning Road
1087 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1092 // it's a free chunk
1097 colflag = 1; // let's begin a new collection of free memory
1099 else dsize += (csize+4); // add the new size including header
1101 // not a free chunk: did we start a collection ?
1103 if(colflag == 1) { // collection is over
1105 *newchunk = SWAP32(dsize | 1);
1110 chunk = (u32*)((uptr)chunk + csize + 4);
1112 // if neccessary free memory on end of heap
1114 *newchunk = SWAP32(dsize | 1);
1117 csize = ((u32)*chunk) & 0xfffffffc;
1118 cstat = ((u32)*chunk) & 1;
1119 dsize = (a0 + 3) & 0xfffffffc;
1121 // exit on uninitialized heap
1122 if (chunk == NULL) {
1123 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1129 // search an unused chunk that is big enough until the end of the heap
1130 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1131 chunk = (u32*)((uptr)chunk + csize + 4);
1133 // catch out of memory
1134 if(chunk >= heap_end) {
1135 printf("malloc %x,%x: Out of memory error!\n",
1141 csize = ((u32)*chunk) & 0xfffffffc;
1142 cstat = ((u32)*chunk) & 1;
1146 if(dsize == csize) {
1147 // chunk has same size
1148 *chunk &= 0xfffffffc;
1149 } else if (dsize > csize) {
1154 *chunk = SWAP32(dsize);
1155 newchunk = (u32*)((uptr)chunk + dsize + 4);
1156 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1159 // return pointer to allocated memory
1160 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1162 //printf ("malloc %x,%x\n", v0, a0);
1166 void psxBios_free() { // 0x34
1169 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1172 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1175 *(u32*)(Ra0-4) |= 1; // set chunk to free
1179 void psxBios_calloc() { // 0x37
1182 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1192 void psxBios_realloc() { // 0x38
1196 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1200 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1205 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1210 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1211 /* Note that it is not quite implemented this way here. */
1221 /* InitHeap(void *block , int n) */
1222 void psxBios_InitHeap() { // 0x39
1226 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1229 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1234 heap_addr = (u32 *)Ra0;
1236 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1237 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1238 //*heap_addr = SWAP32(size | 1);
1240 SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1245 void psxBios_getchar() { //0x3b
1246 v0 = getchar(); pc0 = ra;
1249 void psxBios_printf() { // 0x3f
1259 memcpy(save, psp, 4 * 4);
1260 psxMu32ref(sp) = SWAP32((u32)a0);
1261 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1262 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1263 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1275 tmp2[j++] = Ra0[i]; goto _start;
1277 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1288 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1292 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1298 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1300 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1302 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1304 *ptmp++ = Ra0[i]; break;
1315 memcpy(psp, save, 4 * 4);
1317 SysPrintf("%s", tmp);
1322 void psxBios_format() { // 0x41
1323 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1325 CreateMcd(Config.Mcd1);
1326 LoadMcd(1, Config.Mcd1);
1329 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1331 CreateMcd(Config.Mcd2);
1332 LoadMcd(2, Config.Mcd2);
1343 * long Load(char *name, struct EXEC *header);
1346 void psxBios_Load() { // 0x42
1351 PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1);
1355 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1356 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1364 * int Exec(struct EXEC *header , int argc , char **argv);
1367 void psxBios_Exec() { // 43
1368 EXEC *header = (EXEC*)Ra0;
1372 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1382 if (header->S_addr != 0) {
1383 tmp = header->S_addr + header->s_size;
1399 void psxBios_FlushCache() { // 44
1401 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1407 void psxBios_GPU_dw() { // 0x46
1412 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1415 GPU_writeData(0xa0000000);
1416 GPU_writeData((a1<<16)|(a0&0xffff));
1417 GPU_writeData((a3<<16)|(a2&0xffff));
1419 ptr = (s32*)PSXM(Rsp[4]); //that is correct?
1421 GPU_writeData(SWAP32(*ptr));
1428 void psxBios_mem2vram() { // 0x47
1431 GPU_writeData(0xa0000000);
1432 GPU_writeData((a1<<16)|(a0&0xffff));
1433 GPU_writeData((a3<<16)|(a2&0xffff));
1435 GPU_writeStatus(0x04000002);
1436 psxHwWrite32(0x1f8010f4,0);
1437 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1438 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1439 psxHwWrite32(0x1f8010a4,((size/16)<<16)|16);
1440 psxHwWrite32(0x1f8010a8,0x01000201);
1445 void psxBios_SendGPU() { // 0x48
1446 GPU_writeStatus(a0);
1451 void psxBios_GPU_cw() { // 0x49
1456 void psxBios_GPU_cwb() { // 0x4a
1457 s32 *ptr = (s32*)Ra0;
1460 GPU_writeData(SWAP32(*ptr));
1467 void psxBios_GPU_SendPackets() { //4b:
1468 GPU_writeStatus(0x04000002);
1469 psxHwWrite32(0x1f8010f4,0);
1470 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1471 psxHwWrite32(0x1f8010a0,a0);
1472 psxHwWrite32(0x1f8010a4,0);
1473 psxHwWrite32(0x1f8010a8,0x010000401);
1477 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1478 psxHwWrite32(0x1f8010a8,0x00000401);
1479 GPU_writeData(0x0400000);
1480 GPU_writeData(0x0200000);
1481 GPU_writeData(0x0100000);
1486 void psxBios_GPU_GetGPUStatus() { // 0x4d
1487 v0 = GPU_readStatus();
1493 void psxBios_LoadExec() { // 51
1494 EXEC *header = (EXEC*)PSXM(0xf000);
1498 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1500 s_addr = a1; s_size = a2;
1505 header->S_addr = s_addr;
1506 header->s_size = s_size;
1508 a0 = 0xf000; a1 = 0; a2 = 0;
1512 void psxBios__bu_init() { // 70
1514 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1517 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1518 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1523 void psxBios__96_init() { // 71
1525 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1531 void psxBios__96_remove() { // 72
1533 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1539 void psxBios_SetMem() { // 9f
1540 u32 new = psxHu32(0x1060);
1543 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1548 psxHu32ref(0x1060) = SWAP32(new);
1549 psxMu32ref(0x060) = a0;
1550 SysPrintf("Change effective memory : %d MBytes\n",a0);
1554 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1555 psxMu32ref(0x060) = a0;
1556 SysPrintf("Change effective memory : %d MBytes\n",a0);
1559 SysPrintf("Effective memory must be 2/8 MBytes\n");
1566 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1567 void psxBios_get_cd_status(void) //a6
1573 void psxBios__card_info() { // ab
1575 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1578 card_active_chan = a0;
1580 switch (card_active_chan)
1582 case 0x00: case 0x01: case 0x02: case 0x03:
1583 ret = Config.Mcd1[0] ? 0x2 : 0x8;
1585 case 0x10: case 0x11: case 0x12: case 0x13:
1586 ret = Config.Mcd2[0] ? 0x2 : 0x8;
1590 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1596 DeliverEvent(0x11, 0x2); // 0xf4000001, 0x0004
1597 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
1601 void psxBios__card_load() { // ac
1603 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1606 card_active_chan = a0;
1608 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1609 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1614 /* System calls B0 */
1616 void psxBios_SetRCnt() { // 02
1618 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1625 psxRcntWtarget(a0, a1);
1626 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1627 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1628 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1629 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1630 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1632 psxRcntWmode(a0, mode);
1637 void psxBios_GetRCnt() { // 03
1639 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1643 if (a0 != 3) v0 = psxRcntRcount(a0);
1648 void psxBios_StartRCnt() { // 04
1650 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1654 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1655 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1659 void psxBios_StopRCnt() { // 05
1661 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1665 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1666 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1670 void psxBios_ResetRCnt() { // 06
1672 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1677 psxRcntWmode(a0, 0);
1678 psxRcntWtarget(a0, 0);
1679 psxRcntWcount(a0, 0);
1685 /* gets ev for use with Event */
1687 ev = (a0 >> 24) & 0xf; \
1688 if (ev == 0xf) ev = 0x5; \
1692 /* gets spec for use with Event */
1696 case 0x0301: spec = 16; break; \
1697 case 0x0302: spec = 17; break; \
1699 for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1703 void psxBios_DeliverEvent() { // 07
1711 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1714 DeliverEvent(ev, spec);
1719 void psxBios_OpenEvent() { // 08
1727 PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1730 Event[ev][spec].status = EvStWAIT;
1731 Event[ev][spec].mode = a2;
1732 Event[ev][spec].fhandler = a3;
1734 v0 = ev | (spec << 8);
1738 void psxBios_CloseEvent() { // 09
1742 spec = (a0 >> 8) & 0xff;
1745 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1748 Event[ev][spec].status = EvStUNUSED;
1753 void psxBios_WaitEvent() { // 0a
1757 spec = (a0 >> 8) & 0xff;
1759 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1761 if (Event[ev][spec].status == EvStUNUSED)
1768 if (Event[ev][spec].status == EvStALREADY)
1770 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1771 if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE;
1781 void psxBios_TestEvent() { // 0b
1785 spec = (a0 >> 8) & 0xff;
1787 if (Event[ev][spec].status == EvStALREADY)
1789 if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE;
1798 PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1804 void psxBios_EnableEvent() { // 0c
1808 spec = (a0 >> 8) & 0xff;
1811 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1814 Event[ev][spec].status = EvStACTIVE;
1819 void psxBios_DisableEvent() { // 0d
1823 spec = (a0 >> 8) & 0xff;
1826 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1829 Event[ev][spec].status = EvStWAIT;
1835 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1838 void psxBios_OpenTh() { // 0e
1841 for (th=1; th<8; th++)
1843 if (Thread[th].status == 0) break;
1847 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1848 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1850 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1857 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1860 Thread[th].status = 1;
1861 Thread[th].func = a0;
1862 Thread[th].reg[29] = a1;
1863 Thread[th].reg[28] = a2;
1869 * int CloseTh(long thread);
1872 void psxBios_CloseTh() { // 0f
1876 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
1878 /* The return value is always 1 (even if the handle was already closed). */
1880 if (Thread[th].status != 0) {
1881 Thread[th].status = 0;
1888 * int ChangeTh(long thread);
1891 void psxBios_ChangeTh() { // 10
1895 // PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
1897 /* The return value is always 1. */
1899 if (Thread[th].status == 0 || CurThread == th) {
1902 if (Thread[CurThread].status == 2) {
1903 Thread[CurThread].status = 1;
1904 Thread[CurThread].func = ra;
1905 memcpy(Thread[CurThread].reg, psxRegs.GPR.r, 32*4);
1908 memcpy(psxRegs.GPR.r, Thread[th].reg, 32*4);
1909 pc0 = Thread[th].func;
1910 Thread[th].status = 2;
1915 void psxBios_InitPAD() { // 0x12
1917 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
1920 pad_buf1 = (char*)Ra0;
1922 pad_buf2 = (char*)Ra2;
1928 void psxBios_StartPAD() { // 13
1930 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
1933 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
1934 psxRegs.CP0.n.Status |= 0x401;
1938 void psxBios_StopPAD() { // 14
1940 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
1948 void psxBios_PAD_init() { // 15
1950 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
1952 if (!(a0 == 0x20000000 || a0 == 0x20000001))
1958 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
1959 pad_buf = (int *)Ra1;
1961 psxRegs.CP0.n.Status |= 0x401;
1966 void psxBios_PAD_dr() { // 16
1968 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
1974 void psxBios_ReturnFromException() { // 17
1977 pc0 = psxRegs.CP0.n.EPC;
1979 if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;
1981 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
1982 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
1985 void psxBios_ResetEntryInt() { // 18
1987 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
1994 void psxBios_HookEntryInt() { // 19
1996 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
1999 jmp_int = (u32*)Ra0;
2003 void psxBios_UnDeliverEvent() { // 0x20
2011 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2014 if (Event[ev][spec].status == EvStALREADY &&
2015 Event[ev][spec].mode == EvMdNOINTR)
2016 Event[ev][spec].status = EvStACTIVE;
2021 char ffile[64], *pfile;
2023 static void buopen(int mcd, u8 *ptr, u8 *cfg)
2028 strcpy(FDesc[1 + mcd].name, Ra0+5);
2029 FDesc[1 + mcd].offset = 0;
2030 FDesc[1 + mcd].mode = a1;
2032 for (i=1; i<16; i++) {
2034 if ((*fptr & 0xF0) != 0x50) continue;
2035 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2036 FDesc[1 + mcd].mcfile = i;
2037 SysPrintf("open %s\n", fptr+0xa);
2041 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2043 for (i=1; i<16; i++) {
2044 int j, xor, nblk = a1 >> 16;
2048 if ((*fptr & 0xF0) != 0xa0) continue;
2050 FDesc[1 + mcd].mcfile = i;
2053 fptr[5] = 0x20 * nblk;
2056 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2057 pptr = fptr2 = fptr;
2058 for(j=2; j<=nblk; j++) {
2060 for(i++; i<16; i++) {
2063 memset(fptr2, 0, 128);
2064 fptr2[0] = j < nblk ? 0x52 : 0x53;
2067 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2072 /* shouldn't this return ENOSPC if i == 16? */
2074 pptr[8] = pptr[9] = 0xff;
2075 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2077 SysPrintf("openC %s %d\n", ptr, nblk);
2079 /* just go ahead and resave them all */
2080 SaveMcd(cfg, ptr, 128, 128 * 15);
2083 /* shouldn't this return ENOSPC if i == 16? */
2088 * int open(char *name , int mode);
2091 void psxBios_open() { // 0x32
2097 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2103 if (!strncmp(pa0, "bu00", 4)) {
2104 buopen(1, Mcd1Data, Config.Mcd1);
2107 if (!strncmp(pa0, "bu10", 4)) {
2108 buopen(2, Mcd2Data, Config.Mcd2);
2116 * int lseek(int fd , int offset , int whence);
2119 void psxBios_lseek() { // 0x33
2121 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2126 FDesc[a0].offset = a1;
2128 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2129 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2133 FDesc[a0].offset+= a1;
2134 v0 = FDesc[a0].offset;
2143 * int read(int fd , void *buf , int nbytes);
2146 void psxBios_read() { // 0x34
2151 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2158 case 2: buread(pa1, 1, a2); break;
2159 case 3: buread(pa1, 2, a2); break;
2167 * int write(int fd , void *buf , int nbytes);
2170 void psxBios_write() { // 0x35/0x03
2175 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2184 if (a0 == 1) { // stdout
2189 SysPrintf("%c", *ptr++); a2--;
2195 case 2: buwrite(pa1, 1, a2); break;
2196 case 3: buwrite(pa1, 2, a2); break;
2203 * int close(int fd);
2206 void psxBios_close() { // 0x36
2208 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2215 void psxBios_putchar() { // 3d
2216 SysPrintf("%c", (char)a0);
2220 void psxBios_puts() { // 3e/3f
2221 SysPrintf("%s", Ra0);
2226 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2227 * We want to mimic the PSX's behaviour in this case for bufile. */
2228 static size_t strlen_internal(char* p)
2230 size_t size_of_array = 0;
2231 while (*p++) size_of_array++;
2232 return size_of_array;
2235 #define bufile(mcd) { \
2236 size_t size_of_name = strlen_internal(dir->name); \
2237 while (nfile < 16) { \
2240 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2242 if ((*ptr & 0xF0) != 0x50) continue; \
2243 /* Bug link files show up as free block. */ \
2244 if (!ptr[0xa]) continue; \
2246 if (pfile[0] == 0) { \
2247 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2248 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2249 } else for (i=0; i<20; i++) { \
2250 if (pfile[i] == ptr[i]) { \
2251 dir->name[i] = ptr[i]; continue; } \
2252 if (pfile[i] == '?') { \
2253 dir->name[i] = ptr[i]; continue; } \
2254 if (pfile[i] == '*') { \
2255 strcpy(dir->name+i, ptr+i); break; } \
2258 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2259 if (match == 0) { continue; } \
2267 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2270 void psxBios_firstfile() { // 42
2271 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2278 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2287 if (!strncmp(pa0, "bu00", 4)) {
2288 // firstfile() calls _card_read() internally, so deliver it's event
2289 DeliverEvent(0x11, 0x2);
2291 } else if (!strncmp(pa0, "bu10", 4)) {
2292 // firstfile() calls _card_read() internally, so deliver it's event
2293 DeliverEvent(0x11, 0x2);
2302 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2305 void psxBios_nextfile() { // 43
2306 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2312 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2317 if (!strncmp(ffile, "bu00", 4)) {
2321 if (!strncmp(ffile, "bu10", 4)) {
2328 #define burename(mcd) { \
2329 for (i=1; i<16; i++) { \
2330 int namelen, j, xor = 0; \
2331 ptr = Mcd##mcd##Data + 128 * i; \
2332 if ((*ptr & 0xF0) != 0x50) continue; \
2333 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2334 namelen = strlen(Ra1+5); \
2335 memcpy(ptr+0xa, Ra1+5, namelen); \
2336 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2337 for (j=0; j<127; j++) xor^= ptr[j]; \
2339 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2346 * int rename(char *old, char *new);
2349 void psxBios_rename() { // 44
2356 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2362 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2366 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2375 #define budelete(mcd) { \
2376 for (i=1; i<16; i++) { \
2377 ptr = Mcd##mcd##Data + 128 * i; \
2378 if ((*ptr & 0xF0) != 0x50) continue; \
2379 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2380 *ptr = (*ptr & 0xf) | 0xA0; \
2381 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2382 SysPrintf("delete %s\n", ptr+0xa); \
2389 * int delete(char *name);
2392 void psxBios_delete() { // 45
2398 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2404 if (!strncmp(pa0, "bu00", 4)) {
2408 if (!strncmp(pa0, "bu10", 4)) {
2416 void psxBios_InitCARD() { // 4a
2418 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2426 void psxBios_StartCARD() { // 4b
2428 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2431 if (CardState == 0) CardState = 1;
2436 void psxBios_StopCARD() { // 4c
2438 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2441 if (CardState == 1) CardState = 0;
2446 void psxBios__card_write() { // 0x4e
2451 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2454 Function also accepts sector 400h (a bug).
2455 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2459 /* Invalid sectors */
2463 card_active_chan = a0;
2468 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2469 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2471 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2472 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2476 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2477 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2482 void psxBios__card_read() { // 0x4f
2487 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2490 Function also accepts sector 400h (a bug).
2491 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2495 /* Invalid sectors */
2499 card_active_chan = a0;
2504 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2506 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2510 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2511 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2516 void psxBios__new_card() { // 0x50
2518 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2524 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2525 void psxBios__get_error(void) // 55
2531 void psxBios_Krom2RawAdd() { // 0x51
2534 const u32 table_8140[][2] = {
2535 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2536 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2537 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2538 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2539 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2540 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2541 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2542 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2543 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2547 const u32 table_889f[][2] = {
2548 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2549 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2550 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2551 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2552 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2553 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2554 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2555 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2559 if (a0 >= 0x8140 && a0 <= 0x84be) {
2560 while (table_8140[i][0] <= a0) i++;
2561 a0 -= table_8140[i - 1][0];
2562 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2563 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2564 while (table_889f[i][0] <= a0) i++;
2565 a0 -= table_889f[i - 1][0];
2566 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2574 void psxBios_GetC0Table() { // 56
2576 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2579 v0 = 0x674; pc0 = ra;
2582 void psxBios_GetB0Table() { // 57
2584 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2587 v0 = 0x874; pc0 = ra;
2590 void psxBios__card_chan() { // 0x58
2592 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2595 v0 = card_active_chan;
2599 void psxBios_ChangeClearPad() { // 5b
2601 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2607 void psxBios__card_status() { // 5c
2609 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2612 v0 = card_active_chan;
2616 void psxBios__card_wait() { // 5d
2618 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2625 /* System calls C0 */
2628 * int SysEnqIntRP(int index , long *queue);
2631 void psxBios_SysEnqIntRP() { // 02
2633 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2642 * int SysDeqIntRP(int index , long *queue);
2645 void psxBios_SysDeqIntRP() { // 03
2647 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2655 void psxBios_ChangeClearRCnt() { // 0a
2659 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2662 ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2666 // psxRegs.CP0.n.Status|= 0x404;
2670 void psxBios_dummy() {
2672 PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2677 void (*biosA0[256])();
2678 void (*biosB0[256])();
2679 void (*biosC0[256])();
2681 #include "sjisfont.h"
2683 void psxBiosInit() {
2689 for(i = 0; i < 256; i++) {
2694 biosA0[0x3e] = psxBios_puts;
2695 biosA0[0x3f] = psxBios_printf;
2697 biosB0[0x3d] = psxBios_putchar;
2698 biosB0[0x3f] = psxBios_puts;
2700 if (!Config.HLE) return;
2702 for(i = 0; i < 256; i++) {
2703 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2704 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2705 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2708 biosA0[0x00] = psxBios_open;
2709 biosA0[0x01] = psxBios_lseek;
2710 biosA0[0x02] = psxBios_read;
2711 biosA0[0x03] = psxBios_write;
2712 biosA0[0x04] = psxBios_close;
2713 //biosA0[0x05] = psxBios_ioctl;
2714 //biosA0[0x06] = psxBios_exit;
2715 //biosA0[0x07] = psxBios_sys_a0_07;
2716 biosA0[0x08] = psxBios_getc;
2717 biosA0[0x09] = psxBios_putc;
2718 biosA0[0x0a] = psxBios_todigit;
2719 //biosA0[0x0b] = psxBios_atof;
2720 //biosA0[0x0c] = psxBios_strtoul;
2721 //biosA0[0x0d] = psxBios_strtol;
2722 biosA0[0x0e] = psxBios_abs;
2723 biosA0[0x0f] = psxBios_labs;
2724 biosA0[0x10] = psxBios_atoi;
2725 biosA0[0x11] = psxBios_atol;
2726 //biosA0[0x12] = psxBios_atob;
2727 biosA0[0x13] = psxBios_setjmp;
2728 biosA0[0x14] = psxBios_longjmp;
2729 biosA0[0x15] = psxBios_strcat;
2730 biosA0[0x16] = psxBios_strncat;
2731 biosA0[0x17] = psxBios_strcmp;
2732 biosA0[0x18] = psxBios_strncmp;
2733 biosA0[0x19] = psxBios_strcpy;
2734 biosA0[0x1a] = psxBios_strncpy;
2735 biosA0[0x1b] = psxBios_strlen;
2736 biosA0[0x1c] = psxBios_index;
2737 biosA0[0x1d] = psxBios_rindex;
2738 biosA0[0x1e] = psxBios_strchr;
2739 biosA0[0x1f] = psxBios_strrchr;
2740 biosA0[0x20] = psxBios_strpbrk;
2741 biosA0[0x21] = psxBios_strspn;
2742 biosA0[0x22] = psxBios_strcspn;
2743 biosA0[0x23] = psxBios_strtok;
2744 biosA0[0x24] = psxBios_strstr;
2745 biosA0[0x25] = psxBios_toupper;
2746 biosA0[0x26] = psxBios_tolower;
2747 biosA0[0x27] = psxBios_bcopy;
2748 biosA0[0x28] = psxBios_bzero;
2749 biosA0[0x29] = psxBios_bcmp;
2750 biosA0[0x2a] = psxBios_memcpy;
2751 biosA0[0x2b] = psxBios_memset;
2752 biosA0[0x2c] = psxBios_memmove;
2753 biosA0[0x2d] = psxBios_memcmp;
2754 biosA0[0x2e] = psxBios_memchr;
2755 biosA0[0x2f] = psxBios_rand;
2756 biosA0[0x30] = psxBios_srand;
2757 biosA0[0x31] = psxBios_qsort;
2758 //biosA0[0x32] = psxBios_strtod;
2759 biosA0[0x33] = psxBios_malloc;
2760 biosA0[0x34] = psxBios_free;
2761 //biosA0[0x35] = psxBios_lsearch;
2762 //biosA0[0x36] = psxBios_bsearch;
2763 biosA0[0x37] = psxBios_calloc;
2764 biosA0[0x38] = psxBios_realloc;
2765 biosA0[0x39] = psxBios_InitHeap;
2766 //biosA0[0x3a] = psxBios__exit;
2767 biosA0[0x3b] = psxBios_getchar;
2768 biosA0[0x3c] = psxBios_putchar;
2769 //biosA0[0x3d] = psxBios_gets;
2770 //biosA0[0x40] = psxBios_sys_a0_40;
2771 //biosA0[0x41] = psxBios_LoadTest;
2772 biosA0[0x42] = psxBios_Load;
2773 biosA0[0x43] = psxBios_Exec;
2774 biosA0[0x44] = psxBios_FlushCache;
2775 //biosA0[0x45] = psxBios_InstallInterruptHandler;
2776 biosA0[0x46] = psxBios_GPU_dw;
2777 biosA0[0x47] = psxBios_mem2vram;
2778 biosA0[0x48] = psxBios_SendGPU;
2779 biosA0[0x49] = psxBios_GPU_cw;
2780 biosA0[0x4a] = psxBios_GPU_cwb;
2781 biosA0[0x4b] = psxBios_GPU_SendPackets;
2782 biosA0[0x4c] = psxBios_sys_a0_4c;
2783 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2784 //biosA0[0x4e] = psxBios_GPU_sync;
2785 //biosA0[0x4f] = psxBios_sys_a0_4f;
2786 //biosA0[0x50] = psxBios_sys_a0_50;
2787 biosA0[0x51] = psxBios_LoadExec;
2788 //biosA0[0x52] = psxBios_GetSysSp;
2789 //biosA0[0x53] = psxBios_sys_a0_53;
2790 //biosA0[0x54] = psxBios__96_init_a54;
2791 //biosA0[0x55] = psxBios__bu_init_a55;
2792 //biosA0[0x56] = psxBios__96_remove_a56;
2793 //biosA0[0x57] = psxBios_sys_a0_57;
2794 //biosA0[0x58] = psxBios_sys_a0_58;
2795 //biosA0[0x59] = psxBios_sys_a0_59;
2796 //biosA0[0x5a] = psxBios_sys_a0_5a;
2797 //biosA0[0x5b] = psxBios_dev_tty_init;
2798 //biosA0[0x5c] = psxBios_dev_tty_open;
2799 //biosA0[0x5d] = psxBios_sys_a0_5d;
2800 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2801 //biosA0[0x5f] = psxBios_dev_cd_open;
2802 //biosA0[0x60] = psxBios_dev_cd_read;
2803 //biosA0[0x61] = psxBios_dev_cd_close;
2804 //biosA0[0x62] = psxBios_dev_cd_firstfile;
2805 //biosA0[0x63] = psxBios_dev_cd_nextfile;
2806 //biosA0[0x64] = psxBios_dev_cd_chdir;
2807 //biosA0[0x65] = psxBios_dev_card_open;
2808 //biosA0[0x66] = psxBios_dev_card_read;
2809 //biosA0[0x67] = psxBios_dev_card_write;
2810 //biosA0[0x68] = psxBios_dev_card_close;
2811 //biosA0[0x69] = psxBios_dev_card_firstfile;
2812 //biosA0[0x6a] = psxBios_dev_card_nextfile;
2813 //biosA0[0x6b] = psxBios_dev_card_erase;
2814 //biosA0[0x6c] = psxBios_dev_card_undelete;
2815 //biosA0[0x6d] = psxBios_dev_card_format;
2816 //biosA0[0x6e] = psxBios_dev_card_rename;
2817 //biosA0[0x6f] = psxBios_dev_card_6f;
2818 biosA0[0x70] = psxBios__bu_init;
2819 biosA0[0x71] = psxBios__96_init;
2820 biosA0[0x72] = psxBios__96_remove;
2821 //biosA0[0x73] = psxBios_sys_a0_73;
2822 //biosA0[0x74] = psxBios_sys_a0_74;
2823 //biosA0[0x75] = psxBios_sys_a0_75;
2824 //biosA0[0x76] = psxBios_sys_a0_76;
2825 //biosA0[0x77] = psxBios_sys_a0_77;
2826 //biosA0[0x78] = psxBios__96_CdSeekL;
2827 //biosA0[0x79] = psxBios_sys_a0_79;
2828 //biosA0[0x7a] = psxBios_sys_a0_7a;
2829 //biosA0[0x7b] = psxBios_sys_a0_7b;
2830 //biosA0[0x7c] = psxBios__96_CdGetStatus;
2831 //biosA0[0x7d] = psxBios_sys_a0_7d;
2832 //biosA0[0x7e] = psxBios__96_CdRead;
2833 //biosA0[0x7f] = psxBios_sys_a0_7f;
2834 //biosA0[0x80] = psxBios_sys_a0_80;
2835 //biosA0[0x81] = psxBios_sys_a0_81;
2836 //biosA0[0x82] = psxBios_sys_a0_82;
2837 //biosA0[0x83] = psxBios_sys_a0_83;
2838 //biosA0[0x84] = psxBios_sys_a0_84;
2839 //biosA0[0x85] = psxBios__96_CdStop;
2840 //biosA0[0x86] = psxBios_sys_a0_86;
2841 //biosA0[0x87] = psxBios_sys_a0_87;
2842 //biosA0[0x88] = psxBios_sys_a0_88;
2843 //biosA0[0x89] = psxBios_sys_a0_89;
2844 //biosA0[0x8a] = psxBios_sys_a0_8a;
2845 //biosA0[0x8b] = psxBios_sys_a0_8b;
2846 //biosA0[0x8c] = psxBios_sys_a0_8c;
2847 //biosA0[0x8d] = psxBios_sys_a0_8d;
2848 //biosA0[0x8e] = psxBios_sys_a0_8e;
2849 //biosA0[0x8f] = psxBios_sys_a0_8f;
2850 //biosA0[0x90] = psxBios_sys_a0_90;
2851 //biosA0[0x91] = psxBios_sys_a0_91;
2852 //biosA0[0x92] = psxBios_sys_a0_92;
2853 //biosA0[0x93] = psxBios_sys_a0_93;
2854 //biosA0[0x94] = psxBios_sys_a0_94;
2855 //biosA0[0x95] = psxBios_sys_a0_95;
2856 //biosA0[0x96] = psxBios_AddCDROMDevice;
2857 //biosA0[0x97] = psxBios_AddMemCardDevide;
2858 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2859 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2860 //biosA0[0x9a] = psxBios_sys_a0_9a;
2861 //biosA0[0x9b] = psxBios_sys_a0_9b;
2862 //biosA0[0x9c] = psxBios_SetConf;
2863 //biosA0[0x9d] = psxBios_GetConf;
2864 //biosA0[0x9e] = psxBios_sys_a0_9e;
2865 biosA0[0x9f] = psxBios_SetMem;
2866 //biosA0[0xa0] = psxBios__boot;
2867 //biosA0[0xa1] = psxBios_SystemError;
2868 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2869 //biosA0[0xa3] = psxBios_DequeueCdIntr;
2870 //biosA0[0xa4] = psxBios_sys_a0_a4;
2871 //biosA0[0xa5] = psxBios_ReadSector;
2872 biosA0[0xa6] = psxBios_get_cd_status;
2873 //biosA0[0xa7] = psxBios_bufs_cb_0;
2874 //biosA0[0xa8] = psxBios_bufs_cb_1;
2875 //biosA0[0xa9] = psxBios_bufs_cb_2;
2876 //biosA0[0xaa] = psxBios_bufs_cb_3;
2877 biosA0[0xab] = psxBios__card_info;
2878 biosA0[0xac] = psxBios__card_load;
2879 //biosA0[0axd] = psxBios__card_auto;
2880 //biosA0[0xae] = psxBios_bufs_cd_4;
2881 //biosA0[0xaf] = psxBios_sys_a0_af;
2882 //biosA0[0xb0] = psxBios_sys_a0_b0;
2883 //biosA0[0xb1] = psxBios_sys_a0_b1;
2884 //biosA0[0xb2] = psxBios_do_a_long_jmp
2885 //biosA0[0xb3] = psxBios_sys_a0_b3;
2886 //biosA0[0xb4] = psxBios_sub_function;
2887 //*******************B0 CALLS****************************
2888 //biosB0[0x00] = psxBios_SysMalloc;
2889 //biosB0[0x01] = psxBios_sys_b0_01;
2890 biosB0[0x02] = psxBios_SetRCnt;
2891 biosB0[0x03] = psxBios_GetRCnt;
2892 biosB0[0x04] = psxBios_StartRCnt;
2893 biosB0[0x05] = psxBios_StopRCnt;
2894 biosB0[0x06] = psxBios_ResetRCnt;
2895 biosB0[0x07] = psxBios_DeliverEvent;
2896 biosB0[0x08] = psxBios_OpenEvent;
2897 biosB0[0x09] = psxBios_CloseEvent;
2898 biosB0[0x0a] = psxBios_WaitEvent;
2899 biosB0[0x0b] = psxBios_TestEvent;
2900 biosB0[0x0c] = psxBios_EnableEvent;
2901 biosB0[0x0d] = psxBios_DisableEvent;
2902 biosB0[0x0e] = psxBios_OpenTh;
2903 biosB0[0x0f] = psxBios_CloseTh;
2904 biosB0[0x10] = psxBios_ChangeTh;
2905 //biosB0[0x11] = psxBios_psxBios_b0_11;
2906 biosB0[0x12] = psxBios_InitPAD;
2907 biosB0[0x13] = psxBios_StartPAD;
2908 biosB0[0x14] = psxBios_StopPAD;
2909 biosB0[0x15] = psxBios_PAD_init;
2910 biosB0[0x16] = psxBios_PAD_dr;
2911 biosB0[0x17] = psxBios_ReturnFromException;
2912 biosB0[0x18] = psxBios_ResetEntryInt;
2913 biosB0[0x19] = psxBios_HookEntryInt;
2914 //biosB0[0x1a] = psxBios_sys_b0_1a;
2915 //biosB0[0x1b] = psxBios_sys_b0_1b;
2916 //biosB0[0x1c] = psxBios_sys_b0_1c;
2917 //biosB0[0x1d] = psxBios_sys_b0_1d;
2918 //biosB0[0x1e] = psxBios_sys_b0_1e;
2919 //biosB0[0x1f] = psxBios_sys_b0_1f;
2920 biosB0[0x20] = psxBios_UnDeliverEvent;
2921 //biosB0[0x21] = psxBios_sys_b0_21;
2922 //biosB0[0x22] = psxBios_sys_b0_22;
2923 //biosB0[0x23] = psxBios_sys_b0_23;
2924 //biosB0[0x24] = psxBios_sys_b0_24;
2925 //biosB0[0x25] = psxBios_sys_b0_25;
2926 //biosB0[0x26] = psxBios_sys_b0_26;
2927 //biosB0[0x27] = psxBios_sys_b0_27;
2928 //biosB0[0x28] = psxBios_sys_b0_28;
2929 //biosB0[0x29] = psxBios_sys_b0_29;
2930 //biosB0[0x2a] = psxBios_sys_b0_2a;
2931 //biosB0[0x2b] = psxBios_sys_b0_2b;
2932 //biosB0[0x2c] = psxBios_sys_b0_2c;
2933 //biosB0[0x2d] = psxBios_sys_b0_2d;
2934 //biosB0[0x2e] = psxBios_sys_b0_2e;
2935 //biosB0[0x2f] = psxBios_sys_b0_2f;
2936 //biosB0[0x30] = psxBios_sys_b0_30;
2937 //biosB0[0x31] = psxBios_sys_b0_31;
2938 biosB0[0x32] = psxBios_open;
2939 biosB0[0x33] = psxBios_lseek;
2940 biosB0[0x34] = psxBios_read;
2941 biosB0[0x35] = psxBios_write;
2942 biosB0[0x36] = psxBios_close;
2943 //biosB0[0x37] = psxBios_ioctl;
2944 //biosB0[0x38] = psxBios_exit;
2945 //biosB0[0x39] = psxBios_sys_b0_39;
2946 //biosB0[0x3a] = psxBios_getc;
2947 //biosB0[0x3b] = psxBios_putc;
2948 biosB0[0x3c] = psxBios_getchar;
2949 //biosB0[0x3e] = psxBios_gets;
2950 //biosB0[0x40] = psxBios_cd;
2951 biosB0[0x41] = psxBios_format;
2952 biosB0[0x42] = psxBios_firstfile;
2953 biosB0[0x43] = psxBios_nextfile;
2954 biosB0[0x44] = psxBios_rename;
2955 biosB0[0x45] = psxBios_delete;
2956 //biosB0[0x46] = psxBios_undelete;
2957 //biosB0[0x47] = psxBios_AddDevice;
2958 //biosB0[0x48] = psxBios_RemoteDevice;
2959 //biosB0[0x49] = psxBios_PrintInstalledDevices;
2960 biosB0[0x4a] = psxBios_InitCARD;
2961 biosB0[0x4b] = psxBios_StartCARD;
2962 biosB0[0x4c] = psxBios_StopCARD;
2963 //biosB0[0x4d] = psxBios_sys_b0_4d;
2964 biosB0[0x4e] = psxBios__card_write;
2965 biosB0[0x4f] = psxBios__card_read;
2966 biosB0[0x50] = psxBios__new_card;
2967 biosB0[0x51] = psxBios_Krom2RawAdd;
2968 //biosB0[0x52] = psxBios_sys_b0_52;
2969 //biosB0[0x53] = psxBios_sys_b0_53;
2970 //biosB0[0x54] = psxBios__get_errno;
2971 biosB0[0x55] = psxBios__get_error;
2972 biosB0[0x56] = psxBios_GetC0Table;
2973 biosB0[0x57] = psxBios_GetB0Table;
2974 biosB0[0x58] = psxBios__card_chan;
2975 //biosB0[0x59] = psxBios_sys_b0_59;
2976 //biosB0[0x5a] = psxBios_sys_b0_5a;
2977 biosB0[0x5b] = psxBios_ChangeClearPad;
2978 biosB0[0x5c] = psxBios__card_status;
2979 biosB0[0x5d] = psxBios__card_wait;
2980 //*******************C0 CALLS****************************
2981 //biosC0[0x00] = psxBios_InitRCnt;
2982 //biosC0[0x01] = psxBios_InitException;
2983 biosC0[0x02] = psxBios_SysEnqIntRP;
2984 biosC0[0x03] = psxBios_SysDeqIntRP;
2985 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
2986 //biosC0[0x05] = psxBios_get_free_TCB_slot;
2987 //biosC0[0x06] = psxBios_ExceptionHandler;
2988 //biosC0[0x07] = psxBios_InstallExeptionHandler;
2989 //biosC0[0x08] = psxBios_SysInitMemory;
2990 //biosC0[0x09] = psxBios_SysInitKMem;
2991 biosC0[0x0a] = psxBios_ChangeClearRCnt;
2992 //biosC0[0x0b] = psxBios_SystemError;
2993 //biosC0[0x0c] = psxBios_InitDefInt;
2994 //biosC0[0x0d] = psxBios_sys_c0_0d;
2995 //biosC0[0x0e] = psxBios_sys_c0_0e;
2996 //biosC0[0x0f] = psxBios_sys_c0_0f;
2997 //biosC0[0x10] = psxBios_sys_c0_10;
2998 //biosC0[0x11] = psxBios_sys_c0_11;
2999 //biosC0[0x12] = psxBios_InstallDevices;
3000 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3001 //biosC0[0x14] = psxBios_sys_c0_14;
3002 //biosC0[0x15] = psxBios__cdevinput;
3003 //biosC0[0x16] = psxBios__cdevscan;
3004 //biosC0[0x17] = psxBios__circgetc;
3005 //biosC0[0x18] = psxBios__circputc;
3006 //biosC0[0x19] = psxBios_ioabort;
3007 //biosC0[0x1a] = psxBios_sys_c0_1a
3008 //biosC0[0x1b] = psxBios_KernelRedirect;
3009 //biosC0[0x1c] = psxBios_PatchAOTable;
3010 //************** THE END ***************************************
3013 size = sizeof(EvCB) * 32;
3014 Event = (void *)&psxR[base]; base += size * 6;
3015 memset(Event, 0, size * 6);
3018 RcEV = Event + 32 * 2;
3019 UeEV = Event + 32 * 3;
3020 SwEV = Event + 32 * 4;
3021 ThEV = Event + 32 * 5;
3023 ptr = (u32 *)&psxM[0x0874]; // b0 table
3024 ptr[0] = SWAPu32(0x4c54 - 0x884);
3026 ptr = (u32 *)&psxM[0x0674]; // c0 table
3027 ptr[6] = SWAPu32(0xc80);
3029 memset(SysIntRP, 0, sizeof(SysIntRP));
3030 memset(Thread, 0, sizeof(Thread));
3031 Thread[0].status = 2; // main thread
3038 pad_buf1len = pad_buf2len = 0;
3044 memset(FDesc, 0, sizeof(FDesc));
3045 card_active_chan = 0;
3047 psxMu32ref(0x0150) = SWAPu32(0x160);
3048 psxMu32ref(0x0154) = SWAPu32(0x320);
3049 psxMu32ref(0x0160) = SWAPu32(0x248);
3050 strcpy((char *)&psxM[0x248], "bu");
3051 /* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3052 psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3053 psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3054 psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3055 psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3058 psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
3059 /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
3060 Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3061 //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
3062 psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3063 psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3064 psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3065 psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3066 psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3067 psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3068 psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3069 psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3071 // initial stack pointer for BIOS interrupt
3072 psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3075 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3078 len = 0x80000 - 0x66000;
3079 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3080 len = 0x80000 - 0x69d68;
3081 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3084 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3086 hleSoftCall = FALSE;
3088 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3089 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3090 Here are some examples of games not working with this fix in place :
3091 R-type won't get past the Irem logo if not implemented.
3092 Crash Team Racing will softlock after the Sony logo.
3095 psxMu32ref(0x0000) = SWAPu32(0x00000003);
3097 But overwritten by 00000003h after soon.
3098 psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3100 psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3101 psxMu32ref(0x0008) = SWAPu32(0x08000403);
3102 psxMu32ref(0x000C) = SWAPu32(0x00000000);
3105 void psxBiosShutdown() {
3108 #define psxBios_PADpoll(pad) { \
3109 PAD##pad##_startPoll(pad); \
3110 pad_buf##pad[0] = 0; \
3111 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3112 if (!(pad_buf##pad[1] & 0x0f)) { \
3115 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3117 PAD##pad##_poll(0); \
3119 while (bufcount--) { \
3120 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3124 void biosInterrupt() {
3127 // if (psxHu32(0x1070) & 0x1) { // Vsync
3128 if (pad_buf != NULL) {
3129 u32 *buf = (u32*)pad_buf;
3131 if (!Config.UseNet) {
3133 if (PAD1_poll(0x42) == 0x23) {
3135 *buf = PAD1_poll(0) << 8;
3136 *buf |= PAD1_poll(0);
3138 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3139 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3142 *buf = PAD1_poll(0) << 8;
3143 *buf|= PAD1_poll(0);
3147 if (PAD2_poll(0x42) == 0x23) {
3149 *buf |= PAD2_poll(0) << 24;
3150 *buf |= PAD2_poll(0) << 16;
3152 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3153 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3156 *buf |= PAD2_poll(0) << 24;
3157 *buf |= PAD2_poll(0) << 16;
3165 data = PAD1_poll(0) << 8;
3166 data |= PAD1_poll(0);
3168 if (NET_sendPadData(&data, 2) == -1)
3171 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3173 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3177 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3180 if (NET_sendPadData(pad_buf1, i) == -1)
3183 if (NET_recvPadData(pad_buf1, 1) == -1)
3185 if (NET_recvPadData(pad_buf2, 2) == -1)
3199 if (psxHu32(0x1070) & 0x1) { // Vsync
3200 if (RcEV[3][1].status == EvStACTIVE) {
3201 softCall(RcEV[3][1].fhandler);
3202 // hwWrite32(0x1f801070, ~(1));
3206 if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3209 for (i = 0; i < 3; i++) {
3210 if (psxHu32(0x1070) & (1 << (i + 4))) {
3211 if (RcEV[i][1].status == EvStACTIVE) {
3212 softCall(RcEV[i][1].fhandler);
3214 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3220 void psxBiosException() {
3223 switch (psxRegs.CP0.n.Cause & 0x3c) {
3224 case 0x00: // Interrupt
3225 interrupt_r26=psxRegs.CP0.n.EPC;
3227 // PSXCPU_LOG("interrupt\n");
3231 sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3235 for (i = 0; i < 8; i++) {
3237 u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3244 if (jmp_int != NULL) {
3247 psxHwWrite32(0x1f801070, 0xffffffff);
3252 for (i = 0; i < 8; i++) // s0-s7
3253 psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3260 psxHwWrite16(0x1f801070, 0);
3263 case 0x20: // Syscall
3265 PSXCPU_LOG("syscall exp %x\n", a0);
3268 case 1: // EnterCritical - disable irq's
3269 /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3270 v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3271 psxRegs.CP0.n.Status &= ~0x404;
3274 case 2: // ExitCritical - enable irq's
3275 psxRegs.CP0.n.Status |= 0x404;
3277 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3281 pc0 = psxRegs.CP0.n.EPC + 4;
3283 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3284 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3289 PSXCPU_LOG("unknown bios exception!\n");
3294 pc0 = psxRegs.CP0.n.EPC;
3295 if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3297 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3298 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3301 #define bfreeze(ptr, size) { \
3302 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3303 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3307 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3308 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3310 #define bfreezepsxMptr(ptr, type) { \
3312 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3313 else psxRu32ref(base) = 0; \
3315 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3316 else (ptr) = NULL; \
3318 base += sizeof(u32); \
3321 void psxBiosFreeze(int Mode) {
3324 bfreezepsxMptr(jmp_int, u32);
3325 bfreezepsxMptr(pad_buf, int);
3326 bfreezepsxMptr(pad_buf1, char);
3327 bfreezepsxMptr(pad_buf2, char);
3328 bfreezepsxMptr(heap_addr, u32);
3329 bfreezel(&pad_buf1len);
3330 bfreezel(&pad_buf2len);
3333 bfreezel(&CardState);
3335 bfreezel(&CurThread);
3337 bfreezel(&card_active_chan);
3338 bfreezel(&pad_stopped);
3339 bfreezel(&heap_size);