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 mips_return_void(void)
352 static void use_cycles(u32 cycle)
354 psxRegs.cycle += cycle * 2;
357 static void mips_return_c(u32 val, u32 cycle)
363 static void mips_return_void_c(u32 cycle)
369 static int returned_from_exception(void)
371 // 0x80000080 means it took another exception just after return
372 return pc0 == k0 || pc0 == 0x80000080;
375 static inline void softCall(u32 pc) {
377 u32 ssr = psxRegs.CP0.n.SR;
381 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
383 while (pc0 != 0x80001000 && ++lim < 1000000)
384 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
387 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
389 psxRegs.CP0.n.SR |= ssr & 0x404;
392 static inline void softCallInException(u32 pc) {
398 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
399 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
402 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
403 if (pc0 == 0x80001000)
407 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
408 static u32 DeliverEvent(u32 class, u32 spec);
409 static u32 UnDeliverEvent(u32 class, u32 spec);
410 static void CloseEvent(u32 ev);
415 // System calls A0 */
418 #define buread(Ra1, mcd, length) { \
419 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); \
420 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
421 memcpy(Ra1, ptr, length); \
422 psxCpu->Clear(a1, (length + 3) / 4); \
423 if (FDesc[1 + mcd].mode & 0x8000) { \
424 DeliverEvent(0xf0000011, 0x0004); \
425 DeliverEvent(0xf4000001, 0x0004); \
428 FDesc[1 + mcd].offset += v0; \
431 #define buwrite(Ra1, mcd, length) { \
432 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
433 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
434 ptr = Mcd##mcd##Data + offset; \
435 memcpy(ptr, Ra1, length); \
436 FDesc[1 + mcd].offset += length; \
437 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
438 if (FDesc[1 + mcd].mode & 0x8000) { \
439 DeliverEvent(0xf0000011, 0x0004); \
440 DeliverEvent(0xf4000001, 0x0004); \
445 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
446 /* For some strange reason, the returned character is sign-expanded; */
447 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
448 /* TODO FIX ME : Properly implement this behaviour */
449 void psxBios_getc(void) // 0x03, 0x35
454 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
458 if (pa1 != INVALID_PTR) {
460 case 2: buread(pa1, 1, 1); break;
461 case 3: buread(pa1, 2, 1); break;
468 /* Copy of psxBios_write, except size is 1. */
469 void psxBios_putc(void) // 0x09, 0x3B
474 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
477 if (pa1 == INVALID_PTR) {
482 if (a0 == 1) { // stdout
483 char *ptr = (char *)pa1;
487 printf("%c", *ptr++); a2--;
493 case 2: buwrite(pa1, 1, 1); break;
494 case 3: buwrite(pa1, 2, 1); break;
500 void psxBios_todigit(void) // 0x0a
504 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
507 if (c >= 0x30 && c < 0x3A) {
510 else if (c > 0x60 && c < 0x7B) {
513 else if (c > 0x40 && c < 0x5B) {
516 else if (c >= 0x80) {
527 void psxBios_abs() { // 0x0e
528 if ((s32)a0 < 0) v0 = -(s32)a0;
533 void psxBios_labs() { // 0x0f
537 void psxBios_atoi() { // 0x10
539 char *p = (char *)Ra0;
543 case ' ': case '\t': continue;
550 while (*p >= '0' && *p <= '9') {
551 n = n * 10 + *p++ - '0';
558 void psxBios_atol() { // 0x11
568 static void psxBios_setjmp() { // 0x13
569 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
572 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
574 jmp_buf->ra_ = SWAP32(ra);
575 jmp_buf->sp_ = SWAP32(sp);
576 jmp_buf->fp_ = SWAP32(fp);
577 for (i = 0; i < 8; i++) // s0-s7
578 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
579 jmp_buf->gp_ = SWAP32(gp);
581 mips_return_c(0, 15);
584 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
588 ra = SWAP32(jmp_buf->ra_);
589 sp = SWAP32(jmp_buf->sp_);
590 fp = SWAP32(jmp_buf->fp_);
591 for (i = 0; i < 8; i++) // s0-s7
592 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
593 gp = SWAP32(jmp_buf->gp_);;
596 void psxBios_longjmp() { // 0x14
597 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
599 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
600 longjmp_load(jmp_buf);
601 mips_return_c(a1, 15);
604 void psxBios_strcat() { // 0x15
605 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
608 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
610 if (a0 == 0 || a1 == 0)
618 while ((*p1++ = *p2++) != '\0');
623 void psxBios_strncat() { // 0x16
624 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
628 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
630 if (a0 == 0 || a1 == 0)
638 while ((*p1++ = *p2++) != '\0') {
648 void psxBios_strcmp() { // 0x17
649 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
651 if (a0 == 0 && a1 == 0)
657 else if (a0 == 0 && a1 != 0)
663 else if (a0 != 0 && a1 == 0)
670 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
673 while (*p1 == *p2++) {
692 void psxBios_strncmp() { // 0x18
693 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
695 if (a0 == 0 && a1 == 0)
701 else if (a0 == 0 && a1 != 0)
707 else if (a0 != 0 && a1 == 0)
714 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
717 while (--n >= 0 && *p1 == *p2++) {
721 v1 = a2 - ((a2-n) - 1);
729 v0 = (n < 0 ? 0 : *p1 - *--p2);
731 v1 = a2 - ((a2-n) - 1);
737 void psxBios_strcpy() { // 0x19
738 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
739 if (a0 == 0 || a1 == 0)
745 while ((*p1++ = *p2++) != '\0');
750 void psxBios_strncpy() { // 0x1a
751 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
753 if (a0 == 0 || a1 == 0)
759 for (i = 0; i < n; i++) {
760 if ((*p1++ = *p2++) == '\0') {
772 void psxBios_strlen() { // 0x1b
773 char *p = (char *)Ra0;
784 void psxBios_index() { // 0x1c
785 char *p = (char *)Ra0;
795 v0 = a0 + (p - (char *)Ra0);
799 } while (*p++ != '\0');
804 void psxBios_rindex() { // 0x1d
805 char *p = (char *)Ra0;
815 v0 = a0 + (p - (char *)Ra0);
816 } while (*p++ != '\0');
821 void psxBios_strchr() { // 0x1e
825 void psxBios_strrchr() { // 0x1f
829 void psxBios_strpbrk() { // 0x20
830 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
832 while ((c = *p1++) != '\0') {
833 for (scanp = p2; (sc = *scanp++) != '\0';) {
835 v0 = a0 + (p1 - 1 - (char *)Ra0);
842 // BUG: return a0 instead of NULL if not found
846 void psxBios_strspn() { // 0x21
849 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
850 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
851 if (*p2 == '\0') break;
854 v0 = p1 - (char *)Ra0; pc0 = ra;
857 void psxBios_strcspn() { // 0x22
860 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
861 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
862 if (*p2 != '\0') break;
865 v0 = p1 - (char *)Ra0; pc0 = ra;
868 void psxBios_strtok() { // 0x23
869 char *pcA0 = (char *)Ra0;
870 char *pcRet = strtok(pcA0, (char *)Ra1);
872 v0 = a0 + pcRet - pcA0;
878 void psxBios_strstr() { // 0x24
879 char *p = (char *)Ra0, *p1, *p2;
885 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
890 v0 = a0 + (p - (char *)Ra0);
901 void psxBios_toupper() { // 0x25
902 v0 = (s8)(a0 & 0xff);
903 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
907 void psxBios_tolower() { // 0x26
908 v0 = (s8)(a0 & 0xff);
909 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
913 static void do_memset(u32 dst, u32 v, s32 len)
919 if (db != INVALID_PTR)
923 psxCpu->Clear(dst, (len + 3) / 4);
926 static void do_memcpy(u32 dst, u32 src, s32 len)
928 u32 d = dst, s = src;
931 const u8 *sb = PSXM(s);
933 if (db != INVALID_PTR && sb != INVALID_PTR)
938 psxCpu->Clear(dst, (len + 3) / 4);
941 static void psxBios_memcpy();
943 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
944 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
945 u32 ret = a0, cycles = 0;
946 if (a0 == 0) // ...but it checks src this time
953 do_memcpy(a1, a0, a2);
959 mips_return_c(ret, cycles + 5);
962 static void psxBios_bzero() { // 0x28
963 /* Same as memset here (See memset below) */
964 u32 ret = a0, cycles;
965 if (a0 == 0 || (s32)a1 <= 0)
970 do_memset(a0, 0, a1);
974 // todo: many more cycles due to uncached bios mem
975 mips_return_c(ret, cycles + 5);
978 void psxBios_bcmp() { // 0x29
979 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
981 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
983 while ((s32)a2-- > 0) {
984 if (*p1++ != *p2++) {
985 v0 = *p1 - *p2; // BUG: compare the NEXT byte
994 static void psxBios_memcpy() { // 0x2a
995 u32 ret = a0, cycles = 0;
1003 do_memcpy(a0, a1, a2);
1009 mips_return_c(ret, cycles + 5);
1012 static void psxBios_memset() { // 0x2b
1013 u32 ret = a0, cycles;
1014 if (a0 == 0 || (s32)a2 <= 0)
1016 mips_return_c(0, 6);
1019 do_memset(a0, a1, a2);
1023 // todo: many more cycles due to uncached bios mem
1024 mips_return_c(ret, cycles + 5);
1027 void psxBios_memmove() { // 0x2c
1028 u32 ret = a0, cycles = 0;
1031 mips_return_c(0, 4);
1035 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1036 u32 dst = a0, len = a2 + 1;
1039 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1040 const u8 *sb = PSXM(a1);
1042 if (db != INVALID_PTR && sb != INVALID_PTR)
1048 psxCpu->Clear(dst, (len + 3) / 4);
1049 cycles = 10 + len * 8;
1050 } else if ((s32)a2 > 0) {
1051 do_memcpy(a0, a1, a2);
1057 mips_return_c(ret, cycles + 5);
1060 void psxBios_memcmp() { // 0x2d
1064 void psxBios_memchr() { // 0x2e
1065 char *p = (char *)Ra0;
1067 if (a0 == 0 || a2 > 0x7FFFFFFF)
1073 while ((s32)a2-- > 0) {
1074 if (*p++ != (s8)a1) continue;
1075 v0 = a0 + (p - (char *)Ra0 - 1);
1083 void psxBios_rand() { // 0x2f
1084 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1085 v0 = (s >> 16) & 0x7fff;
1086 psxMu32ref(0x9010) = SWAPu32(s);
1090 void psxBios_srand() { // 0x30
1091 psxMu32ref(0x9010) = SWAPu32(a0);
1095 static u32 qscmpfunc, qswidth;
1097 static inline int qscmp(char *a, char *b) {
1100 a0 = sa0 + (a - (char *)PSXM(sa0));
1101 a1 = sa0 + (b - (char *)PSXM(sa0));
1103 softCall(qscmpfunc);
1109 static inline void qexchange(char *i, char *j) {
1120 static inline void q3exchange(char *i, char *j, char *k) {
1132 static void qsort_main(char *a, char *l) {
1133 char *i, *j, *lp, *hp;
1138 if ((n = l - a) <= qswidth)
1140 n = qswidth * (n / (2 * qswidth));
1146 if ((c = qscmp(i, lp)) == 0) {
1147 qexchange(i, lp -= qswidth);
1158 if ((c = qscmp(hp, j)) == 0) {
1159 qexchange(hp += qswidth, j);
1164 q3exchange(i, hp += qswidth, j);
1178 if (lp - a >= l - hp) {
1179 qsort_main(hp + qswidth, l);
1188 q3exchange(j, lp -= qswidth, i);
1193 void psxBios_qsort() { // 0x31
1196 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1201 // this isn't how the real bios works, but maybe good enough
1202 static void psxBios_malloc() { // 0x33
1203 u32 *heap_addr, *heap_end;
1204 u32 *chunk, *newchunk = NULL;
1205 unsigned int dsize = 0, csize, cstat;
1207 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
1208 heap_addr = loadRam32ptr(A_HEAP_BASE);
1209 heap_end = loadRam32ptr(A_HEAP_END);
1210 if (heap_addr >= heap_end) {
1216 // scan through heap and combine free chunks of space
1219 while(chunk < heap_end) {
1220 // get size and status of actual chunk
1221 csize = ((u32)*chunk) & 0xfffffffc;
1222 cstat = ((u32)*chunk) & 1;
1224 // most probably broken heap descriptor
1225 // this fixes Burning Road
1228 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1233 // it's a free chunk
1238 colflag = 1; // let's begin a new collection of free memory
1240 else dsize += (csize+4); // add the new size including header
1242 // not a free chunk: did we start a collection ?
1244 if(colflag == 1) { // collection is over
1246 *newchunk = SWAP32(dsize | 1);
1251 chunk = (u32*)((uptr)chunk + csize + 4);
1253 // if neccessary free memory on end of heap
1255 *newchunk = SWAP32(dsize | 1);
1258 csize = ((u32)*chunk) & 0xfffffffc;
1259 cstat = ((u32)*chunk) & 1;
1260 dsize = (a0 + 3) & 0xfffffffc;
1262 // exit on uninitialized heap
1263 if (chunk == NULL) {
1264 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1270 // search an unused chunk that is big enough until the end of the heap
1271 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1272 chunk = (u32*)((uptr)chunk + csize + 4);
1274 // catch out of memory
1275 if(chunk >= heap_end) {
1276 printf("malloc %x,%x: Out of memory error!\n",
1282 csize = ((u32)*chunk) & 0xfffffffc;
1283 cstat = ((u32)*chunk) & 1;
1287 if(dsize == csize) {
1288 // chunk has same size
1289 *chunk &= 0xfffffffc;
1290 } else if (dsize > csize) {
1295 *chunk = SWAP32(dsize);
1296 newchunk = (u32*)((uptr)chunk + dsize + 4);
1297 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1300 // return pointer to allocated memory
1301 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1303 //printf ("malloc %x,%x\n", v0, a0);
1307 static void psxBios_free() { // 0x34
1308 PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1309 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1310 mips_return_void_c(5);
1313 static void psxBios_calloc() { // 0x37
1315 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1317 a0 = size = a0 * a1;
1321 a0 = ret; a1 = size;
1324 mips_return_c(ret, 21);
1327 void psxBios_realloc() { // 0x38
1331 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1335 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1340 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1345 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1346 /* Note that it is not quite implemented this way here. */
1356 /* InitHeap(void *block , int n) */
1357 static void psxBios_InitHeap() { // 0x39
1358 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1360 storeRam32(A_HEAP_BASE, a0);
1361 storeRam32(A_HEAP_SIZE, a1);
1362 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1363 storeRam32(A_HEAP_FLAG, 0);
1366 mips_return_void_c(14);
1369 void psxBios_getchar() { //0x3b
1370 v0 = getchar(); pc0 = ra;
1373 static void psxBios_printf_psxout() { // 0x3f
1382 if (psp != INVALID_PTR) {
1383 memcpy(save, psp, 4 * 4);
1384 psxMu32ref(sp) = SWAP32((u32)a0);
1385 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1386 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1387 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1399 tmp2[j++] = Ra0[i]; goto _start;
1401 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1412 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1416 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1422 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1424 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1426 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1428 *ptmp++ = Ra0[i]; break;
1438 if (psp != INVALID_PTR)
1439 memcpy(psp, save, 4 * 4);
1442 SysPrintf("%s", tmp);
1445 void psxBios_printf() { // 0x3f
1446 psxBios_printf_psxout();
1450 void psxBios_format() { // 0x41
1451 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1453 CreateMcd(Config.Mcd1);
1454 LoadMcd(1, Config.Mcd1);
1457 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1459 CreateMcd(Config.Mcd2);
1460 LoadMcd(2, Config.Mcd2);
1470 static void psxBios_SystemErrorUnresolvedException() {
1471 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1472 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1473 storeRam32(0xfffc, 0x12345678);
1475 mips_return_void_c(1000);
1478 static void FlushCache() {
1479 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1480 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1482 // runs from uncached mem so tons of cycles
1487 * long Load(char *name, struct EXEC *header);
1490 void psxBios_Load() { // 0x42
1495 if (pa1 != INVALID_PTR && LoadCdromFile(Ra0, &eheader) == 0) {
1496 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1497 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1501 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1507 * int Exec(struct EXEC *header , int argc , char **argv);
1510 void psxBios_Exec() { // 43
1511 EXEC *header = (EXEC *)castRam32ptr(a0);
1515 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1517 header->_sp = SWAP32(sp);
1518 header->_fp = SWAP32(fp);
1519 header->_sp = SWAP32(sp);
1520 header->_gp = SWAP32(gp);
1521 header->ret = SWAP32(ra);
1522 header->base = SWAP32(s0);
1524 ptr = SWAP32(header->b_addr);
1525 len = SWAP32(header->b_size);
1531 if (header->S_addr != 0)
1532 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1534 gp = SWAP32(header->gp0);
1542 pc0 = SWAP32(header->_pc0);
1545 static void psxBios_FlushCache() { // 44
1546 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1551 void psxBios_GPU_dw() { // 0x46
1556 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1559 GPU_writeData(0xa0000000);
1560 GPU_writeData((a1<<0x10)|(a0&0xffff));
1561 GPU_writeData((a3<<0x10)|(a2&0xffff));
1563 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1566 GPU_writeData(SWAPu32(*ptr++));
1572 void psxBios_mem2vram() { // 0x47
1575 GPU_writeData(0xa0000000);
1576 GPU_writeData((a1<<0x10)|(a0&0xffff));
1577 GPU_writeData((a3<<0x10)|(a2&0xffff));
1578 size = ((((a2 * a3) / 2) >> 4) << 16);
1579 GPU_writeStatus(0x04000002);
1580 psxHwWrite32(0x1f8010f4,0);
1581 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1582 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1583 psxHwWrite32(0x1f8010a4, size | 0x10);
1584 psxHwWrite32(0x1f8010a8,0x01000201);
1589 void psxBios_SendGPU() { // 0x48
1590 GPU_writeStatus(a0);
1595 void psxBios_GPU_cw() { // 0x49
1602 void psxBios_GPU_cwb() { // 0x4a
1603 u32 *ptr = (u32*)Ra0;
1608 GPU_writeData(SWAPu32(*ptr++));
1614 void psxBios_GPU_SendPackets() { //4b:
1616 GPU_writeStatus(0x04000002);
1617 psxHwWrite32(0x1f8010f4,0);
1618 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1619 psxHwWrite32(0x1f8010a0,a0);
1620 psxHwWrite32(0x1f8010a4,0);
1621 psxHwWrite32(0x1f8010a8,0x010000401);
1625 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1626 psxHwWrite32(0x1f8010a8,0x00000401);
1627 GPU_writeData(0x0400000);
1628 GPU_writeData(0x0200000);
1629 GPU_writeData(0x0100000);
1634 void psxBios_GPU_GetGPUStatus() { // 0x4d
1635 v0 = GPU_readStatus();
1641 void psxBios_LoadExec() { // 51
1642 EXEC *header = (EXEC*)PSXM(0xf000);
1646 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1648 s_addr = a1; s_size = a2;
1653 header->S_addr = s_addr;
1654 header->s_size = s_size;
1656 a0 = 0xf000; a1 = 0; a2 = 0;
1660 void psxBios__bu_init() { // 70
1662 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1665 DeliverEvent(0xf0000011, 0x0004);
1666 DeliverEvent(0xf4000001, 0x0004);
1671 void psxBios__96_init() { // 71
1673 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1679 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1680 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1681 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1683 static void psxBios_DequeueCdIntr_() {
1684 psxBios_SysDeqIntRP_(0, 0x91d0);
1685 psxBios_SysDeqIntRP_(0, 0x91e0);
1689 static void psxBios_DequeueCdIntr() { // a3
1690 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1691 psxBios_DequeueCdIntr_();
1694 static void psxBios_CdRemove() { // 56, 72
1695 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1697 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1698 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1699 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1700 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1701 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1702 psxBios_DequeueCdIntr_();
1704 // EnterCriticalSection - should be done at the beginning,
1705 // but this way is much easier to implement
1711 void psxBios_SetMem() { // 9f
1712 u32 new = psxHu32(0x1060);
1715 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1720 psxHu32ref(0x1060) = SWAP32(new);
1721 psxMu32ref(0x060) = a0;
1722 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1726 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1727 psxMu32ref(0x060) = a0;
1728 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1731 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1738 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1739 static void psxBios_get_cd_status() // a6
1741 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1746 static void psxBios__card_info() { // ab
1747 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1749 storeRam32(A_CARD_CHAN1, a0);
1756 if (McdDisable[port & 1])
1760 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1765 if (McdDisable[0] && McdDisable[1])
1768 DeliverEvent(0xf0000011, 0x0004);
1769 // DeliverEvent(0xf4000001, 0x0004);
1770 DeliverEvent(0xf4000001, ret);
1774 void psxBios__card_load() { // ac
1776 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1779 storeRam32(A_CARD_CHAN1, a0);
1781 // DeliverEvent(0xf0000011, 0x0004);
1782 DeliverEvent(0xf4000001, 0x0004);
1787 static void psxBios_GetSystemInfo() { // b4
1789 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1790 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1793 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1794 case 2: ret = 0xbfc0012c; break;
1795 case 5: ret = loadRam32(0x60) << 10; break;
1797 mips_return_c(ret, 20);
1800 /* System calls B0 */
1802 static u32 psxBios_SysMalloc_(u32 size);
1804 static void psxBios_SysMalloc() { // B 00
1805 u32 ret = psxBios_SysMalloc_(a0);
1807 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1808 mips_return_c(ret, 33);
1811 void psxBios_SetRCnt() { // 02
1813 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1820 psxRcntWtarget(a0, a1);
1821 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1822 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1823 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1824 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1825 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1827 psxRcntWmode(a0, mode);
1832 void psxBios_GetRCnt() { // 03
1834 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1838 if (a0 != 3) v0 = psxRcntRcount(a0);
1843 void psxBios_StartRCnt() { // 04
1845 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1849 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1850 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1854 void psxBios_StopRCnt() { // 05
1856 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1860 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1861 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1865 void psxBios_ResetRCnt() { // 06
1867 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1872 psxRcntWmode(a0, 0);
1873 psxRcntWtarget(a0, 0);
1874 psxRcntWcount(a0, 0);
1879 static u32 DeliverEvent(u32 class, u32 spec) {
1880 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1881 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1882 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1883 u32 i, lim = evcb_len / 0x1c;
1885 for (i = 0; i < lim; i++, ev++) {
1887 if (SWAP32(ev->status) != EvStACTIVE)
1890 if (SWAP32(ev->class) != class)
1893 if (SWAP32(ev->spec) != spec)
1896 ret = SWAP32(ev->mode);
1897 if (ret == EvMdMARK) {
1898 ev->status = SWAP32(EvStALREADY);
1902 if (ret == EvMdCALL) {
1903 ret = SWAP32(ev->fhandler);
1915 static u32 UnDeliverEvent(u32 class, u32 spec) {
1916 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1917 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1918 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1919 u32 i, lim = evcb_len / 0x1c;
1921 for (i = 0; i < lim; i++, ev++) {
1923 if (SWAP32(ev->status) != EvStALREADY)
1926 if (SWAP32(ev->class) != class)
1929 if (SWAP32(ev->spec) != spec)
1932 if (SWAP32(ev->mode) == EvMdMARK)
1933 ev->status = SWAP32(EvStACTIVE);
1939 static void psxBios_DeliverEvent() { // 07
1941 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1943 ret = DeliverEvent(a0, a1);
1947 static s32 get_free_EvCB_slot() {
1948 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1949 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1952 for (i = 0; i < lim; i++, ev++) {
1954 if (ev->status == SWAP32(EvStUNUSED))
1960 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
1961 u32 ret = get_free_EvCB_slot();
1962 if ((s32)ret >= 0) {
1963 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
1964 ev->class = SWAP32(class);
1965 ev->status = SWAP32(EvStDISABLED);
1966 ev->spec = SWAP32(spec);
1967 ev->mode = SWAP32(mode);
1968 ev->fhandler = SWAP32(func);
1974 static void psxBios_OpenEvent() { // 08
1975 u32 ret = OpenEvent(a0, a1, a2, a3);
1976 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
1977 biosB0n[0x08], a0, a1, a2, a3, ret);
1978 mips_return_c(ret, 36);
1981 static void CloseEvent(u32 ev)
1983 u32 base = loadRam32(A_TT_EvCB);
1984 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
1987 static void psxBios_CloseEvent() { // 09
1988 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
1989 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
1991 mips_return_c(1, 10);
1994 static void psxBios_WaitEvent() { // 0a
1995 u32 base = loadRam32(A_TT_EvCB);
1996 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1997 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2000 if (status == EvStALREADY) {
2001 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2005 if (status != EvStACTIVE)
2007 mips_return_c(0, 2);
2011 // retrigger this hlecall after the next emulation event
2013 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2014 psxRegs.cycle = next_interupt;
2018 static void psxBios_TestEvent() { // 0b
2019 u32 base = loadRam32(A_TT_EvCB);
2020 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2022 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2023 if (status == EvStALREADY) {
2024 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2028 mips_return_c(ret, 15);
2031 static void psxBios_EnableEvent() { // 0c
2032 u32 base = loadRam32(A_TT_EvCB);
2033 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2034 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2035 if (status != EvStUNUSED)
2036 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2038 mips_return_c(1, 15);
2041 static void psxBios_DisableEvent() { // 0d
2042 u32 base = loadRam32(A_TT_EvCB);
2043 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2044 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2045 if (status != EvStUNUSED)
2046 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2048 mips_return_c(1, 15);
2052 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2055 void psxBios_OpenTh() { // 0e
2056 TCB *tcb = loadRam32ptr(A_TT_TCB);
2057 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2060 for (th = 1; th < limit; th++)
2062 if (tcb[th].status != SWAP32(0x4000)) break;
2066 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2067 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2069 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2071 mips_return_c(0xffffffff, 20);
2074 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
2076 tcb[th].status = SWAP32(0x4000);
2077 tcb[th].mode = SWAP32(0x1000);
2078 tcb[th].epc = SWAP32(a0);
2079 tcb[th].reg[30] = SWAP32(a1); // fp
2080 tcb[th].reg[29] = SWAP32(a1); // sp
2081 tcb[th].reg[28] = SWAP32(a2); // gp
2083 mips_return_c(0xff000000 + th, 34);
2087 * int CloseTh(long thread);
2090 void psxBios_CloseTh() { // 0f
2091 TCB *tcb = loadRam32ptr(A_TT_TCB);
2092 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2096 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2098 /* The return value is always 1 (even if the handle was already closed). */
2100 if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2101 tcb[th].status = SWAP32(0x1000);
2108 * int ChangeTh(long thread);
2111 void psxBios_ChangeTh() { // 10
2112 u32 tcbBase = loadRam32(A_TT_TCB);
2113 u32 th = a0 & 0xffff;
2115 // this is quite spammy
2116 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2118 // without doing any argument checks, just issue a syscall
2119 // (like the real bios does)
2121 a1 = tcbBase + th * sizeof(TCB);
2126 void psxBios_InitPAD() { // 0x12
2127 u32 i, *ram32 = (u32 *)psxM;
2128 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2130 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2131 ram32[A_PAD_DR_DST/4] = 0;
2132 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2133 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2134 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2135 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2136 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2137 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2138 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2139 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2141 for (i = 0; i < a1; i++) {
2143 storeRam8(a0 + i, 0);
2145 for (i = 0; i < a3; i++) {
2147 storeRam8(a2 + i, 0);
2149 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2151 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2153 mips_return_c(1, 200);
2156 void psxBios_StartPAD() { // 13
2157 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2159 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2160 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2161 psxHwWrite16(0x1f801070, ~1);
2162 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2163 storeRam32(A_PAD_ACK_VBL, 1);
2164 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2165 psxRegs.CP0.n.SR |= 0x401;
2167 mips_return_c(1, 300);
2170 void psxBios_StopPAD() { // 14
2171 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2172 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2173 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2174 psxRegs.CP0.n.SR |= 0x401;
2175 mips_return_void_c(200);
2178 static void psxBios_PAD_init() { // 15
2180 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2181 if (a0 == 0x20000000 || a0 == 0x20000001)
2184 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2185 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2188 storeRam32(A_PAD_DR_DST, dst);
2191 mips_return_c(ret, 100);
2194 static u32 psxBios_PAD_dr_() {
2195 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2196 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2197 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2198 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2199 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2201 dst[0] = buf1[3], dst[1] = buf1[2];
2202 if (buf1[1] == 0x23) {
2203 dst[0] |= 0xc7, dst[1] |= 7;
2204 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2205 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2208 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2210 dst[2] = buf2[3], dst[3] = buf2[2];
2211 if (buf2[1] == 0x23) {
2212 dst[2] |= 0xc7, dst[3] |= 7;
2213 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2214 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2218 return SWAP32(*(u32 *)dst);
2221 static void psxBios_PAD_dr() { // 16
2222 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2223 u32 ret = psxBios_PAD_dr_();
2227 static void psxBios_ReturnFromException() { // 17
2228 u32 tcbPtr = loadRam32(A_TT_PCB);
2229 const TCB *tcb = loadRam32ptr(tcbPtr);
2233 for (i = 1; i < 32; i++)
2234 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2235 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2236 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2237 sr = SWAP32(tcb->sr);
2239 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2240 pc0 = k0 = SWAP32(tcb->epc);
2242 // the interpreter wants to know about sr changes, so do a MTC0
2243 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2244 MTC0(&psxRegs, 12, sr);
2250 void psxBios_ResetEntryInt() { // 18
2251 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2253 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2254 mips_return_void_c(5);
2257 void psxBios_HookEntryInt() { // 19
2258 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2260 storeRam32(A_EEXIT_PTR, a0);
2261 mips_return_void_c(3);
2264 static void psxBios_UnDeliverEvent() { // 0x20
2266 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2268 ret = UnDeliverEvent(a0, a1);
2272 static void buopen(int mcd, char *ptr, char *cfg)
2275 char *mcd_data = ptr;
2277 strcpy(FDesc[1 + mcd].name, Ra0+5);
2278 FDesc[1 + mcd].offset = 0;
2279 FDesc[1 + mcd].mode = a1;
2281 for (i=1; i<16; i++) {
2282 const char *fptr = mcd_data + 128 * i;
2283 if ((*fptr & 0xF0) != 0x50) continue;
2284 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2285 FDesc[1 + mcd].mcfile = i;
2286 PSXBIOS_LOG("open %s\n", fptr+0xa);
2290 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2291 for (i=1; i<16; i++) {
2292 int j, xor, nblk = a1 >> 16;
2294 char *fptr = mcd_data + 128 * i;
2296 if ((*fptr & 0xF0) != 0xa0) continue;
2298 FDesc[1 + mcd].mcfile = i;
2301 fptr[5] = 0x20 * nblk;
2304 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2305 pptr = fptr2 = fptr;
2306 for(j=2; j<=nblk; j++) {
2308 for(i++; i<16; i++) {
2311 memset(fptr2, 0, 128);
2312 fptr2[0] = j < nblk ? 0x52 : 0x53;
2315 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2320 /* shouldn't this return ENOSPC if i == 16? */
2322 pptr[8] = pptr[9] = 0xff;
2323 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2325 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2327 /* just go ahead and resave them all */
2328 SaveMcd(cfg, ptr, 128, 128 * 15);
2331 /* shouldn't this return ENOSPC if i == 16? */
2336 * int open(char *name , int mode);
2339 void psxBios_open() { // 0x32
2343 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2348 if (pa0 != INVALID_PTR) {
2349 if (!strncmp(pa0, "bu00", 4)) {
2350 buopen(1, Mcd1Data, Config.Mcd1);
2353 if (!strncmp(pa0, "bu10", 4)) {
2354 buopen(2, Mcd2Data, Config.Mcd2);
2362 * int lseek(int fd , int offset , int whence);
2365 void psxBios_lseek() { // 0x33
2367 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2372 FDesc[a0].offset = a1;
2374 // DeliverEvent(0xf0000011, 0x0004);
2375 // DeliverEvent(0xf4000001, 0x0004);
2379 FDesc[a0].offset+= a1;
2380 v0 = FDesc[a0].offset;
2389 * int read(int fd , void *buf , int nbytes);
2392 void psxBios_read() { // 0x34
2397 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2402 if (pa1 != INVALID_PTR) {
2404 case 2: buread(pa1, 1, a2); break;
2405 case 3: buread(pa1, 2, a2); break;
2413 * int write(int fd , void *buf , int nbytes);
2416 void psxBios_write() { // 0x35/0x03
2420 if (a0 != 1) // stdout
2421 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2424 if (pa1 == INVALID_PTR) {
2429 if (a0 == 1) { // stdout
2433 if (Config.PsxOut) while (a2 > 0) {
2434 SysPrintf("%c", *ptr++); a2--;
2440 case 2: buwrite(pa1, 1, a2); break;
2441 case 3: buwrite(pa1, 2, a2); break;
2447 static void psxBios_write_psxout() {
2448 if (a0 == 1) { // stdout
2449 const char *ptr = Ra1;
2452 if (ptr != INVALID_PTR)
2454 SysPrintf("%c", *ptr++);
2458 static void psxBios_putchar_psxout() { // 3d
2459 SysPrintf("%c", (char)a0);
2462 static void psxBios_puts_psxout() { // 3e/3f
2463 SysPrintf("%s", Ra0);
2467 * int close(int fd);
2470 void psxBios_close() { // 0x36
2472 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2479 void psxBios_putchar() { // 3d
2480 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2484 void psxBios_puts() { // 3e/3f
2485 if (Config.PsxOut) SysPrintf("%s", Ra0);
2490 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2491 * We want to mimic the PSX's behaviour in this case for bufile. */
2492 static size_t strlen_internal(char* p)
2494 size_t size_of_array = 0;
2495 while (*p++) size_of_array++;
2496 return size_of_array;
2499 #define bufile(mcd) { \
2500 size_t size_of_name = strlen_internal(dir->name); \
2501 while (nfile < 16) { \
2504 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2506 if ((*ptr & 0xF0) != 0x50) continue; \
2507 /* Bug link files show up as free block. */ \
2508 if (!ptr[0xa]) continue; \
2510 if (pfile[0] == 0) { \
2511 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2512 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2513 } else for (i=0; i<20; i++) { \
2514 if (pfile[i] == ptr[i]) { \
2515 dir->name[i] = ptr[i]; continue; } \
2516 if (pfile[i] == '?') { \
2517 dir->name[i] = ptr[i]; continue; } \
2518 if (pfile[i] == '*') { \
2519 strcpy(dir->name+i, ptr+i); break; } \
2522 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2523 if (match == 0) { continue; } \
2531 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2534 void psxBios_firstfile() { // 42
2535 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2542 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2547 if (pa0 != INVALID_PTR) {
2551 if (!strncmp(pa0, "bu00", 4)) {
2552 // firstfile() calls _card_read() internally, so deliver it's event
2553 DeliverEvent(0xf0000011, 0x0004);
2555 } else if (!strncmp(pa0, "bu10", 4)) {
2556 // firstfile() calls _card_read() internally, so deliver it's event
2557 DeliverEvent(0xf0000011, 0x0004);
2566 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2569 void psxBios_nextfile() { // 43
2570 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2576 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2581 if (!strncmp(ffile, "bu00", 4)) {
2585 if (!strncmp(ffile, "bu10", 4)) {
2592 #define burename(mcd) { \
2593 for (i=1; i<16; i++) { \
2594 int namelen, j, xor = 0; \
2595 ptr = Mcd##mcd##Data + 128 * i; \
2596 if ((*ptr & 0xF0) != 0x50) continue; \
2597 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2598 namelen = strlen(Ra1+5); \
2599 memcpy(ptr+0xa, Ra1+5, namelen); \
2600 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2601 for (j=0; j<127; j++) xor^= ptr[j]; \
2603 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2610 * int rename(char *old, char *new);
2613 void psxBios_rename() { // 44
2620 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2625 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2626 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2630 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2639 #define budelete(mcd) { \
2640 for (i=1; i<16; i++) { \
2641 ptr = Mcd##mcd##Data + 128 * i; \
2642 if ((*ptr & 0xF0) != 0x50) continue; \
2643 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2644 *ptr = (*ptr & 0xf) | 0xA0; \
2645 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2646 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2653 * int delete(char *name);
2656 void psxBios_delete() { // 45
2662 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2667 if (pa0 != INVALID_PTR) {
2668 if (!strncmp(pa0, "bu00", 4)) {
2672 if (!strncmp(pa0, "bu10", 4)) {
2680 void psxBios_InitCARD() { // 4a
2681 u32 *ram32 = (u32 *)psxM;
2682 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2683 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2684 // (maybe) todo: early_card_irq, etc
2686 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2688 psxBios_FlushCache();
2689 mips_return_c(0, 34+13+15+6);
2692 void psxBios_StartCARD() { // 4b
2693 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2694 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2695 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2697 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2698 storeRam32(A_PAD_ACK_VBL, 1);
2699 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2700 storeRam32(A_CARD_IRQR_ENA, 1);
2701 psxRegs.CP0.n.SR |= 0x401;
2703 mips_return_c(1, 200);
2706 void psxBios_StopCARD() { // 4c
2707 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2708 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2709 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2710 storeRam32(A_CARD_IRQR_ENA, 0);
2711 psxRegs.CP0.n.SR |= 0x401;
2712 mips_return_void_c(200);
2715 void psxBios__card_write() { // 0x4e
2720 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2723 Function also accepts sector 400h (a bug).
2724 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2728 /* Invalid sectors */
2732 storeRam32(A_CARD_CHAN1, a0);
2735 if (pa2 != INVALID_PTR) {
2737 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2738 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2740 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2741 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2745 DeliverEvent(0xf0000011, 0x0004);
2746 // DeliverEvent(0xf4000001, 0x0004);
2751 void psxBios__card_read() { // 0x4f
2756 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2759 Function also accepts sector 400h (a bug).
2760 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2764 /* Invalid sectors */
2768 storeRam32(A_CARD_CHAN1, a0);
2771 if (pa2 != INVALID_PTR) {
2773 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2775 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2779 DeliverEvent(0xf0000011, 0x0004);
2780 // DeliverEvent(0xf4000001, 0x0004);
2785 void psxBios__new_card() { // 0x50
2787 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2793 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2794 void psxBios__get_error(void) // 55
2796 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2801 void psxBios_Krom2RawAdd() { // 0x51
2804 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2805 const u32 table_8140[][2] = {
2806 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2807 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2808 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2809 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2810 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2811 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2812 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2813 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2814 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2818 const u32 table_889f[][2] = {
2819 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2820 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2821 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2822 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2823 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2824 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2825 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2826 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2830 if (a0 >= 0x8140 && a0 <= 0x84be) {
2831 while (table_8140[i][0] <= a0) i++;
2832 a0 -= table_8140[i - 1][0];
2833 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2834 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2835 while (table_889f[i][0] <= a0) i++;
2836 a0 -= table_889f[i - 1][0];
2837 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2845 void psxBios_GetC0Table() { // 56
2846 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2847 log_unhandled("GetC0Table @%08x\n", ra);
2849 mips_return_c(A_C0_TABLE, 3);
2852 void psxBios_GetB0Table() { // 57
2853 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2854 log_unhandled("GetB0Table @%08x\n", ra);
2856 mips_return_c(A_B0_TABLE, 3);
2859 static void psxBios__card_chan() { // 0x58
2861 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2863 // todo: should return active slot chan
2864 // (active - which was last processed by irq code)
2865 ret = loadRam32(A_CARD_CHAN1);
2866 mips_return_c(ret, 8);
2869 static void psxBios_ChangeClearPad() { // 5b
2871 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2872 ret = loadRam32(A_PAD_ACK_VBL);
2873 storeRam32(A_PAD_ACK_VBL, a0);
2875 mips_return_c(ret, 6);
2878 static void psxBios__card_status() { // 5c
2879 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2885 static void psxBios__card_wait() { // 5d
2886 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2892 /* System calls C0 */
2894 static void psxBios_InitRCnt() { // 00
2896 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2897 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2898 for (i = 0; i < 3; i++) {
2899 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2900 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2901 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2903 psxBios_SysEnqIntRP_(a0, 0x6d88);
2904 mips_return_c(0, 9);
2907 static void psxBios_InitException() { // 01
2908 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2909 psxBios_SysEnqIntRP_(a0, 0x6da8);
2910 mips_return_c(0, 9);
2914 * int SysEnqIntRP(int index , long *queue);
2917 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2918 u32 old, base = loadRam32(A_TT_ExCB);
2920 old = loadRam32(base + (priority << 3));
2921 storeRam32(base + (priority << 3), chain_eptr);
2922 storeRam32(chain_eptr, old);
2923 mips_return_c(0, 9);
2926 static void psxBios_SysEnqIntRP() { // 02
2927 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2928 psxBios_SysEnqIntRP_(a0, a1);
2932 * int SysDeqIntRP(int index , long *queue);
2935 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2936 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2937 u32 lim = 0, ret = 0;
2939 // as in original: no arg checks of any kind, bug if a1 == 0
2940 ptr = loadRam32(base + (priority << 3));
2942 next = loadRam32(ptr);
2943 if (ptr == chain_rm_eptr) {
2944 storeRam32(base + (priority << 3), next);
2949 while (next && next != chain_rm_eptr && lim++ < 100) {
2951 next = loadRam32(ptr);
2954 if (next == chain_rm_eptr) {
2955 next = loadRam32(next);
2956 storeRam32(ptr, next);
2963 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2965 mips_return_c(ret, 12);
2968 static void psxBios_SysDeqIntRP() { // 03
2969 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2970 psxBios_SysDeqIntRP_(a0, a1);
2973 static void psxBios_get_free_EvCB_slot() { // 04
2974 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
2975 s32 ret = get_free_EvCB_slot();
2976 mips_return_c(ret, 0);
2979 static void psxBios_SysInitMemory_(u32 base, u32 size) {
2980 storeRam32(base, 0);
2981 storeRam32(A_KMALLOC_PTR, base);
2982 storeRam32(A_KMALLOC_SIZE, size);
2983 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2986 // this should be much more complicated, but maybe that'll be enough
2987 static u32 psxBios_SysMalloc_(u32 size) {
2988 u32 ptr = loadRam32(A_KMALLOC_PTR);
2990 size = (size + 3) & ~3;
2991 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2992 storeRam32(ptr, size);
2996 static void psxBios_SysInitMemory() { // 08
2997 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2999 psxBios_SysInitMemory_(a0, a1);
3000 mips_return_void_c(12);
3003 static void psxBios_ChangeClearRCnt() { // 0a
3006 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3008 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3009 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3010 mips_return_c(ret, 8);
3013 static void psxBios_InitDefInt() { // 0c
3014 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3015 // should also clear the autoack table
3016 psxBios_SysEnqIntRP_(a0, 0x6d98);
3017 mips_return_c(0, 20 + 6*2);
3020 void psxBios_dummy() {
3021 u32 pc = (pc0 & 0x1fffff) - 4;
3022 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3023 : pc == 0xc0 ? biosC0n : NULL;
3024 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3025 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3026 (void)pc; (void)ntab;
3027 mips_return_c(0, 100);
3030 void (*biosA0[256])();
3031 // C0 and B0 overlap (end of C0 is start of B0)
3032 void (*biosC0[256+128])();
3033 void (**biosB0)() = biosC0 + 128;
3035 static void setup_mips_code()
3038 ptr = (u32 *)&psxM[A_SYSCALL];
3039 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3040 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3041 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3043 ptr = (u32 *)&psxM[A_EXCEPTION];
3044 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3045 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3046 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3047 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3048 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3049 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3050 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3051 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3052 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3053 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3055 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3056 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3057 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3059 ptr[0xb0/4] = HLEOP(hleop_exception);
3062 static const struct {
3066 { 0xbfc050a4, hleop_exc0_0_1 },
3067 { 0xbfc04fbc, hleop_exc0_0_2 },
3068 { 0xbfc0506c, hleop_exc0_1_1 },
3069 { 0xbfc04dec, hleop_exc0_1_2 },
3070 { 0x1a00, hleop_exc0_2_2 },
3071 { 0x19c8, hleop_exc1_0_1 },
3072 { 0x18bc, hleop_exc1_0_2 },
3073 { 0x1990, hleop_exc1_1_1 },
3074 { 0x1858, hleop_exc1_1_2 },
3075 { 0x1958, hleop_exc1_2_1 },
3076 { 0x17f4, hleop_exc1_2_2 },
3077 { 0x1920, hleop_exc1_3_1 },
3078 { 0x1794, hleop_exc1_3_2 },
3079 { 0x2458, hleop_exc3_0_2 },
3080 { 0x49bc, hleop_exc_padcard1 },
3081 { 0x4a4c, hleop_exc_padcard2 },
3084 static int chain_hle_op(u32 handler)
3088 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3089 if (chainfns[i].addr == handler)
3090 return chainfns[i].op;
3094 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3096 d[0] = SWAPu32(next);
3097 d[1] = SWAPu32(handler1);
3098 d[2] = SWAPu32(handler2);
3100 // install the hle traps
3101 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3102 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3105 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
3107 u32 *ram32 = (u32 *)psxM;
3108 u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
3109 u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
3110 u32 p_excb, p_evcb, p_pcb, p_tcb;
3112 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3113 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3114 p_excb = psxBios_SysMalloc_(s_excb);
3115 p_evcb = psxBios_SysMalloc_(s_evcb);
3116 p_pcb = psxBios_SysMalloc_(s_pcb);
3117 p_tcb = psxBios_SysMalloc_(s_tcb);
3119 // "table of tables". Some games modify it
3120 assert(A_TT_ExCB == 0x0100);
3121 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3122 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3123 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3124 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3125 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3126 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3127 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3128 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3129 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3130 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3131 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3132 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3134 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3135 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3136 storeRam32(p_excb + 4*4, 0x0000); // chain2
3137 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3139 storeRam32(p_pcb, p_tcb);
3140 storeRam32(p_tcb, 0x4000); // first TCB
3143 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3144 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3145 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3146 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3147 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3148 DeliverEvent(0xf0000003, 0x0010);
3151 static const u32 gpu_ctl_def[] = {
3152 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3153 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3156 static const u32 gpu_data_def[] = {
3157 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3158 0xe5001000, 0xe6000000,
3159 0x02000000, 0x00000000, 0x01ff03ff
3163 static const u16 spu_config[] = {
3164 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3165 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3166 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3167 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3168 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3169 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3170 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3171 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3174 void psxBiosSetupBootState(void)
3176 boolean hle = Config.HLE;
3177 u32 *hw = (u32 *)psxH;
3180 // see also SetBootRegs()
3183 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3184 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3186 k0 = 0xbfc0d968; k1 = 0xf1c;
3187 ra = 0xf0001234; // just to easily detect attempts to return
3188 psxRegs.CP0.n.Cause = 0x20;
3189 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3191 hw[0x1000/4] = SWAP32(0x1f000000);
3192 hw[0x1004/4] = SWAP32(0x1f802000);
3193 hw[0x1008/4] = SWAP32(0x0013243f);
3194 hw[0x100c/4] = SWAP32(0x00003022);
3195 hw[0x1010/4] = SWAP32(0x0013243f);
3196 hw[0x1014/4] = SWAP32(0x200931e1);
3197 hw[0x1018/4] = SWAP32(0x00020943);
3198 hw[0x101c/4] = SWAP32(0x00070777);
3199 hw[0x1020/4] = SWAP32(0x0000132c);
3200 hw[0x1060/4] = SWAP32(0x00000b88);
3201 hw[0x1070/4] = SWAP32(0x00000001);
3202 hw[0x1074/4] = SWAP32(0x0000000c);
3203 hw[0x2040/4] = SWAP32(0x00000900);
3206 hw[0x10a0/4] = SWAP32(0x00ffffff);
3207 hw[0x10a8/4] = SWAP32(0x00000401);
3208 hw[0x10b0/4] = SWAP32(0x0008b000);
3209 hw[0x10b4/4] = SWAP32(0x00010200);
3210 hw[0x10e0/4] = SWAP32(0x000eccf4);
3211 hw[0x10e4/4] = SWAP32(0x00000400);
3212 hw[0x10e8/4] = SWAP32(0x00000002);
3213 hw[0x10f0/4] = SWAP32(0x00009099);
3214 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3223 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3224 GPU_writeStatus(gpu_ctl_def[i]);
3225 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3226 GPU_writeData(gpu_data_def[i]);
3227 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3230 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3231 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3234 #include "sjisfont.h"
3236 void psxBiosInit() {
3237 u32 *ptr, *ram32, *rom32;
3241 memset(psxM, 0, 0x10000);
3242 for(i = 0; i < 256; i++) {
3247 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3248 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3249 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3250 biosA0[0x3f] = psxBios_printf_psxout;
3252 if (!Config.HLE) return;
3254 for(i = 0; i < 256; i++) {
3255 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3256 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3257 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3260 biosA0[0x00] = psxBios_open;
3261 biosA0[0x01] = psxBios_lseek;
3262 biosA0[0x02] = psxBios_read;
3263 biosA0[0x03] = psxBios_write;
3264 biosA0[0x04] = psxBios_close;
3265 //biosA0[0x05] = psxBios_ioctl;
3266 //biosA0[0x06] = psxBios_exit;
3267 //biosA0[0x07] = psxBios_sys_a0_07;
3268 biosA0[0x08] = psxBios_getc;
3269 biosA0[0x09] = psxBios_putc;
3270 biosA0[0x0a] = psxBios_todigit;
3271 //biosA0[0x0b] = psxBios_atof;
3272 //biosA0[0x0c] = psxBios_strtoul;
3273 //biosA0[0x0d] = psxBios_strtol;
3274 biosA0[0x0e] = psxBios_abs;
3275 biosA0[0x0f] = psxBios_labs;
3276 biosA0[0x10] = psxBios_atoi;
3277 biosA0[0x11] = psxBios_atol;
3278 //biosA0[0x12] = psxBios_atob;
3279 biosA0[0x13] = psxBios_setjmp;
3280 biosA0[0x14] = psxBios_longjmp;
3281 biosA0[0x15] = psxBios_strcat;
3282 biosA0[0x16] = psxBios_strncat;
3283 biosA0[0x17] = psxBios_strcmp;
3284 biosA0[0x18] = psxBios_strncmp;
3285 biosA0[0x19] = psxBios_strcpy;
3286 biosA0[0x1a] = psxBios_strncpy;
3287 biosA0[0x1b] = psxBios_strlen;
3288 biosA0[0x1c] = psxBios_index;
3289 biosA0[0x1d] = psxBios_rindex;
3290 biosA0[0x1e] = psxBios_strchr;
3291 biosA0[0x1f] = psxBios_strrchr;
3292 biosA0[0x20] = psxBios_strpbrk;
3293 biosA0[0x21] = psxBios_strspn;
3294 biosA0[0x22] = psxBios_strcspn;
3295 biosA0[0x23] = psxBios_strtok;
3296 biosA0[0x24] = psxBios_strstr;
3297 biosA0[0x25] = psxBios_toupper;
3298 biosA0[0x26] = psxBios_tolower;
3299 biosA0[0x27] = psxBios_bcopy;
3300 biosA0[0x28] = psxBios_bzero;
3301 biosA0[0x29] = psxBios_bcmp;
3302 biosA0[0x2a] = psxBios_memcpy;
3303 biosA0[0x2b] = psxBios_memset;
3304 biosA0[0x2c] = psxBios_memmove;
3305 biosA0[0x2d] = psxBios_memcmp;
3306 biosA0[0x2e] = psxBios_memchr;
3307 biosA0[0x2f] = psxBios_rand;
3308 biosA0[0x30] = psxBios_srand;
3309 biosA0[0x31] = psxBios_qsort;
3310 //biosA0[0x32] = psxBios_strtod;
3311 biosA0[0x33] = psxBios_malloc;
3312 biosA0[0x34] = psxBios_free;
3313 //biosA0[0x35] = psxBios_lsearch;
3314 //biosA0[0x36] = psxBios_bsearch;
3315 biosA0[0x37] = psxBios_calloc;
3316 biosA0[0x38] = psxBios_realloc;
3317 biosA0[0x39] = psxBios_InitHeap;
3318 //biosA0[0x3a] = psxBios__exit;
3319 biosA0[0x3b] = psxBios_getchar;
3320 biosA0[0x3c] = psxBios_putchar;
3321 //biosA0[0x3d] = psxBios_gets;
3322 biosA0[0x3e] = psxBios_puts;
3323 biosA0[0x3f] = psxBios_printf;
3324 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3325 //biosA0[0x41] = psxBios_LoadTest;
3326 biosA0[0x42] = psxBios_Load;
3327 biosA0[0x43] = psxBios_Exec;
3328 biosA0[0x44] = psxBios_FlushCache;
3329 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3330 biosA0[0x46] = psxBios_GPU_dw;
3331 biosA0[0x47] = psxBios_mem2vram;
3332 biosA0[0x48] = psxBios_SendGPU;
3333 biosA0[0x49] = psxBios_GPU_cw;
3334 biosA0[0x4a] = psxBios_GPU_cwb;
3335 biosA0[0x4b] = psxBios_GPU_SendPackets;
3336 biosA0[0x4c] = psxBios_sys_a0_4c;
3337 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3338 //biosA0[0x4e] = psxBios_GPU_sync;
3339 //biosA0[0x4f] = psxBios_sys_a0_4f;
3340 //biosA0[0x50] = psxBios_sys_a0_50;
3341 biosA0[0x51] = psxBios_LoadExec;
3342 //biosA0[0x52] = psxBios_GetSysSp;
3343 //biosA0[0x53] = psxBios_sys_a0_53;
3344 //biosA0[0x54] = psxBios__96_init_a54;
3345 //biosA0[0x55] = psxBios__bu_init_a55;
3346 biosA0[0x56] = psxBios_CdRemove;
3347 //biosA0[0x57] = psxBios_sys_a0_57;
3348 //biosA0[0x58] = psxBios_sys_a0_58;
3349 //biosA0[0x59] = psxBios_sys_a0_59;
3350 //biosA0[0x5a] = psxBios_sys_a0_5a;
3351 //biosA0[0x5b] = psxBios_dev_tty_init;
3352 //biosA0[0x5c] = psxBios_dev_tty_open;
3353 //biosA0[0x5d] = psxBios_sys_a0_5d;
3354 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3355 //biosA0[0x5f] = psxBios_dev_cd_open;
3356 //biosA0[0x60] = psxBios_dev_cd_read;
3357 //biosA0[0x61] = psxBios_dev_cd_close;
3358 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3359 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3360 //biosA0[0x64] = psxBios_dev_cd_chdir;
3361 //biosA0[0x65] = psxBios_dev_card_open;
3362 //biosA0[0x66] = psxBios_dev_card_read;
3363 //biosA0[0x67] = psxBios_dev_card_write;
3364 //biosA0[0x68] = psxBios_dev_card_close;
3365 //biosA0[0x69] = psxBios_dev_card_firstfile;
3366 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3367 //biosA0[0x6b] = psxBios_dev_card_erase;
3368 //biosA0[0x6c] = psxBios_dev_card_undelete;
3369 //biosA0[0x6d] = psxBios_dev_card_format;
3370 //biosA0[0x6e] = psxBios_dev_card_rename;
3371 //biosA0[0x6f] = psxBios_dev_card_6f;
3372 biosA0[0x70] = psxBios__bu_init;
3373 biosA0[0x71] = psxBios__96_init;
3374 biosA0[0x72] = psxBios_CdRemove;
3375 //biosA0[0x73] = psxBios_sys_a0_73;
3376 //biosA0[0x74] = psxBios_sys_a0_74;
3377 //biosA0[0x75] = psxBios_sys_a0_75;
3378 //biosA0[0x76] = psxBios_sys_a0_76;
3379 //biosA0[0x77] = psxBios_sys_a0_77;
3380 //biosA0[0x78] = psxBios__96_CdSeekL;
3381 //biosA0[0x79] = psxBios_sys_a0_79;
3382 //biosA0[0x7a] = psxBios_sys_a0_7a;
3383 //biosA0[0x7b] = psxBios_sys_a0_7b;
3384 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3385 //biosA0[0x7d] = psxBios_sys_a0_7d;
3386 //biosA0[0x7e] = psxBios__96_CdRead;
3387 //biosA0[0x7f] = psxBios_sys_a0_7f;
3388 //biosA0[0x80] = psxBios_sys_a0_80;
3389 //biosA0[0x81] = psxBios_sys_a0_81;
3390 //biosA0[0x82] = psxBios_sys_a0_82;
3391 //biosA0[0x83] = psxBios_sys_a0_83;
3392 //biosA0[0x84] = psxBios_sys_a0_84;
3393 //biosA0[0x85] = psxBios__96_CdStop;
3394 //biosA0[0x86] = psxBios_sys_a0_86;
3395 //biosA0[0x87] = psxBios_sys_a0_87;
3396 //biosA0[0x88] = psxBios_sys_a0_88;
3397 //biosA0[0x89] = psxBios_sys_a0_89;
3398 //biosA0[0x8a] = psxBios_sys_a0_8a;
3399 //biosA0[0x8b] = psxBios_sys_a0_8b;
3400 //biosA0[0x8c] = psxBios_sys_a0_8c;
3401 //biosA0[0x8d] = psxBios_sys_a0_8d;
3402 //biosA0[0x8e] = psxBios_sys_a0_8e;
3403 //biosA0[0x8f] = psxBios_sys_a0_8f;
3404 biosA0[0x90] = hleExc0_1_2;
3405 biosA0[0x91] = hleExc0_0_2;
3406 biosA0[0x92] = hleExc0_1_1;
3407 biosA0[0x93] = hleExc0_0_1;
3408 //biosA0[0x94] = psxBios_sys_a0_94;
3409 //biosA0[0x95] = psxBios_sys_a0_95;
3410 //biosA0[0x96] = psxBios_AddCDROMDevice;
3411 //biosA0[0x97] = psxBios_AddMemCardDevide;
3412 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3413 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3414 //biosA0[0x9a] = psxBios_sys_a0_9a;
3415 //biosA0[0x9b] = psxBios_sys_a0_9b;
3416 //biosA0[0x9c] = psxBios_SetConf;
3417 //biosA0[0x9d] = psxBios_GetConf;
3418 //biosA0[0x9e] = psxBios_sys_a0_9e;
3419 biosA0[0x9f] = psxBios_SetMem;
3420 //biosA0[0xa0] = psxBios__boot;
3421 //biosA0[0xa1] = psxBios_SystemError;
3422 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3423 biosA0[0xa3] = psxBios_DequeueCdIntr;
3424 //biosA0[0xa4] = psxBios_sys_a0_a4;
3425 //biosA0[0xa5] = psxBios_ReadSector;
3426 biosA0[0xa6] = psxBios_get_cd_status;
3427 //biosA0[0xa7] = psxBios_bufs_cb_0;
3428 //biosA0[0xa8] = psxBios_bufs_cb_1;
3429 //biosA0[0xa9] = psxBios_bufs_cb_2;
3430 //biosA0[0xaa] = psxBios_bufs_cb_3;
3431 biosA0[0xab] = psxBios__card_info;
3432 biosA0[0xac] = psxBios__card_load;
3433 //biosA0[0axd] = psxBios__card_auto;
3434 //biosA0[0xae] = psxBios_bufs_cd_4;
3435 //biosA0[0xaf] = psxBios_sys_a0_af;
3436 //biosA0[0xb0] = psxBios_sys_a0_b0;
3437 //biosA0[0xb1] = psxBios_sys_a0_b1;
3438 //biosA0[0xb2] = psxBios_do_a_long_jmp
3439 //biosA0[0xb3] = psxBios_sys_a0_b3;
3440 biosA0[0xb4] = psxBios_GetSystemInfo;
3441 //*******************B0 CALLS****************************
3442 biosB0[0x00] = psxBios_SysMalloc;
3443 //biosB0[0x01] = psxBios_sys_b0_01;
3444 biosB0[0x02] = psxBios_SetRCnt;
3445 biosB0[0x03] = psxBios_GetRCnt;
3446 biosB0[0x04] = psxBios_StartRCnt;
3447 biosB0[0x05] = psxBios_StopRCnt;
3448 biosB0[0x06] = psxBios_ResetRCnt;
3449 biosB0[0x07] = psxBios_DeliverEvent;
3450 biosB0[0x08] = psxBios_OpenEvent;
3451 biosB0[0x09] = psxBios_CloseEvent;
3452 biosB0[0x0a] = psxBios_WaitEvent;
3453 biosB0[0x0b] = psxBios_TestEvent;
3454 biosB0[0x0c] = psxBios_EnableEvent;
3455 biosB0[0x0d] = psxBios_DisableEvent;
3456 biosB0[0x0e] = psxBios_OpenTh;
3457 biosB0[0x0f] = psxBios_CloseTh;
3458 biosB0[0x10] = psxBios_ChangeTh;
3459 //biosB0[0x11] = psxBios_psxBios_b0_11;
3460 biosB0[0x12] = psxBios_InitPAD;
3461 biosB0[0x13] = psxBios_StartPAD;
3462 biosB0[0x14] = psxBios_StopPAD;
3463 biosB0[0x15] = psxBios_PAD_init;
3464 biosB0[0x16] = psxBios_PAD_dr;
3465 biosB0[0x17] = psxBios_ReturnFromException;
3466 biosB0[0x18] = psxBios_ResetEntryInt;
3467 biosB0[0x19] = psxBios_HookEntryInt;
3468 //biosB0[0x1a] = psxBios_sys_b0_1a;
3469 //biosB0[0x1b] = psxBios_sys_b0_1b;
3470 //biosB0[0x1c] = psxBios_sys_b0_1c;
3471 //biosB0[0x1d] = psxBios_sys_b0_1d;
3472 //biosB0[0x1e] = psxBios_sys_b0_1e;
3473 //biosB0[0x1f] = psxBios_sys_b0_1f;
3474 biosB0[0x20] = psxBios_UnDeliverEvent;
3475 //biosB0[0x21] = psxBios_sys_b0_21;
3476 //biosB0[0x22] = psxBios_sys_b0_22;
3477 //biosB0[0x23] = psxBios_sys_b0_23;
3478 //biosB0[0x24] = psxBios_sys_b0_24;
3479 //biosB0[0x25] = psxBios_sys_b0_25;
3480 //biosB0[0x26] = psxBios_sys_b0_26;
3481 //biosB0[0x27] = psxBios_sys_b0_27;
3482 //biosB0[0x28] = psxBios_sys_b0_28;
3483 //biosB0[0x29] = psxBios_sys_b0_29;
3484 //biosB0[0x2a] = psxBios_sys_b0_2a;
3485 //biosB0[0x2b] = psxBios_sys_b0_2b;
3486 //biosB0[0x2c] = psxBios_sys_b0_2c;
3487 //biosB0[0x2d] = psxBios_sys_b0_2d;
3488 //biosB0[0x2e] = psxBios_sys_b0_2e;
3489 //biosB0[0x2f] = psxBios_sys_b0_2f;
3490 //biosB0[0x30] = psxBios_sys_b0_30;
3491 //biosB0[0x31] = psxBios_sys_b0_31;
3492 biosB0[0x32] = psxBios_open;
3493 biosB0[0x33] = psxBios_lseek;
3494 biosB0[0x34] = psxBios_read;
3495 biosB0[0x35] = psxBios_write;
3496 biosB0[0x36] = psxBios_close;
3497 //biosB0[0x37] = psxBios_ioctl;
3498 //biosB0[0x38] = psxBios_exit;
3499 //biosB0[0x39] = psxBios_sys_b0_39;
3500 //biosB0[0x3a] = psxBios_getc;
3501 //biosB0[0x3b] = psxBios_putc;
3502 biosB0[0x3c] = psxBios_getchar;
3503 biosB0[0x3d] = psxBios_putchar;
3504 //biosB0[0x3e] = psxBios_gets;
3505 biosB0[0x3f] = psxBios_puts;
3506 //biosB0[0x40] = psxBios_cd;
3507 biosB0[0x41] = psxBios_format;
3508 biosB0[0x42] = psxBios_firstfile;
3509 biosB0[0x43] = psxBios_nextfile;
3510 biosB0[0x44] = psxBios_rename;
3511 biosB0[0x45] = psxBios_delete;
3512 //biosB0[0x46] = psxBios_undelete;
3513 //biosB0[0x47] = psxBios_AddDevice;
3514 //biosB0[0x48] = psxBios_RemoteDevice;
3515 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3516 biosB0[0x4a] = psxBios_InitCARD;
3517 biosB0[0x4b] = psxBios_StartCARD;
3518 biosB0[0x4c] = psxBios_StopCARD;
3519 //biosB0[0x4d] = psxBios_sys_b0_4d;
3520 biosB0[0x4e] = psxBios__card_write;
3521 biosB0[0x4f] = psxBios__card_read;
3522 biosB0[0x50] = psxBios__new_card;
3523 biosB0[0x51] = psxBios_Krom2RawAdd;
3524 //biosB0[0x52] = psxBios_sys_b0_52;
3525 //biosB0[0x53] = psxBios_sys_b0_53;
3526 //biosB0[0x54] = psxBios__get_errno;
3527 biosB0[0x55] = psxBios__get_error;
3528 biosB0[0x56] = psxBios_GetC0Table;
3529 biosB0[0x57] = psxBios_GetB0Table;
3530 biosB0[0x58] = psxBios__card_chan;
3531 //biosB0[0x59] = psxBios_sys_b0_59;
3532 //biosB0[0x5a] = psxBios_sys_b0_5a;
3533 biosB0[0x5b] = psxBios_ChangeClearPad;
3534 biosB0[0x5c] = psxBios__card_status;
3535 biosB0[0x5d] = psxBios__card_wait;
3536 //*******************C0 CALLS****************************
3537 biosC0[0x00] = psxBios_InitRCnt;
3538 biosC0[0x01] = psxBios_InitException;
3539 biosC0[0x02] = psxBios_SysEnqIntRP;
3540 biosC0[0x03] = psxBios_SysDeqIntRP;
3541 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3542 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3543 //biosC0[0x06] = psxBios_ExceptionHandler;
3544 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3545 biosC0[0x08] = psxBios_SysInitMemory;
3546 //biosC0[0x09] = psxBios_SysInitKMem;
3547 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3548 //biosC0[0x0b] = psxBios_SystemError;
3549 biosC0[0x0c] = psxBios_InitDefInt;
3550 //biosC0[0x0d] = psxBios_sys_c0_0d;
3551 //biosC0[0x0e] = psxBios_sys_c0_0e;
3552 //biosC0[0x0f] = psxBios_sys_c0_0f;
3553 //biosC0[0x10] = psxBios_sys_c0_10;
3554 //biosC0[0x11] = psxBios_sys_c0_11;
3555 //biosC0[0x12] = psxBios_InstallDevices;
3556 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3557 //biosC0[0x14] = psxBios_sys_c0_14;
3558 //biosC0[0x15] = psxBios__cdevinput;
3559 //biosC0[0x16] = psxBios__cdevscan;
3560 //biosC0[0x17] = psxBios__circgetc;
3561 //biosC0[0x18] = psxBios__circputc;
3562 //biosC0[0x19] = psxBios_ioabort;
3563 //biosC0[0x1a] = psxBios_sys_c0_1a
3564 //biosC0[0x1b] = psxBios_KernelRedirect;
3565 //biosC0[0x1c] = psxBios_PatchAOTable;
3566 //************** THE END ***************************************
3569 memset(FDesc, 0, sizeof(FDesc));
3572 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3574 // somewhat pretend to be a SCPH1001 BIOS
3575 // some games look for these and take an exception if they're missing
3576 rom32 = (u32 *)psxR;
3577 rom32[0x100/4] = SWAP32(0x19951204);
3578 rom32[0x104/4] = SWAP32(3);
3579 strcpy(psxR + 0x108, "PCSX authors");
3580 strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3581 strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3582 strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
3585 len = 0x80000 - 0x66000;
3586 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3587 len = 0x80000 - 0x69d68;
3588 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3590 // trap attempts to call bios directly
3591 rom32[0x00000/4] = HLEOP(hleop_dummy);
3592 rom32[0x00180/4] = HLEOP(hleop_dummy);
3593 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3594 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3595 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3597 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3598 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3599 Here are some examples of games not working with this fix in place :
3600 R-type won't get past the Irem logo if not implemented.
3601 Crash Team Racing will softlock after the Sony logo.
3604 ram32 = (u32 *)psxM;
3605 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3606 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3607 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3608 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3610 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3611 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3613 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3614 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3615 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3616 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3618 ram32[0x00a0/4] = HLEOP(hleop_a0);
3619 ram32[0x00b0/4] = HLEOP(hleop_b0);
3620 ram32[0x00c0/4] = HLEOP(hleop_c0);
3624 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3625 strcpy((char *)&ram32[0xeff0/4], "bu");
3627 // default exception handler chains
3628 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3629 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3630 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3631 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3632 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3633 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3634 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3635 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3639 // fill the api jumptables with fake entries as some games patch them
3640 // (or rather the funcs listed there)
3641 ptr = (u32 *)&psxM[A_A0_TABLE];
3642 for (i = 0; i < 256; i++)
3643 ptr[i] = SWAP32(0x1000);
3645 ptr = (u32 *)&psxM[A_B0_TABLE];
3646 for (i = 0; i < 256; i++)
3647 ptr[i] = SWAP32(0x2000);
3648 // B(5b) is special because games patch (sometimes even jump to)
3649 // code at fixed offsets from it, nocash lists offsets:
3650 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3651 // call: +7a0=4b70, +884=4c54, +894=4c64
3652 ptr[0x5b] = SWAP32(0x43d0);
3653 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3655 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3656 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3657 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3659 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3660 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3662 ptr = (u32 *)&psxM[A_C0_TABLE];
3663 for (i = 0; i < 256/2; i++)
3664 ptr[i] = SWAP32(0x3000);
3665 ptr[6] = SWAP32(A_EXCEPTION);
3668 ram32[0x1000/4] = HLEOP(hleop_dummy);
3669 ram32[0x2000/4] = HLEOP(hleop_dummy);
3670 ram32[0x3000/4] = HLEOP(hleop_dummy);
3671 ram32[0x4c54/4] = HLEOP(hleop_dummy); // for B12_InitPad?
3672 ram32[0x8000/4] = HLEOP(hleop_execret);
3674 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3675 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3676 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3677 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3678 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3679 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3682 void psxBiosShutdown() {
3685 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3686 if (tcb_cnt != 4 || evcb_cnt != 16)
3687 setup_tt(tcb_cnt, evcb_cnt);
3690 #define psxBios_PADpoll(pad) { \
3691 PAD##pad##_startPoll(pad); \
3692 pad_buf##pad[0] = 0; \
3693 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3694 if (!(pad_buf##pad[1] & 0x0f)) { \
3697 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3699 PAD##pad##_poll(0); \
3701 while (bufcount--) { \
3702 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3706 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3710 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3711 psxBios_ReturnFromException();
3717 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3718 // so this is only partially implemented
3719 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3721 u32 cdrom_dma_ack_enable = 1; // a000b93c
3722 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3725 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3728 //PSXBIOS_LOG("%s\n", __func__);
3730 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3731 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3732 //if (--cdrom_irq_counter == 0) // 0xa0009180
3733 // DeliverEvent(0xf0000003, 0x10);
3737 mips_return_c(ret, 20);
3740 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3742 u32 cdrom_irq_ack_enable = 1; // a000b938
3743 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3746 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3749 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3750 PSXBIOS_LOG("%s TODO\n", __func__);
3753 mips_return_c(ret, 20);
3756 void hleExc0_2_2_syscall() // not in any A/B/C table
3758 u32 tcbPtr = loadRam32(A_TT_PCB);
3759 TCB *tcb = loadRam32ptr(tcbPtr);
3760 u32 code = SWAP32(tcb->cause) >> 2;
3762 if (code != R3000E_Syscall) {
3764 DeliverEvent(0xf0000010, 0x1000);
3765 //psxBios_SystemErrorUnresolvedException();
3767 mips_return_c(0, 17);
3771 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3772 tcb->epc += SWAP32(4);
3773 switch (SWAP32(tcb->reg[4])) { // a0
3777 case 1: { // EnterCritical - disable irqs
3778 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3779 tcb->reg[2] = SWAP32(was_enabled);
3780 tcb->sr &= SWAP32(~0x404);
3783 case 2: // ExitCritical - enable irqs
3784 tcb->sr |= SWAP32(0x404);
3787 case 3: { // ChangeThreadSubFunction
3788 u32 tcbPtr = loadRam32(A_TT_PCB);
3789 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3793 DeliverEvent(0xf0000010, 0x4000);
3797 psxBios_ReturnFromException();
3800 void hleExc1_0_1(void)
3802 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3803 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3806 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3809 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3810 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3813 mips_return_c(ret, 22);
3816 void hleExc1_0_2(void)
3818 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3821 void hleExc1_1_1(void)
3823 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3824 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3827 void hleExc1_1_2(void)
3829 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3832 void hleExc1_2_1(void)
3834 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3835 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3838 void hleExc1_2_2(void)
3840 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3843 void hleExc1_3_1(void)
3845 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3846 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3849 void hleExc1_3_2(void)
3851 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3854 void hleExc3_0_2_defint(void)
3856 static const struct {
3867 { 6, 6 }, // rcnt2 (bug)
3872 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3873 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3874 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3879 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3882 void hleExcPadCard1(void)
3884 if (loadRam32(A_PAD_IRQR_ENA)) {
3885 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3886 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3892 if (loadRam32(A_PAD_DR_DST))
3895 if (loadRam32(A_PAD_ACK_VBL))
3896 psxHwWrite16(0x1f801070, ~1);
3897 if (loadRam32(A_CARD_IRQR_ENA)) {
3901 mips_return_c(0, 18);
3904 void hleExcPadCard2(void)
3906 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3907 mips_return_c(ret, 15);
3910 void psxBiosException() {
3911 u32 tcbPtr = loadRam32(A_TT_PCB);
3912 u32 *chains = loadRam32ptr(A_TT_ExCB);
3913 TCB *tcb = loadRam32ptr(tcbPtr);
3919 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3920 for (i = 4; i < 32; i++) {
3923 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3925 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3926 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3927 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3928 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3929 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3930 sp = fp = loadRam32(A_EXC_SP);
3934 // do the chains (always 4)
3935 for (c = lim = 0; c < 4; c++) {
3936 if (chains[c * 2] == 0)
3938 ptr = SWAP32(chains[c * 2]);
3939 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3940 chain = castRam32ptr(ptr);
3945 softCallInException(SWAP32(chain[2]));
3946 if (returned_from_exception())
3949 if (v0 == 0 || chain[1] == 0)
3951 softCallInException(SWAP32(chain[1]));
3952 if (returned_from_exception())
3958 // return from exception (custom or default)
3960 ptr = loadRam32(A_EEXIT_PTR);
3961 if (ptr != A_EEXIT_DEF) {
3962 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3963 longjmp_load(jmp_buf);
3968 psxBios_ReturnFromException();
3971 #define bfreeze(ptr, size) { \
3972 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3973 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3977 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3978 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3980 #define bfreezepsxMptr(ptr, type) { \
3982 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3983 else psxRu32ref(base) = 0; \
3985 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3986 else (ptr) = NULL; \
3988 base += sizeof(u32); \
3991 void psxBiosFreeze(int Mode) {