1 /***************************************************************************
2 * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3 * dmitrysmagin, senquack *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
19 ***************************************************************************/
21 /* Gameblabla 2018-2019 :
22 * Numerous changes to bios calls as well as improvements in order to conform to nocash's findings
23 * for the PSX bios calls. Thanks senquack for helping out with some of the changes
24 * and helping to spot issues and refine my patches.
28 * Internal simulated HLE BIOS.
31 // TODO: implement all system calls, count the exact CPU cycles of system calls.
39 #define SysPrintf if (Config.PsxOut) printf
41 char *biosA0n[256] = {
43 "open", "lseek", "read", "write",
44 "close", "ioctl", "exit", "sys_a0_07",
45 "getc", "putc", "todigit", "atof",
46 "strtoul", "strtol", "abs", "labs",
48 "atoi", "atol", "atob", "setjmp",
49 "longjmp", "strcat", "strncat", "strcmp",
50 "strncmp", "strcpy", "strncpy", "strlen",
51 "index", "rindex", "strchr", "strrchr",
53 "strpbrk", "strspn", "strcspn", "strtok",
54 "strstr", "toupper", "tolower", "bcopy",
55 "bzero", "bcmp", "memcpy", "memset",
56 "memmove", "memcmp", "memchr", "rand",
58 "srand", "qsort", "strtod", "malloc",
59 "free", "lsearch", "bsearch", "calloc",
60 "realloc", "InitHeap", "_exit", "getchar",
61 "putchar", "gets", "puts", "printf",
63 "sys_a0_40", "LoadTest", "Load", "Exec",
64 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
65 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
66 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
68 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
69 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
70 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
71 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
73 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
74 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
75 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
76 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
78 "_bu_init", "_96_init", "_96_remove", "sys_a0_73",
79 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
80 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
81 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
83 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
84 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
85 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
86 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
88 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
89 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
90 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
91 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
93 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
94 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
95 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
96 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
98 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
102 char *biosB0n[256] = {
104 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
105 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
106 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
107 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
109 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
110 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
111 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
112 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
114 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
115 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
116 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
117 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
119 "sys_b0_30", "sys_b0_31", "open", "lseek",
120 "read", "write", "close", "ioctl",
121 "exit", "sys_b0_39", "getc", "putc",
122 "getchar", "putchar", "gets", "puts",
124 "cd", "format", "firstfile", "nextfile",
125 "rename", "delete", "undelete", "AddDevice",
126 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
127 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
129 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
130 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
131 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
132 "_card_status", "_card_wait",
135 char *biosC0n[256] = {
137 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
138 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
139 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
140 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
142 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
143 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
144 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
148 //#define r0 (psxRegs.GPR.n.r0)
149 #define at (psxRegs.GPR.n.at)
150 #define v0 (psxRegs.GPR.n.v0)
151 #define v1 (psxRegs.GPR.n.v1)
152 #define a0 (psxRegs.GPR.n.a0)
153 #define a1 (psxRegs.GPR.n.a1)
154 #define a2 (psxRegs.GPR.n.a2)
155 #define a3 (psxRegs.GPR.n.a3)
156 #define t0 (psxRegs.GPR.n.t0)
157 #define t1 (psxRegs.GPR.n.t1)
158 #define t2 (psxRegs.GPR.n.t2)
159 #define t3 (psxRegs.GPR.n.t3)
160 #define t4 (psxRegs.GPR.n.t4)
161 #define t5 (psxRegs.GPR.n.t5)
162 #define t6 (psxRegs.GPR.n.t6)
163 #define t7 (psxRegs.GPR.n.t7)
164 #define t8 (psxRegs.GPR.n.t8)
165 #define t9 (psxRegs.GPR.n.t9)
166 #define s0 (psxRegs.GPR.n.s0)
167 #define s1 (psxRegs.GPR.n.s1)
168 #define s2 (psxRegs.GPR.n.s2)
169 #define s3 (psxRegs.GPR.n.s3)
170 #define s4 (psxRegs.GPR.n.s4)
171 #define s5 (psxRegs.GPR.n.s5)
172 #define s6 (psxRegs.GPR.n.s6)
173 #define s7 (psxRegs.GPR.n.s7)
174 #define k0 (psxRegs.GPR.n.k0)
175 #define k1 (psxRegs.GPR.n.k1)
176 #define gp (psxRegs.GPR.n.gp)
177 #define sp (psxRegs.GPR.n.sp)
178 #define fp (psxRegs.GPR.n.s8)
179 #define ra (psxRegs.GPR.n.ra)
180 #define pc0 (psxRegs.pc)
182 #define Ra0 ((char *)PSXM(a0))
183 #define Ra1 ((char *)PSXM(a1))
184 #define Ra2 ((char *)PSXM(a2))
185 #define Ra3 ((char *)PSXM(a3))
186 #define Rv0 ((char *)PSXM(v0))
187 #define Rsp ((char *)PSXM(sp))
196 #define EvStUNUSED 0x0000
197 #define EvStWAIT 0x1000
198 #define EvStACTIVE 0x2000
199 #define EvStALREADY 0x4000
201 #define EvMdINTR 0x1000
202 #define EvMdNOINTR 0x2000
231 u32 _sp, _fp, _gp, ret, base;
251 static u32 *jmp_int = NULL;
252 static int *pad_buf = NULL;
253 static char *pad_buf1 = NULL, *pad_buf2 = NULL;
254 static int pad_buf1len, pad_buf2len;
255 static int pad_stopped = 0;
259 static EvCB *HwEV; // 0xf0
260 static EvCB *EvEV; // 0xf1
261 static EvCB *RcEV; // 0xf2
262 static EvCB *UeEV; // 0xf3
263 static EvCB *SwEV; // 0xf4
264 static EvCB *ThEV; // 0xff
265 static u32 heap_size = 0;
266 static u32 *heap_addr = NULL;
267 static u32 *heap_end = NULL;
268 static u32 SysIntRP[8];
269 static int CardState = -1;
270 static TCB Thread[8];
271 static int CurThread = 0;
272 static FileDesc FDesc[32];
273 static u32 card_active_chan;
275 boolean hleSoftCall = FALSE;
277 static inline void softCall(u32 pc) {
283 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
288 static inline void softCall2(u32 pc) {
295 while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
301 static inline void DeliverEvent(u32 ev, u32 spec) {
302 if (Event[ev][spec].status != EvStACTIVE) return;
304 // Event[ev][spec].status = EvStALREADY;
305 if (Event[ev][spec].mode == EvMdINTR) {
306 softCall2(Event[ev][spec].fhandler);
307 } else Event[ev][spec].status = EvStALREADY;
310 static unsigned interrupt_r26=0x8004E8B0;
312 static inline void SaveRegs() {
313 memcpy(regs, psxRegs.GPR.r, 32*4);
314 regs[32] = psxRegs.GPR.n.lo;
315 regs[33] = psxRegs.GPR.n.hi;
316 regs[34] = psxRegs.pc;
319 static inline void LoadRegs() {
320 memcpy(psxRegs.GPR.r, regs, 32*4);
321 psxRegs.GPR.n.lo = regs[32];
322 psxRegs.GPR.n.hi = regs[33];
328 // System calls A0 */
331 #define buread(Ra1, mcd, length) { \
332 SysPrintf("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
333 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
334 memcpy(Ra1, ptr, length); \
335 if (FDesc[1 + mcd].mode & 0x8000) { \
336 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
337 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
340 FDesc[1 + mcd].offset += v0; \
343 #define buwrite(Ra1, mcd, length) { \
344 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
345 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
346 ptr = Mcd##mcd##Data + offset; \
347 memcpy(ptr, Ra1, length); \
348 FDesc[1 + mcd].offset += length; \
349 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
350 if (FDesc[1 + mcd].mode & 0x8000) { \
351 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
352 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
358 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
359 /* For some strange reason, the returned character is sign-expanded; */
360 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
361 /* TODO FIX ME : Properly implement this behaviour */
362 void psxBios_getc(void) // 0x03, 0x35
367 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
373 case 2: buread(pa1, 1, 1); break;
374 case 3: buread(pa1, 2, 1); break;
381 /* Copy of psxBios_write, except size is 1. */
382 void psxBios_putc(void) // 0x09, 0x3B
387 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
395 if (a0 == 1) { // stdout
396 char *ptr = (char *)pa1;
400 printf("%c", *ptr++); a2--;
406 case 2: buwrite(pa1, 1, 1); break;
407 case 3: buwrite(pa1, 2, 1); break;
413 void psxBios_todigit(void) // 0x0a
417 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
420 if (c >= 0x30 && c < 0x3A) {
423 else if (c > 0x60 && c < 0x7B) {
426 else if (c > 0x40 && c < 0x5B) {
429 else if (c >= 0x80) {
440 void psxBios_abs() { // 0x0e
441 if ((s32)a0 < 0) v0 = -(s32)a0;
446 void psxBios_labs() { // 0x0f
450 void psxBios_atoi() { // 0x10
452 char *p = (char *)Ra0;
456 case ' ': case '\t': continue;
463 while (*p >= '0' && *p <= '9') {
464 n = n * 10 + *p++ - '0';
471 void psxBios_atol() { // 0x11
475 void psxBios_setjmp() { // 0x13
476 u32 *jmp_buf = (u32 *)Ra0;
480 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x13]);
486 for (i = 0; i < 8; i++) // s0-s7
487 jmp_buf[3 + i] = psxRegs.GPR.r[16 + i];
493 void psxBios_longjmp() { // 0x14
494 u32 *jmp_buf = (u32 *)Ra0;
498 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
501 ra = jmp_buf[0]; /* ra */
502 sp = jmp_buf[1]; /* sp */
503 fp = jmp_buf[2]; /* fp */
504 for (i = 0; i < 8; i++) // s0-s7
505 psxRegs.GPR.r[16 + i] = jmp_buf[3 + i];
506 gp = jmp_buf[11]; /* gp */
511 void psxBios_strcat() { // 0x15
512 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
515 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
517 if (a0 == 0 || a1 == 0)
525 while ((*p1++ = *p2++) != '\0');
530 void psxBios_strncat() { // 0x16
531 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
535 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
537 if (a0 == 0 || a1 == 0)
545 while ((*p1++ = *p2++) != '\0') {
555 void psxBios_strcmp() { // 0x17
556 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
558 if (a0 == 0 && a1 == 0)
564 else if (a0 == 0 && a1 != 0)
570 else if (a0 != 0 && a1 == 0)
577 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
580 while (*p1 == *p2++) {
599 void psxBios_strncmp() { // 0x18
600 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
602 if (a0 == 0 && a1 == 0)
608 else if (a0 == 0 && a1 != 0)
614 else if (a0 != 0 && a1 == 0)
621 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
624 while (--n >= 0 && *p1 == *p2++) {
628 v1 = a2 - ((a2-n) - 1);
636 v0 = (n < 0 ? 0 : *p1 - *--p2);
638 v1 = a2 - ((a2-n) - 1);
644 void psxBios_strcpy() { // 0x19
645 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
646 if (a0 == 0 || a1 == 0)
652 while ((*p1++ = *p2++) != '\0');
657 void psxBios_strncpy() { // 0x1a
658 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
660 if (a0 == 0 || a1 == 0)
666 for (i = 0; i < n; i++) {
667 if ((*p1++ = *p2++) == '\0') {
679 void psxBios_strlen() { // 0x1b
680 char *p = (char *)Ra0;
691 void psxBios_index() { // 0x1c
692 char *p = (char *)Ra0;
702 v0 = a0 + (p - (char *)Ra0);
706 } while (*p++ != '\0');
711 void psxBios_rindex() { // 0x1d
712 char *p = (char *)Ra0;
722 v0 = a0 + (p - (char *)Ra0);
723 } while (*p++ != '\0');
728 void psxBios_strchr() { // 0x1e
732 void psxBios_strrchr() { // 0x1f
736 void psxBios_strpbrk() { // 0x20
737 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
739 while ((c = *p1++) != '\0') {
740 for (scanp = p2; (sc = *scanp++) != '\0';) {
742 v0 = a0 + (p1 - 1 - (char *)Ra0);
749 // BUG: return a0 instead of NULL if not found
753 void psxBios_strspn() { // 0x21
756 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
757 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
758 if (*p2 == '\0') break;
761 v0 = p1 - (char *)Ra0; pc0 = ra;
764 void psxBios_strcspn() { // 0x22
767 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
768 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
769 if (*p2 != '\0') break;
772 v0 = p1 - (char *)Ra0; pc0 = ra;
775 void psxBios_strtok() { // 0x23
776 char *pcA0 = (char *)Ra0;
777 char *pcRet = strtok(pcA0, (char *)Ra1);
779 v0 = a0 + pcRet - pcA0;
785 void psxBios_strstr() { // 0x24
786 char *p = (char *)Ra0, *p1, *p2;
792 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
797 v0 = a0 + (p - (char *)Ra0);
808 void psxBios_toupper() { // 0x25
809 v0 = (s8)(a0 & 0xff);
810 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
814 void psxBios_tolower() { // 0x26
815 v0 = (s8)(a0 & 0xff);
816 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
820 void psxBios_bcopy() { // 0x27
821 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
823 if (a0 == 0 || a2 > 0x7FFFFFFF)
828 while ((s32)a2-- > 0) *p1++ = *p2++;
833 void psxBios_bzero() { // 0x28
834 char *p = (char *)Ra0;
836 /* Same as memset here (See memset below) */
837 if (a1 > 0x7FFFFFFF || a1 == 0)
848 while ((s32)a1-- > 0) *p++ = '\0';
853 void psxBios_bcmp() { // 0x29
854 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
856 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
858 while ((s32)a2-- > 0) {
859 if (*p1++ != *p2++) {
860 v0 = *p1 - *p2; // BUG: compare the NEXT byte
869 void psxBios_memcpy() { // 0x2a
870 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
872 if (a0 == 0 || a2 > 0x7FFFFFFF)
877 while ((s32)a2-- > 0) {
884 void psxBios_memset() { // 0x2b
885 char *p = (char *)Ra0;
887 if (a2 > 0x7FFFFFFF || a2 == 0)
898 while ((s32)a2-- > 0) *p++ = (char)a1;
903 void psxBios_memmove() { // 0x2c
904 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
906 if (a0 == 0 || a2 > 0x7FFFFFFF)
911 if (p2 <= p1 && p2 + a2 > p1) {
912 a2++; // BUG: copy one more byte here
915 while ((s32)a2-- > 0) *--p1 = *--p2;
917 while ((s32)a2-- > 0) *p1++ = *p2++;
922 void psxBios_memcmp() { // 0x2d
926 void psxBios_memchr() { // 0x2e
927 char *p = (char *)Ra0;
929 if (a0 == 0 || a2 > 0x7FFFFFFF)
935 while ((s32)a2-- > 0) {
936 if (*p++ != (s8)a1) continue;
937 v0 = a0 + (p - (char *)Ra0 - 1);
945 void psxBios_rand() { // 0x2f
946 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
947 v0 = (s >> 16) & 0x7fff;
948 psxMu32ref(0x9010) = SWAPu32(s);
952 void psxBios_srand() { // 0x30
953 psxMu32ref(0x9010) = SWAPu32(a0);
957 static u32 qscmpfunc, qswidth;
959 static inline int qscmp(char *a, char *b) {
962 a0 = sa0 + (a - (char *)PSXM(sa0));
963 a1 = sa0 + (b - (char *)PSXM(sa0));
965 softCall2(qscmpfunc);
971 static inline void qexchange(char *i, char *j) {
982 static inline void q3exchange(char *i, char *j, char *k) {
994 static void qsort_main(char *a, char *l) {
995 char *i, *j, *lp, *hp;
1000 if ((n = l - a) <= qswidth)
1002 n = qswidth * (n / (2 * qswidth));
1008 if ((c = qscmp(i, lp)) == 0) {
1009 qexchange(i, lp -= qswidth);
1020 if ((c = qscmp(hp, j)) == 0) {
1021 qexchange(hp += qswidth, j);
1026 q3exchange(i, hp += qswidth, j);
1040 if (lp - a >= l - hp) {
1041 qsort_main(hp + qswidth, l);
1050 q3exchange(j, lp -= qswidth, i);
1055 void psxBios_qsort() { // 0x31
1058 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1063 void psxBios_malloc() { // 0x33
1064 unsigned int *chunk, *newchunk = NULL;
1065 unsigned int dsize = 0, csize, cstat;
1068 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1070 if (!a0 || (!heap_size || !heap_addr)) {
1076 // scan through heap and combine free chunks of space
1079 while(chunk < heap_end) {
1080 // get size and status of actual chunk
1081 csize = ((u32)*chunk) & 0xfffffffc;
1082 cstat = ((u32)*chunk) & 1;
1084 // most probably broken heap descriptor
1085 // this fixes Burning Road
1088 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1093 // it's a free chunk
1098 colflag = 1; // let's begin a new collection of free memory
1100 else dsize += (csize+4); // add the new size including header
1102 // not a free chunk: did we start a collection ?
1104 if(colflag == 1) { // collection is over
1106 *newchunk = SWAP32(dsize | 1);
1111 chunk = (u32*)((uptr)chunk + csize + 4);
1113 // if neccessary free memory on end of heap
1115 *newchunk = SWAP32(dsize | 1);
1118 csize = ((u32)*chunk) & 0xfffffffc;
1119 cstat = ((u32)*chunk) & 1;
1120 dsize = (a0 + 3) & 0xfffffffc;
1122 // exit on uninitialized heap
1123 if (chunk == NULL) {
1124 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1130 // search an unused chunk that is big enough until the end of the heap
1131 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1132 chunk = (u32*)((uptr)chunk + csize + 4);
1134 // catch out of memory
1135 if(chunk >= heap_end) {
1136 printf("malloc %x,%x: Out of memory error!\n",
1142 csize = ((u32)*chunk) & 0xfffffffc;
1143 cstat = ((u32)*chunk) & 1;
1147 if(dsize == csize) {
1148 // chunk has same size
1149 *chunk &= 0xfffffffc;
1150 } else if (dsize > csize) {
1155 *chunk = SWAP32(dsize);
1156 newchunk = (u32*)((uptr)chunk + dsize + 4);
1157 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1160 // return pointer to allocated memory
1161 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1163 //printf ("malloc %x,%x\n", v0, a0);
1167 void psxBios_free() { // 0x34
1170 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1173 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1176 *(u32*)(Ra0-4) |= 1; // set chunk to free
1180 void psxBios_calloc() { // 0x37
1183 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1193 void psxBios_realloc() { // 0x38
1197 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1201 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1206 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1211 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1212 /* Note that it is not quite implemented this way here. */
1222 /* InitHeap(void *block , int n) */
1223 void psxBios_InitHeap() { // 0x39
1227 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1230 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1235 heap_addr = (u32 *)Ra0;
1237 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1238 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1239 //*heap_addr = SWAP32(size | 1);
1241 SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1246 void psxBios_getchar() { //0x3b
1247 v0 = getchar(); pc0 = ra;
1250 void psxBios_printf() { // 0x3f
1260 memcpy(save, psp, 4 * 4);
1261 psxMu32ref(sp) = SWAP32((u32)a0);
1262 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1263 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1264 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1276 tmp2[j++] = Ra0[i]; goto _start;
1278 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1289 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1293 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1299 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1301 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1303 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1305 *ptmp++ = Ra0[i]; break;
1316 memcpy(psp, save, 4 * 4);
1318 SysPrintf("%s", tmp);
1323 void psxBios_format() { // 0x41
1324 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1326 CreateMcd(Config.Mcd1);
1327 LoadMcd(1, Config.Mcd1);
1330 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1332 CreateMcd(Config.Mcd2);
1333 LoadMcd(2, Config.Mcd2);
1344 * long Load(char *name, struct EXEC *header);
1347 void psxBios_Load() { // 0x42
1352 PSXBIOS_LOG("psxBios_%s: %s, %x\n", biosA0n[0x42], Ra0, a1);
1356 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1357 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1365 * int Exec(struct EXEC *header , int argc , char **argv);
1368 void psxBios_Exec() { // 43
1369 EXEC *header = (EXEC*)Ra0;
1373 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1383 if (header->S_addr != 0) {
1384 tmp = header->S_addr + header->s_size;
1400 void psxBios_FlushCache() { // 44
1402 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1408 void psxBios_GPU_dw() { // 0x46
1413 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1416 GPU_writeData(0xa0000000);
1417 GPU_writeData((a1<<16)|(a0&0xffff));
1418 GPU_writeData((a3<<16)|(a2&0xffff));
1420 ptr = (s32*)PSXM(Rsp[4]); //that is correct?
1422 GPU_writeData(SWAP32(*ptr));
1429 void psxBios_mem2vram() { // 0x47
1432 GPU_writeData(0xa0000000);
1433 GPU_writeData((a1<<16)|(a0&0xffff));
1434 GPU_writeData((a3<<16)|(a2&0xffff));
1436 GPU_writeStatus(0x04000002);
1437 psxHwWrite32(0x1f8010f4,0);
1438 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1439 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1440 psxHwWrite32(0x1f8010a4,((size/16)<<16)|16);
1441 psxHwWrite32(0x1f8010a8,0x01000201);
1446 void psxBios_SendGPU() { // 0x48
1447 GPU_writeStatus(a0);
1452 void psxBios_GPU_cw() { // 0x49
1457 void psxBios_GPU_cwb() { // 0x4a
1458 s32 *ptr = (s32*)Ra0;
1461 GPU_writeData(SWAP32(*ptr));
1468 void psxBios_GPU_SendPackets() { //4b:
1469 GPU_writeStatus(0x04000002);
1470 psxHwWrite32(0x1f8010f4,0);
1471 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1472 psxHwWrite32(0x1f8010a0,a0);
1473 psxHwWrite32(0x1f8010a4,0);
1474 psxHwWrite32(0x1f8010a8,0x010000401);
1478 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1479 psxHwWrite32(0x1f8010a8,0x00000401);
1480 GPU_writeData(0x0400000);
1481 GPU_writeData(0x0200000);
1482 GPU_writeData(0x0100000);
1487 void psxBios_GPU_GetGPUStatus() { // 0x4d
1488 v0 = GPU_readStatus();
1494 void psxBios_LoadExec() { // 51
1495 EXEC *header = (EXEC*)PSXM(0xf000);
1499 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1501 s_addr = a1; s_size = a2;
1506 header->S_addr = s_addr;
1507 header->s_size = s_size;
1509 a0 = 0xf000; a1 = 0; a2 = 0;
1513 void psxBios__bu_init() { // 70
1515 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1518 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1519 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1524 void psxBios__96_init() { // 71
1526 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1532 void psxBios__96_remove() { // 72
1534 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1540 void psxBios_SetMem() { // 9f
1541 u32 new = psxHu32(0x1060);
1544 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1549 psxHu32ref(0x1060) = SWAP32(new);
1550 psxMu32ref(0x060) = a0;
1551 SysPrintf("Change effective memory : %d MBytes\n",a0);
1555 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1556 psxMu32ref(0x060) = a0;
1557 SysPrintf("Change effective memory : %d MBytes\n",a0);
1560 SysPrintf("Effective memory must be 2/8 MBytes\n");
1567 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1568 void psxBios_get_cd_status(void) //a6
1574 void psxBios__card_info() { // ab
1576 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1579 card_active_chan = a0;
1581 switch (card_active_chan)
1583 case 0x00: case 0x01: case 0x02: case 0x03:
1584 ret = Config.Mcd1[0] ? 0x2 : 0x8;
1586 case 0x10: case 0x11: case 0x12: case 0x13:
1587 ret = Config.Mcd2[0] ? 0x2 : 0x8;
1591 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1597 DeliverEvent(0x11, 0x2); // 0xf4000001, 0x0004
1598 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
1602 void psxBios__card_load() { // ac
1604 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1607 card_active_chan = a0;
1609 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1610 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1615 /* System calls B0 */
1617 void psxBios_SetRCnt() { // 02
1619 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1626 psxRcntWtarget(a0, a1);
1627 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1628 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1629 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1630 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1631 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1633 psxRcntWmode(a0, mode);
1638 void psxBios_GetRCnt() { // 03
1640 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1644 if (a0 != 3) v0 = psxRcntRcount(a0);
1649 void psxBios_StartRCnt() { // 04
1651 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1655 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1656 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1660 void psxBios_StopRCnt() { // 05
1662 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1666 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1667 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1671 void psxBios_ResetRCnt() { // 06
1673 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1678 psxRcntWmode(a0, 0);
1679 psxRcntWtarget(a0, 0);
1680 psxRcntWcount(a0, 0);
1686 /* gets ev for use with Event */
1688 ev = (a0 >> 24) & 0xf; \
1689 if (ev == 0xf) ev = 0x5; \
1693 /* gets spec for use with Event */
1697 case 0x0301: spec = 16; break; \
1698 case 0x0302: spec = 17; break; \
1700 for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1704 void psxBios_DeliverEvent() { // 07
1712 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1715 DeliverEvent(ev, spec);
1720 void psxBios_OpenEvent() { // 08
1728 PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1731 Event[ev][spec].status = EvStWAIT;
1732 Event[ev][spec].mode = a2;
1733 Event[ev][spec].fhandler = a3;
1735 v0 = ev | (spec << 8);
1739 void psxBios_CloseEvent() { // 09
1743 spec = (a0 >> 8) & 0xff;
1746 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1749 Event[ev][spec].status = EvStUNUSED;
1754 void psxBios_WaitEvent() { // 0a
1758 spec = (a0 >> 8) & 0xff;
1760 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1762 if (Event[ev][spec].status == EvStUNUSED)
1769 if (Event[ev][spec].status == EvStALREADY)
1771 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1772 if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE;
1782 void psxBios_TestEvent() { // 0b
1786 spec = (a0 >> 8) & 0xff;
1788 if (Event[ev][spec].status == EvStALREADY)
1790 if (!(Event[ev][spec].mode == EvMdINTR)) Event[ev][spec].status = EvStACTIVE;
1799 PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1805 void psxBios_EnableEvent() { // 0c
1809 spec = (a0 >> 8) & 0xff;
1812 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1815 Event[ev][spec].status = EvStACTIVE;
1820 void psxBios_DisableEvent() { // 0d
1824 spec = (a0 >> 8) & 0xff;
1827 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1830 Event[ev][spec].status = EvStWAIT;
1836 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1839 void psxBios_OpenTh() { // 0e
1842 for (th=1; th<8; th++)
1844 if (Thread[th].status == 0) break;
1848 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1849 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1851 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1858 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1861 Thread[th].status = 1;
1862 Thread[th].func = a0;
1863 Thread[th].reg[29] = a1;
1864 Thread[th].reg[28] = a2;
1870 * int CloseTh(long thread);
1873 void psxBios_CloseTh() { // 0f
1877 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
1879 /* The return value is always 1 (even if the handle was already closed). */
1881 if (Thread[th].status != 0) {
1882 Thread[th].status = 0;
1889 * int ChangeTh(long thread);
1892 void psxBios_ChangeTh() { // 10
1896 // PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
1898 /* The return value is always 1. */
1900 if (Thread[th].status == 0 || CurThread == th) {
1903 if (Thread[CurThread].status == 2) {
1904 Thread[CurThread].status = 1;
1905 Thread[CurThread].func = ra;
1906 memcpy(Thread[CurThread].reg, psxRegs.GPR.r, 32*4);
1909 memcpy(psxRegs.GPR.r, Thread[th].reg, 32*4);
1910 pc0 = Thread[th].func;
1911 Thread[th].status = 2;
1916 void psxBios_InitPAD() { // 0x12
1918 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
1921 pad_buf1 = (char*)Ra0;
1923 pad_buf2 = (char*)Ra2;
1929 void psxBios_StartPAD() { // 13
1931 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
1934 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
1935 psxRegs.CP0.n.Status |= 0x401;
1939 void psxBios_StopPAD() { // 14
1941 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
1949 void psxBios_PAD_init() { // 15
1951 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
1953 if (!(a0 == 0x20000000 || a0 == 0x20000001))
1959 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
1960 pad_buf = (int *)Ra1;
1962 psxRegs.CP0.n.Status |= 0x401;
1967 void psxBios_PAD_dr() { // 16
1969 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
1975 void psxBios_ReturnFromException() { // 17
1978 pc0 = psxRegs.CP0.n.EPC;
1980 if (psxRegs.CP0.n.Cause & 0x80000000) pc0 += 4;
1982 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
1983 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
1986 void psxBios_ResetEntryInt() { // 18
1988 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
1995 void psxBios_HookEntryInt() { // 19
1997 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x19]);
2000 jmp_int = (u32*)Ra0;
2004 void psxBios_UnDeliverEvent() { // 0x20
2012 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2015 if (Event[ev][spec].status == EvStALREADY &&
2016 Event[ev][spec].mode == EvMdNOINTR)
2017 Event[ev][spec].status = EvStACTIVE;
2022 char ffile[64], *pfile;
2024 static void buopen(int mcd, u8 *ptr, u8 *cfg)
2029 strcpy(FDesc[1 + mcd].name, Ra0+5);
2030 FDesc[1 + mcd].offset = 0;
2031 FDesc[1 + mcd].mode = a1;
2033 for (i=1; i<16; i++) {
2035 if ((*fptr & 0xF0) != 0x50) continue;
2036 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2037 FDesc[1 + mcd].mcfile = i;
2038 SysPrintf("open %s\n", fptr+0xa);
2042 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2044 for (i=1; i<16; i++) {
2045 int j, xor, nblk = a1 >> 16;
2049 if ((*fptr & 0xF0) != 0xa0) continue;
2051 FDesc[1 + mcd].mcfile = i;
2054 fptr[5] = 0x20 * nblk;
2057 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2058 pptr = fptr2 = fptr;
2059 for(j=2; j<=nblk; j++) {
2061 for(i++; i<16; i++) {
2064 memset(fptr2, 0, 128);
2065 fptr2[0] = j < nblk ? 0x52 : 0x53;
2068 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2073 /* shouldn't this return ENOSPC if i == 16? */
2075 pptr[8] = pptr[9] = 0xff;
2076 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2078 SysPrintf("openC %s %d\n", ptr, nblk);
2080 /* just go ahead and resave them all */
2081 SaveMcd(cfg, ptr, 128, 128 * 15);
2084 /* shouldn't this return ENOSPC if i == 16? */
2089 * int open(char *name , int mode);
2092 void psxBios_open() { // 0x32
2098 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2104 if (!strncmp(pa0, "bu00", 4)) {
2105 buopen(1, Mcd1Data, Config.Mcd1);
2108 if (!strncmp(pa0, "bu10", 4)) {
2109 buopen(2, Mcd2Data, Config.Mcd2);
2117 * int lseek(int fd , int offset , int whence);
2120 void psxBios_lseek() { // 0x33
2122 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2127 FDesc[a0].offset = a1;
2129 // DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2130 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2134 FDesc[a0].offset+= a1;
2135 v0 = FDesc[a0].offset;
2144 * int read(int fd , void *buf , int nbytes);
2147 void psxBios_read() { // 0x34
2152 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2159 case 2: buread(pa1, 1, a2); break;
2160 case 3: buread(pa1, 2, a2); break;
2168 * int write(int fd , void *buf , int nbytes);
2171 void psxBios_write() { // 0x35/0x03
2176 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2185 if (a0 == 1) { // stdout
2190 SysPrintf("%c", *ptr++); a2--;
2196 case 2: buwrite(pa1, 1, a2); break;
2197 case 3: buwrite(pa1, 2, a2); break;
2204 * int close(int fd);
2207 void psxBios_close() { // 0x36
2209 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2216 void psxBios_putchar() { // 3d
2217 SysPrintf("%c", (char)a0);
2221 void psxBios_puts() { // 3e/3f
2222 SysPrintf("%s", Ra0);
2227 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2228 * We want to mimic the PSX's behaviour in this case for bufile. */
2229 static size_t strlen_internal(char* p)
2231 size_t size_of_array = 0;
2232 while (*p++) size_of_array++;
2233 return size_of_array;
2236 #define bufile(mcd) { \
2237 size_t size_of_name = strlen_internal(dir->name); \
2238 while (nfile < 16) { \
2241 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2243 if ((*ptr & 0xF0) != 0x50) continue; \
2244 /* Bug link files show up as free block. */ \
2245 if (!ptr[0xa]) continue; \
2247 if (pfile[0] == 0) { \
2248 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2249 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2250 } else for (i=0; i<20; i++) { \
2251 if (pfile[i] == ptr[i]) { \
2252 dir->name[i] = ptr[i]; continue; } \
2253 if (pfile[i] == '?') { \
2254 dir->name[i] = ptr[i]; continue; } \
2255 if (pfile[i] == '*') { \
2256 strcpy(dir->name+i, ptr+i); break; } \
2259 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2260 if (match == 0) { continue; } \
2268 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2271 void psxBios_firstfile() { // 42
2272 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2279 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2288 if (!strncmp(pa0, "bu00", 4)) {
2289 // firstfile() calls _card_read() internally, so deliver it's event
2290 DeliverEvent(0x11, 0x2);
2292 } else if (!strncmp(pa0, "bu10", 4)) {
2293 // firstfile() calls _card_read() internally, so deliver it's event
2294 DeliverEvent(0x11, 0x2);
2303 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2306 void psxBios_nextfile() { // 43
2307 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2313 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2318 if (!strncmp(ffile, "bu00", 4)) {
2322 if (!strncmp(ffile, "bu10", 4)) {
2329 #define burename(mcd) { \
2330 for (i=1; i<16; i++) { \
2331 int namelen, j, xor = 0; \
2332 ptr = Mcd##mcd##Data + 128 * i; \
2333 if ((*ptr & 0xF0) != 0x50) continue; \
2334 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2335 namelen = strlen(Ra1+5); \
2336 memcpy(ptr+0xa, Ra1+5, namelen); \
2337 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2338 for (j=0; j<127; j++) xor^= ptr[j]; \
2340 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2347 * int rename(char *old, char *new);
2350 void psxBios_rename() { // 44
2357 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2363 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2367 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2376 #define budelete(mcd) { \
2377 for (i=1; i<16; i++) { \
2378 ptr = Mcd##mcd##Data + 128 * i; \
2379 if ((*ptr & 0xF0) != 0x50) continue; \
2380 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2381 *ptr = (*ptr & 0xf) | 0xA0; \
2382 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2383 SysPrintf("delete %s\n", ptr+0xa); \
2390 * int delete(char *name);
2393 void psxBios_delete() { // 45
2399 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2405 if (!strncmp(pa0, "bu00", 4)) {
2409 if (!strncmp(pa0, "bu10", 4)) {
2417 void psxBios_InitCARD() { // 4a
2419 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2427 void psxBios_StartCARD() { // 4b
2429 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2432 if (CardState == 0) CardState = 1;
2437 void psxBios_StopCARD() { // 4c
2439 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2442 if (CardState == 1) CardState = 0;
2447 void psxBios__card_write() { // 0x4e
2452 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2455 Function also accepts sector 400h (a bug).
2456 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2460 /* Invalid sectors */
2464 card_active_chan = a0;
2469 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2470 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2472 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2473 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2477 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2478 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2483 void psxBios__card_read() { // 0x4f
2488 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2491 Function also accepts sector 400h (a bug).
2492 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2496 /* Invalid sectors */
2500 card_active_chan = a0;
2505 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2507 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2511 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2512 // DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2517 void psxBios__new_card() { // 0x50
2519 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2525 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2526 void psxBios__get_error(void) // 55
2532 void psxBios_Krom2RawAdd() { // 0x51
2535 const u32 table_8140[][2] = {
2536 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2537 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2538 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2539 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2540 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2541 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2542 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2543 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2544 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2548 const u32 table_889f[][2] = {
2549 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2550 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2551 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2552 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2553 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2554 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2555 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2556 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2560 if (a0 >= 0x8140 && a0 <= 0x84be) {
2561 while (table_8140[i][0] <= a0) i++;
2562 a0 -= table_8140[i - 1][0];
2563 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2564 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2565 while (table_889f[i][0] <= a0) i++;
2566 a0 -= table_889f[i - 1][0];
2567 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2575 void psxBios_GetC0Table() { // 56
2577 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2580 v0 = 0x674; pc0 = ra;
2583 void psxBios_GetB0Table() { // 57
2585 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2588 v0 = 0x874; pc0 = ra;
2591 void psxBios__card_chan() { // 0x58
2593 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2596 v0 = card_active_chan;
2600 void psxBios_ChangeClearPad() { // 5b
2602 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2608 void psxBios__card_status() { // 5c
2610 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2613 v0 = card_active_chan;
2617 void psxBios__card_wait() { // 5d
2619 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2626 /* System calls C0 */
2629 * int SysEnqIntRP(int index , long *queue);
2632 void psxBios_SysEnqIntRP() { // 02
2634 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x02] ,a0);
2643 * int SysDeqIntRP(int index , long *queue);
2646 void psxBios_SysDeqIntRP() { // 03
2648 PSXBIOS_LOG("psxBios_%s: %x\n", biosC0n[0x03], a0);
2656 void psxBios_ChangeClearRCnt() { // 0a
2660 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2663 ptr = (u32*)PSXM((a0 << 2) + 0x8600);
2667 // psxRegs.CP0.n.Status|= 0x404;
2671 void psxBios_dummy() {
2673 PSXBIOS_LOG("unk %x call: %x\n", pc0 & 0x1fffff, t1);
2678 void (*biosA0[256])();
2679 void (*biosB0[256])();
2680 void (*biosC0[256])();
2682 #include "sjisfont.h"
2684 void psxBiosInit() {
2690 for(i = 0; i < 256; i++) {
2695 biosA0[0x3e] = psxBios_puts;
2696 biosA0[0x3f] = psxBios_printf;
2698 biosB0[0x3d] = psxBios_putchar;
2699 biosB0[0x3f] = psxBios_puts;
2701 if (!Config.HLE) return;
2703 for(i = 0; i < 256; i++) {
2704 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
2705 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
2706 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
2709 biosA0[0x00] = psxBios_open;
2710 biosA0[0x01] = psxBios_lseek;
2711 biosA0[0x02] = psxBios_read;
2712 biosA0[0x03] = psxBios_write;
2713 biosA0[0x04] = psxBios_close;
2714 //biosA0[0x05] = psxBios_ioctl;
2715 //biosA0[0x06] = psxBios_exit;
2716 //biosA0[0x07] = psxBios_sys_a0_07;
2717 biosA0[0x08] = psxBios_getc;
2718 biosA0[0x09] = psxBios_putc;
2719 biosA0[0x0a] = psxBios_todigit;
2720 //biosA0[0x0b] = psxBios_atof;
2721 //biosA0[0x0c] = psxBios_strtoul;
2722 //biosA0[0x0d] = psxBios_strtol;
2723 biosA0[0x0e] = psxBios_abs;
2724 biosA0[0x0f] = psxBios_labs;
2725 biosA0[0x10] = psxBios_atoi;
2726 biosA0[0x11] = psxBios_atol;
2727 //biosA0[0x12] = psxBios_atob;
2728 biosA0[0x13] = psxBios_setjmp;
2729 biosA0[0x14] = psxBios_longjmp;
2730 biosA0[0x15] = psxBios_strcat;
2731 biosA0[0x16] = psxBios_strncat;
2732 biosA0[0x17] = psxBios_strcmp;
2733 biosA0[0x18] = psxBios_strncmp;
2734 biosA0[0x19] = psxBios_strcpy;
2735 biosA0[0x1a] = psxBios_strncpy;
2736 biosA0[0x1b] = psxBios_strlen;
2737 biosA0[0x1c] = psxBios_index;
2738 biosA0[0x1d] = psxBios_rindex;
2739 biosA0[0x1e] = psxBios_strchr;
2740 biosA0[0x1f] = psxBios_strrchr;
2741 biosA0[0x20] = psxBios_strpbrk;
2742 biosA0[0x21] = psxBios_strspn;
2743 biosA0[0x22] = psxBios_strcspn;
2744 biosA0[0x23] = psxBios_strtok;
2745 biosA0[0x24] = psxBios_strstr;
2746 biosA0[0x25] = psxBios_toupper;
2747 biosA0[0x26] = psxBios_tolower;
2748 biosA0[0x27] = psxBios_bcopy;
2749 biosA0[0x28] = psxBios_bzero;
2750 biosA0[0x29] = psxBios_bcmp;
2751 biosA0[0x2a] = psxBios_memcpy;
2752 biosA0[0x2b] = psxBios_memset;
2753 biosA0[0x2c] = psxBios_memmove;
2754 biosA0[0x2d] = psxBios_memcmp;
2755 biosA0[0x2e] = psxBios_memchr;
2756 biosA0[0x2f] = psxBios_rand;
2757 biosA0[0x30] = psxBios_srand;
2758 biosA0[0x31] = psxBios_qsort;
2759 //biosA0[0x32] = psxBios_strtod;
2760 biosA0[0x33] = psxBios_malloc;
2761 biosA0[0x34] = psxBios_free;
2762 //biosA0[0x35] = psxBios_lsearch;
2763 //biosA0[0x36] = psxBios_bsearch;
2764 biosA0[0x37] = psxBios_calloc;
2765 biosA0[0x38] = psxBios_realloc;
2766 biosA0[0x39] = psxBios_InitHeap;
2767 //biosA0[0x3a] = psxBios__exit;
2768 biosA0[0x3b] = psxBios_getchar;
2769 biosA0[0x3c] = psxBios_putchar;
2770 //biosA0[0x3d] = psxBios_gets;
2771 //biosA0[0x40] = psxBios_sys_a0_40;
2772 //biosA0[0x41] = psxBios_LoadTest;
2773 biosA0[0x42] = psxBios_Load;
2774 biosA0[0x43] = psxBios_Exec;
2775 biosA0[0x44] = psxBios_FlushCache;
2776 //biosA0[0x45] = psxBios_InstallInterruptHandler;
2777 biosA0[0x46] = psxBios_GPU_dw;
2778 biosA0[0x47] = psxBios_mem2vram;
2779 biosA0[0x48] = psxBios_SendGPU;
2780 biosA0[0x49] = psxBios_GPU_cw;
2781 biosA0[0x4a] = psxBios_GPU_cwb;
2782 biosA0[0x4b] = psxBios_GPU_SendPackets;
2783 biosA0[0x4c] = psxBios_sys_a0_4c;
2784 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
2785 //biosA0[0x4e] = psxBios_GPU_sync;
2786 //biosA0[0x4f] = psxBios_sys_a0_4f;
2787 //biosA0[0x50] = psxBios_sys_a0_50;
2788 biosA0[0x51] = psxBios_LoadExec;
2789 //biosA0[0x52] = psxBios_GetSysSp;
2790 //biosA0[0x53] = psxBios_sys_a0_53;
2791 //biosA0[0x54] = psxBios__96_init_a54;
2792 //biosA0[0x55] = psxBios__bu_init_a55;
2793 //biosA0[0x56] = psxBios__96_remove_a56;
2794 //biosA0[0x57] = psxBios_sys_a0_57;
2795 //biosA0[0x58] = psxBios_sys_a0_58;
2796 //biosA0[0x59] = psxBios_sys_a0_59;
2797 //biosA0[0x5a] = psxBios_sys_a0_5a;
2798 //biosA0[0x5b] = psxBios_dev_tty_init;
2799 //biosA0[0x5c] = psxBios_dev_tty_open;
2800 //biosA0[0x5d] = psxBios_sys_a0_5d;
2801 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
2802 //biosA0[0x5f] = psxBios_dev_cd_open;
2803 //biosA0[0x60] = psxBios_dev_cd_read;
2804 //biosA0[0x61] = psxBios_dev_cd_close;
2805 //biosA0[0x62] = psxBios_dev_cd_firstfile;
2806 //biosA0[0x63] = psxBios_dev_cd_nextfile;
2807 //biosA0[0x64] = psxBios_dev_cd_chdir;
2808 //biosA0[0x65] = psxBios_dev_card_open;
2809 //biosA0[0x66] = psxBios_dev_card_read;
2810 //biosA0[0x67] = psxBios_dev_card_write;
2811 //biosA0[0x68] = psxBios_dev_card_close;
2812 //biosA0[0x69] = psxBios_dev_card_firstfile;
2813 //biosA0[0x6a] = psxBios_dev_card_nextfile;
2814 //biosA0[0x6b] = psxBios_dev_card_erase;
2815 //biosA0[0x6c] = psxBios_dev_card_undelete;
2816 //biosA0[0x6d] = psxBios_dev_card_format;
2817 //biosA0[0x6e] = psxBios_dev_card_rename;
2818 //biosA0[0x6f] = psxBios_dev_card_6f;
2819 biosA0[0x70] = psxBios__bu_init;
2820 biosA0[0x71] = psxBios__96_init;
2821 biosA0[0x72] = psxBios__96_remove;
2822 //biosA0[0x73] = psxBios_sys_a0_73;
2823 //biosA0[0x74] = psxBios_sys_a0_74;
2824 //biosA0[0x75] = psxBios_sys_a0_75;
2825 //biosA0[0x76] = psxBios_sys_a0_76;
2826 //biosA0[0x77] = psxBios_sys_a0_77;
2827 //biosA0[0x78] = psxBios__96_CdSeekL;
2828 //biosA0[0x79] = psxBios_sys_a0_79;
2829 //biosA0[0x7a] = psxBios_sys_a0_7a;
2830 //biosA0[0x7b] = psxBios_sys_a0_7b;
2831 //biosA0[0x7c] = psxBios__96_CdGetStatus;
2832 //biosA0[0x7d] = psxBios_sys_a0_7d;
2833 //biosA0[0x7e] = psxBios__96_CdRead;
2834 //biosA0[0x7f] = psxBios_sys_a0_7f;
2835 //biosA0[0x80] = psxBios_sys_a0_80;
2836 //biosA0[0x81] = psxBios_sys_a0_81;
2837 //biosA0[0x82] = psxBios_sys_a0_82;
2838 //biosA0[0x83] = psxBios_sys_a0_83;
2839 //biosA0[0x84] = psxBios_sys_a0_84;
2840 //biosA0[0x85] = psxBios__96_CdStop;
2841 //biosA0[0x86] = psxBios_sys_a0_86;
2842 //biosA0[0x87] = psxBios_sys_a0_87;
2843 //biosA0[0x88] = psxBios_sys_a0_88;
2844 //biosA0[0x89] = psxBios_sys_a0_89;
2845 //biosA0[0x8a] = psxBios_sys_a0_8a;
2846 //biosA0[0x8b] = psxBios_sys_a0_8b;
2847 //biosA0[0x8c] = psxBios_sys_a0_8c;
2848 //biosA0[0x8d] = psxBios_sys_a0_8d;
2849 //biosA0[0x8e] = psxBios_sys_a0_8e;
2850 //biosA0[0x8f] = psxBios_sys_a0_8f;
2851 //biosA0[0x90] = psxBios_sys_a0_90;
2852 //biosA0[0x91] = psxBios_sys_a0_91;
2853 //biosA0[0x92] = psxBios_sys_a0_92;
2854 //biosA0[0x93] = psxBios_sys_a0_93;
2855 //biosA0[0x94] = psxBios_sys_a0_94;
2856 //biosA0[0x95] = psxBios_sys_a0_95;
2857 //biosA0[0x96] = psxBios_AddCDROMDevice;
2858 //biosA0[0x97] = psxBios_AddMemCardDevide;
2859 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
2860 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
2861 //biosA0[0x9a] = psxBios_sys_a0_9a;
2862 //biosA0[0x9b] = psxBios_sys_a0_9b;
2863 //biosA0[0x9c] = psxBios_SetConf;
2864 //biosA0[0x9d] = psxBios_GetConf;
2865 //biosA0[0x9e] = psxBios_sys_a0_9e;
2866 biosA0[0x9f] = psxBios_SetMem;
2867 //biosA0[0xa0] = psxBios__boot;
2868 //biosA0[0xa1] = psxBios_SystemError;
2869 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
2870 //biosA0[0xa3] = psxBios_DequeueCdIntr;
2871 //biosA0[0xa4] = psxBios_sys_a0_a4;
2872 //biosA0[0xa5] = psxBios_ReadSector;
2873 biosA0[0xa6] = psxBios_get_cd_status;
2874 //biosA0[0xa7] = psxBios_bufs_cb_0;
2875 //biosA0[0xa8] = psxBios_bufs_cb_1;
2876 //biosA0[0xa9] = psxBios_bufs_cb_2;
2877 //biosA0[0xaa] = psxBios_bufs_cb_3;
2878 biosA0[0xab] = psxBios__card_info;
2879 biosA0[0xac] = psxBios__card_load;
2880 //biosA0[0axd] = psxBios__card_auto;
2881 //biosA0[0xae] = psxBios_bufs_cd_4;
2882 //biosA0[0xaf] = psxBios_sys_a0_af;
2883 //biosA0[0xb0] = psxBios_sys_a0_b0;
2884 //biosA0[0xb1] = psxBios_sys_a0_b1;
2885 //biosA0[0xb2] = psxBios_do_a_long_jmp
2886 //biosA0[0xb3] = psxBios_sys_a0_b3;
2887 //biosA0[0xb4] = psxBios_sub_function;
2888 //*******************B0 CALLS****************************
2889 //biosB0[0x00] = psxBios_SysMalloc;
2890 //biosB0[0x01] = psxBios_sys_b0_01;
2891 biosB0[0x02] = psxBios_SetRCnt;
2892 biosB0[0x03] = psxBios_GetRCnt;
2893 biosB0[0x04] = psxBios_StartRCnt;
2894 biosB0[0x05] = psxBios_StopRCnt;
2895 biosB0[0x06] = psxBios_ResetRCnt;
2896 biosB0[0x07] = psxBios_DeliverEvent;
2897 biosB0[0x08] = psxBios_OpenEvent;
2898 biosB0[0x09] = psxBios_CloseEvent;
2899 biosB0[0x0a] = psxBios_WaitEvent;
2900 biosB0[0x0b] = psxBios_TestEvent;
2901 biosB0[0x0c] = psxBios_EnableEvent;
2902 biosB0[0x0d] = psxBios_DisableEvent;
2903 biosB0[0x0e] = psxBios_OpenTh;
2904 biosB0[0x0f] = psxBios_CloseTh;
2905 biosB0[0x10] = psxBios_ChangeTh;
2906 //biosB0[0x11] = psxBios_psxBios_b0_11;
2907 biosB0[0x12] = psxBios_InitPAD;
2908 biosB0[0x13] = psxBios_StartPAD;
2909 biosB0[0x14] = psxBios_StopPAD;
2910 biosB0[0x15] = psxBios_PAD_init;
2911 biosB0[0x16] = psxBios_PAD_dr;
2912 biosB0[0x17] = psxBios_ReturnFromException;
2913 biosB0[0x18] = psxBios_ResetEntryInt;
2914 biosB0[0x19] = psxBios_HookEntryInt;
2915 //biosB0[0x1a] = psxBios_sys_b0_1a;
2916 //biosB0[0x1b] = psxBios_sys_b0_1b;
2917 //biosB0[0x1c] = psxBios_sys_b0_1c;
2918 //biosB0[0x1d] = psxBios_sys_b0_1d;
2919 //biosB0[0x1e] = psxBios_sys_b0_1e;
2920 //biosB0[0x1f] = psxBios_sys_b0_1f;
2921 biosB0[0x20] = psxBios_UnDeliverEvent;
2922 //biosB0[0x21] = psxBios_sys_b0_21;
2923 //biosB0[0x22] = psxBios_sys_b0_22;
2924 //biosB0[0x23] = psxBios_sys_b0_23;
2925 //biosB0[0x24] = psxBios_sys_b0_24;
2926 //biosB0[0x25] = psxBios_sys_b0_25;
2927 //biosB0[0x26] = psxBios_sys_b0_26;
2928 //biosB0[0x27] = psxBios_sys_b0_27;
2929 //biosB0[0x28] = psxBios_sys_b0_28;
2930 //biosB0[0x29] = psxBios_sys_b0_29;
2931 //biosB0[0x2a] = psxBios_sys_b0_2a;
2932 //biosB0[0x2b] = psxBios_sys_b0_2b;
2933 //biosB0[0x2c] = psxBios_sys_b0_2c;
2934 //biosB0[0x2d] = psxBios_sys_b0_2d;
2935 //biosB0[0x2e] = psxBios_sys_b0_2e;
2936 //biosB0[0x2f] = psxBios_sys_b0_2f;
2937 //biosB0[0x30] = psxBios_sys_b0_30;
2938 //biosB0[0x31] = psxBios_sys_b0_31;
2939 biosB0[0x32] = psxBios_open;
2940 biosB0[0x33] = psxBios_lseek;
2941 biosB0[0x34] = psxBios_read;
2942 biosB0[0x35] = psxBios_write;
2943 biosB0[0x36] = psxBios_close;
2944 //biosB0[0x37] = psxBios_ioctl;
2945 //biosB0[0x38] = psxBios_exit;
2946 //biosB0[0x39] = psxBios_sys_b0_39;
2947 //biosB0[0x3a] = psxBios_getc;
2948 //biosB0[0x3b] = psxBios_putc;
2949 biosB0[0x3c] = psxBios_getchar;
2950 //biosB0[0x3e] = psxBios_gets;
2951 //biosB0[0x40] = psxBios_cd;
2952 biosB0[0x41] = psxBios_format;
2953 biosB0[0x42] = psxBios_firstfile;
2954 biosB0[0x43] = psxBios_nextfile;
2955 biosB0[0x44] = psxBios_rename;
2956 biosB0[0x45] = psxBios_delete;
2957 //biosB0[0x46] = psxBios_undelete;
2958 //biosB0[0x47] = psxBios_AddDevice;
2959 //biosB0[0x48] = psxBios_RemoteDevice;
2960 //biosB0[0x49] = psxBios_PrintInstalledDevices;
2961 biosB0[0x4a] = psxBios_InitCARD;
2962 biosB0[0x4b] = psxBios_StartCARD;
2963 biosB0[0x4c] = psxBios_StopCARD;
2964 //biosB0[0x4d] = psxBios_sys_b0_4d;
2965 biosB0[0x4e] = psxBios__card_write;
2966 biosB0[0x4f] = psxBios__card_read;
2967 biosB0[0x50] = psxBios__new_card;
2968 biosB0[0x51] = psxBios_Krom2RawAdd;
2969 //biosB0[0x52] = psxBios_sys_b0_52;
2970 //biosB0[0x53] = psxBios_sys_b0_53;
2971 //biosB0[0x54] = psxBios__get_errno;
2972 biosB0[0x55] = psxBios__get_error;
2973 biosB0[0x56] = psxBios_GetC0Table;
2974 biosB0[0x57] = psxBios_GetB0Table;
2975 biosB0[0x58] = psxBios__card_chan;
2976 //biosB0[0x59] = psxBios_sys_b0_59;
2977 //biosB0[0x5a] = psxBios_sys_b0_5a;
2978 biosB0[0x5b] = psxBios_ChangeClearPad;
2979 biosB0[0x5c] = psxBios__card_status;
2980 biosB0[0x5d] = psxBios__card_wait;
2981 //*******************C0 CALLS****************************
2982 //biosC0[0x00] = psxBios_InitRCnt;
2983 //biosC0[0x01] = psxBios_InitException;
2984 biosC0[0x02] = psxBios_SysEnqIntRP;
2985 biosC0[0x03] = psxBios_SysDeqIntRP;
2986 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
2987 //biosC0[0x05] = psxBios_get_free_TCB_slot;
2988 //biosC0[0x06] = psxBios_ExceptionHandler;
2989 //biosC0[0x07] = psxBios_InstallExeptionHandler;
2990 //biosC0[0x08] = psxBios_SysInitMemory;
2991 //biosC0[0x09] = psxBios_SysInitKMem;
2992 biosC0[0x0a] = psxBios_ChangeClearRCnt;
2993 //biosC0[0x0b] = psxBios_SystemError;
2994 //biosC0[0x0c] = psxBios_InitDefInt;
2995 //biosC0[0x0d] = psxBios_sys_c0_0d;
2996 //biosC0[0x0e] = psxBios_sys_c0_0e;
2997 //biosC0[0x0f] = psxBios_sys_c0_0f;
2998 //biosC0[0x10] = psxBios_sys_c0_10;
2999 //biosC0[0x11] = psxBios_sys_c0_11;
3000 //biosC0[0x12] = psxBios_InstallDevices;
3001 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3002 //biosC0[0x14] = psxBios_sys_c0_14;
3003 //biosC0[0x15] = psxBios__cdevinput;
3004 //biosC0[0x16] = psxBios__cdevscan;
3005 //biosC0[0x17] = psxBios__circgetc;
3006 //biosC0[0x18] = psxBios__circputc;
3007 //biosC0[0x19] = psxBios_ioabort;
3008 //biosC0[0x1a] = psxBios_sys_c0_1a
3009 //biosC0[0x1b] = psxBios_KernelRedirect;
3010 //biosC0[0x1c] = psxBios_PatchAOTable;
3011 //************** THE END ***************************************
3014 size = sizeof(EvCB) * 32;
3015 Event = (void *)&psxR[base]; base += size * 6;
3016 memset(Event, 0, size * 6);
3019 RcEV = Event + 32 * 2;
3020 UeEV = Event + 32 * 3;
3021 SwEV = Event + 32 * 4;
3022 ThEV = Event + 32 * 5;
3024 ptr = (u32 *)&psxM[0x0874]; // b0 table
3025 ptr[0] = SWAPu32(0x4c54 - 0x884);
3027 ptr = (u32 *)&psxM[0x0674]; // c0 table
3028 ptr[6] = SWAPu32(0xc80);
3030 memset(SysIntRP, 0, sizeof(SysIntRP));
3031 memset(Thread, 0, sizeof(Thread));
3032 Thread[0].status = 2; // main thread
3039 pad_buf1len = pad_buf2len = 0;
3045 memset(FDesc, 0, sizeof(FDesc));
3046 card_active_chan = 0;
3048 psxMu32ref(0x0150) = SWAPu32(0x160);
3049 psxMu32ref(0x0154) = SWAPu32(0x320);
3050 psxMu32ref(0x0160) = SWAPu32(0x248);
3051 strcpy((char *)&psxM[0x248], "bu");
3052 /* psxMu32ref(0x0ca8) = SWAPu32(0x1f410004);
3053 psxMu32ref(0x0cf0) = SWAPu32(0x3c020000);
3054 psxMu32ref(0x0cf4) = SWAPu32(0x2442641c);
3055 psxMu32ref(0x09e0) = SWAPu32(0x43d0);
3056 psxMu32ref(0x4d98) = SWAPu32(0x946f000a);
3059 psxRu32ref(0x0000) = SWAPu32((0x3b << 26) | 4);
3060 /* Whatever this does, it actually breaks CTR, even without the uninitiliazed memory patch.
3061 Normally games shouldn't read from address 0 yet they do. See explanation below in details. */
3062 //psxMu32ref(0x0000) = SWAPu32((0x3b << 26) | 0);
3063 psxMu32ref(0x00a0) = SWAPu32((0x3b << 26) | 1);
3064 psxMu32ref(0x00b0) = SWAPu32((0x3b << 26) | 2);
3065 psxMu32ref(0x00c0) = SWAPu32((0x3b << 26) | 3);
3066 psxMu32ref(0x4c54) = SWAPu32((0x3b << 26) | 0);
3067 psxMu32ref(0x8000) = SWAPu32((0x3b << 26) | 5);
3068 psxMu32ref(0x07a0) = SWAPu32((0x3b << 26) | 0);
3069 psxMu32ref(0x0884) = SWAPu32((0x3b << 26) | 0);
3070 psxMu32ref(0x0894) = SWAPu32((0x3b << 26) | 0);
3072 // initial stack pointer for BIOS interrupt
3073 psxMu32ref(0x6c80) = SWAPu32(0x000085c8);
3076 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3079 len = 0x80000 - 0x66000;
3080 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3081 len = 0x80000 - 0x69d68;
3082 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3085 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3087 hleSoftCall = FALSE;
3089 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3090 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3091 Here are some examples of games not working with this fix in place :
3092 R-type won't get past the Irem logo if not implemented.
3093 Crash Team Racing will softlock after the Sony logo.
3096 psxMu32ref(0x0000) = SWAPu32(0x00000003);
3098 But overwritten by 00000003h after soon.
3099 psxMu32ref(0x0000) = SWAPu32(0x00001A3C);
3101 psxMu32ref(0x0004) = SWAPu32(0x800C5A27);
3102 psxMu32ref(0x0008) = SWAPu32(0x08000403);
3103 psxMu32ref(0x000C) = SWAPu32(0x00000000);
3106 void psxBiosShutdown() {
3109 #define psxBios_PADpoll(pad) { \
3110 PAD##pad##_startPoll(pad); \
3111 pad_buf##pad[0] = 0; \
3112 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3113 if (!(pad_buf##pad[1] & 0x0f)) { \
3116 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3118 PAD##pad##_poll(0); \
3120 while (bufcount--) { \
3121 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3125 void biosInterrupt() {
3128 // if (psxHu32(0x1070) & 0x1) { // Vsync
3129 if (pad_buf != NULL) {
3130 u32 *buf = (u32*)pad_buf;
3132 if (!Config.UseNet) {
3134 if (PAD1_poll(0x42) == 0x23) {
3136 *buf = PAD1_poll(0) << 8;
3137 *buf |= PAD1_poll(0);
3139 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3140 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3143 *buf = PAD1_poll(0) << 8;
3144 *buf|= PAD1_poll(0);
3148 if (PAD2_poll(0x42) == 0x23) {
3150 *buf |= PAD2_poll(0) << 24;
3151 *buf |= PAD2_poll(0) << 16;
3153 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3154 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3157 *buf |= PAD2_poll(0) << 24;
3158 *buf |= PAD2_poll(0) << 16;
3166 data = PAD1_poll(0) << 8;
3167 data |= PAD1_poll(0);
3169 if (NET_sendPadData(&data, 2) == -1)
3172 if (NET_recvPadData(&((u16*)buf)[0], 1) == -1)
3174 if (NET_recvPadData(&((u16*)buf)[1], 2) == -1)
3178 if (Config.UseNet && pad_buf1 != NULL && pad_buf2 != NULL) {
3181 if (NET_sendPadData(pad_buf1, i) == -1)
3184 if (NET_recvPadData(pad_buf1, 1) == -1)
3186 if (NET_recvPadData(pad_buf2, 2) == -1)
3200 if (psxHu32(0x1070) & 0x1) { // Vsync
3201 if (RcEV[3][1].status == EvStACTIVE) {
3202 softCall(RcEV[3][1].fhandler);
3203 // hwWrite32(0x1f801070, ~(1));
3207 if (psxHu32(0x1070) & 0x70) { // Rcnt 0,1,2
3210 for (i = 0; i < 3; i++) {
3211 if (psxHu32(0x1070) & (1 << (i + 4))) {
3212 if (RcEV[i][1].status == EvStACTIVE) {
3213 softCall(RcEV[i][1].fhandler);
3215 psxHwWrite32(0x1f801070, ~(1 << (i + 4)));
3221 void psxBiosException() {
3224 switch (psxRegs.CP0.n.Cause & 0x3c) {
3225 case 0x00: // Interrupt
3226 interrupt_r26=psxRegs.CP0.n.EPC;
3228 // PSXCPU_LOG("interrupt\n");
3232 sp = psxMu32(0x6c80); // create new stack for interrupt handlers
3236 for (i = 0; i < 8; i++) {
3238 u32 *queue = (u32 *)PSXM(SysIntRP[i]);
3245 if (jmp_int != NULL) {
3248 psxHwWrite32(0x1f801070, 0xffffffff);
3253 for (i = 0; i < 8; i++) // s0-s7
3254 psxRegs.GPR.r[16 + i] = jmp_int[3 + i];
3261 psxHwWrite16(0x1f801070, 0);
3264 case 0x20: // Syscall
3266 PSXCPU_LOG("syscall exp %x\n", a0);
3269 case 1: // EnterCritical - disable irq's
3270 /* Fixes Medievil 2 not loading up new game, Digimon World not booting up and possibly others */
3271 v0 = (psxRegs.CP0.n.Status & 0x404) == 0x404;
3272 psxRegs.CP0.n.Status &= ~0x404;
3275 case 2: // ExitCritical - enable irq's
3276 psxRegs.CP0.n.Status |= 0x404;
3278 /* Normally this should cover SYS(00h, SYS(04h but they don't do anything relevant so... */
3282 pc0 = psxRegs.CP0.n.EPC + 4;
3284 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3285 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3290 PSXCPU_LOG("unknown bios exception!\n");
3295 pc0 = psxRegs.CP0.n.EPC;
3296 if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;
3298 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
3299 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
3302 #define bfreeze(ptr, size) { \
3303 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3304 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3308 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3309 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3311 #define bfreezepsxMptr(ptr, type) { \
3313 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3314 else psxRu32ref(base) = 0; \
3316 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3317 else (ptr) = NULL; \
3319 base += sizeof(u32); \
3322 void psxBiosFreeze(int Mode) {
3325 bfreezepsxMptr(jmp_int, u32);
3326 bfreezepsxMptr(pad_buf, int);
3327 bfreezepsxMptr(pad_buf1, char);
3328 bfreezepsxMptr(pad_buf2, char);
3329 bfreezepsxMptr(heap_addr, u32);
3330 bfreezel(&pad_buf1len);
3331 bfreezel(&pad_buf2len);
3334 bfreezel(&CardState);
3336 bfreezel(&CurThread);
3338 bfreezel(&card_active_chan);
3339 bfreezel(&pad_stopped);
3340 bfreezel(&heap_size);