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 #include "psxinterpreter.h"
41 #if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
42 #pragma GCC diagnostic ignored "-Wpointer-sign"
46 //#define PSXBIOS_LOG printf
47 #define PSXBIOS_LOG(...)
50 char *biosA0n[256] = {
52 "open", "lseek", "read", "write",
53 "close", "ioctl", "exit", "sys_a0_07",
54 "getc", "putc", "todigit", "atof",
55 "strtoul", "strtol", "abs", "labs",
57 "atoi", "atol", "atob", "setjmp",
58 "longjmp", "strcat", "strncat", "strcmp",
59 "strncmp", "strcpy", "strncpy", "strlen",
60 "index", "rindex", "strchr", "strrchr",
62 "strpbrk", "strspn", "strcspn", "strtok",
63 "strstr", "toupper", "tolower", "bcopy",
64 "bzero", "bcmp", "memcpy", "memset",
65 "memmove", "memcmp", "memchr", "rand",
67 "srand", "qsort", "strtod", "malloc",
68 "free", "lsearch", "bsearch", "calloc",
69 "realloc", "InitHeap", "_exit", "getchar",
70 "putchar", "gets", "puts", "printf",
72 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
73 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
74 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
75 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
77 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
78 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
79 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
80 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
82 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
83 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
84 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
85 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
87 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
88 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
89 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
90 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
92 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
93 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
94 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
95 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
97 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
98 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
99 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
100 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
102 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
103 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
104 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
105 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
107 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
111 char *biosB0n[256] = {
113 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
114 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
115 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
116 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
118 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
119 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
120 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
121 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
123 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
124 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
125 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
126 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
128 "sys_b0_30", "sys_b0_31", "open", "lseek",
129 "read", "write", "close", "ioctl",
130 "exit", "sys_b0_39", "getc", "putc",
131 "getchar", "putchar", "gets", "puts",
133 "cd", "format", "firstfile", "nextfile",
134 "rename", "delete", "undelete", "AddDevice",
135 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
136 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
138 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
139 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
140 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
141 "_card_status", "_card_wait",
144 char *biosC0n[256] = {
146 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
147 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
148 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
149 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
151 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
152 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
153 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
157 //#define r0 (psxRegs.GPR.n.r0)
158 #define at (psxRegs.GPR.n.at)
159 #define v0 (psxRegs.GPR.n.v0)
160 #define v1 (psxRegs.GPR.n.v1)
161 #define a0 (psxRegs.GPR.n.a0)
162 #define a1 (psxRegs.GPR.n.a1)
163 #define a2 (psxRegs.GPR.n.a2)
164 #define a3 (psxRegs.GPR.n.a3)
165 #define t0 (psxRegs.GPR.n.t0)
166 #define t1 (psxRegs.GPR.n.t1)
167 #define t2 (psxRegs.GPR.n.t2)
168 #define t3 (psxRegs.GPR.n.t3)
169 #define t4 (psxRegs.GPR.n.t4)
170 #define t5 (psxRegs.GPR.n.t5)
171 #define t6 (psxRegs.GPR.n.t6)
172 #define t7 (psxRegs.GPR.n.t7)
173 #define t8 (psxRegs.GPR.n.t8)
174 #define t9 (psxRegs.GPR.n.t9)
175 #define s0 (psxRegs.GPR.n.s0)
176 #define s1 (psxRegs.GPR.n.s1)
177 #define s2 (psxRegs.GPR.n.s2)
178 #define s3 (psxRegs.GPR.n.s3)
179 #define s4 (psxRegs.GPR.n.s4)
180 #define s5 (psxRegs.GPR.n.s5)
181 #define s6 (psxRegs.GPR.n.s6)
182 #define s7 (psxRegs.GPR.n.s7)
183 #define k0 (psxRegs.GPR.n.k0)
184 #define k1 (psxRegs.GPR.n.k1)
185 #define gp (psxRegs.GPR.n.gp)
186 #define sp (psxRegs.GPR.n.sp)
187 #define fp (psxRegs.GPR.n.fp)
188 #define ra (psxRegs.GPR.n.ra)
189 #define pc0 (psxRegs.pc)
191 #define Ra0 ((char *)PSXM(a0))
192 #define Ra1 ((char *)PSXM(a1))
193 #define Ra2 ((char *)PSXM(a2))
194 #define Ra3 ((char *)PSXM(a3))
195 #define Rv0 ((char *)PSXM(v0))
196 #define Rsp ((char *)PSXM(sp))
207 #define EvStUNUSED 0x0000
208 #define EvStDISABLED 0x1000
209 #define EvStACTIVE 0x2000
210 #define EvStALREADY 0x4000
212 #define EvMdCALL 0x1000
213 #define EvMdMARK 0x2000
236 u32 _sp, _fp, _gp, ret, base;
256 // todo: FileDesc layout is wrong
257 // todo: get rid of these globals
258 static FileDesc FDesc[32];
259 static char ffile[64], *pfile;
262 // fixed RAM offsets, SCPH1001 compatible
263 #define A_TT_ExCB 0x0100
264 #define A_TT_PCB 0x0108
265 #define A_TT_TCB 0x0110
266 #define A_TT_EvCB 0x0120
267 #define A_A0_TABLE 0x0200
268 #define A_B0_TABLE 0x0874
269 #define A_C0_TABLE 0x0674
270 #define A_SYSCALL 0x0650
271 #define A_EXCEPTION 0x0c80
272 #define A_EXC_SP 0x6cf0
273 #define A_EEXIT_DEF 0x6cf4
274 #define A_KMALLOC_PTR 0x7460
275 #define A_KMALLOC_SIZE 0x7464
276 #define A_KMALLOC_END 0x7468
277 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
278 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
279 #define A_CARD_IRQR_ENA 0x74bc // same for card
280 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
281 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
282 #define A_PAD_IN_LEN 0x74d8
283 #define A_PAD_OUT_LEN 0x74e0
284 #define A_PAD_DR_DST 0x74c4
285 #define A_CARD_CHAN1 0x7500
286 #define A_PAD_DR_BUF1 0x7570
287 #define A_PAD_DR_BUF2 0x7598
288 #define A_EEXIT_PTR 0x75d0
289 #define A_EXC_STACK 0x85d8 // exception stack top
290 #define A_RCNT_VBL_ACK 0x8600
291 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
292 #define A_HEAP_BASE 0x9000
293 #define A_HEAP_SIZE 0x9004
294 #define A_HEAP_END 0x9008
295 #define A_HEAP_FLAG 0x900c
296 #define A_CD_EVENTS 0xb9b8
297 #define A_EXC_GP 0xf450
299 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
301 static u32 loadRam32(u32 addr)
303 assert(!(addr & 0x5f800000));
304 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
307 static void *castRam8ptr(u32 addr)
309 assert(!(addr & 0x5f800000));
310 return psxM + (addr & 0x1fffff);
313 static void *castRam32ptr(u32 addr)
315 assert(!(addr & 0x5f800003));
316 return psxM + (addr & 0x1ffffc);
319 static void *loadRam8ptr(u32 addr)
321 return castRam8ptr(loadRam32(addr));
324 static void *loadRam32ptr(u32 addr)
326 return castRam32ptr(loadRam32(addr));
329 static void storeRam8(u32 addr, u8 d)
331 assert(!(addr & 0x5f800000));
332 *((u8 *)psxM + (addr & 0x1fffff)) = d;
335 static void storeRam32(u32 addr, u32 d)
337 assert(!(addr & 0x5f800000));
338 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
341 static void mips_return(u32 val)
347 static void use_cycles(u32 cycle)
349 psxRegs.cycle += cycle * 2;
352 static void mips_return_c(u32 val, u32 cycle)
358 static void mips_return_void_c(u32 cycle)
364 static int returned_from_exception(void)
366 // 0x80000080 means it took another exception just after return
367 return pc0 == k0 || pc0 == 0x80000080;
370 static inline void softCall(u32 pc) {
372 u32 ssr = psxRegs.CP0.n.SR;
376 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
378 while (pc0 != 0x80001000 && ++lim < 1000000)
379 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
382 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
384 psxRegs.CP0.n.SR |= ssr & 0x404;
387 static inline void softCallInException(u32 pc) {
393 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
394 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
397 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
398 if (pc0 == 0x80001000)
402 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
403 static u32 DeliverEvent(u32 class, u32 spec);
404 static u32 UnDeliverEvent(u32 class, u32 spec);
405 static void CloseEvent(u32 ev);
410 // System calls A0 */
413 #define buread(Ra1, mcd, length) { \
414 PSXBIOS_LOG("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
415 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
416 memcpy(Ra1, ptr, length); \
417 psxCpu->Clear(a1, (length + 3) / 4); \
418 if (FDesc[1 + mcd].mode & 0x8000) { \
419 DeliverEvent(0xf0000011, 0x0004); \
420 DeliverEvent(0xf4000001, 0x0004); \
423 FDesc[1 + mcd].offset += v0; \
426 #define buwrite(Ra1, mcd, length) { \
427 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
428 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
429 ptr = Mcd##mcd##Data + offset; \
430 memcpy(ptr, Ra1, length); \
431 FDesc[1 + mcd].offset += length; \
432 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
433 if (FDesc[1 + mcd].mode & 0x8000) { \
434 DeliverEvent(0xf0000011, 0x0004); \
435 DeliverEvent(0xf4000001, 0x0004); \
440 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
441 /* For some strange reason, the returned character is sign-expanded; */
442 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
443 /* TODO FIX ME : Properly implement this behaviour */
444 void psxBios_getc(void) // 0x03, 0x35
449 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
453 if (pa1 != INVALID_PTR) {
455 case 2: buread(pa1, 1, 1); break;
456 case 3: buread(pa1, 2, 1); break;
463 /* Copy of psxBios_write, except size is 1. */
464 void psxBios_putc(void) // 0x09, 0x3B
469 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
472 if (pa1 == INVALID_PTR) {
477 if (a0 == 1) { // stdout
478 char *ptr = (char *)pa1;
482 printf("%c", *ptr++); a2--;
488 case 2: buwrite(pa1, 1, 1); break;
489 case 3: buwrite(pa1, 2, 1); break;
495 void psxBios_todigit(void) // 0x0a
499 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
502 if (c >= 0x30 && c < 0x3A) {
505 else if (c > 0x60 && c < 0x7B) {
508 else if (c > 0x40 && c < 0x5B) {
511 else if (c >= 0x80) {
522 void psxBios_abs() { // 0x0e
523 if ((s32)a0 < 0) v0 = -(s32)a0;
528 void psxBios_labs() { // 0x0f
532 void psxBios_atoi() { // 0x10
534 char *p = (char *)Ra0;
538 case ' ': case '\t': continue;
545 while (*p >= '0' && *p <= '9') {
546 n = n * 10 + *p++ - '0';
553 void psxBios_atol() { // 0x11
563 static void psxBios_setjmp() { // 0x13
564 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
567 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
569 jmp_buf->ra_ = SWAP32(ra);
570 jmp_buf->sp_ = SWAP32(sp);
571 jmp_buf->fp_ = SWAP32(fp);
572 for (i = 0; i < 8; i++) // s0-s7
573 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
574 jmp_buf->gp_ = SWAP32(gp);
576 mips_return_c(0, 15);
579 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
583 ra = SWAP32(jmp_buf->ra_);
584 sp = SWAP32(jmp_buf->sp_);
585 fp = SWAP32(jmp_buf->fp_);
586 for (i = 0; i < 8; i++) // s0-s7
587 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
588 gp = SWAP32(jmp_buf->gp_);;
591 void psxBios_longjmp() { // 0x14
592 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
594 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
595 longjmp_load(jmp_buf);
596 mips_return_c(a1, 15);
599 void psxBios_strcat() { // 0x15
600 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
603 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
605 if (a0 == 0 || a1 == 0)
613 while ((*p1++ = *p2++) != '\0');
618 void psxBios_strncat() { // 0x16
619 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
623 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
625 if (a0 == 0 || a1 == 0)
633 while ((*p1++ = *p2++) != '\0') {
643 void psxBios_strcmp() { // 0x17
644 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
646 if (a0 == 0 && a1 == 0)
652 else if (a0 == 0 && a1 != 0)
658 else if (a0 != 0 && a1 == 0)
665 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
668 while (*p1 == *p2++) {
687 void psxBios_strncmp() { // 0x18
688 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
690 if (a0 == 0 && a1 == 0)
696 else if (a0 == 0 && a1 != 0)
702 else if (a0 != 0 && a1 == 0)
709 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
712 while (--n >= 0 && *p1 == *p2++) {
716 v1 = a2 - ((a2-n) - 1);
724 v0 = (n < 0 ? 0 : *p1 - *--p2);
726 v1 = a2 - ((a2-n) - 1);
732 void psxBios_strcpy() { // 0x19
733 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
734 if (a0 == 0 || a1 == 0)
740 while ((*p1++ = *p2++) != '\0');
745 void psxBios_strncpy() { // 0x1a
746 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
748 if (a0 == 0 || a1 == 0)
754 for (i = 0; i < n; i++) {
755 if ((*p1++ = *p2++) == '\0') {
767 void psxBios_strlen() { // 0x1b
768 char *p = (char *)Ra0;
779 void psxBios_index() { // 0x1c
780 char *p = (char *)Ra0;
790 v0 = a0 + (p - (char *)Ra0);
794 } while (*p++ != '\0');
799 void psxBios_rindex() { // 0x1d
800 char *p = (char *)Ra0;
810 v0 = a0 + (p - (char *)Ra0);
811 } while (*p++ != '\0');
816 void psxBios_strchr() { // 0x1e
820 void psxBios_strrchr() { // 0x1f
824 void psxBios_strpbrk() { // 0x20
825 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
827 while ((c = *p1++) != '\0') {
828 for (scanp = p2; (sc = *scanp++) != '\0';) {
830 v0 = a0 + (p1 - 1 - (char *)Ra0);
837 // BUG: return a0 instead of NULL if not found
841 void psxBios_strspn() { // 0x21
844 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
845 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
846 if (*p2 == '\0') break;
849 v0 = p1 - (char *)Ra0; pc0 = ra;
852 void psxBios_strcspn() { // 0x22
855 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
856 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
857 if (*p2 != '\0') break;
860 v0 = p1 - (char *)Ra0; pc0 = ra;
863 void psxBios_strtok() { // 0x23
864 char *pcA0 = (char *)Ra0;
865 char *pcRet = strtok(pcA0, (char *)Ra1);
867 v0 = a0 + pcRet - pcA0;
873 void psxBios_strstr() { // 0x24
874 char *p = (char *)Ra0, *p1, *p2;
880 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
885 v0 = a0 + (p - (char *)Ra0);
896 void psxBios_toupper() { // 0x25
897 v0 = (s8)(a0 & 0xff);
898 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
902 void psxBios_tolower() { // 0x26
903 v0 = (s8)(a0 & 0xff);
904 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
908 static void do_memset(u32 dst, u32 v, s32 len)
914 if (db != INVALID_PTR)
918 psxCpu->Clear(dst, (len + 3) / 4);
921 static void do_memcpy(u32 dst, u32 src, s32 len)
923 u32 d = dst, s = src;
926 const u8 *sb = PSXM(s);
928 if (db != INVALID_PTR && sb != INVALID_PTR)
933 psxCpu->Clear(dst, (len + 3) / 4);
936 static void psxBios_memcpy();
938 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
939 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
940 u32 ret = a0, cycles = 0;
941 if (a0 == 0) // ...but it checks src this time
948 do_memcpy(a1, a0, a2);
954 mips_return_c(ret, cycles + 5);
957 static void psxBios_bzero() { // 0x28
958 /* Same as memset here (See memset below) */
959 u32 ret = a0, cycles;
960 if (a0 == 0 || (s32)a1 <= 0)
965 do_memset(a0, 0, a1);
969 // todo: many more cycles due to uncached bios mem
970 mips_return_c(ret, cycles + 5);
973 void psxBios_bcmp() { // 0x29
974 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
976 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
978 while ((s32)a2-- > 0) {
979 if (*p1++ != *p2++) {
980 v0 = *p1 - *p2; // BUG: compare the NEXT byte
989 static void psxBios_memcpy() { // 0x2a
990 u32 ret = a0, cycles = 0;
997 do_memcpy(a0, a1, a2);
1004 mips_return_c(ret, cycles + 5);
1007 static void psxBios_memset() { // 0x2b
1008 u32 ret = a0, cycles;
1009 if (a0 == 0 || (s32)a2 <= 0)
1011 mips_return_c(0, 6);
1014 do_memset(a0, a1, a2);
1018 // todo: many more cycles due to uncached bios mem
1019 mips_return_c(ret, cycles + 5);
1022 void psxBios_memmove() { // 0x2c
1023 u32 ret = a0, cycles = 0;
1026 mips_return_c(0, 4);
1030 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1031 u32 dst = a0, len = a2 + 1;
1034 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1035 const u8 *sb = PSXM(a1);
1037 if (db != INVALID_PTR && sb != INVALID_PTR)
1043 psxCpu->Clear(dst, (len + 3) / 4);
1044 cycles = 10 + len * 8;
1045 } else if ((s32)a2 > 0) {
1046 do_memcpy(a0, a1, a2);
1052 mips_return_c(ret, cycles + 5);
1055 void psxBios_memcmp() { // 0x2d
1059 void psxBios_memchr() { // 0x2e
1060 char *p = (char *)Ra0;
1062 if (a0 == 0 || a2 > 0x7FFFFFFF)
1068 while ((s32)a2-- > 0) {
1069 if (*p++ != (s8)a1) continue;
1070 v0 = a0 + (p - (char *)Ra0 - 1);
1078 void psxBios_rand() { // 0x2f
1079 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1080 v0 = (s >> 16) & 0x7fff;
1081 psxMu32ref(0x9010) = SWAPu32(s);
1085 void psxBios_srand() { // 0x30
1086 psxMu32ref(0x9010) = SWAPu32(a0);
1090 static u32 qscmpfunc, qswidth;
1092 static inline int qscmp(char *a, char *b) {
1095 a0 = sa0 + (a - (char *)PSXM(sa0));
1096 a1 = sa0 + (b - (char *)PSXM(sa0));
1098 softCall(qscmpfunc);
1104 static inline void qexchange(char *i, char *j) {
1115 static inline void q3exchange(char *i, char *j, char *k) {
1127 static void qsort_main(char *a, char *l) {
1128 char *i, *j, *lp, *hp;
1133 if ((n = l - a) <= qswidth)
1135 n = qswidth * (n / (2 * qswidth));
1141 if ((c = qscmp(i, lp)) == 0) {
1142 qexchange(i, lp -= qswidth);
1153 if ((c = qscmp(hp, j)) == 0) {
1154 qexchange(hp += qswidth, j);
1159 q3exchange(i, hp += qswidth, j);
1173 if (lp - a >= l - hp) {
1174 qsort_main(hp + qswidth, l);
1183 q3exchange(j, lp -= qswidth, i);
1188 void psxBios_qsort() { // 0x31
1191 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1196 // this isn't how the real bios works, but maybe good enough
1197 static void psxBios_malloc() { // 0x33
1198 u32 *heap_addr, *heap_end;
1199 u32 *chunk, *newchunk = NULL;
1200 unsigned int dsize = 0, csize, cstat;
1202 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
1203 heap_addr = loadRam32ptr(A_HEAP_BASE);
1204 heap_end = loadRam32ptr(A_HEAP_END);
1205 if (heap_addr >= heap_end) {
1211 // scan through heap and combine free chunks of space
1214 while(chunk < heap_end) {
1215 // get size and status of actual chunk
1216 csize = ((u32)*chunk) & 0xfffffffc;
1217 cstat = ((u32)*chunk) & 1;
1219 // most probably broken heap descriptor
1220 // this fixes Burning Road
1223 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1228 // it's a free chunk
1233 colflag = 1; // let's begin a new collection of free memory
1235 else dsize += (csize+4); // add the new size including header
1237 // not a free chunk: did we start a collection ?
1239 if(colflag == 1) { // collection is over
1241 *newchunk = SWAP32(dsize | 1);
1246 chunk = (u32*)((uptr)chunk + csize + 4);
1248 // if neccessary free memory on end of heap
1250 *newchunk = SWAP32(dsize | 1);
1253 csize = ((u32)*chunk) & 0xfffffffc;
1254 cstat = ((u32)*chunk) & 1;
1255 dsize = (a0 + 3) & 0xfffffffc;
1257 // exit on uninitialized heap
1258 if (chunk == NULL) {
1259 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1265 // search an unused chunk that is big enough until the end of the heap
1266 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1267 chunk = (u32*)((uptr)chunk + csize + 4);
1269 // catch out of memory
1270 if(chunk >= heap_end) {
1271 printf("malloc %x,%x: Out of memory error!\n",
1277 csize = ((u32)*chunk) & 0xfffffffc;
1278 cstat = ((u32)*chunk) & 1;
1282 if(dsize == csize) {
1283 // chunk has same size
1284 *chunk &= 0xfffffffc;
1285 } else if (dsize > csize) {
1290 *chunk = SWAP32(dsize);
1291 newchunk = (u32*)((uptr)chunk + dsize + 4);
1292 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1295 // return pointer to allocated memory
1296 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1298 //printf ("malloc %x,%x\n", v0, a0);
1302 static void psxBios_free() { // 0x34
1303 PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1304 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1305 mips_return_void_c(5);
1308 static void psxBios_calloc() { // 0x37
1310 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1312 a0 = size = a0 * a1;
1316 a0 = ret; a1 = size;
1319 mips_return_c(ret, 21);
1322 void psxBios_realloc() { // 0x38
1326 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1330 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1335 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1340 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1341 /* Note that it is not quite implemented this way here. */
1351 /* InitHeap(void *block , int n) */
1352 static void psxBios_InitHeap() { // 0x39
1353 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1355 storeRam32(A_HEAP_BASE, a0);
1356 storeRam32(A_HEAP_SIZE, a1);
1357 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1358 storeRam32(A_HEAP_FLAG, 0);
1361 mips_return_void_c(14);
1364 void psxBios_getchar() { //0x3b
1365 v0 = getchar(); pc0 = ra;
1368 static void psxBios_printf_psxout() { // 0x3f
1377 if (psp != INVALID_PTR) {
1378 memcpy(save, psp, 4 * 4);
1379 psxMu32ref(sp) = SWAP32((u32)a0);
1380 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1381 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1382 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1394 tmp2[j++] = Ra0[i]; goto _start;
1396 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1407 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1411 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1417 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1419 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1421 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1423 *ptmp++ = Ra0[i]; break;
1433 if (psp != INVALID_PTR)
1434 memcpy(psp, save, 4 * 4);
1437 SysPrintf("%s", tmp);
1440 void psxBios_printf() { // 0x3f
1441 psxBios_printf_psxout();
1445 void psxBios_format() { // 0x41
1446 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1448 CreateMcd(Config.Mcd1);
1449 LoadMcd(1, Config.Mcd1);
1452 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1454 CreateMcd(Config.Mcd2);
1455 LoadMcd(2, Config.Mcd2);
1465 static void psxBios_SystemErrorUnresolvedException() {
1466 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1467 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1468 storeRam32(0xfffc, 0x12345678);
1470 mips_return_void_c(1000);
1474 * long Load(char *name, struct EXEC *header);
1477 void psxBios_Load() { // 0x42
1482 if (pa1 != INVALID_PTR && LoadCdromFile(Ra0, &eheader) == 0) {
1483 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1484 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1487 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1493 * int Exec(struct EXEC *header , int argc , char **argv);
1496 void psxBios_Exec() { // 43
1497 EXEC *header = (EXEC *)castRam32ptr(a0);
1501 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1503 header->_sp = SWAP32(sp);
1504 header->_fp = SWAP32(fp);
1505 header->_sp = SWAP32(sp);
1506 header->_gp = SWAP32(gp);
1507 header->ret = SWAP32(ra);
1508 header->base = SWAP32(s0);
1510 ptr = SWAP32(header->b_addr);
1511 len = SWAP32(header->b_size);
1517 if (header->S_addr != 0)
1518 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1520 gp = SWAP32(header->gp0);
1528 pc0 = SWAP32(header->_pc0);
1531 void psxBios_FlushCache() { // 44
1533 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1535 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1536 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1540 void psxBios_GPU_dw() { // 0x46
1545 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1548 GPU_writeData(0xa0000000);
1549 GPU_writeData((a1<<0x10)|(a0&0xffff));
1550 GPU_writeData((a3<<0x10)|(a2&0xffff));
1552 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1555 GPU_writeData(SWAPu32(*ptr++));
1561 void psxBios_mem2vram() { // 0x47
1564 GPU_writeData(0xa0000000);
1565 GPU_writeData((a1<<0x10)|(a0&0xffff));
1566 GPU_writeData((a3<<0x10)|(a2&0xffff));
1567 size = ((((a2 * a3) / 2) >> 4) << 16);
1568 GPU_writeStatus(0x04000002);
1569 psxHwWrite32(0x1f8010f4,0);
1570 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1571 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1572 psxHwWrite32(0x1f8010a4, size | 0x10);
1573 psxHwWrite32(0x1f8010a8,0x01000201);
1578 void psxBios_SendGPU() { // 0x48
1579 GPU_writeStatus(a0);
1584 void psxBios_GPU_cw() { // 0x49
1591 void psxBios_GPU_cwb() { // 0x4a
1592 u32 *ptr = (u32*)Ra0;
1597 GPU_writeData(SWAPu32(*ptr++));
1603 void psxBios_GPU_SendPackets() { //4b:
1605 GPU_writeStatus(0x04000002);
1606 psxHwWrite32(0x1f8010f4,0);
1607 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1608 psxHwWrite32(0x1f8010a0,a0);
1609 psxHwWrite32(0x1f8010a4,0);
1610 psxHwWrite32(0x1f8010a8,0x010000401);
1614 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1615 psxHwWrite32(0x1f8010a8,0x00000401);
1616 GPU_writeData(0x0400000);
1617 GPU_writeData(0x0200000);
1618 GPU_writeData(0x0100000);
1623 void psxBios_GPU_GetGPUStatus() { // 0x4d
1624 v0 = GPU_readStatus();
1630 void psxBios_LoadExec() { // 51
1631 EXEC *header = (EXEC*)PSXM(0xf000);
1635 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1637 s_addr = a1; s_size = a2;
1642 header->S_addr = s_addr;
1643 header->s_size = s_size;
1645 a0 = 0xf000; a1 = 0; a2 = 0;
1649 void psxBios__bu_init() { // 70
1651 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1654 DeliverEvent(0xf0000011, 0x0004);
1655 DeliverEvent(0xf4000001, 0x0004);
1660 void psxBios__96_init() { // 71
1662 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1668 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1669 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1670 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1672 static void psxBios_DequeueCdIntr_() {
1673 psxBios_SysDeqIntRP_(0, 0x91d0);
1674 psxBios_SysDeqIntRP_(0, 0x91e0);
1678 static void psxBios_DequeueCdIntr() { // a3
1679 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1680 psxBios_DequeueCdIntr_();
1683 static void psxBios_CdRemove() { // 56, 72
1684 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1686 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1687 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1688 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1689 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1690 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1691 psxBios_DequeueCdIntr_();
1693 // EnterCriticalSection - should be done at the beginning,
1694 // but this way is much easier to implement
1700 void psxBios_SetMem() { // 9f
1701 u32 new = psxHu32(0x1060);
1704 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1709 psxHu32ref(0x1060) = SWAP32(new);
1710 psxMu32ref(0x060) = a0;
1711 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1715 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1716 psxMu32ref(0x060) = a0;
1717 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1720 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1727 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1728 static void psxBios_get_cd_status() // a6
1730 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1735 static void psxBios__card_info() { // ab
1736 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1738 storeRam32(A_CARD_CHAN1, a0);
1745 if (McdDisable[port & 1])
1749 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1754 if (McdDisable[0] && McdDisable[1])
1757 DeliverEvent(0xf0000011, 0x0004);
1758 // DeliverEvent(0xf4000001, 0x0004);
1759 DeliverEvent(0xf4000001, ret);
1763 void psxBios__card_load() { // ac
1765 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1768 storeRam32(A_CARD_CHAN1, a0);
1770 // DeliverEvent(0xf0000011, 0x0004);
1771 DeliverEvent(0xf4000001, 0x0004);
1776 static void psxBios_GetSystemInfo() { // b4
1778 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1779 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1782 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1783 case 2: ret = 0xbfc0012c; break;
1784 case 5: ret = loadRam32(0x60) << 10; break;
1786 mips_return_c(ret, 20);
1789 /* System calls B0 */
1791 static u32 psxBios_SysMalloc_(u32 size);
1793 static void psxBios_SysMalloc() { // B 00
1794 u32 ret = psxBios_SysMalloc_(a0);
1796 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1797 mips_return_c(ret, 33);
1800 void psxBios_SetRCnt() { // 02
1802 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1809 psxRcntWtarget(a0, a1);
1810 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1811 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1812 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1813 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1814 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1816 psxRcntWmode(a0, mode);
1821 void psxBios_GetRCnt() { // 03
1823 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1827 if (a0 != 3) v0 = psxRcntRcount(a0);
1832 void psxBios_StartRCnt() { // 04
1834 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1838 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1839 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1843 void psxBios_StopRCnt() { // 05
1845 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1849 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1850 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1854 void psxBios_ResetRCnt() { // 06
1856 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1861 psxRcntWmode(a0, 0);
1862 psxRcntWtarget(a0, 0);
1863 psxRcntWcount(a0, 0);
1868 static u32 DeliverEvent(u32 class, u32 spec) {
1869 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1870 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1871 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1872 u32 i, lim = evcb_len / 0x1c;
1874 for (i = 0; i < lim; i++, ev++) {
1876 if (SWAP32(ev->status) != EvStACTIVE)
1879 if (SWAP32(ev->class) != class)
1882 if (SWAP32(ev->spec) != spec)
1885 ret = SWAP32(ev->mode);
1886 if (ret == EvMdMARK) {
1887 ev->status = SWAP32(EvStALREADY);
1891 if (ret == EvMdCALL) {
1892 ret = SWAP32(ev->fhandler);
1904 static u32 UnDeliverEvent(u32 class, u32 spec) {
1905 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1906 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1907 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1908 u32 i, lim = evcb_len / 0x1c;
1910 for (i = 0; i < lim; i++, ev++) {
1912 if (SWAP32(ev->status) != EvStALREADY)
1915 if (SWAP32(ev->class) != class)
1918 if (SWAP32(ev->spec) != spec)
1921 if (SWAP32(ev->mode) == EvMdMARK)
1922 ev->status = SWAP32(EvStACTIVE);
1928 static void psxBios_DeliverEvent() { // 07
1930 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1932 ret = DeliverEvent(a0, a1);
1936 static s32 get_free_EvCB_slot() {
1937 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1938 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1941 for (i = 0; i < lim; i++, ev++) {
1943 if (ev->status == SWAP32(EvStUNUSED))
1949 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
1950 u32 ret = get_free_EvCB_slot();
1951 if ((s32)ret >= 0) {
1952 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
1953 ev->class = SWAP32(class);
1954 ev->status = SWAP32(EvStDISABLED);
1955 ev->spec = SWAP32(spec);
1956 ev->mode = SWAP32(mode);
1957 ev->fhandler = SWAP32(func);
1963 static void psxBios_OpenEvent() { // 08
1964 u32 ret = OpenEvent(a0, a1, a2, a3);
1965 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
1966 biosB0n[0x08], a0, a1, a2, a3, ret);
1967 mips_return_c(ret, 36);
1970 static void CloseEvent(u32 ev)
1972 u32 base = loadRam32(A_TT_EvCB);
1973 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
1976 static void psxBios_CloseEvent() { // 09
1977 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
1978 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
1980 mips_return_c(1, 10);
1983 static void psxBios_WaitEvent() { // 0a
1984 u32 base = loadRam32(A_TT_EvCB);
1985 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1986 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
1989 if (status == EvStALREADY) {
1990 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1994 if (status != EvStACTIVE)
1996 mips_return_c(0, 2);
2000 // retrigger this hlecall after the next emulation event
2002 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2003 psxRegs.cycle = next_interupt;
2007 static void psxBios_TestEvent() { // 0b
2008 u32 base = loadRam32(A_TT_EvCB);
2009 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2011 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2012 if (status == EvStALREADY) {
2013 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2017 mips_return_c(ret, 15);
2020 static void psxBios_EnableEvent() { // 0c
2021 u32 base = loadRam32(A_TT_EvCB);
2022 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2023 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2024 if (status != EvStUNUSED)
2025 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2027 mips_return_c(1, 15);
2030 static void psxBios_DisableEvent() { // 0d
2031 u32 base = loadRam32(A_TT_EvCB);
2032 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2033 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2034 if (status != EvStUNUSED)
2035 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2037 mips_return_c(1, 15);
2041 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2044 void psxBios_OpenTh() { // 0e
2045 TCB *tcb = loadRam32ptr(A_TT_TCB);
2046 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2049 for (th = 1; th < limit; th++)
2051 if (tcb[th].status != SWAP32(0x4000)) break;
2055 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2056 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2058 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2060 mips_return_c(0xffffffff, 20);
2063 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
2065 tcb[th].status = SWAP32(0x4000);
2066 tcb[th].mode = SWAP32(0x1000);
2067 tcb[th].epc = SWAP32(a0);
2068 tcb[th].reg[30] = SWAP32(a1); // fp
2069 tcb[th].reg[29] = SWAP32(a1); // sp
2070 tcb[th].reg[28] = SWAP32(a2); // gp
2072 mips_return_c(0xff000000 + th, 34);
2076 * int CloseTh(long thread);
2079 void psxBios_CloseTh() { // 0f
2080 TCB *tcb = loadRam32ptr(A_TT_TCB);
2081 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2085 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2087 /* The return value is always 1 (even if the handle was already closed). */
2089 if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2090 tcb[th].status = SWAP32(0x1000);
2097 * int ChangeTh(long thread);
2100 void psxBios_ChangeTh() { // 10
2101 u32 tcbBase = loadRam32(A_TT_TCB);
2102 u32 th = a0 & 0xffff;
2104 // this is quite spammy
2105 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2107 // without doing any argument checks, just issue a syscall
2108 // (like the real bios does)
2110 a1 = tcbBase + th * sizeof(TCB);
2115 void psxBios_InitPAD() { // 0x12
2116 u32 i, *ram32 = (u32 *)psxM;
2117 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2119 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2120 ram32[A_PAD_DR_DST/4] = 0;
2121 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2122 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2123 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2124 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2125 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2126 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2127 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2128 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2130 for (i = 0; i < a1; i++) {
2132 storeRam8(a0 + i, 0);
2134 for (i = 0; i < a3; i++) {
2136 storeRam8(a2 + i, 0);
2138 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2140 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2142 mips_return_c(1, 200);
2145 void psxBios_StartPAD() { // 13
2146 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2148 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2149 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2150 psxHwWrite16(0x1f801070, ~1);
2151 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2152 storeRam32(A_PAD_ACK_VBL, 1);
2153 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2154 psxRegs.CP0.n.SR |= 0x401;
2156 mips_return_c(1, 300);
2159 void psxBios_StopPAD() { // 14
2160 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2161 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2162 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2163 psxRegs.CP0.n.SR |= 0x401;
2164 mips_return_void_c(200);
2167 static void psxBios_PAD_init() { // 15
2169 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2170 if (a0 == 0x20000000 || a0 == 0x20000001)
2173 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2174 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2177 storeRam32(A_PAD_DR_DST, dst);
2180 mips_return_c(ret, 100);
2183 static u32 psxBios_PAD_dr_() {
2184 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2185 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2186 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2187 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2188 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2190 dst[0] = buf1[3], dst[1] = buf1[2];
2191 if (buf1[1] == 0x23) {
2192 dst[0] |= 0xc7, dst[1] |= 7;
2193 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2194 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2197 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2199 dst[2] = buf2[3], dst[3] = buf2[2];
2200 if (buf2[1] == 0x23) {
2201 dst[2] |= 0xc7, dst[3] |= 7;
2202 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2203 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2207 return SWAP32(*(u32 *)dst);
2210 static void psxBios_PAD_dr() { // 16
2211 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2212 u32 ret = psxBios_PAD_dr_();
2216 static void psxBios_ReturnFromException() { // 17
2217 u32 tcbPtr = loadRam32(A_TT_PCB);
2218 const TCB *tcb = loadRam32ptr(tcbPtr);
2222 for (i = 1; i < 32; i++)
2223 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2224 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2225 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2226 sr = SWAP32(tcb->sr);
2228 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2229 pc0 = k0 = SWAP32(tcb->epc);
2231 // the interpreter wants to know about sr changes, so do a MTC0
2232 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2233 MTC0(&psxRegs, 12, sr);
2239 void psxBios_ResetEntryInt() { // 18
2240 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2242 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2243 mips_return_void_c(5);
2246 void psxBios_HookEntryInt() { // 19
2247 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2249 storeRam32(A_EEXIT_PTR, a0);
2250 mips_return_void_c(3);
2253 static void psxBios_UnDeliverEvent() { // 0x20
2255 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2257 ret = UnDeliverEvent(a0, a1);
2261 static void buopen(int mcd, char *ptr, char *cfg)
2264 char *mcd_data = ptr;
2266 strcpy(FDesc[1 + mcd].name, Ra0+5);
2267 FDesc[1 + mcd].offset = 0;
2268 FDesc[1 + mcd].mode = a1;
2270 for (i=1; i<16; i++) {
2271 const char *fptr = mcd_data + 128 * i;
2272 if ((*fptr & 0xF0) != 0x50) continue;
2273 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2274 FDesc[1 + mcd].mcfile = i;
2275 PSXBIOS_LOG("open %s\n", fptr+0xa);
2279 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2280 for (i=1; i<16; i++) {
2281 int j, xor, nblk = a1 >> 16;
2283 char *fptr = mcd_data + 128 * i;
2285 if ((*fptr & 0xF0) != 0xa0) continue;
2287 FDesc[1 + mcd].mcfile = i;
2290 fptr[5] = 0x20 * nblk;
2293 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2294 pptr = fptr2 = fptr;
2295 for(j=2; j<=nblk; j++) {
2297 for(i++; i<16; i++) {
2300 memset(fptr2, 0, 128);
2301 fptr2[0] = j < nblk ? 0x52 : 0x53;
2304 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2309 /* shouldn't this return ENOSPC if i == 16? */
2311 pptr[8] = pptr[9] = 0xff;
2312 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2314 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2316 /* just go ahead and resave them all */
2317 SaveMcd(cfg, ptr, 128, 128 * 15);
2320 /* shouldn't this return ENOSPC if i == 16? */
2325 * int open(char *name , int mode);
2328 void psxBios_open() { // 0x32
2332 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2337 if (pa0 != INVALID_PTR) {
2338 if (!strncmp(pa0, "bu00", 4)) {
2339 buopen(1, Mcd1Data, Config.Mcd1);
2342 if (!strncmp(pa0, "bu10", 4)) {
2343 buopen(2, Mcd2Data, Config.Mcd2);
2351 * int lseek(int fd , int offset , int whence);
2354 void psxBios_lseek() { // 0x33
2356 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2361 FDesc[a0].offset = a1;
2363 // DeliverEvent(0xf0000011, 0x0004);
2364 // DeliverEvent(0xf4000001, 0x0004);
2368 FDesc[a0].offset+= a1;
2369 v0 = FDesc[a0].offset;
2378 * int read(int fd , void *buf , int nbytes);
2381 void psxBios_read() { // 0x34
2386 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2391 if (pa1 != INVALID_PTR) {
2393 case 2: buread(pa1, 1, a2); break;
2394 case 3: buread(pa1, 2, a2); break;
2402 * int write(int fd , void *buf , int nbytes);
2405 void psxBios_write() { // 0x35/0x03
2409 if (a0 != 1) // stdout
2410 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2413 if (pa1 == INVALID_PTR) {
2418 if (a0 == 1) { // stdout
2422 if (Config.PsxOut) while (a2 > 0) {
2423 SysPrintf("%c", *ptr++); a2--;
2429 case 2: buwrite(pa1, 1, a2); break;
2430 case 3: buwrite(pa1, 2, a2); break;
2436 static void psxBios_write_psxout() {
2437 if (a0 == 1) { // stdout
2438 const char *ptr = Ra1;
2441 if (ptr != INVALID_PTR)
2443 SysPrintf("%c", *ptr++);
2447 static void psxBios_putchar_psxout() { // 3d
2448 SysPrintf("%c", (char)a0);
2451 static void psxBios_puts_psxout() { // 3e/3f
2452 SysPrintf("%s", Ra0);
2456 * int close(int fd);
2459 void psxBios_close() { // 0x36
2461 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2468 void psxBios_putchar() { // 3d
2469 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2473 void psxBios_puts() { // 3e/3f
2474 if (Config.PsxOut) SysPrintf("%s", Ra0);
2479 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2480 * We want to mimic the PSX's behaviour in this case for bufile. */
2481 static size_t strlen_internal(char* p)
2483 size_t size_of_array = 0;
2484 while (*p++) size_of_array++;
2485 return size_of_array;
2488 #define bufile(mcd) { \
2489 size_t size_of_name = strlen_internal(dir->name); \
2490 while (nfile < 16) { \
2493 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2495 if ((*ptr & 0xF0) != 0x50) continue; \
2496 /* Bug link files show up as free block. */ \
2497 if (!ptr[0xa]) continue; \
2499 if (pfile[0] == 0) { \
2500 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2501 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2502 } else for (i=0; i<20; i++) { \
2503 if (pfile[i] == ptr[i]) { \
2504 dir->name[i] = ptr[i]; continue; } \
2505 if (pfile[i] == '?') { \
2506 dir->name[i] = ptr[i]; continue; } \
2507 if (pfile[i] == '*') { \
2508 strcpy(dir->name+i, ptr+i); break; } \
2511 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2512 if (match == 0) { continue; } \
2520 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2523 void psxBios_firstfile() { // 42
2524 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2531 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2536 if (pa0 != INVALID_PTR) {
2540 if (!strncmp(pa0, "bu00", 4)) {
2541 // firstfile() calls _card_read() internally, so deliver it's event
2542 DeliverEvent(0xf0000011, 0x0004);
2544 } else if (!strncmp(pa0, "bu10", 4)) {
2545 // firstfile() calls _card_read() internally, so deliver it's event
2546 DeliverEvent(0xf0000011, 0x0004);
2555 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2558 void psxBios_nextfile() { // 43
2559 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2565 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2570 if (!strncmp(ffile, "bu00", 4)) {
2574 if (!strncmp(ffile, "bu10", 4)) {
2581 #define burename(mcd) { \
2582 for (i=1; i<16; i++) { \
2583 int namelen, j, xor = 0; \
2584 ptr = Mcd##mcd##Data + 128 * i; \
2585 if ((*ptr & 0xF0) != 0x50) continue; \
2586 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2587 namelen = strlen(Ra1+5); \
2588 memcpy(ptr+0xa, Ra1+5, namelen); \
2589 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2590 for (j=0; j<127; j++) xor^= ptr[j]; \
2592 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2599 * int rename(char *old, char *new);
2602 void psxBios_rename() { // 44
2609 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2614 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2615 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2619 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2628 #define budelete(mcd) { \
2629 for (i=1; i<16; i++) { \
2630 ptr = Mcd##mcd##Data + 128 * i; \
2631 if ((*ptr & 0xF0) != 0x50) continue; \
2632 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2633 *ptr = (*ptr & 0xf) | 0xA0; \
2634 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2635 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2642 * int delete(char *name);
2645 void psxBios_delete() { // 45
2651 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2656 if (pa0 != INVALID_PTR) {
2657 if (!strncmp(pa0, "bu00", 4)) {
2661 if (!strncmp(pa0, "bu10", 4)) {
2669 void psxBios_InitCARD() { // 4a
2670 u32 *ram32 = (u32 *)psxM;
2671 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2672 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2673 // (maybe) todo: early_card_irq, FlushCache etc
2675 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2677 mips_return_c(0, 300);
2680 void psxBios_StartCARD() { // 4b
2681 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2682 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2683 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2685 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2686 storeRam32(A_PAD_ACK_VBL, 1);
2687 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2688 storeRam32(A_CARD_IRQR_ENA, 1);
2689 psxRegs.CP0.n.SR |= 0x401;
2691 mips_return_c(1, 200);
2694 void psxBios_StopCARD() { // 4c
2695 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2696 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2697 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2698 storeRam32(A_CARD_IRQR_ENA, 0);
2699 psxRegs.CP0.n.SR |= 0x401;
2700 mips_return_void_c(200);
2703 void psxBios__card_write() { // 0x4e
2708 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2711 Function also accepts sector 400h (a bug).
2712 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2716 /* Invalid sectors */
2720 storeRam32(A_CARD_CHAN1, a0);
2723 if (pa2 != INVALID_PTR) {
2725 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2726 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2728 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2729 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2733 DeliverEvent(0xf0000011, 0x0004);
2734 // DeliverEvent(0xf4000001, 0x0004);
2739 void psxBios__card_read() { // 0x4f
2744 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2747 Function also accepts sector 400h (a bug).
2748 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2752 /* Invalid sectors */
2756 storeRam32(A_CARD_CHAN1, a0);
2759 if (pa2 != INVALID_PTR) {
2761 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2763 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2767 DeliverEvent(0xf0000011, 0x0004);
2768 // DeliverEvent(0xf4000001, 0x0004);
2773 void psxBios__new_card() { // 0x50
2775 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2781 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2782 void psxBios__get_error(void) // 55
2784 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2789 void psxBios_Krom2RawAdd() { // 0x51
2792 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2793 const u32 table_8140[][2] = {
2794 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2795 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2796 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2797 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2798 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2799 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2800 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2801 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2802 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2806 const u32 table_889f[][2] = {
2807 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2808 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2809 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2810 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2811 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2812 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2813 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2814 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2818 if (a0 >= 0x8140 && a0 <= 0x84be) {
2819 while (table_8140[i][0] <= a0) i++;
2820 a0 -= table_8140[i - 1][0];
2821 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2822 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2823 while (table_889f[i][0] <= a0) i++;
2824 a0 -= table_889f[i - 1][0];
2825 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2833 void psxBios_GetC0Table() { // 56
2834 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2835 log_unhandled("GetC0Table @%08x\n", ra);
2837 mips_return_c(A_C0_TABLE, 3);
2840 void psxBios_GetB0Table() { // 57
2841 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2842 log_unhandled("GetB0Table @%08x\n", ra);
2844 mips_return_c(A_B0_TABLE, 3);
2847 static void psxBios__card_chan() { // 0x58
2849 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2851 // todo: should return active slot chan
2852 // (active - which was last processed by irq code)
2853 ret = loadRam32(A_CARD_CHAN1);
2854 mips_return_c(ret, 8);
2857 static void psxBios_ChangeClearPad() { // 5b
2859 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2860 ret = loadRam32(A_PAD_ACK_VBL);
2861 storeRam32(A_PAD_ACK_VBL, a0);
2863 mips_return_c(ret, 6);
2866 static void psxBios__card_status() { // 5c
2867 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2873 static void psxBios__card_wait() { // 5d
2874 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2880 /* System calls C0 */
2882 static void psxBios_InitRCnt() { // 00
2884 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2885 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2886 for (i = 0; i < 3; i++) {
2887 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2888 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2889 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2891 psxBios_SysEnqIntRP_(a0, 0x6d88);
2892 mips_return_c(0, 9);
2895 static void psxBios_InitException() { // 01
2896 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2897 psxBios_SysEnqIntRP_(a0, 0x6da8);
2898 mips_return_c(0, 9);
2902 * int SysEnqIntRP(int index , long *queue);
2905 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2906 u32 old, base = loadRam32(A_TT_ExCB);
2908 old = loadRam32(base + (priority << 3));
2909 storeRam32(base + (priority << 3), chain_eptr);
2910 storeRam32(chain_eptr, old);
2911 mips_return_c(0, 9);
2914 static void psxBios_SysEnqIntRP() { // 02
2915 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2916 psxBios_SysEnqIntRP_(a0, a1);
2920 * int SysDeqIntRP(int index , long *queue);
2923 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2924 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2925 u32 lim = 0, ret = 0;
2927 // as in original: no arg checks of any kind, bug if a1 == 0
2928 ptr = loadRam32(base + (priority << 3));
2930 next = loadRam32(ptr);
2931 if (ptr == chain_rm_eptr) {
2932 storeRam32(base + (priority << 3), next);
2937 while (next && next != chain_rm_eptr && lim++ < 100) {
2939 next = loadRam32(ptr);
2942 if (next == chain_rm_eptr) {
2943 next = loadRam32(next);
2944 storeRam32(ptr, next);
2951 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2953 mips_return_c(ret, 12);
2956 static void psxBios_SysDeqIntRP() { // 03
2957 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2958 psxBios_SysDeqIntRP_(a0, a1);
2961 static void psxBios_get_free_EvCB_slot() { // 04
2962 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
2963 s32 ret = get_free_EvCB_slot();
2964 mips_return_c(ret, 0);
2967 static void psxBios_SysInitMemory_(u32 base, u32 size) {
2968 storeRam32(base, 0);
2969 storeRam32(A_KMALLOC_PTR, base);
2970 storeRam32(A_KMALLOC_SIZE, size);
2971 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2974 // this should be much more complicated, but maybe that'll be enough
2975 static u32 psxBios_SysMalloc_(u32 size) {
2976 u32 ptr = loadRam32(A_KMALLOC_PTR);
2978 size = (size + 3) & ~3;
2979 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2980 storeRam32(ptr, size);
2984 static void psxBios_SysInitMemory() { // 08
2985 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2987 psxBios_SysInitMemory_(a0, a1);
2988 mips_return_void_c(12);
2991 static void psxBios_ChangeClearRCnt() { // 0a
2994 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2996 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
2997 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
2998 mips_return_c(ret, 8);
3001 static void psxBios_InitDefInt() { // 0c
3002 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3003 // should also clear the autoack table
3004 psxBios_SysEnqIntRP_(a0, 0x6d98);
3005 mips_return_c(0, 20 + 6*2);
3008 void psxBios_dummy() {
3009 u32 pc = (pc0 & 0x1fffff) - 4;
3010 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3011 : pc == 0xc0 ? biosC0n : NULL;
3012 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3013 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3014 (void)pc; (void)ntab;
3015 mips_return_c(0, 100);
3018 void (*biosA0[256])();
3019 // C0 and B0 overlap (end of C0 is start of B0)
3020 void (*biosC0[256+128])();
3021 void (**biosB0)() = biosC0 + 128;
3023 static void setup_mips_code()
3026 ptr = (u32 *)&psxM[A_SYSCALL];
3027 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3028 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3029 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3031 ptr = (u32 *)&psxM[A_EXCEPTION];
3032 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3033 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3034 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3035 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3036 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3037 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3038 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3039 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3040 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3041 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3043 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3044 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3045 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3047 ptr[0xb0/4] = HLEOP(hleop_exception);
3050 static const struct {
3054 { 0xbfc050a4, hleop_exc0_0_1 },
3055 { 0xbfc04fbc, hleop_exc0_0_2 },
3056 { 0xbfc0506c, hleop_exc0_1_1 },
3057 { 0xbfc04dec, hleop_exc0_1_2 },
3058 { 0x1a00, hleop_exc0_2_2 },
3059 { 0x19c8, hleop_exc1_0_1 },
3060 { 0x18bc, hleop_exc1_0_2 },
3061 { 0x1990, hleop_exc1_1_1 },
3062 { 0x1858, hleop_exc1_1_2 },
3063 { 0x1958, hleop_exc1_2_1 },
3064 { 0x17f4, hleop_exc1_2_2 },
3065 { 0x1920, hleop_exc1_3_1 },
3066 { 0x1794, hleop_exc1_3_2 },
3067 { 0x2458, hleop_exc3_0_2 },
3068 { 0x49bc, hleop_exc_padcard1 },
3069 { 0x4a4c, hleop_exc_padcard2 },
3072 static int chain_hle_op(u32 handler)
3076 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3077 if (chainfns[i].addr == handler)
3078 return chainfns[i].op;
3082 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3084 d[0] = SWAPu32(next);
3085 d[1] = SWAPu32(handler1);
3086 d[2] = SWAPu32(handler2);
3088 // install the hle traps
3089 PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3090 PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3093 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
3095 u32 *ram32 = (u32 *)psxM;
3096 u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
3097 u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
3098 u32 p_excb, p_evcb, p_pcb, p_tcb;
3100 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3101 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3102 p_excb = psxBios_SysMalloc_(s_excb);
3103 p_evcb = psxBios_SysMalloc_(s_evcb);
3104 p_pcb = psxBios_SysMalloc_(s_pcb);
3105 p_tcb = psxBios_SysMalloc_(s_tcb);
3107 // "table of tables". Some games modify it
3108 assert(A_TT_ExCB == 0x0100);
3109 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3110 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3111 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3112 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3113 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3114 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3115 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3116 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3117 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3118 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3119 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3120 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3122 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3123 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3124 storeRam32(p_excb + 4*4, 0x0000); // chain2
3125 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3127 storeRam32(p_pcb, p_tcb);
3128 storeRam32(p_tcb, 0x4000); // first TCB
3131 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3132 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3133 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3134 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3135 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3136 DeliverEvent(0xf0000003, 0x0010);
3139 static const u32 gpu_ctl_def[] = {
3140 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3141 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3144 static const u32 gpu_data_def[] = {
3145 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3146 0xe5001000, 0xe6000000,
3147 0x02000000, 0x00000000, 0x01ff03ff
3151 static const u16 spu_config[] = {
3152 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3153 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3154 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3155 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3156 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3157 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3158 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3159 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3162 void psxBiosSetupBootState(void)
3164 boolean hle = Config.HLE;
3165 u32 *hw = (u32 *)psxH;
3168 // see also SetBootRegs()
3171 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3172 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3174 k0 = 0xbfc0d968; k1 = 0xf1c;
3175 ra = 0xf0001234; // just to easily detect attempts to return
3176 psxRegs.CP0.n.Cause = 0x20;
3177 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3179 hw[0x1000/4] = SWAP32(0x1f000000);
3180 hw[0x1004/4] = SWAP32(0x1f802000);
3181 hw[0x1008/4] = SWAP32(0x0013243f);
3182 hw[0x100c/4] = SWAP32(0x00003022);
3183 hw[0x1010/4] = SWAP32(0x0013243f);
3184 hw[0x1014/4] = SWAP32(0x200931e1);
3185 hw[0x1018/4] = SWAP32(0x00020943);
3186 hw[0x101c/4] = SWAP32(0x00070777);
3187 hw[0x1020/4] = SWAP32(0x0000132c);
3188 hw[0x1060/4] = SWAP32(0x00000b88);
3189 hw[0x1070/4] = SWAP32(0x00000001);
3190 hw[0x1074/4] = SWAP32(0x0000000c);
3191 hw[0x2040/4] = SWAP32(0x00000900);
3194 hw[0x10a0/4] = SWAP32(0x00ffffff);
3195 hw[0x10a8/4] = SWAP32(0x00000401);
3196 hw[0x10b0/4] = SWAP32(0x0008b000);
3197 hw[0x10b4/4] = SWAP32(0x00010200);
3198 hw[0x10e0/4] = SWAP32(0x000eccf4);
3199 hw[0x10e4/4] = SWAP32(0x00000400);
3200 hw[0x10e8/4] = SWAP32(0x00000002);
3201 hw[0x10f0/4] = SWAP32(0x00009099);
3202 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3211 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3212 GPU_writeStatus(gpu_ctl_def[i]);
3213 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3214 GPU_writeData(gpu_data_def[i]);
3215 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3218 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3219 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3222 #include "sjisfont.h"
3224 void psxBiosInit() {
3225 u32 *ptr, *ram32, *rom32;
3229 memset(psxM, 0, 0x10000);
3230 for(i = 0; i < 256; i++) {
3235 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3236 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3237 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3238 biosA0[0x3f] = psxBios_printf_psxout;
3240 if (!Config.HLE) return;
3242 for(i = 0; i < 256; i++) {
3243 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3244 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3245 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3248 biosA0[0x00] = psxBios_open;
3249 biosA0[0x01] = psxBios_lseek;
3250 biosA0[0x02] = psxBios_read;
3251 biosA0[0x03] = psxBios_write;
3252 biosA0[0x04] = psxBios_close;
3253 //biosA0[0x05] = psxBios_ioctl;
3254 //biosA0[0x06] = psxBios_exit;
3255 //biosA0[0x07] = psxBios_sys_a0_07;
3256 biosA0[0x08] = psxBios_getc;
3257 biosA0[0x09] = psxBios_putc;
3258 biosA0[0x0a] = psxBios_todigit;
3259 //biosA0[0x0b] = psxBios_atof;
3260 //biosA0[0x0c] = psxBios_strtoul;
3261 //biosA0[0x0d] = psxBios_strtol;
3262 biosA0[0x0e] = psxBios_abs;
3263 biosA0[0x0f] = psxBios_labs;
3264 biosA0[0x10] = psxBios_atoi;
3265 biosA0[0x11] = psxBios_atol;
3266 //biosA0[0x12] = psxBios_atob;
3267 biosA0[0x13] = psxBios_setjmp;
3268 biosA0[0x14] = psxBios_longjmp;
3269 biosA0[0x15] = psxBios_strcat;
3270 biosA0[0x16] = psxBios_strncat;
3271 biosA0[0x17] = psxBios_strcmp;
3272 biosA0[0x18] = psxBios_strncmp;
3273 biosA0[0x19] = psxBios_strcpy;
3274 biosA0[0x1a] = psxBios_strncpy;
3275 biosA0[0x1b] = psxBios_strlen;
3276 biosA0[0x1c] = psxBios_index;
3277 biosA0[0x1d] = psxBios_rindex;
3278 biosA0[0x1e] = psxBios_strchr;
3279 biosA0[0x1f] = psxBios_strrchr;
3280 biosA0[0x20] = psxBios_strpbrk;
3281 biosA0[0x21] = psxBios_strspn;
3282 biosA0[0x22] = psxBios_strcspn;
3283 biosA0[0x23] = psxBios_strtok;
3284 biosA0[0x24] = psxBios_strstr;
3285 biosA0[0x25] = psxBios_toupper;
3286 biosA0[0x26] = psxBios_tolower;
3287 biosA0[0x27] = psxBios_bcopy;
3288 biosA0[0x28] = psxBios_bzero;
3289 biosA0[0x29] = psxBios_bcmp;
3290 biosA0[0x2a] = psxBios_memcpy;
3291 biosA0[0x2b] = psxBios_memset;
3292 biosA0[0x2c] = psxBios_memmove;
3293 biosA0[0x2d] = psxBios_memcmp;
3294 biosA0[0x2e] = psxBios_memchr;
3295 biosA0[0x2f] = psxBios_rand;
3296 biosA0[0x30] = psxBios_srand;
3297 biosA0[0x31] = psxBios_qsort;
3298 //biosA0[0x32] = psxBios_strtod;
3299 biosA0[0x33] = psxBios_malloc;
3300 biosA0[0x34] = psxBios_free;
3301 //biosA0[0x35] = psxBios_lsearch;
3302 //biosA0[0x36] = psxBios_bsearch;
3303 biosA0[0x37] = psxBios_calloc;
3304 biosA0[0x38] = psxBios_realloc;
3305 biosA0[0x39] = psxBios_InitHeap;
3306 //biosA0[0x3a] = psxBios__exit;
3307 biosA0[0x3b] = psxBios_getchar;
3308 biosA0[0x3c] = psxBios_putchar;
3309 //biosA0[0x3d] = psxBios_gets;
3310 biosA0[0x3e] = psxBios_puts;
3311 biosA0[0x3f] = psxBios_printf;
3312 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3313 //biosA0[0x41] = psxBios_LoadTest;
3314 biosA0[0x42] = psxBios_Load;
3315 biosA0[0x43] = psxBios_Exec;
3316 biosA0[0x44] = psxBios_FlushCache;
3317 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3318 biosA0[0x46] = psxBios_GPU_dw;
3319 biosA0[0x47] = psxBios_mem2vram;
3320 biosA0[0x48] = psxBios_SendGPU;
3321 biosA0[0x49] = psxBios_GPU_cw;
3322 biosA0[0x4a] = psxBios_GPU_cwb;
3323 biosA0[0x4b] = psxBios_GPU_SendPackets;
3324 biosA0[0x4c] = psxBios_sys_a0_4c;
3325 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3326 //biosA0[0x4e] = psxBios_GPU_sync;
3327 //biosA0[0x4f] = psxBios_sys_a0_4f;
3328 //biosA0[0x50] = psxBios_sys_a0_50;
3329 biosA0[0x51] = psxBios_LoadExec;
3330 //biosA0[0x52] = psxBios_GetSysSp;
3331 //biosA0[0x53] = psxBios_sys_a0_53;
3332 //biosA0[0x54] = psxBios__96_init_a54;
3333 //biosA0[0x55] = psxBios__bu_init_a55;
3334 biosA0[0x56] = psxBios_CdRemove;
3335 //biosA0[0x57] = psxBios_sys_a0_57;
3336 //biosA0[0x58] = psxBios_sys_a0_58;
3337 //biosA0[0x59] = psxBios_sys_a0_59;
3338 //biosA0[0x5a] = psxBios_sys_a0_5a;
3339 //biosA0[0x5b] = psxBios_dev_tty_init;
3340 //biosA0[0x5c] = psxBios_dev_tty_open;
3341 //biosA0[0x5d] = psxBios_sys_a0_5d;
3342 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3343 //biosA0[0x5f] = psxBios_dev_cd_open;
3344 //biosA0[0x60] = psxBios_dev_cd_read;
3345 //biosA0[0x61] = psxBios_dev_cd_close;
3346 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3347 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3348 //biosA0[0x64] = psxBios_dev_cd_chdir;
3349 //biosA0[0x65] = psxBios_dev_card_open;
3350 //biosA0[0x66] = psxBios_dev_card_read;
3351 //biosA0[0x67] = psxBios_dev_card_write;
3352 //biosA0[0x68] = psxBios_dev_card_close;
3353 //biosA0[0x69] = psxBios_dev_card_firstfile;
3354 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3355 //biosA0[0x6b] = psxBios_dev_card_erase;
3356 //biosA0[0x6c] = psxBios_dev_card_undelete;
3357 //biosA0[0x6d] = psxBios_dev_card_format;
3358 //biosA0[0x6e] = psxBios_dev_card_rename;
3359 //biosA0[0x6f] = psxBios_dev_card_6f;
3360 biosA0[0x70] = psxBios__bu_init;
3361 biosA0[0x71] = psxBios__96_init;
3362 biosA0[0x72] = psxBios_CdRemove;
3363 //biosA0[0x73] = psxBios_sys_a0_73;
3364 //biosA0[0x74] = psxBios_sys_a0_74;
3365 //biosA0[0x75] = psxBios_sys_a0_75;
3366 //biosA0[0x76] = psxBios_sys_a0_76;
3367 //biosA0[0x77] = psxBios_sys_a0_77;
3368 //biosA0[0x78] = psxBios__96_CdSeekL;
3369 //biosA0[0x79] = psxBios_sys_a0_79;
3370 //biosA0[0x7a] = psxBios_sys_a0_7a;
3371 //biosA0[0x7b] = psxBios_sys_a0_7b;
3372 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3373 //biosA0[0x7d] = psxBios_sys_a0_7d;
3374 //biosA0[0x7e] = psxBios__96_CdRead;
3375 //biosA0[0x7f] = psxBios_sys_a0_7f;
3376 //biosA0[0x80] = psxBios_sys_a0_80;
3377 //biosA0[0x81] = psxBios_sys_a0_81;
3378 //biosA0[0x82] = psxBios_sys_a0_82;
3379 //biosA0[0x83] = psxBios_sys_a0_83;
3380 //biosA0[0x84] = psxBios_sys_a0_84;
3381 //biosA0[0x85] = psxBios__96_CdStop;
3382 //biosA0[0x86] = psxBios_sys_a0_86;
3383 //biosA0[0x87] = psxBios_sys_a0_87;
3384 //biosA0[0x88] = psxBios_sys_a0_88;
3385 //biosA0[0x89] = psxBios_sys_a0_89;
3386 //biosA0[0x8a] = psxBios_sys_a0_8a;
3387 //biosA0[0x8b] = psxBios_sys_a0_8b;
3388 //biosA0[0x8c] = psxBios_sys_a0_8c;
3389 //biosA0[0x8d] = psxBios_sys_a0_8d;
3390 //biosA0[0x8e] = psxBios_sys_a0_8e;
3391 //biosA0[0x8f] = psxBios_sys_a0_8f;
3392 biosA0[0x90] = hleExc0_1_2;
3393 biosA0[0x91] = hleExc0_0_2;
3394 biosA0[0x92] = hleExc0_1_1;
3395 biosA0[0x93] = hleExc0_0_1;
3396 //biosA0[0x94] = psxBios_sys_a0_94;
3397 //biosA0[0x95] = psxBios_sys_a0_95;
3398 //biosA0[0x96] = psxBios_AddCDROMDevice;
3399 //biosA0[0x97] = psxBios_AddMemCardDevide;
3400 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3401 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3402 //biosA0[0x9a] = psxBios_sys_a0_9a;
3403 //biosA0[0x9b] = psxBios_sys_a0_9b;
3404 //biosA0[0x9c] = psxBios_SetConf;
3405 //biosA0[0x9d] = psxBios_GetConf;
3406 //biosA0[0x9e] = psxBios_sys_a0_9e;
3407 biosA0[0x9f] = psxBios_SetMem;
3408 //biosA0[0xa0] = psxBios__boot;
3409 //biosA0[0xa1] = psxBios_SystemError;
3410 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3411 biosA0[0xa3] = psxBios_DequeueCdIntr;
3412 //biosA0[0xa4] = psxBios_sys_a0_a4;
3413 //biosA0[0xa5] = psxBios_ReadSector;
3414 biosA0[0xa6] = psxBios_get_cd_status;
3415 //biosA0[0xa7] = psxBios_bufs_cb_0;
3416 //biosA0[0xa8] = psxBios_bufs_cb_1;
3417 //biosA0[0xa9] = psxBios_bufs_cb_2;
3418 //biosA0[0xaa] = psxBios_bufs_cb_3;
3419 biosA0[0xab] = psxBios__card_info;
3420 biosA0[0xac] = psxBios__card_load;
3421 //biosA0[0axd] = psxBios__card_auto;
3422 //biosA0[0xae] = psxBios_bufs_cd_4;
3423 //biosA0[0xaf] = psxBios_sys_a0_af;
3424 //biosA0[0xb0] = psxBios_sys_a0_b0;
3425 //biosA0[0xb1] = psxBios_sys_a0_b1;
3426 //biosA0[0xb2] = psxBios_do_a_long_jmp
3427 //biosA0[0xb3] = psxBios_sys_a0_b3;
3428 biosA0[0xb4] = psxBios_GetSystemInfo;
3429 //*******************B0 CALLS****************************
3430 biosB0[0x00] = psxBios_SysMalloc;
3431 //biosB0[0x01] = psxBios_sys_b0_01;
3432 biosB0[0x02] = psxBios_SetRCnt;
3433 biosB0[0x03] = psxBios_GetRCnt;
3434 biosB0[0x04] = psxBios_StartRCnt;
3435 biosB0[0x05] = psxBios_StopRCnt;
3436 biosB0[0x06] = psxBios_ResetRCnt;
3437 biosB0[0x07] = psxBios_DeliverEvent;
3438 biosB0[0x08] = psxBios_OpenEvent;
3439 biosB0[0x09] = psxBios_CloseEvent;
3440 biosB0[0x0a] = psxBios_WaitEvent;
3441 biosB0[0x0b] = psxBios_TestEvent;
3442 biosB0[0x0c] = psxBios_EnableEvent;
3443 biosB0[0x0d] = psxBios_DisableEvent;
3444 biosB0[0x0e] = psxBios_OpenTh;
3445 biosB0[0x0f] = psxBios_CloseTh;
3446 biosB0[0x10] = psxBios_ChangeTh;
3447 //biosB0[0x11] = psxBios_psxBios_b0_11;
3448 biosB0[0x12] = psxBios_InitPAD;
3449 biosB0[0x13] = psxBios_StartPAD;
3450 biosB0[0x14] = psxBios_StopPAD;
3451 biosB0[0x15] = psxBios_PAD_init;
3452 biosB0[0x16] = psxBios_PAD_dr;
3453 biosB0[0x17] = psxBios_ReturnFromException;
3454 biosB0[0x18] = psxBios_ResetEntryInt;
3455 biosB0[0x19] = psxBios_HookEntryInt;
3456 //biosB0[0x1a] = psxBios_sys_b0_1a;
3457 //biosB0[0x1b] = psxBios_sys_b0_1b;
3458 //biosB0[0x1c] = psxBios_sys_b0_1c;
3459 //biosB0[0x1d] = psxBios_sys_b0_1d;
3460 //biosB0[0x1e] = psxBios_sys_b0_1e;
3461 //biosB0[0x1f] = psxBios_sys_b0_1f;
3462 biosB0[0x20] = psxBios_UnDeliverEvent;
3463 //biosB0[0x21] = psxBios_sys_b0_21;
3464 //biosB0[0x22] = psxBios_sys_b0_22;
3465 //biosB0[0x23] = psxBios_sys_b0_23;
3466 //biosB0[0x24] = psxBios_sys_b0_24;
3467 //biosB0[0x25] = psxBios_sys_b0_25;
3468 //biosB0[0x26] = psxBios_sys_b0_26;
3469 //biosB0[0x27] = psxBios_sys_b0_27;
3470 //biosB0[0x28] = psxBios_sys_b0_28;
3471 //biosB0[0x29] = psxBios_sys_b0_29;
3472 //biosB0[0x2a] = psxBios_sys_b0_2a;
3473 //biosB0[0x2b] = psxBios_sys_b0_2b;
3474 //biosB0[0x2c] = psxBios_sys_b0_2c;
3475 //biosB0[0x2d] = psxBios_sys_b0_2d;
3476 //biosB0[0x2e] = psxBios_sys_b0_2e;
3477 //biosB0[0x2f] = psxBios_sys_b0_2f;
3478 //biosB0[0x30] = psxBios_sys_b0_30;
3479 //biosB0[0x31] = psxBios_sys_b0_31;
3480 biosB0[0x32] = psxBios_open;
3481 biosB0[0x33] = psxBios_lseek;
3482 biosB0[0x34] = psxBios_read;
3483 biosB0[0x35] = psxBios_write;
3484 biosB0[0x36] = psxBios_close;
3485 //biosB0[0x37] = psxBios_ioctl;
3486 //biosB0[0x38] = psxBios_exit;
3487 //biosB0[0x39] = psxBios_sys_b0_39;
3488 //biosB0[0x3a] = psxBios_getc;
3489 //biosB0[0x3b] = psxBios_putc;
3490 biosB0[0x3c] = psxBios_getchar;
3491 biosB0[0x3d] = psxBios_putchar;
3492 //biosB0[0x3e] = psxBios_gets;
3493 biosB0[0x3f] = psxBios_puts;
3494 //biosB0[0x40] = psxBios_cd;
3495 biosB0[0x41] = psxBios_format;
3496 biosB0[0x42] = psxBios_firstfile;
3497 biosB0[0x43] = psxBios_nextfile;
3498 biosB0[0x44] = psxBios_rename;
3499 biosB0[0x45] = psxBios_delete;
3500 //biosB0[0x46] = psxBios_undelete;
3501 //biosB0[0x47] = psxBios_AddDevice;
3502 //biosB0[0x48] = psxBios_RemoteDevice;
3503 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3504 biosB0[0x4a] = psxBios_InitCARD;
3505 biosB0[0x4b] = psxBios_StartCARD;
3506 biosB0[0x4c] = psxBios_StopCARD;
3507 //biosB0[0x4d] = psxBios_sys_b0_4d;
3508 biosB0[0x4e] = psxBios__card_write;
3509 biosB0[0x4f] = psxBios__card_read;
3510 biosB0[0x50] = psxBios__new_card;
3511 biosB0[0x51] = psxBios_Krom2RawAdd;
3512 //biosB0[0x52] = psxBios_sys_b0_52;
3513 //biosB0[0x53] = psxBios_sys_b0_53;
3514 //biosB0[0x54] = psxBios__get_errno;
3515 biosB0[0x55] = psxBios__get_error;
3516 biosB0[0x56] = psxBios_GetC0Table;
3517 biosB0[0x57] = psxBios_GetB0Table;
3518 biosB0[0x58] = psxBios__card_chan;
3519 //biosB0[0x59] = psxBios_sys_b0_59;
3520 //biosB0[0x5a] = psxBios_sys_b0_5a;
3521 biosB0[0x5b] = psxBios_ChangeClearPad;
3522 biosB0[0x5c] = psxBios__card_status;
3523 biosB0[0x5d] = psxBios__card_wait;
3524 //*******************C0 CALLS****************************
3525 biosC0[0x00] = psxBios_InitRCnt;
3526 biosC0[0x01] = psxBios_InitException;
3527 biosC0[0x02] = psxBios_SysEnqIntRP;
3528 biosC0[0x03] = psxBios_SysDeqIntRP;
3529 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3530 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3531 //biosC0[0x06] = psxBios_ExceptionHandler;
3532 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3533 biosC0[0x08] = psxBios_SysInitMemory;
3534 //biosC0[0x09] = psxBios_SysInitKMem;
3535 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3536 //biosC0[0x0b] = psxBios_SystemError;
3537 biosC0[0x0c] = psxBios_InitDefInt;
3538 //biosC0[0x0d] = psxBios_sys_c0_0d;
3539 //biosC0[0x0e] = psxBios_sys_c0_0e;
3540 //biosC0[0x0f] = psxBios_sys_c0_0f;
3541 //biosC0[0x10] = psxBios_sys_c0_10;
3542 //biosC0[0x11] = psxBios_sys_c0_11;
3543 //biosC0[0x12] = psxBios_InstallDevices;
3544 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3545 //biosC0[0x14] = psxBios_sys_c0_14;
3546 //biosC0[0x15] = psxBios__cdevinput;
3547 //biosC0[0x16] = psxBios__cdevscan;
3548 //biosC0[0x17] = psxBios__circgetc;
3549 //biosC0[0x18] = psxBios__circputc;
3550 //biosC0[0x19] = psxBios_ioabort;
3551 //biosC0[0x1a] = psxBios_sys_c0_1a
3552 //biosC0[0x1b] = psxBios_KernelRedirect;
3553 //biosC0[0x1c] = psxBios_PatchAOTable;
3554 //************** THE END ***************************************
3557 memset(FDesc, 0, sizeof(FDesc));
3560 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3562 // somewhat pretend to be a SCPH1001 BIOS
3563 // some games look for these and take an exception if they're missing
3564 rom32 = (u32 *)psxR;
3565 rom32[0x100/4] = SWAP32(0x19951204);
3566 rom32[0x104/4] = SWAP32(3);
3567 strcpy(psxR + 0x108, "PCSX authors");
3568 strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3569 strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3570 strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
3573 len = 0x80000 - 0x66000;
3574 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3575 len = 0x80000 - 0x69d68;
3576 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3578 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3579 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3580 Here are some examples of games not working with this fix in place :
3581 R-type won't get past the Irem logo if not implemented.
3582 Crash Team Racing will softlock after the Sony logo.
3585 ram32 = (u32 *)psxM;
3586 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3587 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3588 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3589 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3591 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3592 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3594 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3595 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3596 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3597 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3599 ram32[0x00a0/4] = HLEOP(hleop_a0);
3600 ram32[0x00b0/4] = HLEOP(hleop_b0);
3601 ram32[0x00c0/4] = HLEOP(hleop_c0);
3605 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3606 strcpy((char *)&ram32[0xeff0/4], "bu");
3608 // default exception handler chains
3609 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3610 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3611 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3612 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3613 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3614 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3615 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3616 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3620 // fill the api jumptables with fake entries as some games patch them
3621 // (or rather the funcs listed there)
3622 ptr = (u32 *)&psxM[A_A0_TABLE];
3623 for (i = 0; i < 256; i++)
3624 ptr[i] = SWAP32(0x1000);
3626 ptr = (u32 *)&psxM[A_B0_TABLE];
3627 for (i = 0; i < 256; i++)
3628 ptr[i] = SWAP32(0x2000);
3629 // B(5b) is special because games patch (sometimes even jump to)
3630 // code at fixed offsets from it, nocash lists offsets:
3631 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3632 // call: +7a0=4b70, +884=4c54, +894=4c64
3633 ptr[0x5b] = SWAP32(0x43d0);
3634 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3636 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3637 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3638 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3640 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3641 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3643 ptr = (u32 *)&psxM[A_C0_TABLE];
3644 for (i = 0; i < 256/2; i++)
3645 ptr[i] = SWAP32(0x3000);
3646 ptr[6] = SWAP32(A_EXCEPTION);
3649 ram32[0x1000/4] = HLEOP(hleop_dummy);
3650 ram32[0x2000/4] = HLEOP(hleop_dummy);
3651 ram32[0x3000/4] = HLEOP(hleop_dummy);
3652 ram32[0x4c54/4] = HLEOP(hleop_dummy); // for B12_InitPad?
3653 ram32[0x8000/4] = HLEOP(hleop_execret);
3655 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3656 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3657 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3658 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3659 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3660 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3663 void psxBiosShutdown() {
3666 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3667 if (tcb_cnt != 4 || evcb_cnt != 16)
3668 setup_tt(tcb_cnt, evcb_cnt);
3671 #define psxBios_PADpoll(pad) { \
3672 PAD##pad##_startPoll(pad); \
3673 pad_buf##pad[0] = 0; \
3674 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3675 if (!(pad_buf##pad[1] & 0x0f)) { \
3678 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3680 PAD##pad##_poll(0); \
3682 while (bufcount--) { \
3683 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3687 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3691 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3692 psxBios_ReturnFromException();
3698 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3699 // so this is only partially implemented
3700 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3702 u32 cdrom_dma_ack_enable = 1; // a000b93c
3703 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3706 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3709 //PSXBIOS_LOG("%s\n", __func__);
3711 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3712 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3713 //if (--cdrom_irq_counter == 0) // 0xa0009180
3714 // DeliverEvent(0xf0000003, 0x10);
3718 mips_return_c(ret, 20);
3721 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3723 u32 cdrom_irq_ack_enable = 1; // a000b938
3724 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3727 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3730 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3731 PSXBIOS_LOG("%s TODO\n", __func__);
3734 mips_return_c(ret, 20);
3737 void hleExc0_2_2_syscall() // not in any A/B/C table
3739 u32 code = (psxRegs.CP0.n.Cause & 0x3c) >> 2;
3740 u32 tcbPtr = loadRam32(A_TT_PCB);
3741 TCB *tcb = loadRam32ptr(tcbPtr);
3743 if (code != R3000E_Syscall) {
3745 DeliverEvent(0xf0000010, 0x1000);
3746 //psxBios_SystemErrorUnresolvedException();
3748 mips_return_c(0, 17);
3752 //printf("%s c=%d a0=%d\n", __func__, code, a0);
3753 tcb->epc += SWAP32(4);
3758 case 1: { // EnterCritical - disable irqs
3759 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3760 tcb->reg[2] = SWAP32(was_enabled);
3761 tcb->sr &= SWAP32(~0x404);
3764 case 2: // ExitCritical - enable irqs
3765 tcb->sr |= SWAP32(0x404);
3768 case 3: { // ChangeThreadSubFunction
3769 u32 tcbPtr = loadRam32(A_TT_PCB);
3770 storeRam32(tcbPtr, a1);
3774 DeliverEvent(0xf0000010, 0x4000);
3778 psxBios_ReturnFromException();
3781 void hleExc1_0_1(void)
3783 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3784 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3787 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3790 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3791 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3794 mips_return_c(ret, 22);
3797 void hleExc1_0_2(void)
3799 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3802 void hleExc1_1_1(void)
3804 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3805 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3808 void hleExc1_1_2(void)
3810 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3813 void hleExc1_2_1(void)
3815 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3816 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3819 void hleExc1_2_2(void)
3821 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3824 void hleExc1_3_1(void)
3826 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3827 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3830 void hleExc1_3_2(void)
3832 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3835 void hleExc3_0_2_defint(void)
3837 static const struct {
3848 { 6, 6 }, // rcnt2 (bug)
3853 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3854 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3855 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3860 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3863 void hleExcPadCard1(void)
3865 if (loadRam32(A_PAD_IRQR_ENA)) {
3866 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3867 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3873 if (loadRam32(A_PAD_DR_DST))
3876 if (loadRam32(A_PAD_ACK_VBL))
3877 psxHwWrite16(0x1f801070, ~1);
3878 if (loadRam32(A_CARD_IRQR_ENA)) {
3882 mips_return_c(0, 18);
3885 void hleExcPadCard2(void)
3887 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3888 mips_return_c(ret, 15);
3891 void psxBiosException() {
3892 u32 tcbPtr = loadRam32(A_TT_PCB);
3893 u32 *chains = loadRam32ptr(A_TT_ExCB);
3894 TCB *tcb = loadRam32ptr(tcbPtr);
3900 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3901 for (i = 4; i < 32; i++) {
3904 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3906 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3907 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3908 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3909 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3910 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3911 sp = fp = loadRam32(A_EXC_SP);
3915 // do the chains (always 4)
3916 for (c = lim = 0; c < 4; c++) {
3917 if (chains[c * 2] == 0)
3919 ptr = SWAP32(chains[c * 2]);
3920 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3921 chain = castRam32ptr(ptr);
3926 softCallInException(SWAP32(chain[2]));
3927 if (returned_from_exception())
3930 if (v0 == 0 || chain[1] == 0)
3932 softCallInException(SWAP32(chain[1]));
3933 if (returned_from_exception())
3939 // return from exception (custom or default)
3941 ptr = loadRam32(A_EEXIT_PTR);
3942 if (ptr != A_EEXIT_DEF) {
3943 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3944 longjmp_load(jmp_buf);
3949 psxBios_ReturnFromException();
3952 #define bfreeze(ptr, size) { \
3953 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3954 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3958 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3959 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3961 #define bfreezepsxMptr(ptr, type) { \
3963 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3964 else psxRu32ref(base) = 0; \
3966 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3967 else (ptr) = NULL; \
3969 base += sizeof(u32); \
3972 void psxBiosFreeze(int Mode) {