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.
38 #if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
39 #pragma GCC diagnostic ignored "-Wpointer-sign"
43 #define SysPrintf if (Config.PsxOut) printf
45 char *biosA0n[256] = {
47 "open", "lseek", "read", "write",
48 "close", "ioctl", "exit", "sys_a0_07",
49 "getc", "putc", "todigit", "atof",
50 "strtoul", "strtol", "abs", "labs",
52 "atoi", "atol", "atob", "setjmp",
53 "longjmp", "strcat", "strncat", "strcmp",
54 "strncmp", "strcpy", "strncpy", "strlen",
55 "index", "rindex", "strchr", "strrchr",
57 "strpbrk", "strspn", "strcspn", "strtok",
58 "strstr", "toupper", "tolower", "bcopy",
59 "bzero", "bcmp", "memcpy", "memset",
60 "memmove", "memcmp", "memchr", "rand",
62 "srand", "qsort", "strtod", "malloc",
63 "free", "lsearch", "bsearch", "calloc",
64 "realloc", "InitHeap", "_exit", "getchar",
65 "putchar", "gets", "puts", "printf",
67 "sys_a0_40", "LoadTest", "Load", "Exec",
68 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
69 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
70 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
72 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
73 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
74 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
75 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
77 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
78 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
79 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
80 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
82 "_bu_init", "_96_init", "_96_remove", "sys_a0_73",
83 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
84 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
85 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
87 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
88 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
89 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
90 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
92 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
93 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
94 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
95 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
97 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
98 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
99 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
100 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
102 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
106 char *biosB0n[256] = {
108 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
109 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
110 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
111 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
113 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
114 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
115 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
116 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
118 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
119 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
120 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
121 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
123 "sys_b0_30", "sys_b0_31", "open", "lseek",
124 "read", "write", "close", "ioctl",
125 "exit", "sys_b0_39", "getc", "putc",
126 "getchar", "putchar", "gets", "puts",
128 "cd", "format", "firstfile", "nextfile",
129 "rename", "delete", "undelete", "AddDevice",
130 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
131 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
133 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
134 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
135 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
136 "_card_status", "_card_wait",
139 char *biosC0n[256] = {
141 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
142 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
143 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
144 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
146 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
147 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
148 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
152 //#define r0 (psxRegs.GPR.n.r0)
153 #define at (psxRegs.GPR.n.at)
154 #define v0 (psxRegs.GPR.n.v0)
155 #define v1 (psxRegs.GPR.n.v1)
156 #define a0 (psxRegs.GPR.n.a0)
157 #define a1 (psxRegs.GPR.n.a1)
158 #define a2 (psxRegs.GPR.n.a2)
159 #define a3 (psxRegs.GPR.n.a3)
160 #define t0 (psxRegs.GPR.n.t0)
161 #define t1 (psxRegs.GPR.n.t1)
162 #define t2 (psxRegs.GPR.n.t2)
163 #define t3 (psxRegs.GPR.n.t3)
164 #define t4 (psxRegs.GPR.n.t4)
165 #define t5 (psxRegs.GPR.n.t5)
166 #define t6 (psxRegs.GPR.n.t6)
167 #define t7 (psxRegs.GPR.n.t7)
168 #define t8 (psxRegs.GPR.n.t8)
169 #define t9 (psxRegs.GPR.n.t9)
170 #define s0 (psxRegs.GPR.n.s0)
171 #define s1 (psxRegs.GPR.n.s1)
172 #define s2 (psxRegs.GPR.n.s2)
173 #define s3 (psxRegs.GPR.n.s3)
174 #define s4 (psxRegs.GPR.n.s4)
175 #define s5 (psxRegs.GPR.n.s5)
176 #define s6 (psxRegs.GPR.n.s6)
177 #define s7 (psxRegs.GPR.n.s7)
178 #define k0 (psxRegs.GPR.n.k0)
179 #define k1 (psxRegs.GPR.n.k1)
180 #define gp (psxRegs.GPR.n.gp)
181 #define sp (psxRegs.GPR.n.sp)
182 #define fp (psxRegs.GPR.n.s8)
183 #define ra (psxRegs.GPR.n.ra)
184 #define pc0 (psxRegs.pc)
186 #define Ra0 ((char *)PSXM(a0))
187 #define Ra1 ((char *)PSXM(a1))
188 #define Ra2 ((char *)PSXM(a2))
189 #define Ra3 ((char *)PSXM(a3))
190 #define Rv0 ((char *)PSXM(v0))
191 #define Rsp ((char *)PSXM(sp))
200 #define EvStUNUSED 0x0000
201 #define EvStWAIT 0x1000
202 #define EvStACTIVE 0x2000
203 #define EvStALREADY 0x4000
205 #define EvMdINTR 0x1000
206 #define EvMdNOINTR 0x2000
235 u32 _sp, _fp, _gp, ret, base;
255 static u32 *jmp_int = NULL;
256 static int *pad_buf = NULL;
257 static char *pad_buf1 = NULL, *pad_buf2 = NULL;
258 static int pad_buf1len, pad_buf2len;
259 static int pad_stopped = 0;
263 static EvCB *HwEV; // 0xf0
264 static EvCB *EvEV; // 0xf1
265 static EvCB *RcEV; // 0xf2
266 static EvCB *UeEV; // 0xf3
267 static EvCB *SwEV; // 0xf4
268 static EvCB *ThEV; // 0xff
269 static u32 heap_size = 0;
270 static u32 *heap_addr = NULL;
271 static u32 *heap_end = NULL;
272 static u32 SysIntRP[8];
273 static int CardState = -1;
274 static TCB Thread[8];
275 static int CurThread = 0;
276 static FileDesc FDesc[32];
277 static u32 card_active_chan;
279 boolean hleSoftCall = FALSE;
281 static inline void softCall(u32 pc) {
287 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
292 static inline void softCall2(u32 pc) {
299 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
305 static inline void DeliverEvent(u32 ev, u32 spec) {
306 if (Event[ev][spec].status != EvStACTIVE) return;
308 // Event[ev][spec].status = EvStALREADY;
309 if (Event[ev][spec].mode == EvMdINTR) {
310 softCall2(Event[ev][spec].fhandler);
311 } else Event[ev][spec].status = EvStALREADY;
314 static unsigned interrupt_r26=0x8004E8B0;
316 static inline void SaveRegs() {
317 memcpy(regs, psxRegs.GPR.r, 32*4);
318 regs[32] = psxRegs.GPR.n.lo;
319 regs[33] = psxRegs.GPR.n.hi;
320 regs[34] = psxRegs.pc;
323 static inline void LoadRegs() {
324 memcpy(psxRegs.GPR.r, regs, 32*4);
325 psxRegs.GPR.n.lo = regs[32];
326 psxRegs.GPR.n.hi = regs[33];
332 // System calls A0 */
335 #define buread(Ra1, mcd, length) { \
336 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); \
337 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
338 memcpy(Ra1, ptr, length); \
339 if (FDesc[1 + mcd].mode & 0x8000) { \
340 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
341 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
344 FDesc[1 + mcd].offset += v0; \
347 #define buwrite(Ra1, mcd, length) { \
348 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
349 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
350 ptr = Mcd##mcd##Data + offset; \
351 memcpy(ptr, Ra1, length); \
352 FDesc[1 + mcd].offset += length; \
353 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
354 if (FDesc[1 + mcd].mode & 0x8000) { \
355 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
356 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
362 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
363 /* For some strange reason, the returned character is sign-expanded; */
364 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
365 /* TODO FIX ME : Properly implement this behaviour */
366 void psxBios_getc(void) // 0x03, 0x35
371 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
377 case 2: buread(pa1, 1, 1); break;
378 case 3: buread(pa1, 2, 1); break;
385 /* Copy of psxBios_write, except size is 1. */
386 void psxBios_putc(void) // 0x09, 0x3B
391 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
399 if (a0 == 1) { // stdout
400 char *ptr = (char *)pa1;
404 printf("%c", *ptr++); a2--;
410 case 2: buwrite(pa1, 1, 1); break;
411 case 3: buwrite(pa1, 2, 1); break;
417 void psxBios_todigit(void) // 0x0a
421 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
424 if (c >= 0x30 && c < 0x3A) {
427 else if (c > 0x60 && c < 0x7B) {
430 else if (c > 0x40 && c < 0x5B) {
433 else if (c >= 0x80) {
444 void psxBios_abs() { // 0x0e
445 if ((s32)a0 < 0) v0 = -(s32)a0;
450 void psxBios_labs() { // 0x0f
454 void psxBios_atoi() { // 0x10
456 char *p = (char *)Ra0;
460 case ' ': case '\t': continue;
467 while (*p >= '0' && *p <= '9') {
468 n = n * 10 + *p++ - '0';
475 void psxBios_atol() { // 0x11
479 void psxBios_setjmp() { // 0x13
480 u32 *jmp_buf = (u32 *)Ra0;
484 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x13]);
490 for (i = 0; i < 8; i++) // s0-s7
491 jmp_buf[3 + i] = psxRegs.GPR.r[16 + i];
497 void psxBios_longjmp() { // 0x14
498 u32 *jmp_buf = (u32 *)Ra0;
502 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
505 ra = jmp_buf[0]; /* ra */
506 sp = jmp_buf[1]; /* sp */
507 fp = jmp_buf[2]; /* fp */
508 for (i = 0; i < 8; i++) // s0-s7
509 psxRegs.GPR.r[16 + i] = jmp_buf[3 + i];
510 gp = jmp_buf[11]; /* gp */
515 void psxBios_strcat() { // 0x15
516 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
519 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
521 if (a0 == 0 || a1 == 0)
529 while ((*p1++ = *p2++) != '\0');
534 void psxBios_strncat() { // 0x16
535 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
539 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
541 if (a0 == 0 || a1 == 0)
549 while ((*p1++ = *p2++) != '\0') {
559 void psxBios_strcmp() { // 0x17
560 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
562 if (a0 == 0 && a1 == 0)
568 else if (a0 == 0 && a1 != 0)
574 else if (a0 != 0 && a1 == 0)
581 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
584 while (*p1 == *p2++) {
603 void psxBios_strncmp() { // 0x18
604 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
606 if (a0 == 0 && a1 == 0)
612 else if (a0 == 0 && a1 != 0)
618 else if (a0 != 0 && a1 == 0)
625 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
628 while (--n >= 0 && *p1 == *p2++) {
632 v1 = a2 - ((a2-n) - 1);
640 v0 = (n < 0 ? 0 : *p1 - *--p2);
642 v1 = a2 - ((a2-n) - 1);
648 void psxBios_strcpy() { // 0x19
649 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
650 if (a0 == 0 || a1 == 0)
656 while ((*p1++ = *p2++) != '\0');
661 void psxBios_strncpy() { // 0x1a
662 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
664 if (a0 == 0 || a1 == 0)
670 for (i = 0; i < n; i++) {
671 if ((*p1++ = *p2++) == '\0') {
683 void psxBios_strlen() { // 0x1b
684 char *p = (char *)Ra0;
695 void psxBios_index() { // 0x1c
696 char *p = (char *)Ra0;
706 v0 = a0 + (p - (char *)Ra0);
710 } while (*p++ != '\0');
715 void psxBios_rindex() { // 0x1d
716 char *p = (char *)Ra0;
726 v0 = a0 + (p - (char *)Ra0);
727 } while (*p++ != '\0');
732 void psxBios_strchr() { // 0x1e
736 void psxBios_strrchr() { // 0x1f
740 void psxBios_strpbrk() { // 0x20
741 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
743 while ((c = *p1++) != '\0') {
744 for (scanp = p2; (sc = *scanp++) != '\0';) {
746 v0 = a0 + (p1 - 1 - (char *)Ra0);
753 // BUG: return a0 instead of NULL if not found
757 void psxBios_strspn() { // 0x21
760 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
761 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
762 if (*p2 == '\0') break;
765 v0 = p1 - (char *)Ra0; pc0 = ra;
768 void psxBios_strcspn() { // 0x22
771 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
772 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
773 if (*p2 != '\0') break;
776 v0 = p1 - (char *)Ra0; pc0 = ra;
779 void psxBios_strtok() { // 0x23
780 char *pcA0 = (char *)Ra0;
781 char *pcRet = strtok(pcA0, (char *)Ra1);
783 v0 = a0 + pcRet - pcA0;
789 void psxBios_strstr() { // 0x24
790 char *p = (char *)Ra0, *p1, *p2;
796 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
801 v0 = a0 + (p - (char *)Ra0);
812 void psxBios_toupper() { // 0x25
813 v0 = (s8)(a0 & 0xff);
814 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
818 void psxBios_tolower() { // 0x26
819 v0 = (s8)(a0 & 0xff);
820 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
824 void psxBios_bcopy() { // 0x27
825 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
827 if (a0 == 0 || a2 > 0x7FFFFFFF)
832 while ((s32)a2-- > 0) *p1++ = *p2++;
837 void psxBios_bzero() { // 0x28
838 char *p = (char *)Ra0;
840 /* Same as memset here (See memset below) */
841 if (a1 > 0x7FFFFFFF || a1 == 0)
852 while ((s32)a1-- > 0) *p++ = '\0';
857 void psxBios_bcmp() { // 0x29
858 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
860 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
862 while ((s32)a2-- > 0) {
863 if (*p1++ != *p2++) {
864 v0 = *p1 - *p2; // BUG: compare the NEXT byte
873 void psxBios_memcpy() { // 0x2a
874 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
876 if (a0 == 0 || a2 > 0x7FFFFFFF)
881 while ((s32)a2-- > 0) {
888 void psxBios_memset() { // 0x2b
889 char *p = (char *)Ra0;
891 if (a2 > 0x7FFFFFFF || a2 == 0)
902 while ((s32)a2-- > 0) *p++ = (char)a1;
907 void psxBios_memmove() { // 0x2c
908 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
910 if (a0 == 0 || a2 > 0x7FFFFFFF)
915 if (p2 <= p1 && p2 + a2 > p1) {
916 a2++; // BUG: copy one more byte here
919 while ((s32)a2-- > 0) *--p1 = *--p2;
921 while ((s32)a2-- > 0) *p1++ = *p2++;
926 void psxBios_memcmp() { // 0x2d
930 void psxBios_memchr() { // 0x2e
931 char *p = (char *)Ra0;
933 if (a0 == 0 || a2 > 0x7FFFFFFF)
939 while ((s32)a2-- > 0) {
940 if (*p++ != (s8)a1) continue;
941 v0 = a0 + (p - (char *)Ra0 - 1);
949 void psxBios_rand() { // 0x2f
950 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
951 v0 = (s >> 16) & 0x7fff;
952 psxMu32ref(0x9010) = SWAPu32(s);
956 void psxBios_srand() { // 0x30
957 psxMu32ref(0x9010) = SWAPu32(a0);
961 static u32 qscmpfunc, qswidth;
963 static inline int qscmp(char *a, char *b) {
966 a0 = sa0 + (a - (char *)PSXM(sa0));
967 a1 = sa0 + (b - (char *)PSXM(sa0));
969 softCall2(qscmpfunc);
975 static inline void qexchange(char *i, char *j) {
986 static inline void q3exchange(char *i, char *j, char *k) {
998 static void qsort_main(char *a, char *l) {
999 char *i, *j, *lp, *hp;
1004 if ((n = l - a) <= qswidth)
1006 n = qswidth * (n / (2 * qswidth));
1012 if ((c = qscmp(i, lp)) == 0) {
1013 qexchange(i, lp -= qswidth);
1024 if ((c = qscmp(hp, j)) == 0) {
1025 qexchange(hp += qswidth, j);
1030 q3exchange(i, hp += qswidth, j);
1044 if (lp - a >= l - hp) {
1045 qsort_main(hp + qswidth, l);
1054 q3exchange(j, lp -= qswidth, i);
1059 void psxBios_qsort() { // 0x31
1062 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1067 void psxBios_malloc() { // 0x33
1068 unsigned int *chunk, *newchunk = NULL;
1069 unsigned int dsize = 0, csize, cstat;
1072 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1074 if (!a0 || (!heap_size || !heap_addr)) {
1080 // scan through heap and combine free chunks of space
1083 while(chunk < heap_end) {
1084 // get size and status of actual chunk
1085 csize = ((u32)*chunk) & 0xfffffffc;
1086 cstat = ((u32)*chunk) & 1;
1088 // most probably broken heap descriptor
1089 // this fixes Burning Road
1092 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1097 // it's a free chunk
1102 colflag = 1; // let's begin a new collection of free memory
1104 else dsize += (csize+4); // add the new size including header
1106 // not a free chunk: did we start a collection ?
1108 if(colflag == 1) { // collection is over
1110 *newchunk = SWAP32(dsize | 1);
1115 chunk = (u32*)((uptr)chunk + csize + 4);
1117 // if neccessary free memory on end of heap
1119 *newchunk = SWAP32(dsize | 1);
1122 csize = ((u32)*chunk) & 0xfffffffc;
1123 cstat = ((u32)*chunk) & 1;
1124 dsize = (a0 + 3) & 0xfffffffc;
1126 // exit on uninitialized heap
1127 if (chunk == NULL) {
1128 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1134 // search an unused chunk that is big enough until the end of the heap
1135 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1136 chunk = (u32*)((uptr)chunk + csize + 4);
1138 // catch out of memory
1139 if(chunk >= heap_end) {
1140 printf("malloc %x,%x: Out of memory error!\n",
1146 csize = ((u32)*chunk) & 0xfffffffc;
1147 cstat = ((u32)*chunk) & 1;
1151 if(dsize == csize) {
1152 // chunk has same size
1153 *chunk &= 0xfffffffc;
1154 } else if (dsize > csize) {
1159 *chunk = SWAP32(dsize);
1160 newchunk = (u32*)((uptr)chunk + dsize + 4);
1161 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1164 // return pointer to allocated memory
1165 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1167 //printf ("malloc %x,%x\n", v0, a0);
1171 void psxBios_free() { // 0x34
1174 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1177 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1180 *(u32*)(Ra0-4) |= 1; // set chunk to free
1184 void psxBios_calloc() { // 0x37
1187 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1197 void psxBios_realloc() { // 0x38
1201 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1205 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1210 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1215 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1216 /* Note that it is not quite implemented this way here. */
1226 /* InitHeap(void *block , int n) */
1227 void psxBios_InitHeap() { // 0x39
1231 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1234 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1239 heap_addr = (u32 *)Ra0;
1241 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1242 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1243 //*heap_addr = SWAP32(size | 1);
1245 SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1250 void psxBios_getchar() { //0x3b
1251 v0 = getchar(); pc0 = ra;
1254 void psxBios_printf() { // 0x3f
1264 memcpy(save, psp, 4 * 4);
1265 psxMu32ref(sp) = SWAP32((u32)a0);
1266 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1267 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1268 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1280 tmp2[j++] = Ra0[i]; goto _start;
1282 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1293 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1297 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1303 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1305 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1307 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1309 *ptmp++ = Ra0[i]; break;
1320 memcpy(psp, save, 4 * 4);
1322 SysPrintf("%s", tmp);
1327 void psxBios_format() { // 0x41
1328 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1330 CreateMcd(Config.Mcd1);
1331 LoadMcd(1, Config.Mcd1);
1334 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1336 CreateMcd(Config.Mcd2);
1337 LoadMcd(2, Config.Mcd2);
1348 * long Load(char *name, struct EXEC *header);
1351 void psxBios_Load() { // 0x42
1356 PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1);
1360 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1361 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1369 * int Exec(struct EXEC *header , int argc , char **argv);
1372 void psxBios_Exec() { // 43
1373 EXEC *header = (EXEC*)Ra0;
1377 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1387 if (header->S_addr != 0) {
1388 tmp = header->S_addr + header->s_size;
1404 void psxBios_FlushCache() { // 44
1406 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1408 #ifdef ICACHE_EMULATION
1409 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1410 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1415 void psxBios_GPU_dw() { // 0x46
1420 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1423 GPU_writeData(0xa0000000);
1424 GPU_writeData((a1<<0x10)|(a0&0xffff));
1425 GPU_writeData((a3<<0x10)|(a2&0xffff));
1427 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1430 GPU_writeData(SWAPu32(*ptr++));
1436 void psxBios_mem2vram() { // 0x47
1439 GPU_writeData(0xa0000000);
1440 GPU_writeData((a1<<0x10)|(a0&0xffff));
1441 GPU_writeData((a3<<0x10)|(a2&0xffff));
1442 size = ((((a2 * a3) / 2) >> 4) << 16);
1443 GPU_writeStatus(0x04000002);
1444 psxHwWrite32(0x1f8010f4,0);
1445 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1446 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1447 psxHwWrite32(0x1f8010a4, size | 0x10);
1448 psxHwWrite32(0x1f8010a8,0x01000201);
1453 void psxBios_SendGPU() { // 0x48
1454 GPU_writeStatus(a0);
1459 void psxBios_GPU_cw() { // 0x49
1466 void psxBios_GPU_cwb() { // 0x4a
1467 u32 *ptr = (u32*)Ra0;
1472 GPU_writeData(SWAPu32(*ptr++));
1478 void psxBios_GPU_SendPackets() { //4b:
1480 GPU_writeStatus(0x04000002);
1481 psxHwWrite32(0x1f8010f4,0);
1482 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1483 psxHwWrite32(0x1f8010a0,a0);
1484 psxHwWrite32(0x1f8010a4,0);
1485 psxHwWrite32(0x1f8010a8,0x010000401);
1489 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1490 psxHwWrite32(0x1f8010a8,0x00000401);
1491 GPU_writeData(0x0400000);
1492 GPU_writeData(0x0200000);
1493 GPU_writeData(0x0100000);
1498 void psxBios_GPU_GetGPUStatus() { // 0x4d
1499 v0 = GPU_readStatus();
1505 void psxBios_LoadExec() { // 51
1506 EXEC *header = (EXEC*)PSXM(0xf000);
1510 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1512 s_addr = a1; s_size = a2;
1517 header->S_addr = s_addr;
1518 header->s_size = s_size;
1520 a0 = 0xf000; a1 = 0; a2 = 0;
1524 void psxBios__bu_init() { // 70
1526 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1529 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1530 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1535 void psxBios__96_init() { // 71
1537 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1543 void psxBios__96_remove() { // 72
1545 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1551 void psxBios_SetMem() { // 9f
1552 u32 new = psxHu32(0x1060);
1555 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1560 psxHu32ref(0x1060) = SWAP32(new);
1561 psxMu32ref(0x060) = a0;
1562 SysPrintf("Change effective memory : %d MBytes\n",a0);
1566 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1567 psxMu32ref(0x060) = a0;
1568 SysPrintf("Change effective memory : %d MBytes\n",a0);
1571 SysPrintf("Effective memory must be 2/8 MBytes\n");
1578 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1579 void psxBios_get_cd_status(void) //a6
1585 void psxBios__card_info() { // ab
1587 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1590 card_active_chan = a0;
1592 switch (card_active_chan)
1594 case 0x00: case 0x01: case 0x02: case 0x03:
1595 ret = Config.Mcd1[0] ? 0x2 : 0x8;
1597 case 0x10: case 0x11: case 0x12: case 0x13:
1598 ret = Config.Mcd2[0] ? 0x2 : 0x8;
1602 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1608 DeliverEvent(0x11, 0x2); // 0xf4000001, 0x0004
1609 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
1613 void psxBios__card_load() { // ac
1615 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1618 card_active_chan = a0;
1620 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1621 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1626 /* System calls B0 */
1628 void psxBios_SetRCnt() { // 02
1630 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1637 psxRcntWtarget(a0, a1);
1638 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1639 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1640 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1641 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1642 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1644 psxRcntWmode(a0, mode);
1649 void psxBios_GetRCnt() { // 03
1651 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1655 if (a0 != 3) v0 = psxRcntRcount(a0);
1660 void psxBios_StartRCnt() { // 04
1662 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1666 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1667 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1671 void psxBios_StopRCnt() { // 05
1673 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1677 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1678 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1682 void psxBios_ResetRCnt() { // 06
1684 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1689 psxRcntWmode(a0, 0);
1690 psxRcntWtarget(a0, 0);
1691 psxRcntWcount(a0, 0);
1697 /* gets ev for use with Event */
1699 ev = (a0 >> 24) & 0xf; \
1700 if (ev == 0xf) ev = 0x5; \
1704 /* gets spec for use with Event */
1708 case 0x0301: spec = 16; break; \
1709 case 0x0302: spec = 17; break; \
1711 for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1715 void psxBios_DeliverEvent() { // 07
1723 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1726 DeliverEvent(ev, spec);
1731 void psxBios_OpenEvent() { // 08
1739 PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1742 Event[ev][spec].status = EvStWAIT;
1743 Event[ev][spec].mode = a2;
1744 Event[ev][spec].fhandler = a3;
1746 v0 = ev | (spec << 8);
1750 void psxBios_CloseEvent() { // 09
1754 spec = (a0 >> 8) & 0xff;
1757 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1760 Event[ev][spec].status = EvStUNUSED;
1765 void psxBios_WaitEvent() { // 0a
1769 spec = (a0 >> 8) & 0xff;
1771 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1773 if (Event[ev][spec].status == EvStUNUSED)
1780 if (Event[ev][spec].status == EvStALREADY)
1782 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1783 if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE;
1793 void psxBios_TestEvent() { // 0b
1797 spec = (a0 >> 8) & 0xff;
1799 if (Event[ev][spec].status == EvStALREADY)
1801 if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE;
1810 PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1816 void psxBios_EnableEvent() { // 0c
1820 spec = (a0 >> 8) & 0xff;
1823 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1826 Event[ev][spec].status = EvStACTIVE;
1831 void psxBios_DisableEvent() { // 0d
1835 spec = (a0 >> 8) & 0xff;
1838 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1841 Event[ev][spec].status = EvStWAIT;
1847 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1850 void psxBios_OpenTh() { // 0e
1853 for (th=1; th<8; th++)
1855 if (Thread[th].status == 0) break;
1859 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1860 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1862 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1869 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1872 Thread[th].status = 1;
1873 Thread[th].func = a0;
1874 Thread[th].reg[29] = a1;
1875 Thread[th].reg[28] = a2;
1881 * int CloseTh(long thread);
1884 void psxBios_CloseTh() { // 0f
1888 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
1890 /* The return value is always 1 (even if the handle was already closed). */
1892 if (Thread[th].status != 0) {
1893 Thread[th].status = 0;
1900 * int ChangeTh(long thread);
1903 void psxBios_ChangeTh() { // 10
1907 // PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
1909 /* The return value is always 1. */
1911 if (Thread[th].status == 0 || CurThread == th) {
1914 if (Thread[CurThread].status == 2) {
1915 Thread[CurThread].status = 1;
1916 Thread[CurThread].func = ra;
1917 memcpy(Thread[CurThread].reg, psxRegs.GPR.r, 32*4);
1920 memcpy(psxRegs.GPR.r, Thread[th].reg, 32*4);
1921 pc0 = Thread[th].func;
1922 Thread[th].status = 2;
1927 void psxBios_InitPAD() { // 0x12
1929 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
1932 pad_buf1 = (char*)Ra0;
1934 pad_buf2 = (char*)Ra2;
1940 void psxBios_StartPAD() { // 13
1942 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
1945 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
1946 psxRegs.CP0.n.Status |= 0x401;
1950 void psxBios_StopPAD() { // 14
1952 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
1960 void psxBios_PAD_init() { // 15
1962 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
1964 if (!(a0 == 0x20000000 || a0 == 0x20000001))
1970 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
1971 pad_buf = (int *)Ra1;
1973 psxRegs.CP0.n.Status |= 0x401;
1978 void psxBios_PAD_dr() { // 16
1980 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
1986 void psxBios_ReturnFromException() { // 17
1989 pc0 = psxRegs.CP0.n.EPC;
1991 if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;
1993 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
1994 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
1997 void psxBios_ResetEntryInt() { // 18
1999 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2006 void psxBios_HookEntryInt() { // 19
2008 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
2011 jmp_int = (u32*)Ra0;
2015 void psxBios_UnDeliverEvent() { // 0x20
2023 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2026 if (Event[ev][spec].status == EvStALREADY &&
2027 Event[ev][spec].mode == EvMdNOINTR)
2028 Event[ev][spec].status = EvStACTIVE;
2033 char ffile[64], *pfile;
2035 static void buopen(int mcd, char *ptr, char *cfg)
2040 strcpy(FDesc[1 + mcd].name, Ra0+5);
2041 FDesc[1 + mcd].offset = 0;
2042 FDesc[1 + mcd].mode = a1;
2044 for (i=1; i<16; i++) {
2046 if ((*fptr & 0xF0) != 0x50) continue;
2047 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2048 FDesc[1 + mcd].mcfile = i;
2049 SysPrintf("open %s\n", fptr+0xa);
2053 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2055 for (i=1; i<16; i++) {
2056 int j, xor, nblk = a1 >> 16;
2060 if ((*fptr & 0xF0) != 0xa0) continue;
2062 FDesc[1 + mcd].mcfile = i;
2065 fptr[5] = 0x20 * nblk;
2068 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2069 pptr = fptr2 = (u8 *)fptr;
2070 for(j=2; j<=nblk; j++) {
2072 for(i++; i<16; i++) {
2075 memset(fptr2, 0, 128);
2076 fptr2[0] = j < nblk ? 0x52 : 0x53;
2079 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2084 /* shouldn't this return ENOSPC if i == 16? */
2086 pptr[8] = pptr[9] = 0xff;
2087 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2089 SysPrintf("openC %s %d\n", ptr, nblk);
2091 /* just go ahead and resave them all */
2092 SaveMcd(cfg, ptr, 128, 128 * 15);
2095 /* shouldn't this return ENOSPC if i == 16? */
2100 * int open(char *name , int mode);
2103 void psxBios_open() { // 0x32
2107 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2113 if (!strncmp(pa0, "bu00", 4)) {
2114 buopen(1, Mcd1Data, Config.Mcd1);
2117 if (!strncmp(pa0, "bu10", 4)) {
2118 buopen(2, Mcd2Data, Config.Mcd2);
2126 * int lseek(int fd , int offset , int whence);
2129 void psxBios_lseek() { // 0x33
2131 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2136 FDesc[a0].offset = a1;
2138 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2139 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2143 FDesc[a0].offset+= a1;
2144 v0 = FDesc[a0].offset;
2153 * int read(int fd , void *buf , int nbytes);
2156 void psxBios_read() { // 0x34
2161 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2168 case 2: buread(pa1, 1, a2); break;
2169 case 3: buread(pa1, 2, a2); break;
2177 * int write(int fd , void *buf , int nbytes);
2180 void psxBios_write() { // 0x35/0x03
2185 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2194 if (a0 == 1) { // stdout
2199 SysPrintf("%c", *ptr++); a2--;
2205 case 2: buwrite(pa1, 1, a2); break;
2206 case 3: buwrite(pa1, 2, a2); break;
2213 * int close(int fd);
2216 void psxBios_close() { // 0x36
2218 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2225 void psxBios_putchar() { // 3d
2226 SysPrintf("%c", (char)a0);
2230 void psxBios_puts() { // 3e/3f
2231 SysPrintf("%s", Ra0);
2236 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2237 * We want to mimic the PSX's behaviour in this case for bufile. */
2238 static size_t strlen_internal(char* p)
2240 size_t size_of_array = 0;
2241 while (*p++) size_of_array++;
2242 return size_of_array;
2245 #define bufile(mcd) { \
2246 size_t size_of_name = strlen_internal(dir->name); \
2247 while (nfile < 16) { \
2250 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2252 if ((*ptr & 0xF0) != 0x50) continue; \
2253 /* Bug link files show up as free block. */ \
2254 if (!ptr[0xa]) continue; \
2256 if (pfile[0] == 0) { \
2257 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2258 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2259 } else for (i=0; i<20; i++) { \
2260 if (pfile[i] == ptr[i]) { \
2261 dir->name[i] = ptr[i]; continue; } \
2262 if (pfile[i] == '?') { \
2263 dir->name[i] = ptr[i]; continue; } \
2264 if (pfile[i] == '*') { \
2265 strcpy(dir->name+i, ptr+i); break; } \
2268 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2269 if (match == 0) { continue; } \
2277 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2280 void psxBios_firstfile() { // 42
2281 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2288 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2297 if (!strncmp(pa0, "bu00", 4)) {
2298 // firstfile() calls _card_read() internally, so deliver it's event
2299 DeliverEvent(0x11, 0x2);
2301 } else if (!strncmp(pa0, "bu10", 4)) {
2302 // firstfile() calls _card_read() internally, so deliver it's event
2303 DeliverEvent(0x11, 0x2);
2312 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2315 void psxBios_nextfile() { // 43
2316 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2322 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2327 if (!strncmp(ffile, "bu00", 4)) {
2331 if (!strncmp(ffile, "bu10", 4)) {
2338 #define burename(mcd) { \
2339 for (i=1; i<16; i++) { \
2340 int namelen, j, xor = 0; \
2341 ptr = Mcd##mcd##Data + 128 * i; \
2342 if ((*ptr & 0xF0) != 0x50) continue; \
2343 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2344 namelen = strlen(Ra1+5); \
2345 memcpy(ptr+0xa, Ra1+5, namelen); \
2346 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2347 for (j=0; j<127; j++) xor^= ptr[j]; \
2349 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2356 * int rename(char *old, char *new);
2359 void psxBios_rename() { // 44
2366 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2372 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2376 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2385 #define budelete(mcd) { \
2386 for (i=1; i<16; i++) { \
2387 ptr = Mcd##mcd##Data + 128 * i; \
2388 if ((*ptr & 0xF0) != 0x50) continue; \
2389 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2390 *ptr = (*ptr & 0xf) | 0xA0; \
2391 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2392 SysPrintf("delete %s\n", ptr+0xa); \
2399 * int delete(char *name);
2402 void psxBios_delete() { // 45
2408 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2414 if (!strncmp(pa0, "bu00", 4)) {
2418 if (!strncmp(pa0, "bu10", 4)) {
2426 void psxBios_InitCARD() { // 4a
2428 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2436 void psxBios_StartCARD() { // 4b
2438 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2441 if (CardState == 0) CardState = 1;
2446 void psxBios_StopCARD() { // 4c
2448 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2451 if (CardState == 1) CardState = 0;
2456 void psxBios__card_write() { // 0x4e
2461 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2464 Function also accepts sector 400h (a bug).
2465 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2469 /* Invalid sectors */
2473 card_active_chan = a0;
2478 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2479 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2481 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2482 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2486 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2487 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2492 void psxBios__card_read() { // 0x4f
2497 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2500 Function also accepts sector 400h (a bug).
2501 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2505 /* Invalid sectors */
2509 card_active_chan = a0;
2514 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2516 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2520 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2521 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2526 void psxBios__new_card() { // 0x50
2528 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2534 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2535 void psxBios__get_error(void) // 55
2541 void psxBios_Krom2RawAdd() { // 0x51
2544 const u32 table_8140[][2] = {
2545 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2546 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2547 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2548 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2549 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2550 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2551 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2552 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2553 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2557 const u32 table_889f[][2] = {
2558 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2559 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2560 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2561 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2562 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2563 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2564 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2565 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2569 if (a0 >= 0x8140 && a0 <= 0x84be) {
2570 while (table_8140[i][0] <= a0) i++;
2571 a0 -= table_8140[i - 1][0];
2572 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2573 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2574 while (table_889f[i][0] <= a0) i++;
2575 a0 -= table_889f[i - 1][0];
2576 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2584 void psxBios_GetC0Table() { // 56
2586 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2589 v0 = 0x674; pc0 = ra;
2592 void psxBios_GetB0Table() { // 57
2594 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2597 v0 = 0x874; pc0 = ra;
2600 void psxBios__card_chan() { // 0x58
2602 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2605 v0 = card_active_chan;
2609 void psxBios_ChangeClearPad() { // 5b
2611 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2617 void psxBios__card_status() { // 5c
2619 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2622 v0 = card_active_chan;
2626 void psxBios__card_wait() { // 5d
2628 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2635 /* System calls C0 */
2638 * int SysEnqIntRP(int index , long *queue);
2641 void psxBios_SysEnqIntRP() { // 02
2643 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2652 * int SysDeqIntRP(int index , long *queue);
2655 void psxBios_SysDeqIntRP() { // 03
2657 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2665 void psxBios_ChangeClearRCnt() { // 0a
2669 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2672 ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2676 // psxRegs.CP0.n.Status|= 0x404;
2680 void psxBios_dummy() {
2682 PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2687 void (*biosA0[256])();
2688 void (*biosB0[256])();
2689 void (*biosC0[256])();
2691 #include "sjisfont.h"
2693 void psxBiosInit() {
2699 for(i = 0; i < 256; i++) {
2704 biosA0[0x3e] = psxBios_puts;
2705 biosA0[0x3f] = psxBios_printf;
2707 biosB0[0x3d] = psxBios_putchar;
2708 biosB0[0x3f] = psxBios_puts;
2710 if (!Config.HLE) return;
2712 for(i = 0; i < 256; i++) {
2713 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2714 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2715 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2718 biosA0[0x00] = psxBios_open;
2719 biosA0[0x01] = psxBios_lseek;
2720 biosA0[0x02] = psxBios_read;
2721 biosA0[0x03] = psxBios_write;
2722 biosA0[0x04] = psxBios_close;
2723 //biosA0[0x05] = psxBios_ioctl;
2724 //biosA0[0x06] = psxBios_exit;
2725 //biosA0[0x07] = psxBios_sys_a0_07;
2726 biosA0[0x08] = psxBios_getc;
2727 biosA0[0x09] = psxBios_putc;
2728 biosA0[0x0a] = psxBios_todigit;
2729 //biosA0[0x0b] = psxBios_atof;
2730 //biosA0[0x0c] = psxBios_strtoul;
2731 //biosA0[0x0d] = psxBios_strtol;
2732 biosA0[0x0e] = psxBios_abs;
2733 biosA0[0x0f] = psxBios_labs;
2734 biosA0[0x10] = psxBios_atoi;
2735 biosA0[0x11] = psxBios_atol;
2736 //biosA0[0x12] = psxBios_atob;
2737 biosA0[0x13] = psxBios_setjmp;
2738 biosA0[0x14] = psxBios_longjmp;
2739 biosA0[0x15] = psxBios_strcat;
2740 biosA0[0x16] = psxBios_strncat;
2741 biosA0[0x17] = psxBios_strcmp;
2742 biosA0[0x18] = psxBios_strncmp;
2743 biosA0[0x19] = psxBios_strcpy;
2744 biosA0[0x1a] = psxBios_strncpy;
2745 biosA0[0x1b] = psxBios_strlen;
2746 biosA0[0x1c] = psxBios_index;
2747 biosA0[0x1d] = psxBios_rindex;
2748 biosA0[0x1e] = psxBios_strchr;
2749 biosA0[0x1f] = psxBios_strrchr;
2750 biosA0[0x20] = psxBios_strpbrk;
2751 biosA0[0x21] = psxBios_strspn;
2752 biosA0[0x22] = psxBios_strcspn;
2753 biosA0[0x23] = psxBios_strtok;
2754 biosA0[0x24] = psxBios_strstr;
2755 biosA0[0x25] = psxBios_toupper;
2756 biosA0[0x26] = psxBios_tolower;
2757 biosA0[0x27] = psxBios_bcopy;
2758 biosA0[0x28] = psxBios_bzero;
2759 biosA0[0x29] = psxBios_bcmp;
2760 biosA0[0x2a] = psxBios_memcpy;
2761 biosA0[0x2b] = psxBios_memset;
2762 biosA0[0x2c] = psxBios_memmove;
2763 biosA0[0x2d] = psxBios_memcmp;
2764 biosA0[0x2e] = psxBios_memchr;
2765 biosA0[0x2f] = psxBios_rand;
2766 biosA0[0x30] = psxBios_srand;
2767 biosA0[0x31] = psxBios_qsort;
2768 //biosA0[0x32] = psxBios_strtod;
2769 biosA0[0x33] = psxBios_malloc;
2770 biosA0[0x34] = psxBios_free;
2771 //biosA0[0x35] = psxBios_lsearch;
2772 //biosA0[0x36] = psxBios_bsearch;
2773 biosA0[0x37] = psxBios_calloc;
2774 biosA0[0x38] = psxBios_realloc;
2775 biosA0[0x39] = psxBios_InitHeap;
2776 //biosA0[0x3a] = psxBios__exit;
2777 biosA0[0x3b] = psxBios_getchar;
2778 biosA0[0x3c] = psxBios_putchar;
2779 //biosA0[0x3d] = psxBios_gets;
2780 //biosA0[0x40] = psxBios_sys_a0_40;
2781 //biosA0[0x41] = psxBios_LoadTest;
2782 biosA0[0x42] = psxBios_Load;
2783 biosA0[0x43] = psxBios_Exec;
2784 biosA0[0x44] = psxBios_FlushCache;
2785 //biosA0[0x45] = psxBios_InstallInterruptHandler;
2786 biosA0[0x46] = psxBios_GPU_dw;
2787 biosA0[0x47] = psxBios_mem2vram;
2788 biosA0[0x48] = psxBios_SendGPU;
2789 biosA0[0x49] = psxBios_GPU_cw;
2790 biosA0[0x4a] = psxBios_GPU_cwb;
2791 biosA0[0x4b] = psxBios_GPU_SendPackets;
2792 biosA0[0x4c] = psxBios_sys_a0_4c;
2793 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2794 //biosA0[0x4e] = psxBios_GPU_sync;
2795 //biosA0[0x4f] = psxBios_sys_a0_4f;
2796 //biosA0[0x50] = psxBios_sys_a0_50;
2797 biosA0[0x51] = psxBios_LoadExec;
2798 //biosA0[0x52] = psxBios_GetSysSp;
2799 //biosA0[0x53] = psxBios_sys_a0_53;
2800 //biosA0[0x54] = psxBios__96_init_a54;
2801 //biosA0[0x55] = psxBios__bu_init_a55;
2802 //biosA0[0x56] = psxBios__96_remove_a56;
2803 //biosA0[0x57] = psxBios_sys_a0_57;
2804 //biosA0[0x58] = psxBios_sys_a0_58;
2805 //biosA0[0x59] = psxBios_sys_a0_59;
2806 //biosA0[0x5a] = psxBios_sys_a0_5a;
2807 //biosA0[0x5b] = psxBios_dev_tty_init;
2808 //biosA0[0x5c] = psxBios_dev_tty_open;
2809 //biosA0[0x5d] = psxBios_sys_a0_5d;
2810 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2811 //biosA0[0x5f] = psxBios_dev_cd_open;
2812 //biosA0[0x60] = psxBios_dev_cd_read;
2813 //biosA0[0x61] = psxBios_dev_cd_close;
2814 //biosA0[0x62] = psxBios_dev_cd_firstfile;
2815 //biosA0[0x63] = psxBios_dev_cd_nextfile;
2816 //biosA0[0x64] = psxBios_dev_cd_chdir;
2817 //biosA0[0x65] = psxBios_dev_card_open;
2818 //biosA0[0x66] = psxBios_dev_card_read;
2819 //biosA0[0x67] = psxBios_dev_card_write;
2820 //biosA0[0x68] = psxBios_dev_card_close;
2821 //biosA0[0x69] = psxBios_dev_card_firstfile;
2822 //biosA0[0x6a] = psxBios_dev_card_nextfile;
2823 //biosA0[0x6b] = psxBios_dev_card_erase;
2824 //biosA0[0x6c] = psxBios_dev_card_undelete;
2825 //biosA0[0x6d] = psxBios_dev_card_format;
2826 //biosA0[0x6e] = psxBios_dev_card_rename;
2827 //biosA0[0x6f] = psxBios_dev_card_6f;
2828 biosA0[0x70] = psxBios__bu_init;
2829 biosA0[0x71] = psxBios__96_init;
2830 biosA0[0x72] = psxBios__96_remove;
2831 //biosA0[0x73] = psxBios_sys_a0_73;
2832 //biosA0[0x74] = psxBios_sys_a0_74;
2833 //biosA0[0x75] = psxBios_sys_a0_75;
2834 //biosA0[0x76] = psxBios_sys_a0_76;
2835 //biosA0[0x77] = psxBios_sys_a0_77;
2836 //biosA0[0x78] = psxBios__96_CdSeekL;
2837 //biosA0[0x79] = psxBios_sys_a0_79;
2838 //biosA0[0x7a] = psxBios_sys_a0_7a;
2839 //biosA0[0x7b] = psxBios_sys_a0_7b;
2840 //biosA0[0x7c] = psxBios__96_CdGetStatus;
2841 //biosA0[0x7d] = psxBios_sys_a0_7d;
2842 //biosA0[0x7e] = psxBios__96_CdRead;
2843 //biosA0[0x7f] = psxBios_sys_a0_7f;
2844 //biosA0[0x80] = psxBios_sys_a0_80;
2845 //biosA0[0x81] = psxBios_sys_a0_81;
2846 //biosA0[0x82] = psxBios_sys_a0_82;
2847 //biosA0[0x83] = psxBios_sys_a0_83;
2848 //biosA0[0x84] = psxBios_sys_a0_84;
2849 //biosA0[0x85] = psxBios__96_CdStop;
2850 //biosA0[0x86] = psxBios_sys_a0_86;
2851 //biosA0[0x87] = psxBios_sys_a0_87;
2852 //biosA0[0x88] = psxBios_sys_a0_88;
2853 //biosA0[0x89] = psxBios_sys_a0_89;
2854 //biosA0[0x8a] = psxBios_sys_a0_8a;
2855 //biosA0[0x8b] = psxBios_sys_a0_8b;
2856 //biosA0[0x8c] = psxBios_sys_a0_8c;
2857 //biosA0[0x8d] = psxBios_sys_a0_8d;
2858 //biosA0[0x8e] = psxBios_sys_a0_8e;
2859 //biosA0[0x8f] = psxBios_sys_a0_8f;
2860 //biosA0[0x90] = psxBios_sys_a0_90;
2861 //biosA0[0x91] = psxBios_sys_a0_91;
2862 //biosA0[0x92] = psxBios_sys_a0_92;
2863 //biosA0[0x93] = psxBios_sys_a0_93;
2864 //biosA0[0x94] = psxBios_sys_a0_94;
2865 //biosA0[0x95] = psxBios_sys_a0_95;
2866 //biosA0[0x96] = psxBios_AddCDROMDevice;
2867 //biosA0[0x97] = psxBios_AddMemCardDevide;
2868 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2869 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2870 //biosA0[0x9a] = psxBios_sys_a0_9a;
2871 //biosA0[0x9b] = psxBios_sys_a0_9b;
2872 //biosA0[0x9c] = psxBios_SetConf;
2873 //biosA0[0x9d] = psxBios_GetConf;
2874 //biosA0[0x9e] = psxBios_sys_a0_9e;
2875 biosA0[0x9f] = psxBios_SetMem;
2876 //biosA0[0xa0] = psxBios__boot;
2877 //biosA0[0xa1] = psxBios_SystemError;
2878 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2879 //biosA0[0xa3] = psxBios_DequeueCdIntr;
2880 //biosA0[0xa4] = psxBios_sys_a0_a4;
2881 //biosA0[0xa5] = psxBios_ReadSector;
2882 biosA0[0xa6] = psxBios_get_cd_status;
2883 //biosA0[0xa7] = psxBios_bufs_cb_0;
2884 //biosA0[0xa8] = psxBios_bufs_cb_1;
2885 //biosA0[0xa9] = psxBios_bufs_cb_2;
2886 //biosA0[0xaa] = psxBios_bufs_cb_3;
2887 biosA0[0xab] = psxBios__card_info;
2888 biosA0[0xac] = psxBios__card_load;
2889 //biosA0[0axd] = psxBios__card_auto;
2890 //biosA0[0xae] = psxBios_bufs_cd_4;
2891 //biosA0[0xaf] = psxBios_sys_a0_af;
2892 //biosA0[0xb0] = psxBios_sys_a0_b0;
2893 //biosA0[0xb1] = psxBios_sys_a0_b1;
2894 //biosA0[0xb2] = psxBios_do_a_long_jmp
2895 //biosA0[0xb3] = psxBios_sys_a0_b3;
2896 //biosA0[0xb4] = psxBios_sub_function;
2897 //*******************B0 CALLS****************************
2898 //biosB0[0x00] = psxBios_SysMalloc;
2899 //biosB0[0x01] = psxBios_sys_b0_01;
2900 biosB0[0x02] = psxBios_SetRCnt;
2901 biosB0[0x03] = psxBios_GetRCnt;
2902 biosB0[0x04] = psxBios_StartRCnt;
2903 biosB0[0x05] = psxBios_StopRCnt;
2904 biosB0[0x06] = psxBios_ResetRCnt;
2905 biosB0[0x07] = psxBios_DeliverEvent;
2906 biosB0[0x08] = psxBios_OpenEvent;
2907 biosB0[0x09] = psxBios_CloseEvent;
2908 biosB0[0x0a] = psxBios_WaitEvent;
2909 biosB0[0x0b] = psxBios_TestEvent;
2910 biosB0[0x0c] = psxBios_EnableEvent;
2911 biosB0[0x0d] = psxBios_DisableEvent;
2912 biosB0[0x0e] = psxBios_OpenTh;
2913 biosB0[0x0f] = psxBios_CloseTh;
2914 biosB0[0x10] = psxBios_ChangeTh;
2915 //biosB0[0x11] = psxBios_psxBios_b0_11;
2916 biosB0[0x12] = psxBios_InitPAD;
2917 biosB0[0x13] = psxBios_StartPAD;
2918 biosB0[0x14] = psxBios_StopPAD;
2919 biosB0[0x15] = psxBios_PAD_init;
2920 biosB0[0x16] = psxBios_PAD_dr;
2921 biosB0[0x17] = psxBios_ReturnFromException;
2922 biosB0[0x18] = psxBios_ResetEntryInt;
2923 biosB0[0x19] = psxBios_HookEntryInt;
2924 //biosB0[0x1a] = psxBios_sys_b0_1a;
2925 //biosB0[0x1b] = psxBios_sys_b0_1b;
2926 //biosB0[0x1c] = psxBios_sys_b0_1c;
2927 //biosB0[0x1d] = psxBios_sys_b0_1d;
2928 //biosB0[0x1e] = psxBios_sys_b0_1e;
2929 //biosB0[0x1f] = psxBios_sys_b0_1f;
2930 biosB0[0x20] = psxBios_UnDeliverEvent;
2931 //biosB0[0x21] = psxBios_sys_b0_21;
2932 //biosB0[0x22] = psxBios_sys_b0_22;
2933 //biosB0[0x23] = psxBios_sys_b0_23;
2934 //biosB0[0x24] = psxBios_sys_b0_24;
2935 //biosB0[0x25] = psxBios_sys_b0_25;
2936 //biosB0[0x26] = psxBios_sys_b0_26;
2937 //biosB0[0x27] = psxBios_sys_b0_27;
2938 //biosB0[0x28] = psxBios_sys_b0_28;
2939 //biosB0[0x29] = psxBios_sys_b0_29;
2940 //biosB0[0x2a] = psxBios_sys_b0_2a;
2941 //biosB0[0x2b] = psxBios_sys_b0_2b;
2942 //biosB0[0x2c] = psxBios_sys_b0_2c;
2943 //biosB0[0x2d] = psxBios_sys_b0_2d;
2944 //biosB0[0x2e] = psxBios_sys_b0_2e;
2945 //biosB0[0x2f] = psxBios_sys_b0_2f;
2946 //biosB0[0x30] = psxBios_sys_b0_30;
2947 //biosB0[0x31] = psxBios_sys_b0_31;
2948 biosB0[0x32] = psxBios_open;
2949 biosB0[0x33] = psxBios_lseek;
2950 biosB0[0x34] = psxBios_read;
2951 biosB0[0x35] = psxBios_write;
2952 biosB0[0x36] = psxBios_close;
2953 //biosB0[0x37] = psxBios_ioctl;
2954 //biosB0[0x38] = psxBios_exit;
2955 //biosB0[0x39] = psxBios_sys_b0_39;
2956 //biosB0[0x3a] = psxBios_getc;
2957 //biosB0[0x3b] = psxBios_putc;
2958 biosB0[0x3c] = psxBios_getchar;
2959 //biosB0[0x3e] = psxBios_gets;
2960 //biosB0[0x40] = psxBios_cd;
2961 biosB0[0x41] = psxBios_format;
2962 biosB0[0x42] = psxBios_firstfile;
2963 biosB0[0x43] = psxBios_nextfile;
2964 biosB0[0x44] = psxBios_rename;
2965 biosB0[0x45] = psxBios_delete;
2966 //biosB0[0x46] = psxBios_undelete;
2967 //biosB0[0x47] = psxBios_AddDevice;
2968 //biosB0[0x48] = psxBios_RemoteDevice;
2969 //biosB0[0x49] = psxBios_PrintInstalledDevices;
2970 biosB0[0x4a] = psxBios_InitCARD;
2971 biosB0[0x4b] = psxBios_StartCARD;
2972 biosB0[0x4c] = psxBios_StopCARD;
2973 //biosB0[0x4d] = psxBios_sys_b0_4d;
2974 biosB0[0x4e] = psxBios__card_write;
2975 biosB0[0x4f] = psxBios__card_read;
2976 biosB0[0x50] = psxBios__new_card;
2977 biosB0[0x51] = psxBios_Krom2RawAdd;
2978 //biosB0[0x52] = psxBios_sys_b0_52;
2979 //biosB0[0x53] = psxBios_sys_b0_53;
2980 //biosB0[0x54] = psxBios__get_errno;
2981 biosB0[0x55] = psxBios__get_error;
2982 biosB0[0x56] = psxBios_GetC0Table;
2983 biosB0[0x57] = psxBios_GetB0Table;
2984 biosB0[0x58] = psxBios__card_chan;
2985 //biosB0[0x59] = psxBios_sys_b0_59;
2986 //biosB0[0x5a] = psxBios_sys_b0_5a;
2987 biosB0[0x5b] = psxBios_ChangeClearPad;
2988 biosB0[0x5c] = psxBios__card_status;
2989 biosB0[0x5d] = psxBios__card_wait;
2990 //*******************C0 CALLS****************************
2991 //biosC0[0x00] = psxBios_InitRCnt;
2992 //biosC0[0x01] = psxBios_InitException;
2993 biosC0[0x02] = psxBios_SysEnqIntRP;
2994 biosC0[0x03] = psxBios_SysDeqIntRP;
2995 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
2996 //biosC0[0x05] = psxBios_get_free_TCB_slot;
2997 //biosC0[0x06] = psxBios_ExceptionHandler;
2998 //biosC0[0x07] = psxBios_InstallExeptionHandler;
2999 //biosC0[0x08] = psxBios_SysInitMemory;
3000 //biosC0[0x09] = psxBios_SysInitKMem;
3001 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3002 //biosC0[0x0b] = psxBios_SystemError;
3003 //biosC0[0x0c] = psxBios_InitDefInt;
3004 //biosC0[0x0d] = psxBios_sys_c0_0d;
3005 //biosC0[0x0e] = psxBios_sys_c0_0e;
3006 //biosC0[0x0f] = psxBios_sys_c0_0f;
3007 //biosC0[0x10] = psxBios_sys_c0_10;
3008 //biosC0[0x11] = psxBios_sys_c0_11;
3009 //biosC0[0x12] = psxBios_InstallDevices;
3010 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3011 //biosC0[0x14] = psxBios_sys_c0_14;
3012 //biosC0[0x15] = psxBios__cdevinput;
3013 //biosC0[0x16] = psxBios__cdevscan;
3014 //biosC0[0x17] = psxBios__circgetc;
3015 //biosC0[0x18] = psxBios__circputc;
3016 //biosC0[0x19] = psxBios_ioabort;
3017 //biosC0[0x1a] = psxBios_sys_c0_1a
3018 //biosC0[0x1b] = psxBios_KernelRedirect;
3019 //biosC0[0x1c] = psxBios_PatchAOTable;
3020 //************** THE END ***************************************
3023 size = sizeof(EvCB) * 32;
3024 Event = (void *)&psxR[base]; base += size * 6;
3025 memset(Event, 0, size * 6);
3028 RcEV = Event + 32 * 2;
3029 UeEV = Event + 32 * 3;
3030 SwEV = Event + 32 * 4;
3031 ThEV = Event + 32 * 5;
3033 ptr = (u32 *)&psxM[0x0874]; // b0 table
3034 ptr[0] = SWAPu32(0x4c54 - 0x884);
3036 ptr = (u32 *)&psxM[0x0674]; // c0 table
3037 ptr[6] = SWAPu32(0xc80);
3039 memset(SysIntRP, 0, sizeof(SysIntRP));
3040 memset(Thread, 0, sizeof(Thread));
3041 Thread[0].status = 2; // main thread
3048 pad_buf1len = pad_buf2len = 0;
3054 memset(FDesc, 0, sizeof(FDesc));
3055 card_active_chan = 0;
3057 psxMu32ref(0x0150) = SWAPu32(0x160);
3058 psxMu32ref(0x0154) = SWAPu32(0x320);
3059 psxMu32ref(0x0160) = SWAPu32(0x248);
3060 strcpy((char *)&psxM[0x248], "bu");
3061 /* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3062 psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3063 psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3064 psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3065 psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3068 psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
3069 /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
3070 Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3071 //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
3072 psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3073 psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3074 psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3075 psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3076 psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3077 psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3078 psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3079 psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3081 // initial stack pointer for BIOS interrupt
3082 psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3085 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3088 len = 0x80000 - 0x66000;
3089 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3090 len = 0x80000 - 0x69d68;
3091 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3094 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3096 hleSoftCall = FALSE;
3098 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3099 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3100 Here are some examples of games not working with this fix in place :
3101 R-type won't get past the Irem logo if not implemented.
3102 Crash Team Racing will softlock after the Sony logo.
3105 psxMu32ref(0x0000) = SWAPu32(0x00000003);
3107 But overwritten by 00000003h after soon.
3108 psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3110 psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3111 psxMu32ref(0x0008) = SWAPu32(0x08000403);
3112 psxMu32ref(0x000C) = SWAPu32(0x00000000);
3115 void psxBiosShutdown() {
3118 #define psxBios_PADpoll(pad) { \
3119 PAD##pad##_startPoll(pad); \
3120 pad_buf##pad[0] = 0; \
3121 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3122 if (!(pad_buf##pad[1] & 0x0f)) { \
3125 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3127 PAD##pad##_poll(0); \
3129 while (bufcount--) { \
3130 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3134 void biosInterrupt() {
3137 // if (psxHu32(0x1070) & 0x1) { // Vsync
3138 if (pad_buf != NULL) {
3139 u32 *buf = (u32*)pad_buf;
3141 if (!Config.UseNet) {
3143 if (PAD1_poll(0x42) == 0x23) {
3145 *buf = PAD1_poll(0) << 8;
3146 *buf |= PAD1_poll(0);
3148 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3149 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3152 *buf = PAD1_poll(0) << 8;
3153 *buf|= PAD1_poll(0);
3157 if (PAD2_poll(0x42) == 0x23) {
3159 *buf |= PAD2_poll(0) << 24;
3160 *buf |= PAD2_poll(0) << 16;
3162 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3163 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3166 *buf |= PAD2_poll(0) << 24;
3167 *buf |= PAD2_poll(0) << 16;
3175 data = PAD1_poll(0) << 8;
3176 data |= PAD1_poll(0);
3178 if (NET_sendPadData(&data, 2) == -1)
3181 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3183 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3187 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3190 if (NET_sendPadData(pad_buf1, i) == -1)
3193 if (NET_recvPadData(pad_buf1, 1) == -1)
3195 if (NET_recvPadData(pad_buf2, 2) == -1)
3209 if (psxHu32(0x1070) & 0x1) { // Vsync
3210 if (RcEV[3][1].status == EvStACTIVE) {
3211 softCall(RcEV[3][1].fhandler);
3212 // hwWrite32(0x1f801070, ~(1));
3216 if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3219 for (i = 0; i < 3; i++) {
3220 if (psxHu32(0x1070) & (1 << (i + 4))) {
3221 if (RcEV[i][1].status == EvStACTIVE) {
3222 softCall(RcEV[i][1].fhandler);
3224 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3230 void psxBiosException() {
3233 switch (psxRegs.CP0.n.Cause & 0x3c) {
3234 case 0x00: // Interrupt
3235 interrupt_r26=psxRegs.CP0.n.EPC;
3237 // PSXCPU_LOG("interrupt\n");
3241 sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3245 for (i = 0; i < 8; i++) {
3247 u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3254 if (jmp_int != NULL) {
3257 psxHwWrite32(0x1f801070, 0xffffffff);
3262 for (i = 0; i < 8; i++) // s0-s7
3263 psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3270 psxHwWrite16(0x1f801070, 0);
3273 case 0x20: // Syscall
3275 PSXCPU_LOG("syscall exp %x\n", a0);
3278 case 1: // EnterCritical - disable irq's
3279 /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3280 v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3281 psxRegs.CP0.n.Status &= ~0x404;
3284 case 2: // ExitCritical - enable irq's
3285 psxRegs.CP0.n.Status |= 0x404;
3287 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3291 pc0 = psxRegs.CP0.n.EPC + 4;
3293 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3294 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3299 PSXCPU_LOG("unknown bios exception!\n");
3304 pc0 = psxRegs.CP0.n.EPC;
3305 if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3307 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3308 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3311 #define bfreeze(ptr, size) { \
3312 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3313 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3317 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3318 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3320 #define bfreezepsxMptr(ptr, type) { \
3322 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3323 else psxRu32ref(base) = 0; \
3325 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3326 else (ptr) = NULL; \
3328 base += sizeof(u32); \
3331 void psxBiosFreeze(int Mode) {
3334 bfreezepsxMptr(jmp_int, u32);
3335 bfreezepsxMptr(pad_buf, int);
3336 bfreezepsxMptr(pad_buf1, char);
3337 bfreezepsxMptr(pad_buf2, char);
3338 bfreezepsxMptr(heap_addr, u32);
3339 bfreezel(&pad_buf1len);
3340 bfreezel(&pad_buf2len);
3343 bfreezel(&CardState);
3345 bfreezel(&CurThread);
3347 bfreezel(&card_active_chan);
3348 bfreezel(&pad_stopped);
3349 bfreezel(&heap_size);