1 /***************************************************************************
2 * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3 * dmitrysmagin, senquack *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
19 ***************************************************************************/
21 /* Gameblabla 2018-2019 :
22 * Numerous changes to bios calls as well as improvements in order to conform to nocash's findings
23 * for the PSX bios calls. Thanks senquack for helping out with some of the changes
24 * and helping to spot issues and refine my patches.
28 * Internal simulated HLE BIOS.
31 // TODO: implement all system calls, count the exact CPU cycles of system calls.
40 #define SysPrintf if (Config.PsxOut) printf
42 char *biosA0n[256] = {
44 "open", "lseek", "read", "write",
45 "close", "ioctl", "exit", "sys_a0_07",
46 "getc", "putc", "todigit", "atof",
47 "strtoul", "strtol", "abs", "labs",
49 "atoi", "atol", "atob", "setjmp",
50 "longjmp", "strcat", "strncat", "strcmp",
51 "strncmp", "strcpy", "strncpy", "strlen",
52 "index", "rindex", "strchr", "strrchr",
54 "strpbrk", "strspn", "strcspn", "strtok",
55 "strstr", "toupper", "tolower", "bcopy",
56 "bzero", "bcmp", "memcpy", "memset",
57 "memmove", "memcmp", "memchr", "rand",
59 "srand", "qsort", "strtod", "malloc",
60 "free", "lsearch", "bsearch", "calloc",
61 "realloc", "InitHeap", "_exit", "getchar",
62 "putchar", "gets", "puts", "printf",
64 "sys_a0_40", "LoadTest", "Load", "Exec",
65 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
66 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
67 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
69 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
70 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
71 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
72 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
74 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
75 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
76 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
77 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
79 "_bu_init", "_96_init", "_96_remove", "sys_a0_73",
80 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
81 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
82 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
84 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
85 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
86 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
87 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
89 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
90 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
91 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
92 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
94 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
95 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
96 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
97 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
99 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
103 char *biosB0n[256] = {
105 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
106 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
107 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
108 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
110 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
111 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
112 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
113 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
115 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
116 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
117 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
118 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
120 "sys_b0_30", "sys_b0_31", "open", "lseek",
121 "read", "write", "close", "ioctl",
122 "exit", "sys_b0_39", "getc", "putc",
123 "getchar", "putchar", "gets", "puts",
125 "cd", "format", "firstfile", "nextfile",
126 "rename", "delete", "undelete", "AddDevice",
127 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
128 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
130 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
131 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
132 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
133 "_card_status", "_card_wait",
136 char *biosC0n[256] = {
138 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
139 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
140 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
141 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
143 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
144 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
145 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
149 //#define r0 (psxRegs.GPR.n.r0)
150 #define at (psxRegs.GPR.n.at)
151 #define v0 (psxRegs.GPR.n.v0)
152 #define v1 (psxRegs.GPR.n.v1)
153 #define a0 (psxRegs.GPR.n.a0)
154 #define a1 (psxRegs.GPR.n.a1)
155 #define a2 (psxRegs.GPR.n.a2)
156 #define a3 (psxRegs.GPR.n.a3)
157 #define t0 (psxRegs.GPR.n.t0)
158 #define t1 (psxRegs.GPR.n.t1)
159 #define t2 (psxRegs.GPR.n.t2)
160 #define t3 (psxRegs.GPR.n.t3)
161 #define t4 (psxRegs.GPR.n.t4)
162 #define t5 (psxRegs.GPR.n.t5)
163 #define t6 (psxRegs.GPR.n.t6)
164 #define t7 (psxRegs.GPR.n.t7)
165 #define t8 (psxRegs.GPR.n.t8)
166 #define t9 (psxRegs.GPR.n.t9)
167 #define s0 (psxRegs.GPR.n.s0)
168 #define s1 (psxRegs.GPR.n.s1)
169 #define s2 (psxRegs.GPR.n.s2)
170 #define s3 (psxRegs.GPR.n.s3)
171 #define s4 (psxRegs.GPR.n.s4)
172 #define s5 (psxRegs.GPR.n.s5)
173 #define s6 (psxRegs.GPR.n.s6)
174 #define s7 (psxRegs.GPR.n.s7)
175 #define k0 (psxRegs.GPR.n.k0)
176 #define k1 (psxRegs.GPR.n.k1)
177 #define gp (psxRegs.GPR.n.gp)
178 #define sp (psxRegs.GPR.n.sp)
179 #define fp (psxRegs.GPR.n.s8)
180 #define ra (psxRegs.GPR.n.ra)
181 #define pc0 (psxRegs.pc)
183 #define Ra0 ((char *)PSXM(a0))
184 #define Ra1 ((char *)PSXM(a1))
185 #define Ra2 ((char *)PSXM(a2))
186 #define Ra3 ((char *)PSXM(a3))
187 #define Rv0 ((char *)PSXM(v0))
188 #define Rsp ((char *)PSXM(sp))
197 #define EvStUNUSED 0x0000
198 #define EvStWAIT 0x1000
199 #define EvStACTIVE 0x2000
200 #define EvStALREADY 0x4000
202 #define EvMdINTR 0x1000
203 #define EvMdNOINTR 0x2000
232 u32 _sp, _fp, _gp, ret, base;
252 static u32 *jmp_int = NULL;
253 static int *pad_buf = NULL;
254 static char *pad_buf1 = NULL, *pad_buf2 = NULL;
255 static int pad_buf1len, pad_buf2len;
256 static int pad_stopped = 0;
259 static EvCB *EventCB;
260 static EvCB *HwEV; // 0xf0
261 static EvCB *EvEV; // 0xf1
262 static EvCB *RcEV; // 0xf2
263 static EvCB *UeEV; // 0xf3
264 static EvCB *SwEV; // 0xf4
265 static EvCB *ThEV; // 0xff
266 static u32 heap_size = 0;
267 static u32 *heap_addr = NULL;
268 static u32 *heap_end = NULL;
269 static u32 SysIntRP[8];
270 static int CardState = -1;
271 static TCB ThreadCB[8];
272 static int CurThread = 0;
273 static FileDesc FDesc[32];
274 static u32 card_active_chan = 0;
276 boolean hleSoftCall = FALSE;
278 static inline void softCall(u32 pc) {
284 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
289 static inline void softCall2(u32 pc) {
296 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
302 static inline void DeliverEvent(u32 ev, u32 spec) {
303 if (EventCB[ev][spec].status != EvStACTIVE) return;
305 // EventCB[ev][spec].status = EvStALREADY;
306 if (EventCB[ev][spec].mode == EvMdINTR) {
307 softCall2(EventCB[ev][spec].fhandler);
308 } else EventCB[ev][spec].status = EvStALREADY;
311 static unsigned interrupt_r26=0x8004E8B0;
313 static inline void SaveRegs() {
314 memcpy(regs, psxRegs.GPR.r, 32*4);
315 regs[32] = psxRegs.GPR.n.lo;
316 regs[33] = psxRegs.GPR.n.hi;
317 regs[34] = psxRegs.pc;
320 static inline void LoadRegs() {
321 memcpy(psxRegs.GPR.r, regs, 32*4);
322 psxRegs.GPR.n.lo = regs[32];
323 psxRegs.GPR.n.hi = regs[33];
329 // System calls A0 */
332 #define buread(Ra1, mcd, length) { \
333 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); \
334 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
335 memcpy(Ra1, ptr, length); \
336 if (FDesc[1 + mcd].mode & 0x8000) { \
337 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
338 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
341 FDesc[1 + mcd].offset += v0; \
344 #define buwrite(Ra1, mcd, length) { \
345 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
346 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
347 ptr = Mcd##mcd##Data + offset; \
348 memcpy(ptr, Ra1, length); \
349 FDesc[1 + mcd].offset += length; \
350 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
351 if (FDesc[1 + mcd].mode & 0x8000) { \
352 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
353 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
359 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
360 /* For some strange reason, the returned character is sign-expanded; */
361 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
362 /* TODO FIX ME : Properly implement this behaviour */
363 void psxBios_getc(void) // 0x03, 0x35
368 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
374 case 2: buread(pa1, 1, 1); break;
375 case 3: buread(pa1, 2, 1); break;
382 /* Copy of psxBios_write, except size is 1. */
383 void psxBios_putc(void) // 0x09, 0x3B
388 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
396 if (a0 == 1) { // stdout
397 char *ptr = (char *)pa1;
401 printf("%c", *ptr++); a2--;
407 case 2: buwrite(pa1, 1, 1); break;
408 case 3: buwrite(pa1, 2, 1); break;
414 void psxBios_todigit(void) // 0x0a
418 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
421 if (c >= 0x30 && c < 0x3A) {
424 else if (c > 0x60 && c < 0x7B) {
427 else if (c > 0x40 && c < 0x5B) {
430 else if (c >= 0x80) {
441 void psxBios_abs() { // 0x0e
442 if ((s32)a0 < 0) v0 = -(s32)a0;
447 void psxBios_labs() { // 0x0f
451 void psxBios_atoi() { // 0x10
453 char *p = (char *)Ra0;
457 case ' ': case '\t': continue;
464 while (*p >= '0' && *p <= '9') {
465 n = n * 10 + *p++ - '0';
472 void psxBios_atol() { // 0x11
476 void psxBios_setjmp() { // 0x13
477 u32 *jmp_buf = (u32 *)Ra0;
481 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x13]);
487 for (i = 0; i < 8; i++) // s0-s7
488 jmp_buf[3 + i] = psxRegs.GPR.r[16 + i];
494 void psxBios_longjmp() { // 0x14
495 u32 *jmp_buf = (u32 *)Ra0;
499 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
502 ra = jmp_buf[0]; /* ra */
503 sp = jmp_buf[1]; /* sp */
504 fp = jmp_buf[2]; /* fp */
505 for (i = 0; i < 8; i++) // s0-s7
506 psxRegs.GPR.r[16 + i] = jmp_buf[3 + i];
507 gp = jmp_buf[11]; /* gp */
512 void psxBios_strcat() { // 0x15
513 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
516 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
518 if (a0 == 0 || a1 == 0)
526 while ((*p1++ = *p2++) != '\0');
531 void psxBios_strncat() { // 0x16
532 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
536 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
538 if (a0 == 0 || a1 == 0)
546 while ((*p1++ = *p2++) != '\0') {
556 void psxBios_strcmp() { // 0x17
557 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
559 if (a0 == 0 && a1 == 0)
565 else if (a0 == 0 && a1 != 0)
571 else if (a0 != 0 && a1 == 0)
578 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
581 while (*p1 == *p2++) {
600 void psxBios_strncmp() { // 0x18
601 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
603 if (a0 == 0 && a1 == 0)
609 else if (a0 == 0 && a1 != 0)
615 else if (a0 != 0 && a1 == 0)
622 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
625 while (--n >= 0 && *p1 == *p2++) {
629 v1 = a2 - ((a2-n) - 1);
637 v0 = (n < 0 ? 0 : *p1 - *--p2);
639 v1 = a2 - ((a2-n) - 1);
645 void psxBios_strcpy() { // 0x19
646 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
647 if (a0 == 0 || a1 == 0)
653 while ((*p1++ = *p2++) != '\0');
658 void psxBios_strncpy() { // 0x1a
659 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
661 if (a0 == 0 || a1 == 0)
667 for (i = 0; i < n; i++) {
668 if ((*p1++ = *p2++) == '\0') {
680 void psxBios_strlen() { // 0x1b
681 char *p = (char *)Ra0;
692 void psxBios_index() { // 0x1c
693 char *p = (char *)Ra0;
703 v0 = a0 + (p - (char *)Ra0);
707 } while (*p++ != '\0');
712 void psxBios_rindex() { // 0x1d
713 char *p = (char *)Ra0;
723 v0 = a0 + (p - (char *)Ra0);
724 } while (*p++ != '\0');
729 void psxBios_strchr() { // 0x1e
733 void psxBios_strrchr() { // 0x1f
737 void psxBios_strpbrk() { // 0x20
738 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
740 while ((c = *p1++) != '\0') {
741 for (scanp = p2; (sc = *scanp++) != '\0';) {
743 v0 = a0 + (p1 - 1 - (char *)Ra0);
750 // BUG: return a0 instead of NULL if not found
754 void psxBios_strspn() { // 0x21
757 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
758 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
759 if (*p2 == '\0') break;
762 v0 = p1 - (char *)Ra0; pc0 = ra;
765 void psxBios_strcspn() { // 0x22
768 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
769 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
770 if (*p2 != '\0') break;
773 v0 = p1 - (char *)Ra0; pc0 = ra;
776 void psxBios_strtok() { // 0x23
777 char *pcA0 = (char *)Ra0;
778 char *pcRet = strtok(pcA0, (char *)Ra1);
780 v0 = a0 + pcRet - pcA0;
786 void psxBios_strstr() { // 0x24
787 char *p = (char *)Ra0, *p1, *p2;
793 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
798 v0 = a0 + (p - (char *)Ra0);
809 void psxBios_toupper() { // 0x25
810 v0 = (s8)(a0 & 0xff);
811 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
815 void psxBios_tolower() { // 0x26
816 v0 = (s8)(a0 & 0xff);
817 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
821 void psxBios_bcopy() { // 0x27
822 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
824 if (a0 == 0 || a2 > 0x7FFFFFFF)
829 while ((s32)a2-- > 0) *p1++ = *p2++;
834 void psxBios_bzero() { // 0x28
835 char *p = (char *)Ra0;
837 /* Same as memset here (See memset below) */
838 if (a1 > 0x7FFFFFFF || a1 == 0)
849 while ((s32)a1-- > 0) *p++ = '\0';
854 void psxBios_bcmp() { // 0x29
855 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
857 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
859 while ((s32)a2-- > 0) {
860 if (*p1++ != *p2++) {
861 v0 = *p1 - *p2; // BUG: compare the NEXT byte
870 void psxBios_memcpy() { // 0x2a
871 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
873 if (a0 == 0 || a2 > 0x7FFFFFFF)
878 while ((s32)a2-- > 0) {
885 void psxBios_memset() { // 0x2b
886 char *p = (char *)Ra0;
888 if (a2 > 0x7FFFFFFF || a2 == 0)
899 while ((s32)a2-- > 0) *p++ = (char)a1;
904 void psxBios_memmove() { // 0x2c
905 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
907 if (a0 == 0 || a2 > 0x7FFFFFFF)
912 if (p2 <= p1 && p2 + a2 > p1) {
913 a2++; // BUG: copy one more byte here
916 while ((s32)a2-- > 0) *--p1 = *--p2;
918 while ((s32)a2-- > 0) *p1++ = *p2++;
923 void psxBios_memcmp() { // 0x2d
927 void psxBios_memchr() { // 0x2e
928 char *p = (char *)Ra0;
930 if (a0 == 0 || a2 > 0x7FFFFFFF)
936 while ((s32)a2-- > 0) {
937 if (*p++ != (s8)a1) continue;
938 v0 = a0 + (p - (char *)Ra0 - 1);
946 void psxBios_rand() { // 0x2f
947 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
948 v0 = (s >> 16) & 0x7fff;
949 psxMu32ref(0x9010) = SWAPu32(s);
953 void psxBios_srand() { // 0x30
954 psxMu32ref(0x9010) = SWAPu32(a0);
958 static u32 qscmpfunc, qswidth;
960 static inline int qscmp(char *a, char *b) {
963 a0 = sa0 + (a - (char *)PSXM(sa0));
964 a1 = sa0 + (b - (char *)PSXM(sa0));
966 softCall2(qscmpfunc);
972 static inline void qexchange(char *i, char *j) {
983 static inline void q3exchange(char *i, char *j, char *k) {
995 static void qsort_main(char *a, char *l) {
996 char *i, *j, *lp, *hp;
1001 if ((n = l - a) <= qswidth)
1003 n = qswidth * (n / (2 * qswidth));
1009 if ((c = qscmp(i, lp)) == 0) {
1010 qexchange(i, lp -= qswidth);
1021 if ((c = qscmp(hp, j)) == 0) {
1022 qexchange(hp += qswidth, j);
1027 q3exchange(i, hp += qswidth, j);
1041 if (lp - a >= l - hp) {
1042 qsort_main(hp + qswidth, l);
1051 q3exchange(j, lp -= qswidth, i);
1056 void psxBios_qsort() { // 0x31
1059 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1064 void psxBios_malloc() { // 0x33
1065 unsigned int *chunk, *newchunk = NULL;
1066 unsigned int dsize = 0, csize, cstat;
1069 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1071 if (!a0 || (!heap_size || !heap_addr)) {
1077 // scan through heap and combine free chunks of space
1080 while(chunk < heap_end) {
1081 // get size and status of actual chunk
1082 csize = ((u32)*chunk) & 0xfffffffc;
1083 cstat = ((u32)*chunk) & 1;
1085 // most probably broken heap descriptor
1086 // this fixes Burning Road
1089 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1094 // it's a free chunk
1099 colflag = 1; // let's begin a new collection of free memory
1101 else dsize += (csize+4); // add the new size including header
1103 // not a free chunk: did we start a collection ?
1105 if(colflag == 1) { // collection is over
1107 *newchunk = SWAP32(dsize | 1);
1112 chunk = (u32*)((uptr)chunk + csize + 4);
1114 // if neccessary free memory on end of heap
1116 *newchunk = SWAP32(dsize | 1);
1119 csize = ((u32)*chunk) & 0xfffffffc;
1120 cstat = ((u32)*chunk) & 1;
1121 dsize = (a0 + 3) & 0xfffffffc;
1123 // exit on uninitialized heap
1124 if (chunk == NULL) {
1125 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1131 // search an unused chunk that is big enough until the end of the heap
1132 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1133 chunk = (u32*)((uptr)chunk + csize + 4);
1135 // catch out of memory
1136 if(chunk >= heap_end) {
1137 printf("malloc %x,%x: Out of memory error!\n",
1143 csize = ((u32)*chunk) & 0xfffffffc;
1144 cstat = ((u32)*chunk) & 1;
1148 if(dsize == csize) {
1149 // chunk has same size
1150 *chunk &= 0xfffffffc;
1151 } else if (dsize > csize) {
1156 *chunk = SWAP32(dsize);
1157 newchunk = (u32*)((uptr)chunk + dsize + 4);
1158 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1161 // return pointer to allocated memory
1162 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1164 //printf ("malloc %x,%x\n", v0, a0);
1168 void psxBios_free() { // 0x34
1171 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1174 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1177 *(u32*)(Ra0-4) |= 1; // set chunk to free
1181 void psxBios_calloc() { // 0x37
1184 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1194 void psxBios_realloc() { // 0x38
1198 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1202 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1207 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1212 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1213 /* Note that it is not quite implemented this way here. */
1223 /* InitHeap(void *block , int n) */
1224 void psxBios_InitHeap() { // 0x39
1228 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1231 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1236 heap_addr = (u32 *)Ra0;
1238 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1239 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1240 //*heap_addr = SWAP32(size | 1);
1242 SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1247 void psxBios_getchar() { //0x3b
1248 v0 = getchar(); pc0 = ra;
1251 void psxBios_printf() { // 0x3f
1261 memcpy(save, psp, 4 * 4);
1262 psxMu32ref(sp) = SWAP32((u32)a0);
1263 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1264 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1265 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1277 tmp2[j++] = Ra0[i]; goto _start;
1279 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1290 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1294 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1300 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1302 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1304 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1306 *ptmp++ = Ra0[i]; break;
1317 memcpy(psp, save, 4 * 4);
1319 SysPrintf("%s", tmp);
1324 void psxBios_format() { // 0x41
1325 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1327 CreateMcd(Config.Mcd1);
1328 LoadMcd(1, Config.Mcd1);
1331 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1333 CreateMcd(Config.Mcd2);
1334 LoadMcd(2, Config.Mcd2);
1345 * long Load(char *name, struct EXEC *header);
1348 void psxBios_Load() { // 0x42
1353 PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1);
1357 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1358 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1366 * int Exec(struct EXEC *header , int argc , char **argv);
1369 void psxBios_Exec() { // 43
1370 EXEC *header = (EXEC*)Ra0;
1374 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1384 if (header->S_addr != 0) {
1385 tmp = header->S_addr + header->s_size;
1401 void psxBios_FlushCache() { // 44
1403 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1405 #ifdef ICACHE_EMULATION
1406 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1407 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1412 void psxBios_GPU_dw() { // 0x46
1417 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1420 GPU_writeData(0xa0000000);
1421 GPU_writeData((a1<<0x10)|(a0&0xffff));
1422 GPU_writeData((a3<<0x10)|(a2&0xffff));
1424 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1427 GPU_writeData(SWAPu32(*ptr++));
1433 void psxBios_mem2vram() { // 0x47
1436 GPU_writeData(0xa0000000);
1437 GPU_writeData((a1<<0x10)|(a0&0xffff));
1438 GPU_writeData((a3<<0x10)|(a2&0xffff));
1439 size = ((((a2 * a3) / 2) >> 4) << 16);
1440 GPU_writeStatus(0x04000002);
1441 psxHwWrite32(0x1f8010f4,0);
1442 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1443 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1444 psxHwWrite32(0x1f8010a4, size | 0x10);
1445 psxHwWrite32(0x1f8010a8,0x01000201);
1450 void psxBios_SendGPU() { // 0x48
1451 GPU_writeStatus(a0);
1456 void psxBios_GPU_cw() { // 0x49
1463 void psxBios_GPU_cwb() { // 0x4a
1464 u32 *ptr = (u32*)Ra0;
1469 GPU_writeData(SWAPu32(*ptr++));
1475 void psxBios_GPU_SendPackets() { //4b:
1477 GPU_writeStatus(0x04000002);
1478 psxHwWrite32(0x1f8010f4,0);
1479 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1480 psxHwWrite32(0x1f8010a0,a0);
1481 psxHwWrite32(0x1f8010a4,0);
1482 psxHwWrite32(0x1f8010a8,0x010000401);
1486 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1487 psxHwWrite32(0x1f8010a8,0x00000401);
1488 GPU_writeData(0x0400000);
1489 GPU_writeData(0x0200000);
1490 GPU_writeData(0x0100000);
1495 void psxBios_GPU_GetGPUStatus() { // 0x4d
1496 v0 = GPU_readStatus();
1502 void psxBios_LoadExec() { // 51
1503 EXEC *header = (EXEC*)PSXM(0xf000);
1507 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1509 s_addr = a1; s_size = a2;
1514 header->S_addr = s_addr;
1515 header->s_size = s_size;
1517 a0 = 0xf000; a1 = 0; a2 = 0;
1521 void psxBios__bu_init() { // 70
1523 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1526 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1527 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1532 void psxBios__96_init() { // 71
1534 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1540 void psxBios__96_remove() { // 72
1542 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1548 void psxBios_SetMem() { // 9f
1549 u32 new = psxHu32(0x1060);
1552 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1557 psxHu32ref(0x1060) = SWAP32(new);
1558 psxMu32ref(0x060) = a0;
1559 SysPrintf("Change effective memory : %d MBytes\n",a0);
1563 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1564 psxMu32ref(0x060) = a0;
1565 SysPrintf("Change effective memory : %d MBytes\n",a0);
1568 SysPrintf("Effective memory must be 2/8 MBytes\n");
1575 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1576 void psxBios_get_cd_status(void) //a6
1582 void psxBios__card_info() { // ab
1584 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1587 card_active_chan = a0;
1588 port = card_active_chan >> 4;
1594 if (McdDisable[port & 1])
1599 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1605 if (McdDisable[0] && McdDisable[1])
1608 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1609 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1610 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
1614 void psxBios__card_load() { // ac
1616 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1619 card_active_chan = a0;
1621 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1622 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1627 /* System calls B0 */
1629 void psxBios_SetRCnt() { // 02
1631 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1638 psxRcntWtarget(a0, a1);
1639 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1640 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1641 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1642 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1643 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1645 psxRcntWmode(a0, mode);
1650 void psxBios_GetRCnt() { // 03
1652 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1656 if (a0 != 3) v0 = psxRcntRcount(a0);
1661 void psxBios_StartRCnt() { // 04
1663 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1667 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1668 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1672 void psxBios_StopRCnt() { // 05
1674 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1678 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1679 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1683 void psxBios_ResetRCnt() { // 06
1685 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1690 psxRcntWmode(a0, 0);
1691 psxRcntWtarget(a0, 0);
1692 psxRcntWcount(a0, 0);
1698 /* gets ev for use with EventCB */
1700 ev = (a0 >> 24) & 0xf; \
1701 if (ev == 0xf) ev = 0x5; \
1705 /* gets spec for use with EventCB */
1709 case 0x0301: spec = 16; break; \
1710 case 0x0302: spec = 17; break; \
1712 for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1716 void psxBios_DeliverEvent() { // 07
1724 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1727 DeliverEvent(ev, spec);
1732 void psxBios_OpenEvent() { // 08
1740 PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1743 EventCB[ev][spec].status = EvStWAIT;
1744 EventCB[ev][spec].mode = a2;
1745 EventCB[ev][spec].fhandler = a3;
1747 v0 = ev | (spec << 8);
1751 void psxBios_CloseEvent() { // 09
1755 spec = (a0 >> 8) & 0xff;
1758 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1761 EventCB[ev][spec].status = EvStUNUSED;
1766 void psxBios_WaitEvent() { // 0a
1770 spec = (a0 >> 8) & 0xff;
1772 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1774 if (EventCB[ev][spec].status == EvStUNUSED)
1781 if (EventCB[ev][spec].status == EvStALREADY)
1783 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1784 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1794 void psxBios_TestEvent() { // 0b
1798 spec = (a0 >> 8) & 0xff;
1800 if (EventCB[ev][spec].status == EvStALREADY)
1802 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1811 PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1817 void psxBios_EnableEvent() { // 0c
1821 spec = (a0 >> 8) & 0xff;
1824 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1827 EventCB[ev][spec].status = EvStACTIVE;
1832 void psxBios_DisableEvent() { // 0d
1836 spec = (a0 >> 8) & 0xff;
1839 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1842 EventCB[ev][spec].status = EvStWAIT;
1848 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1851 void psxBios_OpenTh() { // 0e
1854 for (th=1; th<8; th++)
1856 if (ThreadCB[th].status == 0) break;
1860 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1861 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1863 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1870 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1873 ThreadCB[th].status = 1;
1874 ThreadCB[th].func = a0;
1875 ThreadCB[th].reg[29] = a1;
1876 ThreadCB[th].reg[28] = a2;
1882 * int CloseTh(long thread);
1885 void psxBios_CloseTh() { // 0f
1889 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
1891 /* The return value is always 1 (even if the handle was already closed). */
1893 if (ThreadCB[th].status != 0) {
1894 ThreadCB[th].status = 0;
1901 * int ChangeTh(long thread);
1904 void psxBios_ChangeTh() { // 10
1908 // PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
1910 /* The return value is always 1. */
1912 if (ThreadCB[th].status == 0 || CurThread == th) {
1915 if (ThreadCB[CurThread].status == 2) {
1916 ThreadCB[CurThread].status = 1;
1917 ThreadCB[CurThread].func = ra;
1918 memcpy(ThreadCB[CurThread].reg, psxRegs.GPR.r, 32*4);
1921 memcpy(psxRegs.GPR.r, ThreadCB[th].reg, 32*4);
1922 pc0 = ThreadCB[th].func;
1923 ThreadCB[th].status = 2;
1928 void psxBios_InitPAD() { // 0x12
1930 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
1933 pad_buf1 = (char*)Ra0;
1935 pad_buf2 = (char*)Ra2;
1941 void psxBios_StartPAD() { // 13
1943 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
1946 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
1947 psxRegs.CP0.n.Status |= 0x401;
1951 void psxBios_StopPAD() { // 14
1953 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
1961 void psxBios_PAD_init() { // 15
1963 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
1965 if (!(a0 == 0x20000000 || a0 == 0x20000001))
1971 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
1972 pad_buf = (int *)Ra1;
1974 psxRegs.CP0.n.Status |= 0x401;
1979 void psxBios_PAD_dr() { // 16
1981 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
1987 void psxBios_ReturnFromException() { // 17
1990 pc0 = psxRegs.CP0.n.EPC;
1992 if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;
1994 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
1995 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
1998 void psxBios_ResetEntryInt() { // 18
2000 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2007 void psxBios_HookEntryInt() { // 19
2009 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
2012 jmp_int = (u32*)Ra0;
2016 void psxBios_UnDeliverEvent() { // 0x20
2024 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2027 if (EventCB[ev][spec].status == EvStALREADY &&
2028 EventCB[ev][spec].mode == EvMdNOINTR)
2029 EventCB[ev][spec].status = EvStACTIVE;
2034 char ffile[64], *pfile;
2037 static void buopen(int mcd, char *ptr, char *cfg)
2040 char *mcd_data = ptr;
2042 strcpy(FDesc[1 + mcd].name, Ra0+5);
2043 FDesc[1 + mcd].offset = 0;
2044 FDesc[1 + mcd].mode = a1;
2046 for (i=1; i<16; i++) {
2047 const char *fptr = mcd_data + 128 * i;
2048 if ((*fptr & 0xF0) != 0x50) continue;
2049 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2050 FDesc[1 + mcd].mcfile = i;
2051 SysPrintf("open %s\n", fptr+0xa);
2055 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2056 for (i=1; i<16; i++) {
2057 int j, xor, nblk = a1 >> 16;
2059 char *fptr = mcd_data + 128 * i;
2061 if ((*fptr & 0xF0) != 0xa0) continue;
2063 FDesc[1 + mcd].mcfile = i;
2066 fptr[5] = 0x20 * nblk;
2069 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2070 pptr = fptr2 = fptr;
2071 for(j=2; j<=nblk; j++) {
2073 for(i++; i<16; i++) {
2076 memset(fptr2, 0, 128);
2077 fptr2[0] = j < nblk ? 0x52 : 0x53;
2080 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2085 /* shouldn't this return ENOSPC if i == 16? */
2087 pptr[8] = pptr[9] = 0xff;
2088 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2090 SysPrintf("openC %s %d\n", ptr, nblk);
2092 /* just go ahead and resave them all */
2093 SaveMcd(cfg, ptr, 128, 128 * 15);
2096 /* shouldn't this return ENOSPC if i == 16? */
2101 * int open(char *name , int mode);
2104 void psxBios_open() { // 0x32
2108 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2114 if (!strncmp(pa0, "bu00", 4)) {
2115 buopen(1, Mcd1Data, Config.Mcd1);
2118 if (!strncmp(pa0, "bu10", 4)) {
2119 buopen(2, Mcd2Data, Config.Mcd2);
2127 * int lseek(int fd , int offset , int whence);
2130 void psxBios_lseek() { // 0x33
2132 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2137 FDesc[a0].offset = a1;
2139 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2140 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2144 FDesc[a0].offset+= a1;
2145 v0 = FDesc[a0].offset;
2154 * int read(int fd , void *buf , int nbytes);
2157 void psxBios_read() { // 0x34
2162 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2169 case 2: buread(pa1, 1, a2); break;
2170 case 3: buread(pa1, 2, a2); break;
2178 * int write(int fd , void *buf , int nbytes);
2181 void psxBios_write() { // 0x35/0x03
2186 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2195 if (a0 == 1) { // stdout
2200 SysPrintf("%c", *ptr++); a2--;
2206 case 2: buwrite(pa1, 1, a2); break;
2207 case 3: buwrite(pa1, 2, a2); break;
2214 * int close(int fd);
2217 void psxBios_close() { // 0x36
2219 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2226 void psxBios_putchar() { // 3d
2227 SysPrintf("%c", (char)a0);
2231 void psxBios_puts() { // 3e/3f
2232 SysPrintf("%s", Ra0);
2237 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2238 * We want to mimic the PSX's behaviour in this case for bufile. */
2239 static size_t strlen_internal(char* p)
2241 size_t size_of_array = 0;
2242 while (*p++) size_of_array++;
2243 return size_of_array;
2246 #define bufile(mcd) { \
2247 size_t size_of_name = strlen_internal(dir->name); \
2248 while (nfile < 16) { \
2251 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2253 if ((*ptr & 0xF0) != 0x50) continue; \
2254 /* Bug link files show up as free block. */ \
2255 if (!ptr[0xa]) continue; \
2257 if (pfile[0] == 0) { \
2258 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2259 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2260 } else for (i=0; i<20; i++) { \
2261 if (pfile[i] == ptr[i]) { \
2262 dir->name[i] = ptr[i]; continue; } \
2263 if (pfile[i] == '?') { \
2264 dir->name[i] = ptr[i]; continue; } \
2265 if (pfile[i] == '*') { \
2266 strcpy(dir->name+i, ptr+i); break; } \
2269 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2270 if (match == 0) { continue; } \
2278 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2281 void psxBios_firstfile() { // 42
2282 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2289 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2298 if (!strncmp(pa0, "bu00", 4)) {
2299 // firstfile() calls _card_read() internally, so deliver it's event
2300 DeliverEvent(0x11, 0x2);
2302 } else if (!strncmp(pa0, "bu10", 4)) {
2303 // firstfile() calls _card_read() internally, so deliver it's event
2304 DeliverEvent(0x11, 0x2);
2313 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2316 void psxBios_nextfile() { // 43
2317 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2323 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2328 if (!strncmp(ffile, "bu00", 4)) {
2332 if (!strncmp(ffile, "bu10", 4)) {
2339 #define burename(mcd) { \
2340 for (i=1; i<16; i++) { \
2341 int namelen, j, xor = 0; \
2342 ptr = Mcd##mcd##Data + 128 * i; \
2343 if ((*ptr & 0xF0) != 0x50) continue; \
2344 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2345 namelen = strlen(Ra1+5); \
2346 memcpy(ptr+0xa, Ra1+5, namelen); \
2347 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2348 for (j=0; j<127; j++) xor^= ptr[j]; \
2350 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2357 * int rename(char *old, char *new);
2360 void psxBios_rename() { // 44
2367 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2373 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2377 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2386 #define budelete(mcd) { \
2387 for (i=1; i<16; i++) { \
2388 ptr = Mcd##mcd##Data + 128 * i; \
2389 if ((*ptr & 0xF0) != 0x50) continue; \
2390 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2391 *ptr = (*ptr & 0xf) | 0xA0; \
2392 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2393 SysPrintf("delete %s\n", ptr+0xa); \
2400 * int delete(char *name);
2403 void psxBios_delete() { // 45
2409 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2415 if (!strncmp(pa0, "bu00", 4)) {
2419 if (!strncmp(pa0, "bu10", 4)) {
2427 void psxBios_InitCARD() { // 4a
2429 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2437 void psxBios_StartCARD() { // 4b
2439 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2442 if (CardState == 0) CardState = 1;
2447 void psxBios_StopCARD() { // 4c
2449 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2452 if (CardState == 1) CardState = 0;
2457 void psxBios__card_write() { // 0x4e
2462 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2465 Function also accepts sector 400h (a bug).
2466 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2470 /* Invalid sectors */
2474 card_active_chan = a0;
2479 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2480 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2482 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2483 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2487 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2488 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2493 void psxBios__card_read() { // 0x4f
2498 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2501 Function also accepts sector 400h (a bug).
2502 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2506 /* Invalid sectors */
2510 card_active_chan = a0;
2515 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2517 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2521 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2522 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2527 void psxBios__new_card() { // 0x50
2529 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2535 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2536 void psxBios__get_error(void) // 55
2542 void psxBios_Krom2RawAdd() { // 0x51
2545 const u32 table_8140[][2] = {
2546 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2547 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2548 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2549 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2550 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2551 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2552 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2553 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2554 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2558 const u32 table_889f[][2] = {
2559 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2560 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2561 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2562 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2563 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2564 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2565 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2566 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2570 if (a0 >= 0x8140 && a0 <= 0x84be) {
2571 while (table_8140[i][0] <= a0) i++;
2572 a0 -= table_8140[i - 1][0];
2573 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2574 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2575 while (table_889f[i][0] <= a0) i++;
2576 a0 -= table_889f[i - 1][0];
2577 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2585 void psxBios_GetC0Table() { // 56
2587 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2590 v0 = 0x674; pc0 = ra;
2593 void psxBios_GetB0Table() { // 57
2595 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2598 v0 = 0x874; pc0 = ra;
2601 void psxBios__card_chan() { // 0x58
2603 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2606 v0 = card_active_chan;
2610 void psxBios_ChangeClearPad() { // 5b
2612 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2618 void psxBios__card_status() { // 5c
2620 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2623 v0 = card_active_chan;
2627 void psxBios__card_wait() { // 5d
2629 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2636 /* System calls C0 */
2639 * int SysEnqIntRP(int index , long *queue);
2642 void psxBios_SysEnqIntRP() { // 02
2644 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2653 * int SysDeqIntRP(int index , long *queue);
2656 void psxBios_SysDeqIntRP() { // 03
2658 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2666 void psxBios_ChangeClearRCnt() { // 0a
2670 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2673 ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2677 // psxRegs.CP0.n.Status|= 0x404;
2681 void psxBios_dummy() {
2683 PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2688 void (*biosA0[256])();
2689 void (*biosB0[256])();
2690 void (*biosC0[256])();
2692 #include "sjisfont.h"
2694 void psxBiosInit() {
2700 for(i = 0; i < 256; i++) {
2705 biosA0[0x3e] = psxBios_puts;
2706 biosA0[0x3f] = psxBios_printf;
2708 biosB0[0x3d] = psxBios_putchar;
2709 biosB0[0x3f] = psxBios_puts;
2711 if (!Config.HLE) return;
2713 for(i = 0; i < 256; i++) {
2714 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2715 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2716 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2719 biosA0[0x00] = psxBios_open;
2720 biosA0[0x01] = psxBios_lseek;
2721 biosA0[0x02] = psxBios_read;
2722 biosA0[0x03] = psxBios_write;
2723 biosA0[0x04] = psxBios_close;
2724 //biosA0[0x05] = psxBios_ioctl;
2725 //biosA0[0x06] = psxBios_exit;
2726 //biosA0[0x07] = psxBios_sys_a0_07;
2727 biosA0[0x08] = psxBios_getc;
2728 biosA0[0x09] = psxBios_putc;
2729 biosA0[0x0a] = psxBios_todigit;
2730 //biosA0[0x0b] = psxBios_atof;
2731 //biosA0[0x0c] = psxBios_strtoul;
2732 //biosA0[0x0d] = psxBios_strtol;
2733 biosA0[0x0e] = psxBios_abs;
2734 biosA0[0x0f] = psxBios_labs;
2735 biosA0[0x10] = psxBios_atoi;
2736 biosA0[0x11] = psxBios_atol;
2737 //biosA0[0x12] = psxBios_atob;
2738 biosA0[0x13] = psxBios_setjmp;
2739 biosA0[0x14] = psxBios_longjmp;
2740 biosA0[0x15] = psxBios_strcat;
2741 biosA0[0x16] = psxBios_strncat;
2742 biosA0[0x17] = psxBios_strcmp;
2743 biosA0[0x18] = psxBios_strncmp;
2744 biosA0[0x19] = psxBios_strcpy;
2745 biosA0[0x1a] = psxBios_strncpy;
2746 biosA0[0x1b] = psxBios_strlen;
2747 biosA0[0x1c] = psxBios_index;
2748 biosA0[0x1d] = psxBios_rindex;
2749 biosA0[0x1e] = psxBios_strchr;
2750 biosA0[0x1f] = psxBios_strrchr;
2751 biosA0[0x20] = psxBios_strpbrk;
2752 biosA0[0x21] = psxBios_strspn;
2753 biosA0[0x22] = psxBios_strcspn;
2754 biosA0[0x23] = psxBios_strtok;
2755 biosA0[0x24] = psxBios_strstr;
2756 biosA0[0x25] = psxBios_toupper;
2757 biosA0[0x26] = psxBios_tolower;
2758 biosA0[0x27] = psxBios_bcopy;
2759 biosA0[0x28] = psxBios_bzero;
2760 biosA0[0x29] = psxBios_bcmp;
2761 biosA0[0x2a] = psxBios_memcpy;
2762 biosA0[0x2b] = psxBios_memset;
2763 biosA0[0x2c] = psxBios_memmove;
2764 biosA0[0x2d] = psxBios_memcmp;
2765 biosA0[0x2e] = psxBios_memchr;
2766 biosA0[0x2f] = psxBios_rand;
2767 biosA0[0x30] = psxBios_srand;
2768 biosA0[0x31] = psxBios_qsort;
2769 //biosA0[0x32] = psxBios_strtod;
2770 biosA0[0x33] = psxBios_malloc;
2771 biosA0[0x34] = psxBios_free;
2772 //biosA0[0x35] = psxBios_lsearch;
2773 //biosA0[0x36] = psxBios_bsearch;
2774 biosA0[0x37] = psxBios_calloc;
2775 biosA0[0x38] = psxBios_realloc;
2776 biosA0[0x39] = psxBios_InitHeap;
2777 //biosA0[0x3a] = psxBios__exit;
2778 biosA0[0x3b] = psxBios_getchar;
2779 biosA0[0x3c] = psxBios_putchar;
2780 //biosA0[0x3d] = psxBios_gets;
2781 //biosA0[0x40] = psxBios_sys_a0_40;
2782 //biosA0[0x41] = psxBios_LoadTest;
2783 biosA0[0x42] = psxBios_Load;
2784 biosA0[0x43] = psxBios_Exec;
2785 biosA0[0x44] = psxBios_FlushCache;
2786 //biosA0[0x45] = psxBios_InstallInterruptHandler;
2787 biosA0[0x46] = psxBios_GPU_dw;
2788 biosA0[0x47] = psxBios_mem2vram;
2789 biosA0[0x48] = psxBios_SendGPU;
2790 biosA0[0x49] = psxBios_GPU_cw;
2791 biosA0[0x4a] = psxBios_GPU_cwb;
2792 biosA0[0x4b] = psxBios_GPU_SendPackets;
2793 biosA0[0x4c] = psxBios_sys_a0_4c;
2794 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2795 //biosA0[0x4e] = psxBios_GPU_sync;
2796 //biosA0[0x4f] = psxBios_sys_a0_4f;
2797 //biosA0[0x50] = psxBios_sys_a0_50;
2798 biosA0[0x51] = psxBios_LoadExec;
2799 //biosA0[0x52] = psxBios_GetSysSp;
2800 //biosA0[0x53] = psxBios_sys_a0_53;
2801 //biosA0[0x54] = psxBios__96_init_a54;
2802 //biosA0[0x55] = psxBios__bu_init_a55;
2803 //biosA0[0x56] = psxBios__96_remove_a56;
2804 //biosA0[0x57] = psxBios_sys_a0_57;
2805 //biosA0[0x58] = psxBios_sys_a0_58;
2806 //biosA0[0x59] = psxBios_sys_a0_59;
2807 //biosA0[0x5a] = psxBios_sys_a0_5a;
2808 //biosA0[0x5b] = psxBios_dev_tty_init;
2809 //biosA0[0x5c] = psxBios_dev_tty_open;
2810 //biosA0[0x5d] = psxBios_sys_a0_5d;
2811 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2812 //biosA0[0x5f] = psxBios_dev_cd_open;
2813 //biosA0[0x60] = psxBios_dev_cd_read;
2814 //biosA0[0x61] = psxBios_dev_cd_close;
2815 //biosA0[0x62] = psxBios_dev_cd_firstfile;
2816 //biosA0[0x63] = psxBios_dev_cd_nextfile;
2817 //biosA0[0x64] = psxBios_dev_cd_chdir;
2818 //biosA0[0x65] = psxBios_dev_card_open;
2819 //biosA0[0x66] = psxBios_dev_card_read;
2820 //biosA0[0x67] = psxBios_dev_card_write;
2821 //biosA0[0x68] = psxBios_dev_card_close;
2822 //biosA0[0x69] = psxBios_dev_card_firstfile;
2823 //biosA0[0x6a] = psxBios_dev_card_nextfile;
2824 //biosA0[0x6b] = psxBios_dev_card_erase;
2825 //biosA0[0x6c] = psxBios_dev_card_undelete;
2826 //biosA0[0x6d] = psxBios_dev_card_format;
2827 //biosA0[0x6e] = psxBios_dev_card_rename;
2828 //biosA0[0x6f] = psxBios_dev_card_6f;
2829 biosA0[0x70] = psxBios__bu_init;
2830 biosA0[0x71] = psxBios__96_init;
2831 biosA0[0x72] = psxBios__96_remove;
2832 //biosA0[0x73] = psxBios_sys_a0_73;
2833 //biosA0[0x74] = psxBios_sys_a0_74;
2834 //biosA0[0x75] = psxBios_sys_a0_75;
2835 //biosA0[0x76] = psxBios_sys_a0_76;
2836 //biosA0[0x77] = psxBios_sys_a0_77;
2837 //biosA0[0x78] = psxBios__96_CdSeekL;
2838 //biosA0[0x79] = psxBios_sys_a0_79;
2839 //biosA0[0x7a] = psxBios_sys_a0_7a;
2840 //biosA0[0x7b] = psxBios_sys_a0_7b;
2841 //biosA0[0x7c] = psxBios__96_CdGetStatus;
2842 //biosA0[0x7d] = psxBios_sys_a0_7d;
2843 //biosA0[0x7e] = psxBios__96_CdRead;
2844 //biosA0[0x7f] = psxBios_sys_a0_7f;
2845 //biosA0[0x80] = psxBios_sys_a0_80;
2846 //biosA0[0x81] = psxBios_sys_a0_81;
2847 //biosA0[0x82] = psxBios_sys_a0_82;
2848 //biosA0[0x83] = psxBios_sys_a0_83;
2849 //biosA0[0x84] = psxBios_sys_a0_84;
2850 //biosA0[0x85] = psxBios__96_CdStop;
2851 //biosA0[0x86] = psxBios_sys_a0_86;
2852 //biosA0[0x87] = psxBios_sys_a0_87;
2853 //biosA0[0x88] = psxBios_sys_a0_88;
2854 //biosA0[0x89] = psxBios_sys_a0_89;
2855 //biosA0[0x8a] = psxBios_sys_a0_8a;
2856 //biosA0[0x8b] = psxBios_sys_a0_8b;
2857 //biosA0[0x8c] = psxBios_sys_a0_8c;
2858 //biosA0[0x8d] = psxBios_sys_a0_8d;
2859 //biosA0[0x8e] = psxBios_sys_a0_8e;
2860 //biosA0[0x8f] = psxBios_sys_a0_8f;
2861 //biosA0[0x90] = psxBios_sys_a0_90;
2862 //biosA0[0x91] = psxBios_sys_a0_91;
2863 //biosA0[0x92] = psxBios_sys_a0_92;
2864 //biosA0[0x93] = psxBios_sys_a0_93;
2865 //biosA0[0x94] = psxBios_sys_a0_94;
2866 //biosA0[0x95] = psxBios_sys_a0_95;
2867 //biosA0[0x96] = psxBios_AddCDROMDevice;
2868 //biosA0[0x97] = psxBios_AddMemCardDevide;
2869 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2870 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2871 //biosA0[0x9a] = psxBios_sys_a0_9a;
2872 //biosA0[0x9b] = psxBios_sys_a0_9b;
2873 //biosA0[0x9c] = psxBios_SetConf;
2874 //biosA0[0x9d] = psxBios_GetConf;
2875 //biosA0[0x9e] = psxBios_sys_a0_9e;
2876 biosA0[0x9f] = psxBios_SetMem;
2877 //biosA0[0xa0] = psxBios__boot;
2878 //biosA0[0xa1] = psxBios_SystemError;
2879 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2880 //biosA0[0xa3] = psxBios_DequeueCdIntr;
2881 //biosA0[0xa4] = psxBios_sys_a0_a4;
2882 //biosA0[0xa5] = psxBios_ReadSector;
2883 biosA0[0xa6] = psxBios_get_cd_status;
2884 //biosA0[0xa7] = psxBios_bufs_cb_0;
2885 //biosA0[0xa8] = psxBios_bufs_cb_1;
2886 //biosA0[0xa9] = psxBios_bufs_cb_2;
2887 //biosA0[0xaa] = psxBios_bufs_cb_3;
2888 biosA0[0xab] = psxBios__card_info;
2889 biosA0[0xac] = psxBios__card_load;
2890 //biosA0[0axd] = psxBios__card_auto;
2891 //biosA0[0xae] = psxBios_bufs_cd_4;
2892 //biosA0[0xaf] = psxBios_sys_a0_af;
2893 //biosA0[0xb0] = psxBios_sys_a0_b0;
2894 //biosA0[0xb1] = psxBios_sys_a0_b1;
2895 //biosA0[0xb2] = psxBios_do_a_long_jmp
2896 //biosA0[0xb3] = psxBios_sys_a0_b3;
2897 //biosA0[0xb4] = psxBios_sub_function;
2898 //*******************B0 CALLS****************************
2899 //biosB0[0x00] = psxBios_SysMalloc;
2900 //biosB0[0x01] = psxBios_sys_b0_01;
2901 biosB0[0x02] = psxBios_SetRCnt;
2902 biosB0[0x03] = psxBios_GetRCnt;
2903 biosB0[0x04] = psxBios_StartRCnt;
2904 biosB0[0x05] = psxBios_StopRCnt;
2905 biosB0[0x06] = psxBios_ResetRCnt;
2906 biosB0[0x07] = psxBios_DeliverEvent;
2907 biosB0[0x08] = psxBios_OpenEvent;
2908 biosB0[0x09] = psxBios_CloseEvent;
2909 biosB0[0x0a] = psxBios_WaitEvent;
2910 biosB0[0x0b] = psxBios_TestEvent;
2911 biosB0[0x0c] = psxBios_EnableEvent;
2912 biosB0[0x0d] = psxBios_DisableEvent;
2913 biosB0[0x0e] = psxBios_OpenTh;
2914 biosB0[0x0f] = psxBios_CloseTh;
2915 biosB0[0x10] = psxBios_ChangeTh;
2916 //biosB0[0x11] = psxBios_psxBios_b0_11;
2917 biosB0[0x12] = psxBios_InitPAD;
2918 biosB0[0x13] = psxBios_StartPAD;
2919 biosB0[0x14] = psxBios_StopPAD;
2920 biosB0[0x15] = psxBios_PAD_init;
2921 biosB0[0x16] = psxBios_PAD_dr;
2922 biosB0[0x17] = psxBios_ReturnFromException;
2923 biosB0[0x18] = psxBios_ResetEntryInt;
2924 biosB0[0x19] = psxBios_HookEntryInt;
2925 //biosB0[0x1a] = psxBios_sys_b0_1a;
2926 //biosB0[0x1b] = psxBios_sys_b0_1b;
2927 //biosB0[0x1c] = psxBios_sys_b0_1c;
2928 //biosB0[0x1d] = psxBios_sys_b0_1d;
2929 //biosB0[0x1e] = psxBios_sys_b0_1e;
2930 //biosB0[0x1f] = psxBios_sys_b0_1f;
2931 biosB0[0x20] = psxBios_UnDeliverEvent;
2932 //biosB0[0x21] = psxBios_sys_b0_21;
2933 //biosB0[0x22] = psxBios_sys_b0_22;
2934 //biosB0[0x23] = psxBios_sys_b0_23;
2935 //biosB0[0x24] = psxBios_sys_b0_24;
2936 //biosB0[0x25] = psxBios_sys_b0_25;
2937 //biosB0[0x26] = psxBios_sys_b0_26;
2938 //biosB0[0x27] = psxBios_sys_b0_27;
2939 //biosB0[0x28] = psxBios_sys_b0_28;
2940 //biosB0[0x29] = psxBios_sys_b0_29;
2941 //biosB0[0x2a] = psxBios_sys_b0_2a;
2942 //biosB0[0x2b] = psxBios_sys_b0_2b;
2943 //biosB0[0x2c] = psxBios_sys_b0_2c;
2944 //biosB0[0x2d] = psxBios_sys_b0_2d;
2945 //biosB0[0x2e] = psxBios_sys_b0_2e;
2946 //biosB0[0x2f] = psxBios_sys_b0_2f;
2947 //biosB0[0x30] = psxBios_sys_b0_30;
2948 //biosB0[0x31] = psxBios_sys_b0_31;
2949 biosB0[0x32] = psxBios_open;
2950 biosB0[0x33] = psxBios_lseek;
2951 biosB0[0x34] = psxBios_read;
2952 biosB0[0x35] = psxBios_write;
2953 biosB0[0x36] = psxBios_close;
2954 //biosB0[0x37] = psxBios_ioctl;
2955 //biosB0[0x38] = psxBios_exit;
2956 //biosB0[0x39] = psxBios_sys_b0_39;
2957 //biosB0[0x3a] = psxBios_getc;
2958 //biosB0[0x3b] = psxBios_putc;
2959 biosB0[0x3c] = psxBios_getchar;
2960 //biosB0[0x3e] = psxBios_gets;
2961 //biosB0[0x40] = psxBios_cd;
2962 biosB0[0x41] = psxBios_format;
2963 biosB0[0x42] = psxBios_firstfile;
2964 biosB0[0x43] = psxBios_nextfile;
2965 biosB0[0x44] = psxBios_rename;
2966 biosB0[0x45] = psxBios_delete;
2967 //biosB0[0x46] = psxBios_undelete;
2968 //biosB0[0x47] = psxBios_AddDevice;
2969 //biosB0[0x48] = psxBios_RemoteDevice;
2970 //biosB0[0x49] = psxBios_PrintInstalledDevices;
2971 biosB0[0x4a] = psxBios_InitCARD;
2972 biosB0[0x4b] = psxBios_StartCARD;
2973 biosB0[0x4c] = psxBios_StopCARD;
2974 //biosB0[0x4d] = psxBios_sys_b0_4d;
2975 biosB0[0x4e] = psxBios__card_write;
2976 biosB0[0x4f] = psxBios__card_read;
2977 biosB0[0x50] = psxBios__new_card;
2978 biosB0[0x51] = psxBios_Krom2RawAdd;
2979 //biosB0[0x52] = psxBios_sys_b0_52;
2980 //biosB0[0x53] = psxBios_sys_b0_53;
2981 //biosB0[0x54] = psxBios__get_errno;
2982 biosB0[0x55] = psxBios__get_error;
2983 biosB0[0x56] = psxBios_GetC0Table;
2984 biosB0[0x57] = psxBios_GetB0Table;
2985 biosB0[0x58] = psxBios__card_chan;
2986 //biosB0[0x59] = psxBios_sys_b0_59;
2987 //biosB0[0x5a] = psxBios_sys_b0_5a;
2988 biosB0[0x5b] = psxBios_ChangeClearPad;
2989 biosB0[0x5c] = psxBios__card_status;
2990 biosB0[0x5d] = psxBios__card_wait;
2991 //*******************C0 CALLS****************************
2992 //biosC0[0x00] = psxBios_InitRCnt;
2993 //biosC0[0x01] = psxBios_InitException;
2994 biosC0[0x02] = psxBios_SysEnqIntRP;
2995 biosC0[0x03] = psxBios_SysDeqIntRP;
2996 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
2997 //biosC0[0x05] = psxBios_get_free_TCB_slot;
2998 //biosC0[0x06] = psxBios_ExceptionHandler;
2999 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3000 //biosC0[0x08] = psxBios_SysInitMemory;
3001 //biosC0[0x09] = psxBios_SysInitKMem;
3002 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3003 //biosC0[0x0b] = psxBios_SystemError;
3004 //biosC0[0x0c] = psxBios_InitDefInt;
3005 //biosC0[0x0d] = psxBios_sys_c0_0d;
3006 //biosC0[0x0e] = psxBios_sys_c0_0e;
3007 //biosC0[0x0f] = psxBios_sys_c0_0f;
3008 //biosC0[0x10] = psxBios_sys_c0_10;
3009 //biosC0[0x11] = psxBios_sys_c0_11;
3010 //biosC0[0x12] = psxBios_InstallDevices;
3011 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3012 //biosC0[0x14] = psxBios_sys_c0_14;
3013 //biosC0[0x15] = psxBios__cdevinput;
3014 //biosC0[0x16] = psxBios__cdevscan;
3015 //biosC0[0x17] = psxBios__circgetc;
3016 //biosC0[0x18] = psxBios__circputc;
3017 //biosC0[0x19] = psxBios_ioabort;
3018 //biosC0[0x1a] = psxBios_sys_c0_1a
3019 //biosC0[0x1b] = psxBios_KernelRedirect;
3020 //biosC0[0x1c] = psxBios_PatchAOTable;
3021 //************** THE END ***************************************
3024 size = sizeof(EvCB) * 32;
3025 EventCB = (void *)&psxR[base]; base += size * 6;
3026 memset(EventCB, 0, size * 6);
3028 EvEV = EventCB + 32;
3029 RcEV = EventCB + 32 * 2;
3030 UeEV = EventCB + 32 * 3;
3031 SwEV = EventCB + 32 * 4;
3032 ThEV = EventCB + 32 * 5;
3034 ptr = (u32 *)&psxM[0x0874]; // b0 table
3035 ptr[0] = SWAPu32(0x4c54 - 0x884);
3037 ptr = (u32 *)&psxM[0x0674]; // c0 table
3038 ptr[6] = SWAPu32(0xc80);
3040 memset(SysIntRP, 0, sizeof(SysIntRP));
3041 memset(ThreadCB, 0, sizeof(ThreadCB));
3042 ThreadCB[0].status = 2; // main thread
3049 pad_buf1len = pad_buf2len = 0;
3055 memset(FDesc, 0, sizeof(FDesc));
3056 card_active_chan = 0;
3058 psxMu32ref(0x0150) = SWAPu32(0x160);
3059 psxMu32ref(0x0154) = SWAPu32(0x320);
3060 psxMu32ref(0x0160) = SWAPu32(0x248);
3061 strcpy((char *)&psxM[0x248], "bu");
3062 /* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3063 psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3064 psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3065 psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3066 psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3069 psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
3070 /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
3071 Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3072 //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
3073 psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3074 psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3075 psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3076 psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3077 psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3078 psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3079 psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3080 psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3082 // initial stack pointer for BIOS interrupt
3083 psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3086 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3089 len = 0x80000 - 0x66000;
3090 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3091 len = 0x80000 - 0x69d68;
3092 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3095 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3097 hleSoftCall = FALSE;
3099 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3100 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3101 Here are some examples of games not working with this fix in place :
3102 R-type won't get past the Irem logo if not implemented.
3103 Crash Team Racing will softlock after the Sony logo.
3106 psxMu32ref(0x0000) = SWAPu32(0x00000003);
3108 But overwritten by 00000003h after soon.
3109 psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3111 psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3112 psxMu32ref(0x0008) = SWAPu32(0x08000403);
3113 psxMu32ref(0x000C) = SWAPu32(0x00000000);
3116 void psxBiosShutdown() {
3119 #define psxBios_PADpoll(pad) { \
3120 PAD##pad##_startPoll(pad); \
3121 pad_buf##pad[0] = 0; \
3122 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3123 if (!(pad_buf##pad[1] & 0x0f)) { \
3126 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3128 PAD##pad##_poll(0); \
3130 while (bufcount--) { \
3131 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3135 void biosInterrupt() {
3138 // if (psxHu32(0x1070) & 0x1) { // Vsync
3139 if (pad_buf != NULL) {
3140 u32 *buf = (u32*)pad_buf;
3142 if (!Config.UseNet) {
3144 if (PAD1_poll(0x42) == 0x23) {
3146 *buf = PAD1_poll(0) << 8;
3147 *buf |= PAD1_poll(0);
3149 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3150 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3153 *buf = PAD1_poll(0) << 8;
3154 *buf|= PAD1_poll(0);
3158 if (PAD2_poll(0x42) == 0x23) {
3160 *buf |= PAD2_poll(0) << 24;
3161 *buf |= PAD2_poll(0) << 16;
3163 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3164 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3167 *buf |= PAD2_poll(0) << 24;
3168 *buf |= PAD2_poll(0) << 16;
3176 data = PAD1_poll(0) << 8;
3177 data |= PAD1_poll(0);
3179 if (NET_sendPadData(&data, 2) == -1)
3182 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3184 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3188 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3191 if (NET_sendPadData(pad_buf1, i) == -1)
3194 if (NET_recvPadData(pad_buf1, 1) == -1)
3196 if (NET_recvPadData(pad_buf2, 2) == -1)
3210 if (psxHu32(0x1070) & 0x1) { // Vsync
3211 if (RcEV[3][1].status == EvStACTIVE) {
3212 softCall(RcEV[3][1].fhandler);
3213 // hwWrite32(0x1f801070, ~(1));
3217 if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3220 for (i = 0; i < 3; i++) {
3221 if (psxHu32(0x1070) & (1 << (i + 4))) {
3222 if (RcEV[i][1].status == EvStACTIVE) {
3223 softCall(RcEV[i][1].fhandler);
3225 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3231 void psxBiosException() {
3234 switch (psxRegs.CP0.n.Cause & 0x3c) {
3235 case 0x00: // Interrupt
3236 interrupt_r26=psxRegs.CP0.n.EPC;
3238 // PSXCPU_LOG("interrupt\n");
3242 sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3246 for (i = 0; i < 8; i++) {
3248 u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3255 if (jmp_int != NULL) {
3258 psxHwWrite32(0x1f801070, 0xffffffff);
3263 for (i = 0; i < 8; i++) // s0-s7
3264 psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3271 psxHwWrite16(0x1f801070, 0);
3274 case 0x20: // Syscall
3276 PSXCPU_LOG("syscall exp %x\n", a0);
3279 case 1: // EnterCritical - disable irq's
3280 /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3281 v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3282 psxRegs.CP0.n.Status &= ~0x404;
3285 case 2: // ExitCritical - enable irq's
3286 psxRegs.CP0.n.Status |= 0x404;
3288 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3292 pc0 = psxRegs.CP0.n.EPC + 4;
3294 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3295 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3300 PSXCPU_LOG("unknown bios exception!\n");
3305 pc0 = psxRegs.CP0.n.EPC;
3306 if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3308 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3309 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3312 #define bfreeze(ptr, size) { \
3313 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3314 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3318 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3319 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3321 #define bfreezepsxMptr(ptr, type) { \
3323 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3324 else psxRu32ref(base) = 0; \
3326 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3327 else (ptr) = NULL; \
3329 base += sizeof(u32); \
3332 void psxBiosFreeze(int Mode) {
3335 bfreezepsxMptr(jmp_int, u32);
3336 bfreezepsxMptr(pad_buf, int);
3337 bfreezepsxMptr(pad_buf1, char);
3338 bfreezepsxMptr(pad_buf2, char);
3339 bfreezepsxMptr(heap_addr, u32);
3340 bfreezel(&pad_buf1len);
3341 bfreezel(&pad_buf2len);
3344 bfreezel(&CardState);
3346 bfreezel(&CurThread);
3348 bfreezel(&card_active_chan);
3349 bfreezel(&pad_stopped);
3350 bfreezel(&heap_size);