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 static int *pad_buf = NULL;
257 static u32 heap_size = 0;
258 static u32 *heap_addr = NULL;
259 static u32 *heap_end = NULL;
260 static FileDesc FDesc[32];
261 static u32 card_active_chan = 0;
263 // fixed RAM offsets, SCPH1001 compatible
264 #define A_TT_ExCB 0x0100
265 #define A_TT_PCB 0x0108
266 #define A_TT_TCB 0x0110
267 #define A_TT_EvCB 0x0120
268 #define A_A0_TABLE 0x0200
269 #define A_B0_TABLE 0x0874
270 #define A_C0_TABLE 0x0674
271 #define A_SYSCALL 0x0650
272 #define A_EXCEPTION 0x0c80
273 #define A_EXC_SP 0x6cf0
274 #define A_EEXIT_DEF 0x6cf4
275 #define A_KMALLOC_PTR 0x7460
276 #define A_KMALLOC_SIZE 0x7464
277 #define A_KMALLOC_END 0x7468
278 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry
279 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
280 #define A_CARD_IRQR_ENA 0x74bc // same for card
281 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
282 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
283 #define A_PAD_IN_LEN 0x74d8
284 #define A_PAD_OUT_LEN 0x74e0
285 #define A_EEXIT_PTR 0x75d0
286 #define A_EXC_STACK 0x85d8 // exception stack top
287 #define A_RCNT_VBL_ACK 0x8600
288 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
289 #define A_CD_EVENTS 0xb9b8
290 #define A_EXC_GP 0xf450
292 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
294 static u32 loadRam32(u32 addr)
296 assert(!(addr & 0x5f800000));
297 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
300 static void *castRam8ptr(u32 addr)
302 assert(!(addr & 0x5f800000));
303 return psxM + (addr & 0x1fffff);
306 static void *castRam32ptr(u32 addr)
308 assert(!(addr & 0x5f800003));
309 return psxM + (addr & 0x1ffffc);
312 static void *loadRam8ptr(u32 addr)
314 return castRam8ptr(loadRam32(addr));
317 static void *loadRam32ptr(u32 addr)
319 return castRam32ptr(loadRam32(addr));
322 static void storeRam8(u32 addr, u8 d)
324 assert(!(addr & 0x5f800000));
325 *((u8 *)psxM + (addr & 0x1fffff)) = d;
328 static void storeRam32(u32 addr, u32 d)
330 assert(!(addr & 0x5f800000));
331 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
334 static void mips_return(u32 val)
340 static void use_cycles(u32 cycle)
342 psxRegs.cycle += cycle * 2;
345 static void mips_return_c(u32 val, u32 cycle)
351 static void mips_return_void_c(u32 cycle)
357 static int returned_from_exception(void)
359 // 0x80000080 means it took another exception just after return
360 return pc0 == k0 || pc0 == 0x80000080;
363 static inline void softCall(u32 pc) {
365 u32 ssr = psxRegs.CP0.n.SR;
369 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
371 while (pc0 != 0x80001000 && ++lim < 1000000)
372 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
375 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
377 psxRegs.CP0.n.SR |= ssr & 0x404;
380 static inline void softCallInException(u32 pc) {
386 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
387 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
390 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
391 if (pc0 == 0x80001000)
395 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
396 static u32 DeliverEvent(u32 class, u32 spec);
397 static u32 UnDeliverEvent(u32 class, u32 spec);
398 static void CloseEvent(u32 ev);
403 // System calls A0 */
406 #define buread(Ra1, mcd, length) { \
407 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); \
408 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
409 memcpy(Ra1, ptr, length); \
410 if (FDesc[1 + mcd].mode & 0x8000) { \
411 DeliverEvent(0xf0000011, 0x0004); \
412 DeliverEvent(0xf4000001, 0x0004); \
415 FDesc[1 + mcd].offset += v0; \
418 #define buwrite(Ra1, mcd, length) { \
419 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
420 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
421 ptr = Mcd##mcd##Data + offset; \
422 memcpy(ptr, Ra1, length); \
423 FDesc[1 + mcd].offset += length; \
424 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
425 if (FDesc[1 + mcd].mode & 0x8000) { \
426 DeliverEvent(0xf0000011, 0x0004); \
427 DeliverEvent(0xf4000001, 0x0004); \
432 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
433 /* For some strange reason, the returned character is sign-expanded; */
434 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
435 /* TODO FIX ME : Properly implement this behaviour */
436 void psxBios_getc(void) // 0x03, 0x35
441 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
445 if (pa1 != INVALID_PTR) {
447 case 2: buread(pa1, 1, 1); break;
448 case 3: buread(pa1, 2, 1); break;
455 /* Copy of psxBios_write, except size is 1. */
456 void psxBios_putc(void) // 0x09, 0x3B
461 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
464 if (pa1 == INVALID_PTR) {
469 if (a0 == 1) { // stdout
470 char *ptr = (char *)pa1;
474 printf("%c", *ptr++); a2--;
480 case 2: buwrite(pa1, 1, 1); break;
481 case 3: buwrite(pa1, 2, 1); break;
487 void psxBios_todigit(void) // 0x0a
491 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
494 if (c >= 0x30 && c < 0x3A) {
497 else if (c > 0x60 && c < 0x7B) {
500 else if (c > 0x40 && c < 0x5B) {
503 else if (c >= 0x80) {
514 void psxBios_abs() { // 0x0e
515 if ((s32)a0 < 0) v0 = -(s32)a0;
520 void psxBios_labs() { // 0x0f
524 void psxBios_atoi() { // 0x10
526 char *p = (char *)Ra0;
530 case ' ': case '\t': continue;
537 while (*p >= '0' && *p <= '9') {
538 n = n * 10 + *p++ - '0';
545 void psxBios_atol() { // 0x11
555 static void psxBios_setjmp() { // 0x13
556 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
559 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
561 jmp_buf->ra_ = SWAP32(ra);
562 jmp_buf->sp_ = SWAP32(sp);
563 jmp_buf->fp_ = SWAP32(fp);
564 for (i = 0; i < 8; i++) // s0-s7
565 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
566 jmp_buf->gp_ = SWAP32(gp);
568 mips_return_c(0, 15);
571 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
575 ra = SWAP32(jmp_buf->ra_);
576 sp = SWAP32(jmp_buf->sp_);
577 fp = SWAP32(jmp_buf->fp_);
578 for (i = 0; i < 8; i++) // s0-s7
579 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
580 gp = SWAP32(jmp_buf->gp_);;
583 void psxBios_longjmp() { // 0x14
584 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
586 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
587 longjmp_load(jmp_buf);
588 mips_return_c(a1, 15);
591 void psxBios_strcat() { // 0x15
592 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
595 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
597 if (a0 == 0 || a1 == 0)
605 while ((*p1++ = *p2++) != '\0');
610 void psxBios_strncat() { // 0x16
611 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
615 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
617 if (a0 == 0 || a1 == 0)
625 while ((*p1++ = *p2++) != '\0') {
635 void psxBios_strcmp() { // 0x17
636 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
638 if (a0 == 0 && a1 == 0)
644 else if (a0 == 0 && a1 != 0)
650 else if (a0 != 0 && a1 == 0)
657 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
660 while (*p1 == *p2++) {
679 void psxBios_strncmp() { // 0x18
680 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
682 if (a0 == 0 && a1 == 0)
688 else if (a0 == 0 && a1 != 0)
694 else if (a0 != 0 && a1 == 0)
701 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
704 while (--n >= 0 && *p1 == *p2++) {
708 v1 = a2 - ((a2-n) - 1);
716 v0 = (n < 0 ? 0 : *p1 - *--p2);
718 v1 = a2 - ((a2-n) - 1);
724 void psxBios_strcpy() { // 0x19
725 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
726 if (a0 == 0 || a1 == 0)
732 while ((*p1++ = *p2++) != '\0');
737 void psxBios_strncpy() { // 0x1a
738 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
740 if (a0 == 0 || a1 == 0)
746 for (i = 0; i < n; i++) {
747 if ((*p1++ = *p2++) == '\0') {
759 void psxBios_strlen() { // 0x1b
760 char *p = (char *)Ra0;
771 void psxBios_index() { // 0x1c
772 char *p = (char *)Ra0;
782 v0 = a0 + (p - (char *)Ra0);
786 } while (*p++ != '\0');
791 void psxBios_rindex() { // 0x1d
792 char *p = (char *)Ra0;
802 v0 = a0 + (p - (char *)Ra0);
803 } while (*p++ != '\0');
808 void psxBios_strchr() { // 0x1e
812 void psxBios_strrchr() { // 0x1f
816 void psxBios_strpbrk() { // 0x20
817 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
819 while ((c = *p1++) != '\0') {
820 for (scanp = p2; (sc = *scanp++) != '\0';) {
822 v0 = a0 + (p1 - 1 - (char *)Ra0);
829 // BUG: return a0 instead of NULL if not found
833 void psxBios_strspn() { // 0x21
836 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
837 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
838 if (*p2 == '\0') break;
841 v0 = p1 - (char *)Ra0; pc0 = ra;
844 void psxBios_strcspn() { // 0x22
847 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
848 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
849 if (*p2 != '\0') break;
852 v0 = p1 - (char *)Ra0; pc0 = ra;
855 void psxBios_strtok() { // 0x23
856 char *pcA0 = (char *)Ra0;
857 char *pcRet = strtok(pcA0, (char *)Ra1);
859 v0 = a0 + pcRet - pcA0;
865 void psxBios_strstr() { // 0x24
866 char *p = (char *)Ra0, *p1, *p2;
872 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
877 v0 = a0 + (p - (char *)Ra0);
888 void psxBios_toupper() { // 0x25
889 v0 = (s8)(a0 & 0xff);
890 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
894 void psxBios_tolower() { // 0x26
895 v0 = (s8)(a0 & 0xff);
896 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
900 void psxBios_bcopy() { // 0x27
901 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
903 if (a0 == 0 || a2 > 0x7FFFFFFF)
908 while ((s32)a2-- > 0) *p1++ = *p2++;
913 void psxBios_bzero() { // 0x28
914 char *p = (char *)Ra0;
916 /* Same as memset here (See memset below) */
917 if (a1 > 0x7FFFFFFF || a1 == 0)
928 while ((s32)a1-- > 0) *p++ = '\0';
933 void psxBios_bcmp() { // 0x29
934 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
936 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
938 while ((s32)a2-- > 0) {
939 if (*p1++ != *p2++) {
940 v0 = *p1 - *p2; // BUG: compare the NEXT byte
949 void psxBios_memcpy() { // 0x2a
950 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
952 if (a0 == 0 || a2 > 0x7FFFFFFF)
957 while ((s32)a2-- > 0) {
964 void psxBios_memset() { // 0x2b
965 char *p = (char *)Ra0;
967 if (a2 > 0x7FFFFFFF || a2 == 0)
978 while ((s32)a2-- > 0) *p++ = (char)a1;
983 void psxBios_memmove() { // 0x2c
984 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
986 if (a0 == 0 || a2 > 0x7FFFFFFF)
991 if (p2 <= p1 && p2 + a2 > p1) {
992 a2++; // BUG: copy one more byte here
995 while ((s32)a2-- > 0) *--p1 = *--p2;
997 while ((s32)a2-- > 0) *p1++ = *p2++;
1002 void psxBios_memcmp() { // 0x2d
1006 void psxBios_memchr() { // 0x2e
1007 char *p = (char *)Ra0;
1009 if (a0 == 0 || a2 > 0x7FFFFFFF)
1015 while ((s32)a2-- > 0) {
1016 if (*p++ != (s8)a1) continue;
1017 v0 = a0 + (p - (char *)Ra0 - 1);
1025 void psxBios_rand() { // 0x2f
1026 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1027 v0 = (s >> 16) & 0x7fff;
1028 psxMu32ref(0x9010) = SWAPu32(s);
1032 void psxBios_srand() { // 0x30
1033 psxMu32ref(0x9010) = SWAPu32(a0);
1037 static u32 qscmpfunc, qswidth;
1039 static inline int qscmp(char *a, char *b) {
1042 a0 = sa0 + (a - (char *)PSXM(sa0));
1043 a1 = sa0 + (b - (char *)PSXM(sa0));
1045 softCall(qscmpfunc);
1051 static inline void qexchange(char *i, char *j) {
1062 static inline void q3exchange(char *i, char *j, char *k) {
1074 static void qsort_main(char *a, char *l) {
1075 char *i, *j, *lp, *hp;
1080 if ((n = l - a) <= qswidth)
1082 n = qswidth * (n / (2 * qswidth));
1088 if ((c = qscmp(i, lp)) == 0) {
1089 qexchange(i, lp -= qswidth);
1100 if ((c = qscmp(hp, j)) == 0) {
1101 qexchange(hp += qswidth, j);
1106 q3exchange(i, hp += qswidth, j);
1120 if (lp - a >= l - hp) {
1121 qsort_main(hp + qswidth, l);
1130 q3exchange(j, lp -= qswidth, i);
1135 void psxBios_qsort() { // 0x31
1138 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1143 void psxBios_malloc() { // 0x33
1144 u32 *chunk, *newchunk = NULL;
1145 unsigned int dsize = 0, csize, cstat;
1148 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1150 if (!a0 || (!heap_size || !heap_addr)) {
1156 // scan through heap and combine free chunks of space
1159 while(chunk < heap_end) {
1160 // get size and status of actual chunk
1161 csize = ((u32)*chunk) & 0xfffffffc;
1162 cstat = ((u32)*chunk) & 1;
1164 // most probably broken heap descriptor
1165 // this fixes Burning Road
1168 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1173 // it's a free chunk
1178 colflag = 1; // let's begin a new collection of free memory
1180 else dsize += (csize+4); // add the new size including header
1182 // not a free chunk: did we start a collection ?
1184 if(colflag == 1) { // collection is over
1186 *newchunk = SWAP32(dsize | 1);
1191 chunk = (u32*)((uptr)chunk + csize + 4);
1193 // if neccessary free memory on end of heap
1195 *newchunk = SWAP32(dsize | 1);
1198 csize = ((u32)*chunk) & 0xfffffffc;
1199 cstat = ((u32)*chunk) & 1;
1200 dsize = (a0 + 3) & 0xfffffffc;
1202 // exit on uninitialized heap
1203 if (chunk == NULL) {
1204 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1210 // search an unused chunk that is big enough until the end of the heap
1211 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1212 chunk = (u32*)((uptr)chunk + csize + 4);
1214 // catch out of memory
1215 if(chunk >= heap_end) {
1216 printf("malloc %x,%x: Out of memory error!\n",
1222 csize = ((u32)*chunk) & 0xfffffffc;
1223 cstat = ((u32)*chunk) & 1;
1227 if(dsize == csize) {
1228 // chunk has same size
1229 *chunk &= 0xfffffffc;
1230 } else if (dsize > csize) {
1235 *chunk = SWAP32(dsize);
1236 newchunk = (u32*)((uptr)chunk + dsize + 4);
1237 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1240 // return pointer to allocated memory
1241 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1243 //printf ("malloc %x,%x\n", v0, a0);
1247 void psxBios_free() { // 0x34
1249 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1250 PSXBIOS_LOG("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1253 *(u32*)(Ra0-4) |= 1; // set chunk to free
1257 void psxBios_calloc() { // 0x37
1260 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1270 void psxBios_realloc() { // 0x38
1274 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1278 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1283 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1288 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1289 /* Note that it is not quite implemented this way here. */
1299 /* InitHeap(void *block , int n) */
1300 void psxBios_InitHeap() { // 0x39
1304 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1307 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1312 heap_addr = (u32 *)Ra0;
1314 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1315 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1316 //*heap_addr = SWAP32(size | 1);
1318 PSXBIOS_LOG("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1323 void psxBios_getchar() { //0x3b
1324 v0 = getchar(); pc0 = ra;
1327 static void psxBios_printf_psxout() { // 0x3f
1336 if (psp != INVALID_PTR) {
1337 memcpy(save, psp, 4 * 4);
1338 psxMu32ref(sp) = SWAP32((u32)a0);
1339 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1340 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1341 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1353 tmp2[j++] = Ra0[i]; goto _start;
1355 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1366 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1370 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1376 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1378 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1380 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1382 *ptmp++ = Ra0[i]; break;
1392 if (psp != INVALID_PTR)
1393 memcpy(psp, save, 4 * 4);
1396 SysPrintf("%s", tmp);
1399 void psxBios_printf() { // 0x3f
1400 psxBios_printf_psxout();
1404 void psxBios_format() { // 0x41
1405 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1407 CreateMcd(Config.Mcd1);
1408 LoadMcd(1, Config.Mcd1);
1411 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1413 CreateMcd(Config.Mcd2);
1414 LoadMcd(2, Config.Mcd2);
1424 static void psxBios_SystemErrorUnresolvedException() {
1425 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1426 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1427 storeRam32(0xfffc, 0x12345678);
1429 mips_return_void_c(1000);
1433 * long Load(char *name, struct EXEC *header);
1436 void psxBios_Load() { // 0x42
1441 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1442 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1445 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1451 * int Exec(struct EXEC *header , int argc , char **argv);
1454 void psxBios_Exec() { // 43
1455 EXEC *header = (EXEC *)castRam32ptr(a0);
1459 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1461 header->_sp = SWAP32(sp);
1462 header->_fp = SWAP32(fp);
1463 header->_sp = SWAP32(sp);
1464 header->_gp = SWAP32(gp);
1465 header->ret = SWAP32(ra);
1466 header->base = SWAP32(s0);
1468 ptr = SWAP32(header->b_addr);
1469 len = SWAP32(header->b_size);
1475 if (header->S_addr != 0)
1476 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1478 gp = SWAP32(header->gp0);
1486 pc0 = SWAP32(header->_pc0);
1489 void psxBios_FlushCache() { // 44
1491 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1493 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1494 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1498 void psxBios_GPU_dw() { // 0x46
1503 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1506 GPU_writeData(0xa0000000);
1507 GPU_writeData((a1<<0x10)|(a0&0xffff));
1508 GPU_writeData((a3<<0x10)|(a2&0xffff));
1510 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1513 GPU_writeData(SWAPu32(*ptr++));
1519 void psxBios_mem2vram() { // 0x47
1522 GPU_writeData(0xa0000000);
1523 GPU_writeData((a1<<0x10)|(a0&0xffff));
1524 GPU_writeData((a3<<0x10)|(a2&0xffff));
1525 size = ((((a2 * a3) / 2) >> 4) << 16);
1526 GPU_writeStatus(0x04000002);
1527 psxHwWrite32(0x1f8010f4,0);
1528 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1529 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1530 psxHwWrite32(0x1f8010a4, size | 0x10);
1531 psxHwWrite32(0x1f8010a8,0x01000201);
1536 void psxBios_SendGPU() { // 0x48
1537 GPU_writeStatus(a0);
1542 void psxBios_GPU_cw() { // 0x49
1549 void psxBios_GPU_cwb() { // 0x4a
1550 u32 *ptr = (u32*)Ra0;
1555 GPU_writeData(SWAPu32(*ptr++));
1561 void psxBios_GPU_SendPackets() { //4b:
1563 GPU_writeStatus(0x04000002);
1564 psxHwWrite32(0x1f8010f4,0);
1565 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1566 psxHwWrite32(0x1f8010a0,a0);
1567 psxHwWrite32(0x1f8010a4,0);
1568 psxHwWrite32(0x1f8010a8,0x010000401);
1572 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1573 psxHwWrite32(0x1f8010a8,0x00000401);
1574 GPU_writeData(0x0400000);
1575 GPU_writeData(0x0200000);
1576 GPU_writeData(0x0100000);
1581 void psxBios_GPU_GetGPUStatus() { // 0x4d
1582 v0 = GPU_readStatus();
1588 void psxBios_LoadExec() { // 51
1589 EXEC *header = (EXEC*)PSXM(0xf000);
1593 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1595 s_addr = a1; s_size = a2;
1600 header->S_addr = s_addr;
1601 header->s_size = s_size;
1603 a0 = 0xf000; a1 = 0; a2 = 0;
1607 void psxBios__bu_init() { // 70
1609 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1612 DeliverEvent(0xf0000011, 0x0004);
1613 DeliverEvent(0xf4000001, 0x0004);
1618 void psxBios__96_init() { // 71
1620 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1626 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1627 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1628 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1630 static void psxBios_DequeueCdIntr_() {
1631 psxBios_SysDeqIntRP_(0, 0x91d0);
1632 psxBios_SysDeqIntRP_(0, 0x91e0);
1636 static void psxBios_DequeueCdIntr() { // a3
1637 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1638 psxBios_DequeueCdIntr_();
1641 static void psxBios_CdRemove() { // 56, 72
1642 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1644 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1645 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1646 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1647 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1648 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1649 psxBios_DequeueCdIntr_();
1651 // EnterCriticalSection - should be done at the beginning,
1652 // but this way is much easier to implement
1658 void psxBios_SetMem() { // 9f
1659 u32 new = psxHu32(0x1060);
1662 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1667 psxHu32ref(0x1060) = SWAP32(new);
1668 psxMu32ref(0x060) = a0;
1669 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1673 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1674 psxMu32ref(0x060) = a0;
1675 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1678 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1685 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1686 void psxBios_get_cd_status(void) //a6
1692 void psxBios__card_info() { // ab
1694 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1697 card_active_chan = a0;
1698 port = card_active_chan >> 4;
1704 if (McdDisable[port & 1])
1709 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1715 if (McdDisable[0] && McdDisable[1])
1718 DeliverEvent(0xf0000011, 0x0004);
1719 // DeliverEvent(0xf4000001, 0x0004);
1720 DeliverEvent(0xf4000001, ret);
1724 void psxBios__card_load() { // ac
1726 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1729 card_active_chan = a0;
1731 // DeliverEvent(0xf0000011, 0x0004);
1732 DeliverEvent(0xf4000001, 0x0004);
1737 static void psxBios_GetSystemInfo() { // b4
1739 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1740 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1743 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1744 case 2: ret = 0xbfc0012c; break;
1745 case 5: ret = loadRam32(0x60) << 10; break;
1747 mips_return_c(ret, 20);
1750 /* System calls B0 */
1752 static u32 psxBios_SysMalloc_(u32 size);
1754 static void psxBios_SysMalloc() { // B 00
1755 u32 ret = psxBios_SysMalloc_(a0);
1757 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1758 mips_return_c(ret, 33);
1761 void psxBios_SetRCnt() { // 02
1763 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1770 psxRcntWtarget(a0, a1);
1771 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1772 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1773 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1774 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1775 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1777 psxRcntWmode(a0, mode);
1782 void psxBios_GetRCnt() { // 03
1784 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1788 if (a0 != 3) v0 = psxRcntRcount(a0);
1793 void psxBios_StartRCnt() { // 04
1795 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1799 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1800 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1804 void psxBios_StopRCnt() { // 05
1806 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1810 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1811 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1815 void psxBios_ResetRCnt() { // 06
1817 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1822 psxRcntWmode(a0, 0);
1823 psxRcntWtarget(a0, 0);
1824 psxRcntWcount(a0, 0);
1829 static u32 DeliverEvent(u32 class, u32 spec) {
1830 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1831 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1832 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1833 u32 i, lim = evcb_len / 0x1c;
1835 for (i = 0; i < lim; i++, ev++) {
1837 if (SWAP32(ev->status) != EvStACTIVE)
1840 if (SWAP32(ev->class) != class)
1843 if (SWAP32(ev->spec) != spec)
1846 ret = SWAP32(ev->mode);
1847 if (ret == EvMdMARK) {
1848 ev->status = SWAP32(EvStALREADY);
1852 if (ret == EvMdCALL) {
1853 ret = SWAP32(ev->fhandler);
1865 static u32 UnDeliverEvent(u32 class, u32 spec) {
1866 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1867 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1868 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1869 u32 i, lim = evcb_len / 0x1c;
1871 for (i = 0; i < lim; i++, ev++) {
1873 if (SWAP32(ev->status) != EvStALREADY)
1876 if (SWAP32(ev->class) != class)
1879 if (SWAP32(ev->spec) != spec)
1882 if (SWAP32(ev->mode) == EvMdMARK)
1883 ev->status = SWAP32(EvStACTIVE);
1889 static void psxBios_DeliverEvent() { // 07
1891 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1893 ret = DeliverEvent(a0, a1);
1897 static s32 get_free_EvCB_slot() {
1898 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1899 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1902 for (i = 0; i < lim; i++, ev++) {
1904 if (ev->status == SWAP32(EvStUNUSED))
1910 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
1911 u32 ret = get_free_EvCB_slot();
1912 if ((s32)ret >= 0) {
1913 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
1914 ev->class = SWAP32(class);
1915 ev->status = SWAP32(EvStDISABLED);
1916 ev->spec = SWAP32(spec);
1917 ev->mode = SWAP32(mode);
1918 ev->fhandler = SWAP32(func);
1924 static void psxBios_OpenEvent() { // 08
1925 u32 ret = OpenEvent(a0, a1, a2, a3);
1926 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
1927 biosB0n[0x08], a0, a1, a2, a3, ret);
1928 mips_return_c(ret, 36);
1931 static void CloseEvent(u32 ev)
1933 u32 base = loadRam32(A_TT_EvCB);
1934 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
1937 static void psxBios_CloseEvent() { // 09
1938 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
1939 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
1941 mips_return_c(1, 10);
1944 static void psxBios_WaitEvent() { // 0a
1945 u32 base = loadRam32(A_TT_EvCB);
1946 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1947 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
1950 if (status == EvStALREADY) {
1951 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1955 if (status != EvStACTIVE)
1957 mips_return_c(0, 2);
1961 // retrigger this hlecall after the next emulation event
1963 if ((s32)(next_interupt - psxRegs.cycle) > 0)
1964 psxRegs.cycle = next_interupt;
1968 static void psxBios_TestEvent() { // 0b
1969 u32 base = loadRam32(A_TT_EvCB);
1970 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1972 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
1973 if (status == EvStALREADY) {
1974 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1978 mips_return_c(ret, 15);
1981 static void psxBios_EnableEvent() { // 0c
1982 u32 base = loadRam32(A_TT_EvCB);
1983 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1984 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
1985 if (status != EvStUNUSED)
1986 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1988 mips_return_c(1, 15);
1991 static void psxBios_DisableEvent() { // 0d
1992 u32 base = loadRam32(A_TT_EvCB);
1993 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1994 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
1995 if (status != EvStUNUSED)
1996 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
1998 mips_return_c(1, 15);
2002 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2005 void psxBios_OpenTh() { // 0e
2006 TCB *tcb = loadRam32ptr(A_TT_TCB);
2007 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2010 for (th = 1; th < limit; th++)
2012 if (tcb[th].status != SWAP32(0x4000)) break;
2016 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2017 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2019 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2021 mips_return_c(0xffffffff, 20);
2024 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
2026 tcb[th].status = SWAP32(0x4000);
2027 tcb[th].mode = SWAP32(0x1000);
2028 tcb[th].epc = SWAP32(a0);
2029 tcb[th].reg[30] = SWAP32(a1); // fp
2030 tcb[th].reg[29] = SWAP32(a1); // sp
2031 tcb[th].reg[28] = SWAP32(a2); // gp
2033 mips_return_c(0xff000000 + th, 34);
2037 * int CloseTh(long thread);
2040 void psxBios_CloseTh() { // 0f
2041 TCB *tcb = loadRam32ptr(A_TT_TCB);
2042 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2046 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2048 /* The return value is always 1 (even if the handle was already closed). */
2050 if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2051 tcb[th].status = SWAP32(0x1000);
2058 * int ChangeTh(long thread);
2061 void psxBios_ChangeTh() { // 10
2062 u32 tcbBase = loadRam32(A_TT_TCB);
2063 u32 th = a0 & 0xffff;
2065 // this is quite spammy
2066 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2068 // without doing any argument checks, just issue a syscall
2069 // (like the real bios does)
2071 a1 = tcbBase + th * sizeof(TCB);
2076 void psxBios_InitPAD() { // 0x12
2077 u32 i, *ram32 = (u32 *)psxM;
2078 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2080 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2081 // PAD_dr_enable = 0;
2082 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2083 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2084 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2085 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2086 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2087 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2088 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2089 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2091 for (i = 0; i < a1; i++) {
2093 storeRam8(a0 + i, 0);
2095 for (i = 0; i < a3; i++) {
2097 storeRam8(a2 + i, 0);
2099 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2101 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2103 mips_return_c(1, 200);
2106 void psxBios_StartPAD() { // 13
2107 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2109 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2110 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2111 psxHwWrite16(0x1f801070, ~1);
2112 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2113 storeRam32(A_PAD_ACK_VBL, 1);
2114 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2115 psxRegs.CP0.n.SR |= 0x401;
2117 mips_return_c(1, 300);
2120 void psxBios_StopPAD() { // 14
2121 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2122 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2123 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2124 psxRegs.CP0.n.SR |= 0x401;
2125 mips_return_void_c(200);
2128 void psxBios_PAD_init() { // 15
2130 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2132 if (!(a0 == 0x20000000 || a0 == 0x20000001))
2138 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
2139 pad_buf = (int *)Ra1;
2141 psxRegs.CP0.n.SR |= 0x401;
2146 void psxBios_PAD_dr() { // 16
2148 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2154 static void psxBios_ReturnFromException() { // 17
2155 u32 tcbPtr = loadRam32(A_TT_PCB);
2156 const TCB *tcb = loadRam32ptr(tcbPtr);
2160 for (i = 1; i < 32; i++)
2161 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2162 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2163 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2164 sr = SWAP32(tcb->sr);
2166 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2167 pc0 = k0 = SWAP32(tcb->epc);
2169 // the interpreter wants to know about sr changes, so do a MTC0
2170 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2171 MTC0(&psxRegs, 12, sr);
2177 void psxBios_ResetEntryInt() { // 18
2178 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2180 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2181 mips_return_void_c(5);
2184 void psxBios_HookEntryInt() { // 19
2185 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2187 storeRam32(A_EEXIT_PTR, a0);
2188 mips_return_void_c(3);
2191 static void psxBios_UnDeliverEvent() { // 0x20
2193 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2195 ret = UnDeliverEvent(a0, a1);
2199 char ffile[64], *pfile;
2202 static void buopen(int mcd, char *ptr, char *cfg)
2205 char *mcd_data = ptr;
2207 strcpy(FDesc[1 + mcd].name, Ra0+5);
2208 FDesc[1 + mcd].offset = 0;
2209 FDesc[1 + mcd].mode = a1;
2211 for (i=1; i<16; i++) {
2212 const char *fptr = mcd_data + 128 * i;
2213 if ((*fptr & 0xF0) != 0x50) continue;
2214 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2215 FDesc[1 + mcd].mcfile = i;
2216 PSXBIOS_LOG("open %s\n", fptr+0xa);
2220 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2221 for (i=1; i<16; i++) {
2222 int j, xor, nblk = a1 >> 16;
2224 char *fptr = mcd_data + 128 * i;
2226 if ((*fptr & 0xF0) != 0xa0) continue;
2228 FDesc[1 + mcd].mcfile = i;
2231 fptr[5] = 0x20 * nblk;
2234 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2235 pptr = fptr2 = fptr;
2236 for(j=2; j<=nblk; j++) {
2238 for(i++; i<16; i++) {
2241 memset(fptr2, 0, 128);
2242 fptr2[0] = j < nblk ? 0x52 : 0x53;
2245 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2250 /* shouldn't this return ENOSPC if i == 16? */
2252 pptr[8] = pptr[9] = 0xff;
2253 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2255 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2257 /* just go ahead and resave them all */
2258 SaveMcd(cfg, ptr, 128, 128 * 15);
2261 /* shouldn't this return ENOSPC if i == 16? */
2266 * int open(char *name , int mode);
2269 void psxBios_open() { // 0x32
2273 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2278 if (pa0 != INVALID_PTR) {
2279 if (!strncmp(pa0, "bu00", 4)) {
2280 buopen(1, Mcd1Data, Config.Mcd1);
2283 if (!strncmp(pa0, "bu10", 4)) {
2284 buopen(2, Mcd2Data, Config.Mcd2);
2292 * int lseek(int fd , int offset , int whence);
2295 void psxBios_lseek() { // 0x33
2297 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2302 FDesc[a0].offset = a1;
2304 // DeliverEvent(0xf0000011, 0x0004);
2305 // DeliverEvent(0xf4000001, 0x0004);
2309 FDesc[a0].offset+= a1;
2310 v0 = FDesc[a0].offset;
2319 * int read(int fd , void *buf , int nbytes);
2322 void psxBios_read() { // 0x34
2327 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2332 if (pa1 != INVALID_PTR) {
2334 case 2: buread(pa1, 1, a2); break;
2335 case 3: buread(pa1, 2, a2); break;
2343 * int write(int fd , void *buf , int nbytes);
2346 void psxBios_write() { // 0x35/0x03
2350 if (a0 != 1) // stdout
2351 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2354 if (pa1 == INVALID_PTR) {
2359 if (a0 == 1) { // stdout
2363 if (Config.PsxOut) while (a2 > 0) {
2364 SysPrintf("%c", *ptr++); a2--;
2370 case 2: buwrite(pa1, 1, a2); break;
2371 case 3: buwrite(pa1, 2, a2); break;
2377 static void psxBios_write_psxout() {
2378 if (a0 == 1) { // stdout
2379 const char *ptr = Ra1;
2382 if (ptr != INVALID_PTR)
2384 SysPrintf("%c", *ptr++);
2388 static void psxBios_putchar_psxout() { // 3d
2389 SysPrintf("%c", (char)a0);
2392 static void psxBios_puts_psxout() { // 3e/3f
2393 SysPrintf("%s", Ra0);
2397 * int close(int fd);
2400 void psxBios_close() { // 0x36
2402 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2409 void psxBios_putchar() { // 3d
2410 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2414 void psxBios_puts() { // 3e/3f
2415 if (Config.PsxOut) SysPrintf("%s", Ra0);
2420 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2421 * We want to mimic the PSX's behaviour in this case for bufile. */
2422 static size_t strlen_internal(char* p)
2424 size_t size_of_array = 0;
2425 while (*p++) size_of_array++;
2426 return size_of_array;
2429 #define bufile(mcd) { \
2430 size_t size_of_name = strlen_internal(dir->name); \
2431 while (nfile < 16) { \
2434 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2436 if ((*ptr & 0xF0) != 0x50) continue; \
2437 /* Bug link files show up as free block. */ \
2438 if (!ptr[0xa]) continue; \
2440 if (pfile[0] == 0) { \
2441 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2442 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2443 } else for (i=0; i<20; i++) { \
2444 if (pfile[i] == ptr[i]) { \
2445 dir->name[i] = ptr[i]; continue; } \
2446 if (pfile[i] == '?') { \
2447 dir->name[i] = ptr[i]; continue; } \
2448 if (pfile[i] == '*') { \
2449 strcpy(dir->name+i, ptr+i); break; } \
2452 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2453 if (match == 0) { continue; } \
2461 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2464 void psxBios_firstfile() { // 42
2465 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2472 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2477 if (pa0 != INVALID_PTR) {
2481 if (!strncmp(pa0, "bu00", 4)) {
2482 // firstfile() calls _card_read() internally, so deliver it's event
2483 DeliverEvent(0xf0000011, 0x0004);
2485 } else if (!strncmp(pa0, "bu10", 4)) {
2486 // firstfile() calls _card_read() internally, so deliver it's event
2487 DeliverEvent(0xf0000011, 0x0004);
2496 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2499 void psxBios_nextfile() { // 43
2500 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2506 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2511 if (!strncmp(ffile, "bu00", 4)) {
2515 if (!strncmp(ffile, "bu10", 4)) {
2522 #define burename(mcd) { \
2523 for (i=1; i<16; i++) { \
2524 int namelen, j, xor = 0; \
2525 ptr = Mcd##mcd##Data + 128 * i; \
2526 if ((*ptr & 0xF0) != 0x50) continue; \
2527 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2528 namelen = strlen(Ra1+5); \
2529 memcpy(ptr+0xa, Ra1+5, namelen); \
2530 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2531 for (j=0; j<127; j++) xor^= ptr[j]; \
2533 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2540 * int rename(char *old, char *new);
2543 void psxBios_rename() { // 44
2550 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2555 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2556 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2560 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2569 #define budelete(mcd) { \
2570 for (i=1; i<16; i++) { \
2571 ptr = Mcd##mcd##Data + 128 * i; \
2572 if ((*ptr & 0xF0) != 0x50) continue; \
2573 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2574 *ptr = (*ptr & 0xf) | 0xA0; \
2575 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2576 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2583 * int delete(char *name);
2586 void psxBios_delete() { // 45
2592 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2597 if (pa0 != INVALID_PTR) {
2598 if (!strncmp(pa0, "bu00", 4)) {
2602 if (!strncmp(pa0, "bu10", 4)) {
2610 void psxBios_InitCARD() { // 4a
2611 u32 *ram32 = (u32 *)psxM;
2612 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2613 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2614 // (maybe) todo: early_card_irq, FlushCache etc
2616 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2618 mips_return_c(0, 300);
2621 void psxBios_StartCARD() { // 4b
2622 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2623 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2624 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2626 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2627 storeRam32(A_PAD_ACK_VBL, 1);
2628 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2629 storeRam32(A_CARD_IRQR_ENA, 1);
2630 psxRegs.CP0.n.SR |= 0x401;
2632 mips_return_c(1, 200);
2635 void psxBios_StopCARD() { // 4c
2636 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2637 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2638 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2639 storeRam32(A_CARD_IRQR_ENA, 0);
2640 psxRegs.CP0.n.SR |= 0x401;
2641 mips_return_void_c(200);
2644 void psxBios__card_write() { // 0x4e
2649 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2652 Function also accepts sector 400h (a bug).
2653 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2657 /* Invalid sectors */
2661 card_active_chan = a0;
2664 if (pa2 != INVALID_PTR) {
2666 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2667 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2669 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2670 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2674 DeliverEvent(0xf0000011, 0x0004);
2675 // DeliverEvent(0xf4000001, 0x0004);
2680 void psxBios__card_read() { // 0x4f
2685 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2688 Function also accepts sector 400h (a bug).
2689 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2693 /* Invalid sectors */
2697 card_active_chan = a0;
2700 if (pa2 != INVALID_PTR) {
2702 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2704 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2708 DeliverEvent(0xf0000011, 0x0004);
2709 // DeliverEvent(0xf4000001, 0x0004);
2714 void psxBios__new_card() { // 0x50
2716 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2722 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2723 void psxBios__get_error(void) // 55
2725 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2730 void psxBios_Krom2RawAdd() { // 0x51
2733 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2734 const u32 table_8140[][2] = {
2735 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2736 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2737 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2738 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2739 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2740 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2741 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2742 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2743 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2747 const u32 table_889f[][2] = {
2748 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2749 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2750 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2751 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2752 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2753 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2754 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2755 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2759 if (a0 >= 0x8140 && a0 <= 0x84be) {
2760 while (table_8140[i][0] <= a0) i++;
2761 a0 -= table_8140[i - 1][0];
2762 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2763 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2764 while (table_889f[i][0] <= a0) i++;
2765 a0 -= table_889f[i - 1][0];
2766 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2774 void psxBios_GetC0Table() { // 56
2775 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2776 log_unhandled("GetC0Table @%08x\n", ra);
2778 mips_return_c(A_C0_TABLE, 3);
2781 void psxBios_GetB0Table() { // 57
2782 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2783 log_unhandled("GetB0Table @%08x\n", ra);
2785 mips_return_c(A_B0_TABLE, 3);
2788 void psxBios__card_chan() { // 0x58
2790 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2793 v0 = card_active_chan;
2797 static void psxBios_ChangeClearPad() { // 5b
2799 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2800 ret = loadRam32(A_PAD_ACK_VBL);
2801 storeRam32(A_PAD_ACK_VBL, a0);
2803 mips_return_c(ret, 6);
2806 void psxBios__card_status() { // 5c
2808 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2811 v0 = card_active_chan;
2815 void psxBios__card_wait() { // 5d
2817 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2824 /* System calls C0 */
2826 static void psxBios_InitRCnt() { // 00
2828 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2829 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2830 for (i = 0; i < 3; i++) {
2831 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2832 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2833 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2835 psxBios_SysEnqIntRP_(a0, 0x6d88);
2836 mips_return_c(0, 9);
2839 static void psxBios_InitException() { // 01
2840 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2841 psxBios_SysEnqIntRP_(a0, 0x6da8);
2842 mips_return_c(0, 9);
2846 * int SysEnqIntRP(int index , long *queue);
2849 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2850 u32 old, base = loadRam32(A_TT_ExCB);
2852 old = loadRam32(base + (priority << 3));
2853 storeRam32(base + (priority << 3), chain_eptr);
2854 storeRam32(chain_eptr, old);
2855 mips_return_c(0, 9);
2858 static void psxBios_SysEnqIntRP() { // 02
2859 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2860 psxBios_SysEnqIntRP_(a0, a1);
2864 * int SysDeqIntRP(int index , long *queue);
2867 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2868 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2869 u32 lim = 0, ret = 0;
2871 // as in original: no arg checks of any kind, bug if a1 == 0
2872 ptr = loadRam32(base + (priority << 3));
2874 next = loadRam32(ptr);
2875 if (ptr == chain_rm_eptr) {
2876 storeRam32(base + (priority << 3), next);
2881 while (next && next != chain_rm_eptr && lim++ < 100) {
2883 next = loadRam32(ptr);
2886 if (next == chain_rm_eptr) {
2887 next = loadRam32(next);
2888 storeRam32(ptr, next);
2895 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2897 mips_return_c(ret, 12);
2900 static void psxBios_SysDeqIntRP() { // 03
2901 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2902 psxBios_SysDeqIntRP_(a0, a1);
2905 static void psxBios_get_free_EvCB_slot() { // 04
2906 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
2907 s32 ret = get_free_EvCB_slot();
2908 mips_return_c(ret, 0);
2911 static void psxBios_SysInitMemory_(u32 base, u32 size) {
2912 storeRam32(base, 0);
2913 storeRam32(A_KMALLOC_PTR, base);
2914 storeRam32(A_KMALLOC_SIZE, size);
2915 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2918 // this should be much more complicated, but maybe that'll be enough
2919 static u32 psxBios_SysMalloc_(u32 size) {
2920 u32 ptr = loadRam32(A_KMALLOC_PTR);
2922 size = (size + 3) & ~3;
2923 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2924 storeRam32(ptr, size);
2928 static void psxBios_SysInitMemory() { // 08
2929 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2931 psxBios_SysInitMemory_(a0, a1);
2932 mips_return_void_c(12);
2935 static void psxBios_ChangeClearRCnt() { // 0a
2938 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2940 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
2941 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
2942 mips_return_c(ret, 8);
2945 static void psxBios_InitDefInt() { // 0c
2946 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
2947 // should also clear the autoack table
2948 psxBios_SysEnqIntRP_(a0, 0x6d98);
2949 mips_return_c(0, 20 + 6*2);
2952 void psxBios_dummy() {
2953 u32 pc = (pc0 & 0x1fffff) - 4;
2954 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
2955 : pc == 0xc0 ? biosC0n : NULL;
2956 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
2957 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
2958 (void)pc; (void)ntab;
2959 mips_return_c(0, 100);
2962 void (*biosA0[256])();
2963 // C0 and B0 overlap (end of C0 is start of B0)
2964 void (*biosC0[256+128])();
2965 void (**biosB0)() = biosC0 + 128;
2967 static void setup_mips_code()
2970 ptr = (u32 *)&psxM[A_SYSCALL];
2971 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
2972 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
2973 ptr[0x08/4] = SWAPu32(0x00000000); // nop
2975 ptr = (u32 *)&psxM[A_EXCEPTION];
2976 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
2977 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
2978 ptr[0x14/4] = SWAPu32(0x00000000); // nop
2979 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
2980 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
2981 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
2982 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
2983 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
2984 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
2985 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
2987 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
2988 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
2989 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
2991 ptr[0xb0/4] = HLEOP(hleop_exception);
2994 static const struct {
2998 { 0xbfc050a4, hleop_exc0_0_1 },
2999 { 0xbfc04fbc, hleop_exc0_0_2 },
3000 { 0xbfc0506c, hleop_exc0_1_1 },
3001 { 0xbfc04dec, hleop_exc0_1_2 },
3002 { 0x1a00, hleop_exc0_2_2 },
3003 { 0x19c8, hleop_exc1_0_1 },
3004 { 0x18bc, hleop_exc1_0_2 },
3005 { 0x1990, hleop_exc1_1_1 },
3006 { 0x1858, hleop_exc1_1_2 },
3007 { 0x1958, hleop_exc1_2_1 },
3008 { 0x17f4, hleop_exc1_2_2 },
3009 { 0x1920, hleop_exc1_3_1 },
3010 { 0x1794, hleop_exc1_3_2 },
3011 { 0x2458, hleop_exc3_0_2 },
3012 { 0x49bc, hleop_exc_padcard1 },
3013 { 0x4a4c, hleop_exc_padcard2 },
3016 static int chain_hle_op(u32 handler)
3020 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3021 if (chainfns[i].addr == handler)
3022 return chainfns[i].op;
3026 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3028 d[0] = SWAPu32(next);
3029 d[1] = SWAPu32(handler1);
3030 d[2] = SWAPu32(handler2);
3032 // install the hle traps
3033 PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3034 PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3037 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
3039 u32 *ram32 = (u32 *)psxM;
3040 u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
3041 u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
3042 u32 p_excb, p_evcb, p_pcb, p_tcb;
3044 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3045 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3046 p_excb = psxBios_SysMalloc_(s_excb);
3047 p_evcb = psxBios_SysMalloc_(s_evcb);
3048 p_pcb = psxBios_SysMalloc_(s_pcb);
3049 p_tcb = psxBios_SysMalloc_(s_tcb);
3051 // "table of tables". Some games modify it
3052 assert(A_TT_ExCB == 0x0100);
3053 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3054 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3055 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3056 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3057 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3058 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3059 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3060 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3061 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3062 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3063 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3064 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3066 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3067 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3068 storeRam32(p_excb + 4*4, 0x0000); // chain2
3069 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3071 storeRam32(p_pcb, p_tcb);
3072 storeRam32(p_tcb, 0x4000); // first TCB
3075 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3076 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3077 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3078 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3079 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3080 DeliverEvent(0xf0000003, 0x0010);
3083 static const u32 gpu_ctl_def[] = {
3084 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3085 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3088 static const u32 gpu_data_def[] = {
3089 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3090 0xe5001000, 0xe6000000,
3091 0x02000000, 0x00000000, 0x01ff03ff
3095 static const u16 spu_config[] = {
3096 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3097 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3098 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3099 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3100 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3101 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3102 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3103 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3106 void psxBiosSetupBootState(void)
3108 boolean hle = Config.HLE;
3109 u32 *hw = (u32 *)psxH;
3112 // see also SetBootRegs()
3115 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3116 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3118 k0 = 0xbfc0d968; k1 = 0xf1c;
3119 ra = 0xf0001234; // just to easily detect attempts to return
3120 psxRegs.CP0.n.Cause = 0x20;
3121 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3123 hw[0x1000/4] = SWAP32(0x1f000000);
3124 hw[0x1004/4] = SWAP32(0x1f802000);
3125 hw[0x1008/4] = SWAP32(0x0013243f);
3126 hw[0x100c/4] = SWAP32(0x00003022);
3127 hw[0x1010/4] = SWAP32(0x0013243f);
3128 hw[0x1014/4] = SWAP32(0x200931e1);
3129 hw[0x1018/4] = SWAP32(0x00020943);
3130 hw[0x101c/4] = SWAP32(0x00070777);
3131 hw[0x1020/4] = SWAP32(0x0000132c);
3132 hw[0x1060/4] = SWAP32(0x00000b88);
3133 hw[0x1070/4] = SWAP32(0x00000001);
3134 hw[0x1074/4] = SWAP32(0x0000000c);
3135 hw[0x2040/4] = SWAP32(0x00000900);
3138 hw[0x10a0/4] = SWAP32(0x00ffffff);
3139 hw[0x10a8/4] = SWAP32(0x00000401);
3140 hw[0x10b0/4] = SWAP32(0x0008b000);
3141 hw[0x10b4/4] = SWAP32(0x00010200);
3142 hw[0x10e0/4] = SWAP32(0x000eccf4);
3143 hw[0x10e4/4] = SWAP32(0x00000400);
3144 hw[0x10e8/4] = SWAP32(0x00000002);
3145 hw[0x10f0/4] = SWAP32(0x00009099);
3146 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3155 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3156 GPU_writeStatus(gpu_ctl_def[i]);
3157 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3158 GPU_writeData(gpu_data_def[i]);
3159 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3162 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3163 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3166 #include "sjisfont.h"
3168 void psxBiosInit() {
3169 u32 *ptr, *ram32, *rom32;
3173 memset(psxM, 0, 0x10000);
3174 for(i = 0; i < 256; i++) {
3179 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3180 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3181 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3182 biosA0[0x3f] = psxBios_printf_psxout;
3184 if (!Config.HLE) return;
3186 for(i = 0; i < 256; i++) {
3187 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3188 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3189 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3192 biosA0[0x00] = psxBios_open;
3193 biosA0[0x01] = psxBios_lseek;
3194 biosA0[0x02] = psxBios_read;
3195 biosA0[0x03] = psxBios_write;
3196 biosA0[0x04] = psxBios_close;
3197 //biosA0[0x05] = psxBios_ioctl;
3198 //biosA0[0x06] = psxBios_exit;
3199 //biosA0[0x07] = psxBios_sys_a0_07;
3200 biosA0[0x08] = psxBios_getc;
3201 biosA0[0x09] = psxBios_putc;
3202 biosA0[0x0a] = psxBios_todigit;
3203 //biosA0[0x0b] = psxBios_atof;
3204 //biosA0[0x0c] = psxBios_strtoul;
3205 //biosA0[0x0d] = psxBios_strtol;
3206 biosA0[0x0e] = psxBios_abs;
3207 biosA0[0x0f] = psxBios_labs;
3208 biosA0[0x10] = psxBios_atoi;
3209 biosA0[0x11] = psxBios_atol;
3210 //biosA0[0x12] = psxBios_atob;
3211 biosA0[0x13] = psxBios_setjmp;
3212 biosA0[0x14] = psxBios_longjmp;
3213 biosA0[0x15] = psxBios_strcat;
3214 biosA0[0x16] = psxBios_strncat;
3215 biosA0[0x17] = psxBios_strcmp;
3216 biosA0[0x18] = psxBios_strncmp;
3217 biosA0[0x19] = psxBios_strcpy;
3218 biosA0[0x1a] = psxBios_strncpy;
3219 biosA0[0x1b] = psxBios_strlen;
3220 biosA0[0x1c] = psxBios_index;
3221 biosA0[0x1d] = psxBios_rindex;
3222 biosA0[0x1e] = psxBios_strchr;
3223 biosA0[0x1f] = psxBios_strrchr;
3224 biosA0[0x20] = psxBios_strpbrk;
3225 biosA0[0x21] = psxBios_strspn;
3226 biosA0[0x22] = psxBios_strcspn;
3227 biosA0[0x23] = psxBios_strtok;
3228 biosA0[0x24] = psxBios_strstr;
3229 biosA0[0x25] = psxBios_toupper;
3230 biosA0[0x26] = psxBios_tolower;
3231 biosA0[0x27] = psxBios_bcopy;
3232 biosA0[0x28] = psxBios_bzero;
3233 biosA0[0x29] = psxBios_bcmp;
3234 biosA0[0x2a] = psxBios_memcpy;
3235 biosA0[0x2b] = psxBios_memset;
3236 biosA0[0x2c] = psxBios_memmove;
3237 biosA0[0x2d] = psxBios_memcmp;
3238 biosA0[0x2e] = psxBios_memchr;
3239 biosA0[0x2f] = psxBios_rand;
3240 biosA0[0x30] = psxBios_srand;
3241 biosA0[0x31] = psxBios_qsort;
3242 //biosA0[0x32] = psxBios_strtod;
3243 biosA0[0x33] = psxBios_malloc;
3244 biosA0[0x34] = psxBios_free;
3245 //biosA0[0x35] = psxBios_lsearch;
3246 //biosA0[0x36] = psxBios_bsearch;
3247 biosA0[0x37] = psxBios_calloc;
3248 biosA0[0x38] = psxBios_realloc;
3249 biosA0[0x39] = psxBios_InitHeap;
3250 //biosA0[0x3a] = psxBios__exit;
3251 biosA0[0x3b] = psxBios_getchar;
3252 biosA0[0x3c] = psxBios_putchar;
3253 //biosA0[0x3d] = psxBios_gets;
3254 biosA0[0x3e] = psxBios_puts;
3255 biosA0[0x3f] = psxBios_printf;
3256 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3257 //biosA0[0x41] = psxBios_LoadTest;
3258 biosA0[0x42] = psxBios_Load;
3259 biosA0[0x43] = psxBios_Exec;
3260 biosA0[0x44] = psxBios_FlushCache;
3261 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3262 biosA0[0x46] = psxBios_GPU_dw;
3263 biosA0[0x47] = psxBios_mem2vram;
3264 biosA0[0x48] = psxBios_SendGPU;
3265 biosA0[0x49] = psxBios_GPU_cw;
3266 biosA0[0x4a] = psxBios_GPU_cwb;
3267 biosA0[0x4b] = psxBios_GPU_SendPackets;
3268 biosA0[0x4c] = psxBios_sys_a0_4c;
3269 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3270 //biosA0[0x4e] = psxBios_GPU_sync;
3271 //biosA0[0x4f] = psxBios_sys_a0_4f;
3272 //biosA0[0x50] = psxBios_sys_a0_50;
3273 biosA0[0x51] = psxBios_LoadExec;
3274 //biosA0[0x52] = psxBios_GetSysSp;
3275 //biosA0[0x53] = psxBios_sys_a0_53;
3276 //biosA0[0x54] = psxBios__96_init_a54;
3277 //biosA0[0x55] = psxBios__bu_init_a55;
3278 biosA0[0x56] = psxBios_CdRemove;
3279 //biosA0[0x57] = psxBios_sys_a0_57;
3280 //biosA0[0x58] = psxBios_sys_a0_58;
3281 //biosA0[0x59] = psxBios_sys_a0_59;
3282 //biosA0[0x5a] = psxBios_sys_a0_5a;
3283 //biosA0[0x5b] = psxBios_dev_tty_init;
3284 //biosA0[0x5c] = psxBios_dev_tty_open;
3285 //biosA0[0x5d] = psxBios_sys_a0_5d;
3286 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3287 //biosA0[0x5f] = psxBios_dev_cd_open;
3288 //biosA0[0x60] = psxBios_dev_cd_read;
3289 //biosA0[0x61] = psxBios_dev_cd_close;
3290 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3291 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3292 //biosA0[0x64] = psxBios_dev_cd_chdir;
3293 //biosA0[0x65] = psxBios_dev_card_open;
3294 //biosA0[0x66] = psxBios_dev_card_read;
3295 //biosA0[0x67] = psxBios_dev_card_write;
3296 //biosA0[0x68] = psxBios_dev_card_close;
3297 //biosA0[0x69] = psxBios_dev_card_firstfile;
3298 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3299 //biosA0[0x6b] = psxBios_dev_card_erase;
3300 //biosA0[0x6c] = psxBios_dev_card_undelete;
3301 //biosA0[0x6d] = psxBios_dev_card_format;
3302 //biosA0[0x6e] = psxBios_dev_card_rename;
3303 //biosA0[0x6f] = psxBios_dev_card_6f;
3304 biosA0[0x70] = psxBios__bu_init;
3305 biosA0[0x71] = psxBios__96_init;
3306 biosA0[0x72] = psxBios_CdRemove;
3307 //biosA0[0x73] = psxBios_sys_a0_73;
3308 //biosA0[0x74] = psxBios_sys_a0_74;
3309 //biosA0[0x75] = psxBios_sys_a0_75;
3310 //biosA0[0x76] = psxBios_sys_a0_76;
3311 //biosA0[0x77] = psxBios_sys_a0_77;
3312 //biosA0[0x78] = psxBios__96_CdSeekL;
3313 //biosA0[0x79] = psxBios_sys_a0_79;
3314 //biosA0[0x7a] = psxBios_sys_a0_7a;
3315 //biosA0[0x7b] = psxBios_sys_a0_7b;
3316 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3317 //biosA0[0x7d] = psxBios_sys_a0_7d;
3318 //biosA0[0x7e] = psxBios__96_CdRead;
3319 //biosA0[0x7f] = psxBios_sys_a0_7f;
3320 //biosA0[0x80] = psxBios_sys_a0_80;
3321 //biosA0[0x81] = psxBios_sys_a0_81;
3322 //biosA0[0x82] = psxBios_sys_a0_82;
3323 //biosA0[0x83] = psxBios_sys_a0_83;
3324 //biosA0[0x84] = psxBios_sys_a0_84;
3325 //biosA0[0x85] = psxBios__96_CdStop;
3326 //biosA0[0x86] = psxBios_sys_a0_86;
3327 //biosA0[0x87] = psxBios_sys_a0_87;
3328 //biosA0[0x88] = psxBios_sys_a0_88;
3329 //biosA0[0x89] = psxBios_sys_a0_89;
3330 //biosA0[0x8a] = psxBios_sys_a0_8a;
3331 //biosA0[0x8b] = psxBios_sys_a0_8b;
3332 //biosA0[0x8c] = psxBios_sys_a0_8c;
3333 //biosA0[0x8d] = psxBios_sys_a0_8d;
3334 //biosA0[0x8e] = psxBios_sys_a0_8e;
3335 //biosA0[0x8f] = psxBios_sys_a0_8f;
3336 biosA0[0x90] = hleExc0_1_2;
3337 biosA0[0x91] = hleExc0_0_2;
3338 biosA0[0x92] = hleExc0_1_1;
3339 biosA0[0x93] = hleExc0_0_1;
3340 //biosA0[0x94] = psxBios_sys_a0_94;
3341 //biosA0[0x95] = psxBios_sys_a0_95;
3342 //biosA0[0x96] = psxBios_AddCDROMDevice;
3343 //biosA0[0x97] = psxBios_AddMemCardDevide;
3344 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3345 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3346 //biosA0[0x9a] = psxBios_sys_a0_9a;
3347 //biosA0[0x9b] = psxBios_sys_a0_9b;
3348 //biosA0[0x9c] = psxBios_SetConf;
3349 //biosA0[0x9d] = psxBios_GetConf;
3350 //biosA0[0x9e] = psxBios_sys_a0_9e;
3351 biosA0[0x9f] = psxBios_SetMem;
3352 //biosA0[0xa0] = psxBios__boot;
3353 //biosA0[0xa1] = psxBios_SystemError;
3354 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3355 biosA0[0xa3] = psxBios_DequeueCdIntr;
3356 //biosA0[0xa4] = psxBios_sys_a0_a4;
3357 //biosA0[0xa5] = psxBios_ReadSector;
3358 biosA0[0xa6] = psxBios_get_cd_status;
3359 //biosA0[0xa7] = psxBios_bufs_cb_0;
3360 //biosA0[0xa8] = psxBios_bufs_cb_1;
3361 //biosA0[0xa9] = psxBios_bufs_cb_2;
3362 //biosA0[0xaa] = psxBios_bufs_cb_3;
3363 biosA0[0xab] = psxBios__card_info;
3364 biosA0[0xac] = psxBios__card_load;
3365 //biosA0[0axd] = psxBios__card_auto;
3366 //biosA0[0xae] = psxBios_bufs_cd_4;
3367 //biosA0[0xaf] = psxBios_sys_a0_af;
3368 //biosA0[0xb0] = psxBios_sys_a0_b0;
3369 //biosA0[0xb1] = psxBios_sys_a0_b1;
3370 //biosA0[0xb2] = psxBios_do_a_long_jmp
3371 //biosA0[0xb3] = psxBios_sys_a0_b3;
3372 biosA0[0xb4] = psxBios_GetSystemInfo;
3373 //*******************B0 CALLS****************************
3374 biosB0[0x00] = psxBios_SysMalloc;
3375 //biosB0[0x01] = psxBios_sys_b0_01;
3376 biosB0[0x02] = psxBios_SetRCnt;
3377 biosB0[0x03] = psxBios_GetRCnt;
3378 biosB0[0x04] = psxBios_StartRCnt;
3379 biosB0[0x05] = psxBios_StopRCnt;
3380 biosB0[0x06] = psxBios_ResetRCnt;
3381 biosB0[0x07] = psxBios_DeliverEvent;
3382 biosB0[0x08] = psxBios_OpenEvent;
3383 biosB0[0x09] = psxBios_CloseEvent;
3384 biosB0[0x0a] = psxBios_WaitEvent;
3385 biosB0[0x0b] = psxBios_TestEvent;
3386 biosB0[0x0c] = psxBios_EnableEvent;
3387 biosB0[0x0d] = psxBios_DisableEvent;
3388 biosB0[0x0e] = psxBios_OpenTh;
3389 biosB0[0x0f] = psxBios_CloseTh;
3390 biosB0[0x10] = psxBios_ChangeTh;
3391 //biosB0[0x11] = psxBios_psxBios_b0_11;
3392 biosB0[0x12] = psxBios_InitPAD;
3393 biosB0[0x13] = psxBios_StartPAD;
3394 biosB0[0x14] = psxBios_StopPAD;
3395 biosB0[0x15] = psxBios_PAD_init;
3396 biosB0[0x16] = psxBios_PAD_dr;
3397 biosB0[0x17] = psxBios_ReturnFromException;
3398 biosB0[0x18] = psxBios_ResetEntryInt;
3399 biosB0[0x19] = psxBios_HookEntryInt;
3400 //biosB0[0x1a] = psxBios_sys_b0_1a;
3401 //biosB0[0x1b] = psxBios_sys_b0_1b;
3402 //biosB0[0x1c] = psxBios_sys_b0_1c;
3403 //biosB0[0x1d] = psxBios_sys_b0_1d;
3404 //biosB0[0x1e] = psxBios_sys_b0_1e;
3405 //biosB0[0x1f] = psxBios_sys_b0_1f;
3406 biosB0[0x20] = psxBios_UnDeliverEvent;
3407 //biosB0[0x21] = psxBios_sys_b0_21;
3408 //biosB0[0x22] = psxBios_sys_b0_22;
3409 //biosB0[0x23] = psxBios_sys_b0_23;
3410 //biosB0[0x24] = psxBios_sys_b0_24;
3411 //biosB0[0x25] = psxBios_sys_b0_25;
3412 //biosB0[0x26] = psxBios_sys_b0_26;
3413 //biosB0[0x27] = psxBios_sys_b0_27;
3414 //biosB0[0x28] = psxBios_sys_b0_28;
3415 //biosB0[0x29] = psxBios_sys_b0_29;
3416 //biosB0[0x2a] = psxBios_sys_b0_2a;
3417 //biosB0[0x2b] = psxBios_sys_b0_2b;
3418 //biosB0[0x2c] = psxBios_sys_b0_2c;
3419 //biosB0[0x2d] = psxBios_sys_b0_2d;
3420 //biosB0[0x2e] = psxBios_sys_b0_2e;
3421 //biosB0[0x2f] = psxBios_sys_b0_2f;
3422 //biosB0[0x30] = psxBios_sys_b0_30;
3423 //biosB0[0x31] = psxBios_sys_b0_31;
3424 biosB0[0x32] = psxBios_open;
3425 biosB0[0x33] = psxBios_lseek;
3426 biosB0[0x34] = psxBios_read;
3427 biosB0[0x35] = psxBios_write;
3428 biosB0[0x36] = psxBios_close;
3429 //biosB0[0x37] = psxBios_ioctl;
3430 //biosB0[0x38] = psxBios_exit;
3431 //biosB0[0x39] = psxBios_sys_b0_39;
3432 //biosB0[0x3a] = psxBios_getc;
3433 //biosB0[0x3b] = psxBios_putc;
3434 biosB0[0x3c] = psxBios_getchar;
3435 biosB0[0x3d] = psxBios_putchar;
3436 //biosB0[0x3e] = psxBios_gets;
3437 biosB0[0x3f] = psxBios_puts;
3438 //biosB0[0x40] = psxBios_cd;
3439 biosB0[0x41] = psxBios_format;
3440 biosB0[0x42] = psxBios_firstfile;
3441 biosB0[0x43] = psxBios_nextfile;
3442 biosB0[0x44] = psxBios_rename;
3443 biosB0[0x45] = psxBios_delete;
3444 //biosB0[0x46] = psxBios_undelete;
3445 //biosB0[0x47] = psxBios_AddDevice;
3446 //biosB0[0x48] = psxBios_RemoteDevice;
3447 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3448 biosB0[0x4a] = psxBios_InitCARD;
3449 biosB0[0x4b] = psxBios_StartCARD;
3450 biosB0[0x4c] = psxBios_StopCARD;
3451 //biosB0[0x4d] = psxBios_sys_b0_4d;
3452 biosB0[0x4e] = psxBios__card_write;
3453 biosB0[0x4f] = psxBios__card_read;
3454 biosB0[0x50] = psxBios__new_card;
3455 biosB0[0x51] = psxBios_Krom2RawAdd;
3456 //biosB0[0x52] = psxBios_sys_b0_52;
3457 //biosB0[0x53] = psxBios_sys_b0_53;
3458 //biosB0[0x54] = psxBios__get_errno;
3459 biosB0[0x55] = psxBios__get_error;
3460 biosB0[0x56] = psxBios_GetC0Table;
3461 biosB0[0x57] = psxBios_GetB0Table;
3462 biosB0[0x58] = psxBios__card_chan;
3463 //biosB0[0x59] = psxBios_sys_b0_59;
3464 //biosB0[0x5a] = psxBios_sys_b0_5a;
3465 biosB0[0x5b] = psxBios_ChangeClearPad;
3466 biosB0[0x5c] = psxBios__card_status;
3467 biosB0[0x5d] = psxBios__card_wait;
3468 //*******************C0 CALLS****************************
3469 biosC0[0x00] = psxBios_InitRCnt;
3470 biosC0[0x01] = psxBios_InitException;
3471 biosC0[0x02] = psxBios_SysEnqIntRP;
3472 biosC0[0x03] = psxBios_SysDeqIntRP;
3473 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3474 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3475 //biosC0[0x06] = psxBios_ExceptionHandler;
3476 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3477 biosC0[0x08] = psxBios_SysInitMemory;
3478 //biosC0[0x09] = psxBios_SysInitKMem;
3479 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3480 //biosC0[0x0b] = psxBios_SystemError;
3481 biosC0[0x0c] = psxBios_InitDefInt;
3482 //biosC0[0x0d] = psxBios_sys_c0_0d;
3483 //biosC0[0x0e] = psxBios_sys_c0_0e;
3484 //biosC0[0x0f] = psxBios_sys_c0_0f;
3485 //biosC0[0x10] = psxBios_sys_c0_10;
3486 //biosC0[0x11] = psxBios_sys_c0_11;
3487 //biosC0[0x12] = psxBios_InstallDevices;
3488 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3489 //biosC0[0x14] = psxBios_sys_c0_14;
3490 //biosC0[0x15] = psxBios__cdevinput;
3491 //biosC0[0x16] = psxBios__cdevscan;
3492 //biosC0[0x17] = psxBios__circgetc;
3493 //biosC0[0x18] = psxBios__circputc;
3494 //biosC0[0x19] = psxBios_ioabort;
3495 //biosC0[0x1a] = psxBios_sys_c0_1a
3496 //biosC0[0x1b] = psxBios_KernelRedirect;
3497 //biosC0[0x1c] = psxBios_PatchAOTable;
3498 //************** THE END ***************************************
3505 memset(FDesc, 0, sizeof(FDesc));
3506 card_active_chan = 0;
3509 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3511 // somewhat pretend to be a SCPH1001 BIOS
3512 // some games look for these and take an exception if they're missing
3513 rom32 = (u32 *)psxR;
3514 rom32[0x100/4] = SWAP32(0x19951204);
3515 rom32[0x104/4] = SWAP32(3);
3516 strcpy(psxR + 0x108, "PCSX authors");
3517 strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3518 strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3519 strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
3522 len = 0x80000 - 0x66000;
3523 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3524 len = 0x80000 - 0x69d68;
3525 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3527 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3528 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3529 Here are some examples of games not working with this fix in place :
3530 R-type won't get past the Irem logo if not implemented.
3531 Crash Team Racing will softlock after the Sony logo.
3534 ram32 = (u32 *)psxM;
3535 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3536 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3537 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3538 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3540 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3541 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3543 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3544 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3545 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3546 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3548 ram32[0x00a0/4] = HLEOP(hleop_a0);
3549 ram32[0x00b0/4] = HLEOP(hleop_b0);
3550 ram32[0x00c0/4] = HLEOP(hleop_c0);
3554 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3555 strcpy((char *)&ram32[0xeff0/4], "bu");
3557 // default exception handler chains
3558 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3559 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3560 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3561 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3562 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3563 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3564 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3565 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3569 // fill the api jumptables with fake entries as some games patch them
3570 // (or rather the funcs listed there)
3571 ptr = (u32 *)&psxM[A_A0_TABLE];
3572 for (i = 0; i < 256; i++)
3573 ptr[i] = SWAP32(0x1000);
3575 ptr = (u32 *)&psxM[A_B0_TABLE];
3576 for (i = 0; i < 256; i++)
3577 ptr[i] = SWAP32(0x2000);
3578 // B(5b) is special because games patch (sometimes even jump to)
3579 // code at fixed offsets from it, nocash lists offsets:
3580 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3581 // call: +7a0=4b70, +884=4c54, +894=4c64
3582 ptr[0x5b] = SWAP32(0x43d0);
3583 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3585 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3586 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3587 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3589 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3590 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3592 ptr = (u32 *)&psxM[A_C0_TABLE];
3593 for (i = 0; i < 256/2; i++)
3594 ptr[i] = SWAP32(0x3000);
3595 ptr[6] = SWAP32(A_EXCEPTION);
3598 ram32[0x1000/4] = HLEOP(hleop_dummy);
3599 ram32[0x2000/4] = HLEOP(hleop_dummy);
3600 ram32[0x3000/4] = HLEOP(hleop_dummy);
3601 ram32[0x4c54/4] = HLEOP(hleop_dummy); // for B12_InitPad?
3602 ram32[0x8000/4] = HLEOP(hleop_execret);
3604 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3605 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3606 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3607 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3608 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3609 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3612 void psxBiosShutdown() {
3615 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3616 if (tcb_cnt != 4 || evcb_cnt != 16)
3617 setup_tt(tcb_cnt, evcb_cnt);
3620 #define psxBios_PADpoll(pad) { \
3621 PAD##pad##_startPoll(pad); \
3622 pad_buf##pad[0] = 0; \
3623 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3624 if (!(pad_buf##pad[1] & 0x0f)) { \
3627 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3629 PAD##pad##_poll(0); \
3631 while (bufcount--) { \
3632 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3636 static void biosPadHLE() {
3637 if (pad_buf != NULL) {
3638 u32 *buf = (u32*)pad_buf;
3641 if (PAD1_poll(0x42) == 0x23) {
3643 *buf = PAD1_poll(0) << 8;
3644 *buf |= PAD1_poll(0);
3646 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3647 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3650 *buf = PAD1_poll(0) << 8;
3651 *buf|= PAD1_poll(0);
3655 if (PAD2_poll(0x42) == 0x23) {
3657 *buf |= PAD2_poll(0) << 24;
3658 *buf |= PAD2_poll(0) << 16;
3660 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3661 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3664 *buf |= PAD2_poll(0) << 24;
3665 *buf |= PAD2_poll(0) << 16;
3670 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3674 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3675 psxBios_ReturnFromException();
3681 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3682 // so this is only partially implemented
3683 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3685 u32 cdrom_dma_ack_enable = 1; // a000b93c
3686 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3689 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3692 //PSXBIOS_LOG("%s\n", __func__);
3694 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3695 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3696 //if (--cdrom_irq_counter == 0) // 0xa0009180
3697 // DeliverEvent(0xf0000003, 0x10);
3701 mips_return_c(ret, 20);
3704 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3706 u32 cdrom_irq_ack_enable = 1; // a000b938
3707 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3710 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3713 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3714 PSXBIOS_LOG("%s TODO\n", __func__);
3717 mips_return_c(ret, 20);
3720 void hleExc0_2_2_syscall() // not in any A/B/C table
3722 u32 code = (psxRegs.CP0.n.Cause & 0x3c) >> 2;
3723 u32 tcbPtr = loadRam32(A_TT_PCB);
3724 TCB *tcb = loadRam32ptr(tcbPtr);
3726 if (code != R3000E_Syscall) {
3728 DeliverEvent(0xf0000010, 0x1000);
3729 //psxBios_SystemErrorUnresolvedException();
3731 mips_return_c(0, 17);
3735 //printf("%s c=%d a0=%d\n", __func__, code, a0);
3736 tcb->epc += SWAP32(4);
3741 case 1: { // EnterCritical - disable irqs
3742 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3743 tcb->reg[2] = SWAP32(was_enabled);
3744 tcb->sr &= SWAP32(~0x404);
3747 case 2: // ExitCritical - enable irqs
3748 tcb->sr |= SWAP32(0x404);
3751 case 3: { // ChangeThreadSubFunction
3752 u32 tcbPtr = loadRam32(A_TT_PCB);
3753 storeRam32(tcbPtr, a1);
3757 DeliverEvent(0xf0000010, 0x4000);
3761 psxBios_ReturnFromException();
3764 void hleExc1_0_1(void)
3766 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3767 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3770 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3773 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3774 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3777 mips_return_c(ret, 22);
3780 void hleExc1_0_2(void)
3782 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3785 void hleExc1_1_1(void)
3787 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3788 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3791 void hleExc1_1_2(void)
3793 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3796 void hleExc1_2_1(void)
3798 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3799 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3802 void hleExc1_2_2(void)
3804 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3807 void hleExc1_3_1(void)
3809 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3810 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3813 void hleExc1_3_2(void)
3815 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3818 void hleExc3_0_2_defint(void)
3820 static const struct {
3831 { 6, 6 }, // rcnt2 (bug)
3836 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3837 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3838 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3843 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3846 void hleExcPadCard1(void)
3848 if (loadRam32(A_PAD_IRQR_ENA)) {
3849 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3850 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3858 if (loadRam32(A_PAD_ACK_VBL))
3859 psxHwWrite16(0x1f801070, ~1);
3860 if (loadRam32(A_CARD_IRQR_ENA)) {
3864 mips_return_c(0, 18);
3867 void hleExcPadCard2(void)
3869 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3870 mips_return_c(ret, 15);
3873 void psxBiosException() {
3874 u32 tcbPtr = loadRam32(A_TT_PCB);
3875 u32 *chains = loadRam32ptr(A_TT_ExCB);
3876 TCB *tcb = loadRam32ptr(tcbPtr);
3882 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3883 for (i = 4; i < 32; i++) {
3886 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3888 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3889 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3890 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3891 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3892 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3893 sp = fp = loadRam32(A_EXC_SP);
3897 // do the chains (always 4)
3898 for (c = lim = 0; c < 4; c++) {
3899 if (chains[c * 2] == 0)
3901 ptr = SWAP32(chains[c * 2]);
3902 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3903 chain = castRam32ptr(ptr);
3908 softCallInException(SWAP32(chain[2]));
3909 if (returned_from_exception())
3912 if (v0 == 0 || chain[1] == 0)
3914 softCallInException(SWAP32(chain[1]));
3915 if (returned_from_exception())
3921 // return from exception (custom or default)
3923 ptr = loadRam32(A_EEXIT_PTR);
3924 if (ptr != A_EEXIT_DEF) {
3925 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3926 longjmp_load(jmp_buf);
3931 psxBios_ReturnFromException();
3934 #define bfreeze(ptr, size) { \
3935 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3936 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3940 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3941 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3943 #define bfreezepsxMptr(ptr, type) { \
3945 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3946 else psxRu32ref(base) = 0; \
3948 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3949 else (ptr) = NULL; \
3951 base += sizeof(u32); \
3954 void psxBiosFreeze(int Mode) {
3957 bfreezepsxMptr(pad_buf, int);
3958 bfreezepsxMptr(heap_addr, u32);
3960 bfreezel(&card_active_chan);
3961 bfreezel(&heap_size);