1 /***************************************************************************
2 * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3 * dmitrysmagin, senquack *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
19 ***************************************************************************/
21 /* Gameblabla 2018-2019 :
22 * Numerous changes to bios calls as well as improvements in order to conform to nocash's findings
23 * for the PSX bios calls. Thanks senquack for helping out with some of the changes
24 * and helping to spot issues and refine my patches.
28 * Internal simulated HLE BIOS.
31 // TODO: implement all system calls, count the exact CPU cycles of system calls.
38 #include "psxinterpreter.h"
41 #if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
42 #pragma GCC diagnostic ignored "-Wpointer-sign"
46 //#define PSXBIOS_LOG printf
47 #define PSXBIOS_LOG(...)
50 char *biosA0n[256] = {
52 "open", "lseek", "read", "write",
53 "close", "ioctl", "exit", "sys_a0_07",
54 "getc", "putc", "todigit", "atof",
55 "strtoul", "strtol", "abs", "labs",
57 "atoi", "atol", "atob", "setjmp",
58 "longjmp", "strcat", "strncat", "strcmp",
59 "strncmp", "strcpy", "strncpy", "strlen",
60 "index", "rindex", "strchr", "strrchr",
62 "strpbrk", "strspn", "strcspn", "strtok",
63 "strstr", "toupper", "tolower", "bcopy",
64 "bzero", "bcmp", "memcpy", "memset",
65 "memmove", "memcmp", "memchr", "rand",
67 "srand", "qsort", "strtod", "malloc",
68 "free", "lsearch", "bsearch", "calloc",
69 "realloc", "InitHeap", "_exit", "getchar",
70 "putchar", "gets", "puts", "printf",
72 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
73 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
74 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
75 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
77 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
78 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
79 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
80 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
82 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
83 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
84 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
85 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
87 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
88 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
89 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
90 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
92 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
93 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
94 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
95 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
97 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
98 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
99 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
100 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
102 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
103 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
104 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
105 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
107 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
111 char *biosB0n[256] = {
113 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
114 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
115 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
116 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
118 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
119 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
120 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
121 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
123 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
124 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
125 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
126 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
128 "sys_b0_30", "sys_b0_31", "open", "lseek",
129 "read", "write", "close", "ioctl",
130 "exit", "sys_b0_39", "getc", "putc",
131 "getchar", "putchar", "gets", "puts",
133 "cd", "format", "firstfile", "nextfile",
134 "rename", "delete", "undelete", "AddDevice",
135 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
136 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
138 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
139 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
140 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
141 "_card_status", "_card_wait",
144 char *biosC0n[256] = {
146 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
147 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
148 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
149 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
151 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
152 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
153 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
157 //#define r0 (psxRegs.GPR.n.r0)
158 #define at (psxRegs.GPR.n.at)
159 #define v0 (psxRegs.GPR.n.v0)
160 #define v1 (psxRegs.GPR.n.v1)
161 #define a0 (psxRegs.GPR.n.a0)
162 #define a1 (psxRegs.GPR.n.a1)
163 #define a2 (psxRegs.GPR.n.a2)
164 #define a3 (psxRegs.GPR.n.a3)
165 #define t0 (psxRegs.GPR.n.t0)
166 #define t1 (psxRegs.GPR.n.t1)
167 #define t2 (psxRegs.GPR.n.t2)
168 #define t3 (psxRegs.GPR.n.t3)
169 #define t4 (psxRegs.GPR.n.t4)
170 #define t5 (psxRegs.GPR.n.t5)
171 #define t6 (psxRegs.GPR.n.t6)
172 #define t7 (psxRegs.GPR.n.t7)
173 #define t8 (psxRegs.GPR.n.t8)
174 #define t9 (psxRegs.GPR.n.t9)
175 #define s0 (psxRegs.GPR.n.s0)
176 #define s1 (psxRegs.GPR.n.s1)
177 #define s2 (psxRegs.GPR.n.s2)
178 #define s3 (psxRegs.GPR.n.s3)
179 #define s4 (psxRegs.GPR.n.s4)
180 #define s5 (psxRegs.GPR.n.s5)
181 #define s6 (psxRegs.GPR.n.s6)
182 #define s7 (psxRegs.GPR.n.s7)
183 #define k0 (psxRegs.GPR.n.k0)
184 #define k1 (psxRegs.GPR.n.k1)
185 #define gp (psxRegs.GPR.n.gp)
186 #define sp (psxRegs.GPR.n.sp)
187 #define fp (psxRegs.GPR.n.fp)
188 #define ra (psxRegs.GPR.n.ra)
189 #define pc0 (psxRegs.pc)
191 #define Ra0 ((char *)PSXM(a0))
192 #define Ra1 ((char *)PSXM(a1))
193 #define Ra2 ((char *)PSXM(a2))
194 #define Ra3 ((char *)PSXM(a3))
195 #define Rv0 ((char *)PSXM(v0))
196 #define Rsp ((char *)PSXM(sp))
207 #define EvStUNUSED 0x0000
208 #define EvStDISABLED 0x1000
209 #define EvStACTIVE 0x2000
210 #define EvStALREADY 0x4000
212 #define EvMdCALL 0x1000
213 #define EvMdMARK 0x2000
236 u32 _sp, _fp, _gp, ret, base;
256 // todo: FileDesc layout is wrong
257 // todo: get rid of these globals
258 static FileDesc FDesc[32];
259 static char ffile[64], *pfile;
262 // fixed RAM offsets, SCPH1001 compatible
263 #define A_TT_ExCB 0x0100
264 #define A_TT_PCB 0x0108
265 #define A_TT_TCB 0x0110
266 #define A_TT_EvCB 0x0120
267 #define A_A0_TABLE 0x0200
268 #define A_B0_TABLE 0x0874
269 #define A_C0_TABLE 0x0674
270 #define A_SYSCALL 0x0650
271 #define A_EXCEPTION 0x0c80
272 #define A_EXC_SP 0x6cf0
273 #define A_EEXIT_DEF 0x6cf4
274 #define A_KMALLOC_PTR 0x7460
275 #define A_KMALLOC_SIZE 0x7464
276 #define A_KMALLOC_END 0x7468
277 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
278 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
279 #define A_CARD_IRQR_ENA 0x74bc // same for card
280 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
281 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
282 #define A_PAD_IN_LEN 0x74d8
283 #define A_PAD_OUT_LEN 0x74e0
284 #define A_PAD_DR_DST 0x74c4
285 #define A_CARD_CHAN1 0x7500
286 #define A_PAD_DR_BUF1 0x7570
287 #define A_PAD_DR_BUF2 0x7598
288 #define A_EEXIT_PTR 0x75d0
289 #define A_EXC_STACK 0x85d8 // exception stack top
290 #define A_RCNT_VBL_ACK 0x8600
291 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
292 #define A_HEAP_BASE 0x9000
293 #define A_HEAP_SIZE 0x9004
294 #define A_HEAP_END 0x9008
295 #define A_HEAP_FLAG 0x900c
296 #define A_CD_EVENTS 0xb9b8
297 #define A_EXC_GP 0xf450
299 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
301 static u32 loadRam32(u32 addr)
303 assert(!(addr & 0x5f800000));
304 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
307 static void *castRam8ptr(u32 addr)
309 assert(!(addr & 0x5f800000));
310 return psxM + (addr & 0x1fffff);
313 static void *castRam32ptr(u32 addr)
315 assert(!(addr & 0x5f800003));
316 return psxM + (addr & 0x1ffffc);
319 static void *loadRam8ptr(u32 addr)
321 return castRam8ptr(loadRam32(addr));
324 static void *loadRam32ptr(u32 addr)
326 return castRam32ptr(loadRam32(addr));
329 static void storeRam8(u32 addr, u8 d)
331 assert(!(addr & 0x5f800000));
332 *((u8 *)psxM + (addr & 0x1fffff)) = d;
335 static void storeRam32(u32 addr, u32 d)
337 assert(!(addr & 0x5f800000));
338 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
341 static void mips_return(u32 val)
347 static void use_cycles(u32 cycle)
349 psxRegs.cycle += cycle * 2;
352 static void mips_return_c(u32 val, u32 cycle)
358 static void mips_return_void_c(u32 cycle)
364 static int returned_from_exception(void)
366 // 0x80000080 means it took another exception just after return
367 return pc0 == k0 || pc0 == 0x80000080;
370 static inline void softCall(u32 pc) {
372 u32 ssr = psxRegs.CP0.n.SR;
376 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
378 while (pc0 != 0x80001000 && ++lim < 1000000)
379 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
382 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
384 psxRegs.CP0.n.SR |= ssr & 0x404;
387 static inline void softCallInException(u32 pc) {
393 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
394 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
397 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
398 if (pc0 == 0x80001000)
402 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
403 static u32 DeliverEvent(u32 class, u32 spec);
404 static u32 UnDeliverEvent(u32 class, u32 spec);
405 static void CloseEvent(u32 ev);
410 // System calls A0 */
413 #define buread(Ra1, mcd, length) { \
414 PSXBIOS_LOG("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
415 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
416 memcpy(Ra1, ptr, length); \
417 if (FDesc[1 + mcd].mode & 0x8000) { \
418 DeliverEvent(0xf0000011, 0x0004); \
419 DeliverEvent(0xf4000001, 0x0004); \
422 FDesc[1 + mcd].offset += v0; \
425 #define buwrite(Ra1, mcd, length) { \
426 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
427 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
428 ptr = Mcd##mcd##Data + offset; \
429 memcpy(ptr, Ra1, length); \
430 FDesc[1 + mcd].offset += length; \
431 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
432 if (FDesc[1 + mcd].mode & 0x8000) { \
433 DeliverEvent(0xf0000011, 0x0004); \
434 DeliverEvent(0xf4000001, 0x0004); \
439 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
440 /* For some strange reason, the returned character is sign-expanded; */
441 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
442 /* TODO FIX ME : Properly implement this behaviour */
443 void psxBios_getc(void) // 0x03, 0x35
448 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
452 if (pa1 != INVALID_PTR) {
454 case 2: buread(pa1, 1, 1); break;
455 case 3: buread(pa1, 2, 1); break;
462 /* Copy of psxBios_write, except size is 1. */
463 void psxBios_putc(void) // 0x09, 0x3B
468 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
471 if (pa1 == INVALID_PTR) {
476 if (a0 == 1) { // stdout
477 char *ptr = (char *)pa1;
481 printf("%c", *ptr++); a2--;
487 case 2: buwrite(pa1, 1, 1); break;
488 case 3: buwrite(pa1, 2, 1); break;
494 void psxBios_todigit(void) // 0x0a
498 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
501 if (c >= 0x30 && c < 0x3A) {
504 else if (c > 0x60 && c < 0x7B) {
507 else if (c > 0x40 && c < 0x5B) {
510 else if (c >= 0x80) {
521 void psxBios_abs() { // 0x0e
522 if ((s32)a0 < 0) v0 = -(s32)a0;
527 void psxBios_labs() { // 0x0f
531 void psxBios_atoi() { // 0x10
533 char *p = (char *)Ra0;
537 case ' ': case '\t': continue;
544 while (*p >= '0' && *p <= '9') {
545 n = n * 10 + *p++ - '0';
552 void psxBios_atol() { // 0x11
562 static void psxBios_setjmp() { // 0x13
563 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
566 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
568 jmp_buf->ra_ = SWAP32(ra);
569 jmp_buf->sp_ = SWAP32(sp);
570 jmp_buf->fp_ = SWAP32(fp);
571 for (i = 0; i < 8; i++) // s0-s7
572 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
573 jmp_buf->gp_ = SWAP32(gp);
575 mips_return_c(0, 15);
578 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
582 ra = SWAP32(jmp_buf->ra_);
583 sp = SWAP32(jmp_buf->sp_);
584 fp = SWAP32(jmp_buf->fp_);
585 for (i = 0; i < 8; i++) // s0-s7
586 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
587 gp = SWAP32(jmp_buf->gp_);;
590 void psxBios_longjmp() { // 0x14
591 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
593 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
594 longjmp_load(jmp_buf);
595 mips_return_c(a1, 15);
598 void psxBios_strcat() { // 0x15
599 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
602 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
604 if (a0 == 0 || a1 == 0)
612 while ((*p1++ = *p2++) != '\0');
617 void psxBios_strncat() { // 0x16
618 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
622 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
624 if (a0 == 0 || a1 == 0)
632 while ((*p1++ = *p2++) != '\0') {
642 void psxBios_strcmp() { // 0x17
643 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
645 if (a0 == 0 && a1 == 0)
651 else if (a0 == 0 && a1 != 0)
657 else if (a0 != 0 && a1 == 0)
664 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
667 while (*p1 == *p2++) {
686 void psxBios_strncmp() { // 0x18
687 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
689 if (a0 == 0 && a1 == 0)
695 else if (a0 == 0 && a1 != 0)
701 else if (a0 != 0 && a1 == 0)
708 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
711 while (--n >= 0 && *p1 == *p2++) {
715 v1 = a2 - ((a2-n) - 1);
723 v0 = (n < 0 ? 0 : *p1 - *--p2);
725 v1 = a2 - ((a2-n) - 1);
731 void psxBios_strcpy() { // 0x19
732 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
733 if (a0 == 0 || a1 == 0)
739 while ((*p1++ = *p2++) != '\0');
744 void psxBios_strncpy() { // 0x1a
745 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
747 if (a0 == 0 || a1 == 0)
753 for (i = 0; i < n; i++) {
754 if ((*p1++ = *p2++) == '\0') {
766 void psxBios_strlen() { // 0x1b
767 char *p = (char *)Ra0;
778 void psxBios_index() { // 0x1c
779 char *p = (char *)Ra0;
789 v0 = a0 + (p - (char *)Ra0);
793 } while (*p++ != '\0');
798 void psxBios_rindex() { // 0x1d
799 char *p = (char *)Ra0;
809 v0 = a0 + (p - (char *)Ra0);
810 } while (*p++ != '\0');
815 void psxBios_strchr() { // 0x1e
819 void psxBios_strrchr() { // 0x1f
823 void psxBios_strpbrk() { // 0x20
824 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
826 while ((c = *p1++) != '\0') {
827 for (scanp = p2; (sc = *scanp++) != '\0';) {
829 v0 = a0 + (p1 - 1 - (char *)Ra0);
836 // BUG: return a0 instead of NULL if not found
840 void psxBios_strspn() { // 0x21
843 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
844 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
845 if (*p2 == '\0') break;
848 v0 = p1 - (char *)Ra0; pc0 = ra;
851 void psxBios_strcspn() { // 0x22
854 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
855 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
856 if (*p2 != '\0') break;
859 v0 = p1 - (char *)Ra0; pc0 = ra;
862 void psxBios_strtok() { // 0x23
863 char *pcA0 = (char *)Ra0;
864 char *pcRet = strtok(pcA0, (char *)Ra1);
866 v0 = a0 + pcRet - pcA0;
872 void psxBios_strstr() { // 0x24
873 char *p = (char *)Ra0, *p1, *p2;
879 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
884 v0 = a0 + (p - (char *)Ra0);
895 void psxBios_toupper() { // 0x25
896 v0 = (s8)(a0 & 0xff);
897 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
901 void psxBios_tolower() { // 0x26
902 v0 = (s8)(a0 & 0xff);
903 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
907 void psxBios_bcopy() { // 0x27
908 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
910 if (a0 == 0 || a2 > 0x7FFFFFFF)
915 while ((s32)a2-- > 0) *p1++ = *p2++;
920 static void psxBios_bzero() { // 0x28
921 /* Same as memset here (See memset below) */
923 if (a0 == 0 || (s32)a1 <= 0)
928 while ((s32)a1-- > 0) {
932 // todo: many more cycles due to uncached bios mem
933 mips_return_c(ret, 5);
936 void psxBios_bcmp() { // 0x29
937 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
939 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
941 while ((s32)a2-- > 0) {
942 if (*p1++ != *p2++) {
943 v0 = *p1 - *p2; // BUG: compare the NEXT byte
952 void psxBios_memcpy() { // 0x2a
953 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
955 if (a0 == 0 || a2 > 0x7FFFFFFF)
960 while ((s32)a2-- > 0) {
967 static void psxBios_memset() { // 0x2b
969 if (a0 == 0 || (s32)a2 <= 0)
974 while ((s32)a2-- > 0) {
978 // todo: many more cycles due to uncached bios mem
979 mips_return_c(ret, 5);
982 void psxBios_memmove() { // 0x2c
983 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
985 if (a0 == 0 || a2 > 0x7FFFFFFF)
990 if (p2 <= p1 && p2 + a2 > p1) {
991 a2++; // BUG: copy one more byte here
994 while ((s32)a2-- > 0) *--p1 = *--p2;
996 while ((s32)a2-- > 0) *p1++ = *p2++;
1001 void psxBios_memcmp() { // 0x2d
1005 void psxBios_memchr() { // 0x2e
1006 char *p = (char *)Ra0;
1008 if (a0 == 0 || a2 > 0x7FFFFFFF)
1014 while ((s32)a2-- > 0) {
1015 if (*p++ != (s8)a1) continue;
1016 v0 = a0 + (p - (char *)Ra0 - 1);
1024 void psxBios_rand() { // 0x2f
1025 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1026 v0 = (s >> 16) & 0x7fff;
1027 psxMu32ref(0x9010) = SWAPu32(s);
1031 void psxBios_srand() { // 0x30
1032 psxMu32ref(0x9010) = SWAPu32(a0);
1036 static u32 qscmpfunc, qswidth;
1038 static inline int qscmp(char *a, char *b) {
1041 a0 = sa0 + (a - (char *)PSXM(sa0));
1042 a1 = sa0 + (b - (char *)PSXM(sa0));
1044 softCall(qscmpfunc);
1050 static inline void qexchange(char *i, char *j) {
1061 static inline void q3exchange(char *i, char *j, char *k) {
1073 static void qsort_main(char *a, char *l) {
1074 char *i, *j, *lp, *hp;
1079 if ((n = l - a) <= qswidth)
1081 n = qswidth * (n / (2 * qswidth));
1087 if ((c = qscmp(i, lp)) == 0) {
1088 qexchange(i, lp -= qswidth);
1099 if ((c = qscmp(hp, j)) == 0) {
1100 qexchange(hp += qswidth, j);
1105 q3exchange(i, hp += qswidth, j);
1119 if (lp - a >= l - hp) {
1120 qsort_main(hp + qswidth, l);
1129 q3exchange(j, lp -= qswidth, i);
1134 void psxBios_qsort() { // 0x31
1137 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1142 // this isn't how the real bios works, but maybe good enough
1143 static void psxBios_malloc() { // 0x33
1144 u32 *heap_addr, *heap_end;
1145 u32 *chunk, *newchunk = NULL;
1146 unsigned int dsize = 0, csize, cstat;
1148 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
1149 heap_addr = loadRam32ptr(A_HEAP_BASE);
1150 heap_end = loadRam32ptr(A_HEAP_END);
1151 if (heap_addr >= heap_end) {
1157 // scan through heap and combine free chunks of space
1160 while(chunk < heap_end) {
1161 // get size and status of actual chunk
1162 csize = ((u32)*chunk) & 0xfffffffc;
1163 cstat = ((u32)*chunk) & 1;
1165 // most probably broken heap descriptor
1166 // this fixes Burning Road
1169 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1174 // it's a free chunk
1179 colflag = 1; // let's begin a new collection of free memory
1181 else dsize += (csize+4); // add the new size including header
1183 // not a free chunk: did we start a collection ?
1185 if(colflag == 1) { // collection is over
1187 *newchunk = SWAP32(dsize | 1);
1192 chunk = (u32*)((uptr)chunk + csize + 4);
1194 // if neccessary free memory on end of heap
1196 *newchunk = SWAP32(dsize | 1);
1199 csize = ((u32)*chunk) & 0xfffffffc;
1200 cstat = ((u32)*chunk) & 1;
1201 dsize = (a0 + 3) & 0xfffffffc;
1203 // exit on uninitialized heap
1204 if (chunk == NULL) {
1205 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1211 // search an unused chunk that is big enough until the end of the heap
1212 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1213 chunk = (u32*)((uptr)chunk + csize + 4);
1215 // catch out of memory
1216 if(chunk >= heap_end) {
1217 printf("malloc %x,%x: Out of memory error!\n",
1223 csize = ((u32)*chunk) & 0xfffffffc;
1224 cstat = ((u32)*chunk) & 1;
1228 if(dsize == csize) {
1229 // chunk has same size
1230 *chunk &= 0xfffffffc;
1231 } else if (dsize > csize) {
1236 *chunk = SWAP32(dsize);
1237 newchunk = (u32*)((uptr)chunk + dsize + 4);
1238 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1241 // return pointer to allocated memory
1242 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1244 //printf ("malloc %x,%x\n", v0, a0);
1248 static void psxBios_free() { // 0x34
1249 PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1250 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1251 mips_return_void_c(5);
1254 static void psxBios_calloc() { // 0x37
1256 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1258 a0 = size = a0 * a1;
1262 a0 = ret; a1 = size;
1265 mips_return_c(ret, 21);
1268 void psxBios_realloc() { // 0x38
1272 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1276 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1281 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1286 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1287 /* Note that it is not quite implemented this way here. */
1297 /* InitHeap(void *block , int n) */
1298 static void psxBios_InitHeap() { // 0x39
1299 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1301 storeRam32(A_HEAP_BASE, a0);
1302 storeRam32(A_HEAP_SIZE, a1);
1303 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1304 storeRam32(A_HEAP_FLAG, 0);
1307 mips_return_void_c(14);
1310 void psxBios_getchar() { //0x3b
1311 v0 = getchar(); pc0 = ra;
1314 static void psxBios_printf_psxout() { // 0x3f
1323 if (psp != INVALID_PTR) {
1324 memcpy(save, psp, 4 * 4);
1325 psxMu32ref(sp) = SWAP32((u32)a0);
1326 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1327 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1328 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1340 tmp2[j++] = Ra0[i]; goto _start;
1342 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1353 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1357 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1363 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1365 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1367 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1369 *ptmp++ = Ra0[i]; break;
1379 if (psp != INVALID_PTR)
1380 memcpy(psp, save, 4 * 4);
1383 SysPrintf("%s", tmp);
1386 void psxBios_printf() { // 0x3f
1387 psxBios_printf_psxout();
1391 void psxBios_format() { // 0x41
1392 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1394 CreateMcd(Config.Mcd1);
1395 LoadMcd(1, Config.Mcd1);
1398 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1400 CreateMcd(Config.Mcd2);
1401 LoadMcd(2, Config.Mcd2);
1411 static void psxBios_SystemErrorUnresolvedException() {
1412 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1413 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1414 storeRam32(0xfffc, 0x12345678);
1416 mips_return_void_c(1000);
1420 * long Load(char *name, struct EXEC *header);
1423 void psxBios_Load() { // 0x42
1428 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1429 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1432 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1438 * int Exec(struct EXEC *header , int argc , char **argv);
1441 void psxBios_Exec() { // 43
1442 EXEC *header = (EXEC *)castRam32ptr(a0);
1446 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1448 header->_sp = SWAP32(sp);
1449 header->_fp = SWAP32(fp);
1450 header->_sp = SWAP32(sp);
1451 header->_gp = SWAP32(gp);
1452 header->ret = SWAP32(ra);
1453 header->base = SWAP32(s0);
1455 ptr = SWAP32(header->b_addr);
1456 len = SWAP32(header->b_size);
1462 if (header->S_addr != 0)
1463 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1465 gp = SWAP32(header->gp0);
1473 pc0 = SWAP32(header->_pc0);
1476 void psxBios_FlushCache() { // 44
1478 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1480 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1481 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1485 void psxBios_GPU_dw() { // 0x46
1490 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1493 GPU_writeData(0xa0000000);
1494 GPU_writeData((a1<<0x10)|(a0&0xffff));
1495 GPU_writeData((a3<<0x10)|(a2&0xffff));
1497 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1500 GPU_writeData(SWAPu32(*ptr++));
1506 void psxBios_mem2vram() { // 0x47
1509 GPU_writeData(0xa0000000);
1510 GPU_writeData((a1<<0x10)|(a0&0xffff));
1511 GPU_writeData((a3<<0x10)|(a2&0xffff));
1512 size = ((((a2 * a3) / 2) >> 4) << 16);
1513 GPU_writeStatus(0x04000002);
1514 psxHwWrite32(0x1f8010f4,0);
1515 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1516 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1517 psxHwWrite32(0x1f8010a4, size | 0x10);
1518 psxHwWrite32(0x1f8010a8,0x01000201);
1523 void psxBios_SendGPU() { // 0x48
1524 GPU_writeStatus(a0);
1529 void psxBios_GPU_cw() { // 0x49
1536 void psxBios_GPU_cwb() { // 0x4a
1537 u32 *ptr = (u32*)Ra0;
1542 GPU_writeData(SWAPu32(*ptr++));
1548 void psxBios_GPU_SendPackets() { //4b:
1550 GPU_writeStatus(0x04000002);
1551 psxHwWrite32(0x1f8010f4,0);
1552 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1553 psxHwWrite32(0x1f8010a0,a0);
1554 psxHwWrite32(0x1f8010a4,0);
1555 psxHwWrite32(0x1f8010a8,0x010000401);
1559 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1560 psxHwWrite32(0x1f8010a8,0x00000401);
1561 GPU_writeData(0x0400000);
1562 GPU_writeData(0x0200000);
1563 GPU_writeData(0x0100000);
1568 void psxBios_GPU_GetGPUStatus() { // 0x4d
1569 v0 = GPU_readStatus();
1575 void psxBios_LoadExec() { // 51
1576 EXEC *header = (EXEC*)PSXM(0xf000);
1580 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1582 s_addr = a1; s_size = a2;
1587 header->S_addr = s_addr;
1588 header->s_size = s_size;
1590 a0 = 0xf000; a1 = 0; a2 = 0;
1594 void psxBios__bu_init() { // 70
1596 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1599 DeliverEvent(0xf0000011, 0x0004);
1600 DeliverEvent(0xf4000001, 0x0004);
1605 void psxBios__96_init() { // 71
1607 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1613 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1614 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1615 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1617 static void psxBios_DequeueCdIntr_() {
1618 psxBios_SysDeqIntRP_(0, 0x91d0);
1619 psxBios_SysDeqIntRP_(0, 0x91e0);
1623 static void psxBios_DequeueCdIntr() { // a3
1624 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1625 psxBios_DequeueCdIntr_();
1628 static void psxBios_CdRemove() { // 56, 72
1629 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1631 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1632 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1633 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1634 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1635 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1636 psxBios_DequeueCdIntr_();
1638 // EnterCriticalSection - should be done at the beginning,
1639 // but this way is much easier to implement
1645 void psxBios_SetMem() { // 9f
1646 u32 new = psxHu32(0x1060);
1649 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1654 psxHu32ref(0x1060) = SWAP32(new);
1655 psxMu32ref(0x060) = a0;
1656 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1660 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1661 psxMu32ref(0x060) = a0;
1662 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1665 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1672 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1673 static void psxBios_get_cd_status() // a6
1675 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1680 static void psxBios__card_info() { // ab
1681 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1683 storeRam32(A_CARD_CHAN1, a0);
1690 if (McdDisable[port & 1])
1694 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1699 if (McdDisable[0] && McdDisable[1])
1702 DeliverEvent(0xf0000011, 0x0004);
1703 // DeliverEvent(0xf4000001, 0x0004);
1704 DeliverEvent(0xf4000001, ret);
1708 void psxBios__card_load() { // ac
1710 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1713 storeRam32(A_CARD_CHAN1, a0);
1715 // DeliverEvent(0xf0000011, 0x0004);
1716 DeliverEvent(0xf4000001, 0x0004);
1721 static void psxBios_GetSystemInfo() { // b4
1723 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1724 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1727 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1728 case 2: ret = 0xbfc0012c; break;
1729 case 5: ret = loadRam32(0x60) << 10; break;
1731 mips_return_c(ret, 20);
1734 /* System calls B0 */
1736 static u32 psxBios_SysMalloc_(u32 size);
1738 static void psxBios_SysMalloc() { // B 00
1739 u32 ret = psxBios_SysMalloc_(a0);
1741 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1742 mips_return_c(ret, 33);
1745 void psxBios_SetRCnt() { // 02
1747 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1754 psxRcntWtarget(a0, a1);
1755 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1756 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1757 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1758 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1759 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1761 psxRcntWmode(a0, mode);
1766 void psxBios_GetRCnt() { // 03
1768 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1772 if (a0 != 3) v0 = psxRcntRcount(a0);
1777 void psxBios_StartRCnt() { // 04
1779 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1783 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1784 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1788 void psxBios_StopRCnt() { // 05
1790 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1794 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1795 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1799 void psxBios_ResetRCnt() { // 06
1801 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1806 psxRcntWmode(a0, 0);
1807 psxRcntWtarget(a0, 0);
1808 psxRcntWcount(a0, 0);
1813 static u32 DeliverEvent(u32 class, u32 spec) {
1814 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1815 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1816 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1817 u32 i, lim = evcb_len / 0x1c;
1819 for (i = 0; i < lim; i++, ev++) {
1821 if (SWAP32(ev->status) != EvStACTIVE)
1824 if (SWAP32(ev->class) != class)
1827 if (SWAP32(ev->spec) != spec)
1830 ret = SWAP32(ev->mode);
1831 if (ret == EvMdMARK) {
1832 ev->status = SWAP32(EvStALREADY);
1836 if (ret == EvMdCALL) {
1837 ret = SWAP32(ev->fhandler);
1849 static u32 UnDeliverEvent(u32 class, u32 spec) {
1850 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1851 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1852 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1853 u32 i, lim = evcb_len / 0x1c;
1855 for (i = 0; i < lim; i++, ev++) {
1857 if (SWAP32(ev->status) != EvStALREADY)
1860 if (SWAP32(ev->class) != class)
1863 if (SWAP32(ev->spec) != spec)
1866 if (SWAP32(ev->mode) == EvMdMARK)
1867 ev->status = SWAP32(EvStACTIVE);
1873 static void psxBios_DeliverEvent() { // 07
1875 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1877 ret = DeliverEvent(a0, a1);
1881 static s32 get_free_EvCB_slot() {
1882 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1883 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1886 for (i = 0; i < lim; i++, ev++) {
1888 if (ev->status == SWAP32(EvStUNUSED))
1894 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
1895 u32 ret = get_free_EvCB_slot();
1896 if ((s32)ret >= 0) {
1897 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
1898 ev->class = SWAP32(class);
1899 ev->status = SWAP32(EvStDISABLED);
1900 ev->spec = SWAP32(spec);
1901 ev->mode = SWAP32(mode);
1902 ev->fhandler = SWAP32(func);
1908 static void psxBios_OpenEvent() { // 08
1909 u32 ret = OpenEvent(a0, a1, a2, a3);
1910 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
1911 biosB0n[0x08], a0, a1, a2, a3, ret);
1912 mips_return_c(ret, 36);
1915 static void CloseEvent(u32 ev)
1917 u32 base = loadRam32(A_TT_EvCB);
1918 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
1921 static void psxBios_CloseEvent() { // 09
1922 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
1923 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
1925 mips_return_c(1, 10);
1928 static void psxBios_WaitEvent() { // 0a
1929 u32 base = loadRam32(A_TT_EvCB);
1930 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1931 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
1934 if (status == EvStALREADY) {
1935 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1939 if (status != EvStACTIVE)
1941 mips_return_c(0, 2);
1945 // retrigger this hlecall after the next emulation event
1947 if ((s32)(next_interupt - psxRegs.cycle) > 0)
1948 psxRegs.cycle = next_interupt;
1952 static void psxBios_TestEvent() { // 0b
1953 u32 base = loadRam32(A_TT_EvCB);
1954 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1956 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
1957 if (status == EvStALREADY) {
1958 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1962 mips_return_c(ret, 15);
1965 static void psxBios_EnableEvent() { // 0c
1966 u32 base = loadRam32(A_TT_EvCB);
1967 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1968 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
1969 if (status != EvStUNUSED)
1970 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1972 mips_return_c(1, 15);
1975 static void psxBios_DisableEvent() { // 0d
1976 u32 base = loadRam32(A_TT_EvCB);
1977 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1978 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
1979 if (status != EvStUNUSED)
1980 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
1982 mips_return_c(1, 15);
1986 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1989 void psxBios_OpenTh() { // 0e
1990 TCB *tcb = loadRam32ptr(A_TT_TCB);
1991 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
1994 for (th = 1; th < limit; th++)
1996 if (tcb[th].status != SWAP32(0x4000)) break;
2000 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2001 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2003 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2005 mips_return_c(0xffffffff, 20);
2008 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
2010 tcb[th].status = SWAP32(0x4000);
2011 tcb[th].mode = SWAP32(0x1000);
2012 tcb[th].epc = SWAP32(a0);
2013 tcb[th].reg[30] = SWAP32(a1); // fp
2014 tcb[th].reg[29] = SWAP32(a1); // sp
2015 tcb[th].reg[28] = SWAP32(a2); // gp
2017 mips_return_c(0xff000000 + th, 34);
2021 * int CloseTh(long thread);
2024 void psxBios_CloseTh() { // 0f
2025 TCB *tcb = loadRam32ptr(A_TT_TCB);
2026 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2030 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2032 /* The return value is always 1 (even if the handle was already closed). */
2034 if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2035 tcb[th].status = SWAP32(0x1000);
2042 * int ChangeTh(long thread);
2045 void psxBios_ChangeTh() { // 10
2046 u32 tcbBase = loadRam32(A_TT_TCB);
2047 u32 th = a0 & 0xffff;
2049 // this is quite spammy
2050 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2052 // without doing any argument checks, just issue a syscall
2053 // (like the real bios does)
2055 a1 = tcbBase + th * sizeof(TCB);
2060 void psxBios_InitPAD() { // 0x12
2061 u32 i, *ram32 = (u32 *)psxM;
2062 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2064 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2065 ram32[A_PAD_DR_DST/4] = 0;
2066 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2067 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2068 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2069 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2070 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2071 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2072 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2073 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2075 for (i = 0; i < a1; i++) {
2077 storeRam8(a0 + i, 0);
2079 for (i = 0; i < a3; i++) {
2081 storeRam8(a2 + i, 0);
2083 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2085 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2087 mips_return_c(1, 200);
2090 void psxBios_StartPAD() { // 13
2091 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2093 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2094 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2095 psxHwWrite16(0x1f801070, ~1);
2096 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2097 storeRam32(A_PAD_ACK_VBL, 1);
2098 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2099 psxRegs.CP0.n.SR |= 0x401;
2101 mips_return_c(1, 300);
2104 void psxBios_StopPAD() { // 14
2105 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2106 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2107 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2108 psxRegs.CP0.n.SR |= 0x401;
2109 mips_return_void_c(200);
2112 static void psxBios_PAD_init() { // 15
2114 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2115 if (a0 == 0x20000000 || a0 == 0x20000001)
2118 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2119 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2122 storeRam32(A_PAD_DR_DST, dst);
2125 mips_return_c(ret, 100);
2128 static u32 psxBios_PAD_dr_() {
2129 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2130 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2131 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2132 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2133 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2135 dst[0] = buf1[3], dst[1] = buf1[2];
2136 if (buf1[1] == 0x23) {
2137 dst[0] |= 0xc7, dst[1] |= 7;
2138 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2139 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2142 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2144 dst[2] = buf2[3], dst[3] = buf2[2];
2145 if (buf2[1] == 0x23) {
2146 dst[2] |= 0xc7, dst[3] |= 7;
2147 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2148 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2152 return SWAP32(*(u32 *)dst);
2155 static void psxBios_PAD_dr() { // 16
2156 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2157 u32 ret = psxBios_PAD_dr_();
2161 static void psxBios_ReturnFromException() { // 17
2162 u32 tcbPtr = loadRam32(A_TT_PCB);
2163 const TCB *tcb = loadRam32ptr(tcbPtr);
2167 for (i = 1; i < 32; i++)
2168 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2169 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2170 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2171 sr = SWAP32(tcb->sr);
2173 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2174 pc0 = k0 = SWAP32(tcb->epc);
2176 // the interpreter wants to know about sr changes, so do a MTC0
2177 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2178 MTC0(&psxRegs, 12, sr);
2184 void psxBios_ResetEntryInt() { // 18
2185 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2187 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2188 mips_return_void_c(5);
2191 void psxBios_HookEntryInt() { // 19
2192 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2194 storeRam32(A_EEXIT_PTR, a0);
2195 mips_return_void_c(3);
2198 static void psxBios_UnDeliverEvent() { // 0x20
2200 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2202 ret = UnDeliverEvent(a0, a1);
2206 static void buopen(int mcd, char *ptr, char *cfg)
2209 char *mcd_data = ptr;
2211 strcpy(FDesc[1 + mcd].name, Ra0+5);
2212 FDesc[1 + mcd].offset = 0;
2213 FDesc[1 + mcd].mode = a1;
2215 for (i=1; i<16; i++) {
2216 const char *fptr = mcd_data + 128 * i;
2217 if ((*fptr & 0xF0) != 0x50) continue;
2218 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2219 FDesc[1 + mcd].mcfile = i;
2220 PSXBIOS_LOG("open %s\n", fptr+0xa);
2224 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2225 for (i=1; i<16; i++) {
2226 int j, xor, nblk = a1 >> 16;
2228 char *fptr = mcd_data + 128 * i;
2230 if ((*fptr & 0xF0) != 0xa0) continue;
2232 FDesc[1 + mcd].mcfile = i;
2235 fptr[5] = 0x20 * nblk;
2238 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2239 pptr = fptr2 = fptr;
2240 for(j=2; j<=nblk; j++) {
2242 for(i++; i<16; i++) {
2245 memset(fptr2, 0, 128);
2246 fptr2[0] = j < nblk ? 0x52 : 0x53;
2249 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2254 /* shouldn't this return ENOSPC if i == 16? */
2256 pptr[8] = pptr[9] = 0xff;
2257 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2259 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2261 /* just go ahead and resave them all */
2262 SaveMcd(cfg, ptr, 128, 128 * 15);
2265 /* shouldn't this return ENOSPC if i == 16? */
2270 * int open(char *name , int mode);
2273 void psxBios_open() { // 0x32
2277 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2282 if (pa0 != INVALID_PTR) {
2283 if (!strncmp(pa0, "bu00", 4)) {
2284 buopen(1, Mcd1Data, Config.Mcd1);
2287 if (!strncmp(pa0, "bu10", 4)) {
2288 buopen(2, Mcd2Data, Config.Mcd2);
2296 * int lseek(int fd , int offset , int whence);
2299 void psxBios_lseek() { // 0x33
2301 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2306 FDesc[a0].offset = a1;
2308 // DeliverEvent(0xf0000011, 0x0004);
2309 // DeliverEvent(0xf4000001, 0x0004);
2313 FDesc[a0].offset+= a1;
2314 v0 = FDesc[a0].offset;
2323 * int read(int fd , void *buf , int nbytes);
2326 void psxBios_read() { // 0x34
2331 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2336 if (pa1 != INVALID_PTR) {
2338 case 2: buread(pa1, 1, a2); break;
2339 case 3: buread(pa1, 2, a2); break;
2347 * int write(int fd , void *buf , int nbytes);
2350 void psxBios_write() { // 0x35/0x03
2354 if (a0 != 1) // stdout
2355 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2358 if (pa1 == INVALID_PTR) {
2363 if (a0 == 1) { // stdout
2367 if (Config.PsxOut) while (a2 > 0) {
2368 SysPrintf("%c", *ptr++); a2--;
2374 case 2: buwrite(pa1, 1, a2); break;
2375 case 3: buwrite(pa1, 2, a2); break;
2381 static void psxBios_write_psxout() {
2382 if (a0 == 1) { // stdout
2383 const char *ptr = Ra1;
2386 if (ptr != INVALID_PTR)
2388 SysPrintf("%c", *ptr++);
2392 static void psxBios_putchar_psxout() { // 3d
2393 SysPrintf("%c", (char)a0);
2396 static void psxBios_puts_psxout() { // 3e/3f
2397 SysPrintf("%s", Ra0);
2401 * int close(int fd);
2404 void psxBios_close() { // 0x36
2406 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2413 void psxBios_putchar() { // 3d
2414 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2418 void psxBios_puts() { // 3e/3f
2419 if (Config.PsxOut) SysPrintf("%s", Ra0);
2424 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2425 * We want to mimic the PSX's behaviour in this case for bufile. */
2426 static size_t strlen_internal(char* p)
2428 size_t size_of_array = 0;
2429 while (*p++) size_of_array++;
2430 return size_of_array;
2433 #define bufile(mcd) { \
2434 size_t size_of_name = strlen_internal(dir->name); \
2435 while (nfile < 16) { \
2438 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2440 if ((*ptr & 0xF0) != 0x50) continue; \
2441 /* Bug link files show up as free block. */ \
2442 if (!ptr[0xa]) continue; \
2444 if (pfile[0] == 0) { \
2445 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2446 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2447 } else for (i=0; i<20; i++) { \
2448 if (pfile[i] == ptr[i]) { \
2449 dir->name[i] = ptr[i]; continue; } \
2450 if (pfile[i] == '?') { \
2451 dir->name[i] = ptr[i]; continue; } \
2452 if (pfile[i] == '*') { \
2453 strcpy(dir->name+i, ptr+i); break; } \
2456 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2457 if (match == 0) { continue; } \
2465 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2468 void psxBios_firstfile() { // 42
2469 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2476 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2481 if (pa0 != INVALID_PTR) {
2485 if (!strncmp(pa0, "bu00", 4)) {
2486 // firstfile() calls _card_read() internally, so deliver it's event
2487 DeliverEvent(0xf0000011, 0x0004);
2489 } else if (!strncmp(pa0, "bu10", 4)) {
2490 // firstfile() calls _card_read() internally, so deliver it's event
2491 DeliverEvent(0xf0000011, 0x0004);
2500 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2503 void psxBios_nextfile() { // 43
2504 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2510 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2515 if (!strncmp(ffile, "bu00", 4)) {
2519 if (!strncmp(ffile, "bu10", 4)) {
2526 #define burename(mcd) { \
2527 for (i=1; i<16; i++) { \
2528 int namelen, j, xor = 0; \
2529 ptr = Mcd##mcd##Data + 128 * i; \
2530 if ((*ptr & 0xF0) != 0x50) continue; \
2531 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2532 namelen = strlen(Ra1+5); \
2533 memcpy(ptr+0xa, Ra1+5, namelen); \
2534 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2535 for (j=0; j<127; j++) xor^= ptr[j]; \
2537 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2544 * int rename(char *old, char *new);
2547 void psxBios_rename() { // 44
2554 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2559 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2560 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2564 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2573 #define budelete(mcd) { \
2574 for (i=1; i<16; i++) { \
2575 ptr = Mcd##mcd##Data + 128 * i; \
2576 if ((*ptr & 0xF0) != 0x50) continue; \
2577 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2578 *ptr = (*ptr & 0xf) | 0xA0; \
2579 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2580 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2587 * int delete(char *name);
2590 void psxBios_delete() { // 45
2596 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2601 if (pa0 != INVALID_PTR) {
2602 if (!strncmp(pa0, "bu00", 4)) {
2606 if (!strncmp(pa0, "bu10", 4)) {
2614 void psxBios_InitCARD() { // 4a
2615 u32 *ram32 = (u32 *)psxM;
2616 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2617 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2618 // (maybe) todo: early_card_irq, FlushCache etc
2620 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2622 mips_return_c(0, 300);
2625 void psxBios_StartCARD() { // 4b
2626 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2627 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2628 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2630 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2631 storeRam32(A_PAD_ACK_VBL, 1);
2632 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2633 storeRam32(A_CARD_IRQR_ENA, 1);
2634 psxRegs.CP0.n.SR |= 0x401;
2636 mips_return_c(1, 200);
2639 void psxBios_StopCARD() { // 4c
2640 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2641 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2642 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2643 storeRam32(A_CARD_IRQR_ENA, 0);
2644 psxRegs.CP0.n.SR |= 0x401;
2645 mips_return_void_c(200);
2648 void psxBios__card_write() { // 0x4e
2653 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2656 Function also accepts sector 400h (a bug).
2657 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2661 /* Invalid sectors */
2665 storeRam32(A_CARD_CHAN1, a0);
2668 if (pa2 != INVALID_PTR) {
2670 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2671 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2673 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2674 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2678 DeliverEvent(0xf0000011, 0x0004);
2679 // DeliverEvent(0xf4000001, 0x0004);
2684 void psxBios__card_read() { // 0x4f
2689 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2692 Function also accepts sector 400h (a bug).
2693 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2697 /* Invalid sectors */
2701 storeRam32(A_CARD_CHAN1, a0);
2704 if (pa2 != INVALID_PTR) {
2706 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2708 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2712 DeliverEvent(0xf0000011, 0x0004);
2713 // DeliverEvent(0xf4000001, 0x0004);
2718 void psxBios__new_card() { // 0x50
2720 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2726 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2727 void psxBios__get_error(void) // 55
2729 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2734 void psxBios_Krom2RawAdd() { // 0x51
2737 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2738 const u32 table_8140[][2] = {
2739 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2740 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2741 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2742 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2743 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2744 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2745 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2746 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2747 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2751 const u32 table_889f[][2] = {
2752 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2753 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2754 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2755 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2756 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2757 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2758 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2759 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2763 if (a0 >= 0x8140 && a0 <= 0x84be) {
2764 while (table_8140[i][0] <= a0) i++;
2765 a0 -= table_8140[i - 1][0];
2766 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2767 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2768 while (table_889f[i][0] <= a0) i++;
2769 a0 -= table_889f[i - 1][0];
2770 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2778 void psxBios_GetC0Table() { // 56
2779 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2780 log_unhandled("GetC0Table @%08x\n", ra);
2782 mips_return_c(A_C0_TABLE, 3);
2785 void psxBios_GetB0Table() { // 57
2786 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2787 log_unhandled("GetB0Table @%08x\n", ra);
2789 mips_return_c(A_B0_TABLE, 3);
2792 static void psxBios__card_chan() { // 0x58
2794 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2796 // todo: should return active slot chan
2797 // (active - which was last processed by irq code)
2798 ret = loadRam32(A_CARD_CHAN1);
2799 mips_return_c(ret, 8);
2802 static void psxBios_ChangeClearPad() { // 5b
2804 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2805 ret = loadRam32(A_PAD_ACK_VBL);
2806 storeRam32(A_PAD_ACK_VBL, a0);
2808 mips_return_c(ret, 6);
2811 static void psxBios__card_status() { // 5c
2812 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2818 static void psxBios__card_wait() { // 5d
2819 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2825 /* System calls C0 */
2827 static void psxBios_InitRCnt() { // 00
2829 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2830 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2831 for (i = 0; i < 3; i++) {
2832 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2833 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2834 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2836 psxBios_SysEnqIntRP_(a0, 0x6d88);
2837 mips_return_c(0, 9);
2840 static void psxBios_InitException() { // 01
2841 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2842 psxBios_SysEnqIntRP_(a0, 0x6da8);
2843 mips_return_c(0, 9);
2847 * int SysEnqIntRP(int index , long *queue);
2850 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2851 u32 old, base = loadRam32(A_TT_ExCB);
2853 old = loadRam32(base + (priority << 3));
2854 storeRam32(base + (priority << 3), chain_eptr);
2855 storeRam32(chain_eptr, old);
2856 mips_return_c(0, 9);
2859 static void psxBios_SysEnqIntRP() { // 02
2860 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2861 psxBios_SysEnqIntRP_(a0, a1);
2865 * int SysDeqIntRP(int index , long *queue);
2868 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2869 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2870 u32 lim = 0, ret = 0;
2872 // as in original: no arg checks of any kind, bug if a1 == 0
2873 ptr = loadRam32(base + (priority << 3));
2875 next = loadRam32(ptr);
2876 if (ptr == chain_rm_eptr) {
2877 storeRam32(base + (priority << 3), next);
2882 while (next && next != chain_rm_eptr && lim++ < 100) {
2884 next = loadRam32(ptr);
2887 if (next == chain_rm_eptr) {
2888 next = loadRam32(next);
2889 storeRam32(ptr, next);
2896 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2898 mips_return_c(ret, 12);
2901 static void psxBios_SysDeqIntRP() { // 03
2902 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2903 psxBios_SysDeqIntRP_(a0, a1);
2906 static void psxBios_get_free_EvCB_slot() { // 04
2907 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
2908 s32 ret = get_free_EvCB_slot();
2909 mips_return_c(ret, 0);
2912 static void psxBios_SysInitMemory_(u32 base, u32 size) {
2913 storeRam32(base, 0);
2914 storeRam32(A_KMALLOC_PTR, base);
2915 storeRam32(A_KMALLOC_SIZE, size);
2916 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2919 // this should be much more complicated, but maybe that'll be enough
2920 static u32 psxBios_SysMalloc_(u32 size) {
2921 u32 ptr = loadRam32(A_KMALLOC_PTR);
2923 size = (size + 3) & ~3;
2924 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2925 storeRam32(ptr, size);
2929 static void psxBios_SysInitMemory() { // 08
2930 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2932 psxBios_SysInitMemory_(a0, a1);
2933 mips_return_void_c(12);
2936 static void psxBios_ChangeClearRCnt() { // 0a
2939 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2941 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
2942 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
2943 mips_return_c(ret, 8);
2946 static void psxBios_InitDefInt() { // 0c
2947 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
2948 // should also clear the autoack table
2949 psxBios_SysEnqIntRP_(a0, 0x6d98);
2950 mips_return_c(0, 20 + 6*2);
2953 void psxBios_dummy() {
2954 u32 pc = (pc0 & 0x1fffff) - 4;
2955 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
2956 : pc == 0xc0 ? biosC0n : NULL;
2957 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
2958 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
2959 (void)pc; (void)ntab;
2960 mips_return_c(0, 100);
2963 void (*biosA0[256])();
2964 // C0 and B0 overlap (end of C0 is start of B0)
2965 void (*biosC0[256+128])();
2966 void (**biosB0)() = biosC0 + 128;
2968 static void setup_mips_code()
2971 ptr = (u32 *)&psxM[A_SYSCALL];
2972 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
2973 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
2974 ptr[0x08/4] = SWAPu32(0x00000000); // nop
2976 ptr = (u32 *)&psxM[A_EXCEPTION];
2977 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
2978 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
2979 ptr[0x14/4] = SWAPu32(0x00000000); // nop
2980 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
2981 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
2982 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
2983 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
2984 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
2985 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
2986 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
2988 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
2989 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
2990 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
2992 ptr[0xb0/4] = HLEOP(hleop_exception);
2995 static const struct {
2999 { 0xbfc050a4, hleop_exc0_0_1 },
3000 { 0xbfc04fbc, hleop_exc0_0_2 },
3001 { 0xbfc0506c, hleop_exc0_1_1 },
3002 { 0xbfc04dec, hleop_exc0_1_2 },
3003 { 0x1a00, hleop_exc0_2_2 },
3004 { 0x19c8, hleop_exc1_0_1 },
3005 { 0x18bc, hleop_exc1_0_2 },
3006 { 0x1990, hleop_exc1_1_1 },
3007 { 0x1858, hleop_exc1_1_2 },
3008 { 0x1958, hleop_exc1_2_1 },
3009 { 0x17f4, hleop_exc1_2_2 },
3010 { 0x1920, hleop_exc1_3_1 },
3011 { 0x1794, hleop_exc1_3_2 },
3012 { 0x2458, hleop_exc3_0_2 },
3013 { 0x49bc, hleop_exc_padcard1 },
3014 { 0x4a4c, hleop_exc_padcard2 },
3017 static int chain_hle_op(u32 handler)
3021 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3022 if (chainfns[i].addr == handler)
3023 return chainfns[i].op;
3027 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3029 d[0] = SWAPu32(next);
3030 d[1] = SWAPu32(handler1);
3031 d[2] = SWAPu32(handler2);
3033 // install the hle traps
3034 PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3035 PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3038 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
3040 u32 *ram32 = (u32 *)psxM;
3041 u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
3042 u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
3043 u32 p_excb, p_evcb, p_pcb, p_tcb;
3045 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3046 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3047 p_excb = psxBios_SysMalloc_(s_excb);
3048 p_evcb = psxBios_SysMalloc_(s_evcb);
3049 p_pcb = psxBios_SysMalloc_(s_pcb);
3050 p_tcb = psxBios_SysMalloc_(s_tcb);
3052 // "table of tables". Some games modify it
3053 assert(A_TT_ExCB == 0x0100);
3054 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3055 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3056 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3057 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3058 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3059 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3060 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3061 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3062 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3063 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3064 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3065 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3067 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3068 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3069 storeRam32(p_excb + 4*4, 0x0000); // chain2
3070 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3072 storeRam32(p_pcb, p_tcb);
3073 storeRam32(p_tcb, 0x4000); // first TCB
3076 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3077 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3078 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3079 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3080 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3081 DeliverEvent(0xf0000003, 0x0010);
3084 static const u32 gpu_ctl_def[] = {
3085 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3086 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3089 static const u32 gpu_data_def[] = {
3090 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3091 0xe5001000, 0xe6000000,
3092 0x02000000, 0x00000000, 0x01ff03ff
3096 static const u16 spu_config[] = {
3097 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3098 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3099 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3100 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3101 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3102 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3103 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3104 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3107 void psxBiosSetupBootState(void)
3109 boolean hle = Config.HLE;
3110 u32 *hw = (u32 *)psxH;
3113 // see also SetBootRegs()
3116 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3117 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3119 k0 = 0xbfc0d968; k1 = 0xf1c;
3120 ra = 0xf0001234; // just to easily detect attempts to return
3121 psxRegs.CP0.n.Cause = 0x20;
3122 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3124 hw[0x1000/4] = SWAP32(0x1f000000);
3125 hw[0x1004/4] = SWAP32(0x1f802000);
3126 hw[0x1008/4] = SWAP32(0x0013243f);
3127 hw[0x100c/4] = SWAP32(0x00003022);
3128 hw[0x1010/4] = SWAP32(0x0013243f);
3129 hw[0x1014/4] = SWAP32(0x200931e1);
3130 hw[0x1018/4] = SWAP32(0x00020943);
3131 hw[0x101c/4] = SWAP32(0x00070777);
3132 hw[0x1020/4] = SWAP32(0x0000132c);
3133 hw[0x1060/4] = SWAP32(0x00000b88);
3134 hw[0x1070/4] = SWAP32(0x00000001);
3135 hw[0x1074/4] = SWAP32(0x0000000c);
3136 hw[0x2040/4] = SWAP32(0x00000900);
3139 hw[0x10a0/4] = SWAP32(0x00ffffff);
3140 hw[0x10a8/4] = SWAP32(0x00000401);
3141 hw[0x10b0/4] = SWAP32(0x0008b000);
3142 hw[0x10b4/4] = SWAP32(0x00010200);
3143 hw[0x10e0/4] = SWAP32(0x000eccf4);
3144 hw[0x10e4/4] = SWAP32(0x00000400);
3145 hw[0x10e8/4] = SWAP32(0x00000002);
3146 hw[0x10f0/4] = SWAP32(0x00009099);
3147 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3156 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3157 GPU_writeStatus(gpu_ctl_def[i]);
3158 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3159 GPU_writeData(gpu_data_def[i]);
3160 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3163 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3164 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3167 #include "sjisfont.h"
3169 void psxBiosInit() {
3170 u32 *ptr, *ram32, *rom32;
3174 memset(psxM, 0, 0x10000);
3175 for(i = 0; i < 256; i++) {
3180 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3181 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3182 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3183 biosA0[0x3f] = psxBios_printf_psxout;
3185 if (!Config.HLE) return;
3187 for(i = 0; i < 256; i++) {
3188 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3189 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3190 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3193 biosA0[0x00] = psxBios_open;
3194 biosA0[0x01] = psxBios_lseek;
3195 biosA0[0x02] = psxBios_read;
3196 biosA0[0x03] = psxBios_write;
3197 biosA0[0x04] = psxBios_close;
3198 //biosA0[0x05] = psxBios_ioctl;
3199 //biosA0[0x06] = psxBios_exit;
3200 //biosA0[0x07] = psxBios_sys_a0_07;
3201 biosA0[0x08] = psxBios_getc;
3202 biosA0[0x09] = psxBios_putc;
3203 biosA0[0x0a] = psxBios_todigit;
3204 //biosA0[0x0b] = psxBios_atof;
3205 //biosA0[0x0c] = psxBios_strtoul;
3206 //biosA0[0x0d] = psxBios_strtol;
3207 biosA0[0x0e] = psxBios_abs;
3208 biosA0[0x0f] = psxBios_labs;
3209 biosA0[0x10] = psxBios_atoi;
3210 biosA0[0x11] = psxBios_atol;
3211 //biosA0[0x12] = psxBios_atob;
3212 biosA0[0x13] = psxBios_setjmp;
3213 biosA0[0x14] = psxBios_longjmp;
3214 biosA0[0x15] = psxBios_strcat;
3215 biosA0[0x16] = psxBios_strncat;
3216 biosA0[0x17] = psxBios_strcmp;
3217 biosA0[0x18] = psxBios_strncmp;
3218 biosA0[0x19] = psxBios_strcpy;
3219 biosA0[0x1a] = psxBios_strncpy;
3220 biosA0[0x1b] = psxBios_strlen;
3221 biosA0[0x1c] = psxBios_index;
3222 biosA0[0x1d] = psxBios_rindex;
3223 biosA0[0x1e] = psxBios_strchr;
3224 biosA0[0x1f] = psxBios_strrchr;
3225 biosA0[0x20] = psxBios_strpbrk;
3226 biosA0[0x21] = psxBios_strspn;
3227 biosA0[0x22] = psxBios_strcspn;
3228 biosA0[0x23] = psxBios_strtok;
3229 biosA0[0x24] = psxBios_strstr;
3230 biosA0[0x25] = psxBios_toupper;
3231 biosA0[0x26] = psxBios_tolower;
3232 biosA0[0x27] = psxBios_bcopy;
3233 biosA0[0x28] = psxBios_bzero;
3234 biosA0[0x29] = psxBios_bcmp;
3235 biosA0[0x2a] = psxBios_memcpy;
3236 biosA0[0x2b] = psxBios_memset;
3237 biosA0[0x2c] = psxBios_memmove;
3238 biosA0[0x2d] = psxBios_memcmp;
3239 biosA0[0x2e] = psxBios_memchr;
3240 biosA0[0x2f] = psxBios_rand;
3241 biosA0[0x30] = psxBios_srand;
3242 biosA0[0x31] = psxBios_qsort;
3243 //biosA0[0x32] = psxBios_strtod;
3244 biosA0[0x33] = psxBios_malloc;
3245 biosA0[0x34] = psxBios_free;
3246 //biosA0[0x35] = psxBios_lsearch;
3247 //biosA0[0x36] = psxBios_bsearch;
3248 biosA0[0x37] = psxBios_calloc;
3249 biosA0[0x38] = psxBios_realloc;
3250 biosA0[0x39] = psxBios_InitHeap;
3251 //biosA0[0x3a] = psxBios__exit;
3252 biosA0[0x3b] = psxBios_getchar;
3253 biosA0[0x3c] = psxBios_putchar;
3254 //biosA0[0x3d] = psxBios_gets;
3255 biosA0[0x3e] = psxBios_puts;
3256 biosA0[0x3f] = psxBios_printf;
3257 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3258 //biosA0[0x41] = psxBios_LoadTest;
3259 biosA0[0x42] = psxBios_Load;
3260 biosA0[0x43] = psxBios_Exec;
3261 biosA0[0x44] = psxBios_FlushCache;
3262 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3263 biosA0[0x46] = psxBios_GPU_dw;
3264 biosA0[0x47] = psxBios_mem2vram;
3265 biosA0[0x48] = psxBios_SendGPU;
3266 biosA0[0x49] = psxBios_GPU_cw;
3267 biosA0[0x4a] = psxBios_GPU_cwb;
3268 biosA0[0x4b] = psxBios_GPU_SendPackets;
3269 biosA0[0x4c] = psxBios_sys_a0_4c;
3270 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3271 //biosA0[0x4e] = psxBios_GPU_sync;
3272 //biosA0[0x4f] = psxBios_sys_a0_4f;
3273 //biosA0[0x50] = psxBios_sys_a0_50;
3274 biosA0[0x51] = psxBios_LoadExec;
3275 //biosA0[0x52] = psxBios_GetSysSp;
3276 //biosA0[0x53] = psxBios_sys_a0_53;
3277 //biosA0[0x54] = psxBios__96_init_a54;
3278 //biosA0[0x55] = psxBios__bu_init_a55;
3279 biosA0[0x56] = psxBios_CdRemove;
3280 //biosA0[0x57] = psxBios_sys_a0_57;
3281 //biosA0[0x58] = psxBios_sys_a0_58;
3282 //biosA0[0x59] = psxBios_sys_a0_59;
3283 //biosA0[0x5a] = psxBios_sys_a0_5a;
3284 //biosA0[0x5b] = psxBios_dev_tty_init;
3285 //biosA0[0x5c] = psxBios_dev_tty_open;
3286 //biosA0[0x5d] = psxBios_sys_a0_5d;
3287 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3288 //biosA0[0x5f] = psxBios_dev_cd_open;
3289 //biosA0[0x60] = psxBios_dev_cd_read;
3290 //biosA0[0x61] = psxBios_dev_cd_close;
3291 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3292 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3293 //biosA0[0x64] = psxBios_dev_cd_chdir;
3294 //biosA0[0x65] = psxBios_dev_card_open;
3295 //biosA0[0x66] = psxBios_dev_card_read;
3296 //biosA0[0x67] = psxBios_dev_card_write;
3297 //biosA0[0x68] = psxBios_dev_card_close;
3298 //biosA0[0x69] = psxBios_dev_card_firstfile;
3299 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3300 //biosA0[0x6b] = psxBios_dev_card_erase;
3301 //biosA0[0x6c] = psxBios_dev_card_undelete;
3302 //biosA0[0x6d] = psxBios_dev_card_format;
3303 //biosA0[0x6e] = psxBios_dev_card_rename;
3304 //biosA0[0x6f] = psxBios_dev_card_6f;
3305 biosA0[0x70] = psxBios__bu_init;
3306 biosA0[0x71] = psxBios__96_init;
3307 biosA0[0x72] = psxBios_CdRemove;
3308 //biosA0[0x73] = psxBios_sys_a0_73;
3309 //biosA0[0x74] = psxBios_sys_a0_74;
3310 //biosA0[0x75] = psxBios_sys_a0_75;
3311 //biosA0[0x76] = psxBios_sys_a0_76;
3312 //biosA0[0x77] = psxBios_sys_a0_77;
3313 //biosA0[0x78] = psxBios__96_CdSeekL;
3314 //biosA0[0x79] = psxBios_sys_a0_79;
3315 //biosA0[0x7a] = psxBios_sys_a0_7a;
3316 //biosA0[0x7b] = psxBios_sys_a0_7b;
3317 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3318 //biosA0[0x7d] = psxBios_sys_a0_7d;
3319 //biosA0[0x7e] = psxBios__96_CdRead;
3320 //biosA0[0x7f] = psxBios_sys_a0_7f;
3321 //biosA0[0x80] = psxBios_sys_a0_80;
3322 //biosA0[0x81] = psxBios_sys_a0_81;
3323 //biosA0[0x82] = psxBios_sys_a0_82;
3324 //biosA0[0x83] = psxBios_sys_a0_83;
3325 //biosA0[0x84] = psxBios_sys_a0_84;
3326 //biosA0[0x85] = psxBios__96_CdStop;
3327 //biosA0[0x86] = psxBios_sys_a0_86;
3328 //biosA0[0x87] = psxBios_sys_a0_87;
3329 //biosA0[0x88] = psxBios_sys_a0_88;
3330 //biosA0[0x89] = psxBios_sys_a0_89;
3331 //biosA0[0x8a] = psxBios_sys_a0_8a;
3332 //biosA0[0x8b] = psxBios_sys_a0_8b;
3333 //biosA0[0x8c] = psxBios_sys_a0_8c;
3334 //biosA0[0x8d] = psxBios_sys_a0_8d;
3335 //biosA0[0x8e] = psxBios_sys_a0_8e;
3336 //biosA0[0x8f] = psxBios_sys_a0_8f;
3337 biosA0[0x90] = hleExc0_1_2;
3338 biosA0[0x91] = hleExc0_0_2;
3339 biosA0[0x92] = hleExc0_1_1;
3340 biosA0[0x93] = hleExc0_0_1;
3341 //biosA0[0x94] = psxBios_sys_a0_94;
3342 //biosA0[0x95] = psxBios_sys_a0_95;
3343 //biosA0[0x96] = psxBios_AddCDROMDevice;
3344 //biosA0[0x97] = psxBios_AddMemCardDevide;
3345 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3346 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3347 //biosA0[0x9a] = psxBios_sys_a0_9a;
3348 //biosA0[0x9b] = psxBios_sys_a0_9b;
3349 //biosA0[0x9c] = psxBios_SetConf;
3350 //biosA0[0x9d] = psxBios_GetConf;
3351 //biosA0[0x9e] = psxBios_sys_a0_9e;
3352 biosA0[0x9f] = psxBios_SetMem;
3353 //biosA0[0xa0] = psxBios__boot;
3354 //biosA0[0xa1] = psxBios_SystemError;
3355 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3356 biosA0[0xa3] = psxBios_DequeueCdIntr;
3357 //biosA0[0xa4] = psxBios_sys_a0_a4;
3358 //biosA0[0xa5] = psxBios_ReadSector;
3359 biosA0[0xa6] = psxBios_get_cd_status;
3360 //biosA0[0xa7] = psxBios_bufs_cb_0;
3361 //biosA0[0xa8] = psxBios_bufs_cb_1;
3362 //biosA0[0xa9] = psxBios_bufs_cb_2;
3363 //biosA0[0xaa] = psxBios_bufs_cb_3;
3364 biosA0[0xab] = psxBios__card_info;
3365 biosA0[0xac] = psxBios__card_load;
3366 //biosA0[0axd] = psxBios__card_auto;
3367 //biosA0[0xae] = psxBios_bufs_cd_4;
3368 //biosA0[0xaf] = psxBios_sys_a0_af;
3369 //biosA0[0xb0] = psxBios_sys_a0_b0;
3370 //biosA0[0xb1] = psxBios_sys_a0_b1;
3371 //biosA0[0xb2] = psxBios_do_a_long_jmp
3372 //biosA0[0xb3] = psxBios_sys_a0_b3;
3373 biosA0[0xb4] = psxBios_GetSystemInfo;
3374 //*******************B0 CALLS****************************
3375 biosB0[0x00] = psxBios_SysMalloc;
3376 //biosB0[0x01] = psxBios_sys_b0_01;
3377 biosB0[0x02] = psxBios_SetRCnt;
3378 biosB0[0x03] = psxBios_GetRCnt;
3379 biosB0[0x04] = psxBios_StartRCnt;
3380 biosB0[0x05] = psxBios_StopRCnt;
3381 biosB0[0x06] = psxBios_ResetRCnt;
3382 biosB0[0x07] = psxBios_DeliverEvent;
3383 biosB0[0x08] = psxBios_OpenEvent;
3384 biosB0[0x09] = psxBios_CloseEvent;
3385 biosB0[0x0a] = psxBios_WaitEvent;
3386 biosB0[0x0b] = psxBios_TestEvent;
3387 biosB0[0x0c] = psxBios_EnableEvent;
3388 biosB0[0x0d] = psxBios_DisableEvent;
3389 biosB0[0x0e] = psxBios_OpenTh;
3390 biosB0[0x0f] = psxBios_CloseTh;
3391 biosB0[0x10] = psxBios_ChangeTh;
3392 //biosB0[0x11] = psxBios_psxBios_b0_11;
3393 biosB0[0x12] = psxBios_InitPAD;
3394 biosB0[0x13] = psxBios_StartPAD;
3395 biosB0[0x14] = psxBios_StopPAD;
3396 biosB0[0x15] = psxBios_PAD_init;
3397 biosB0[0x16] = psxBios_PAD_dr;
3398 biosB0[0x17] = psxBios_ReturnFromException;
3399 biosB0[0x18] = psxBios_ResetEntryInt;
3400 biosB0[0x19] = psxBios_HookEntryInt;
3401 //biosB0[0x1a] = psxBios_sys_b0_1a;
3402 //biosB0[0x1b] = psxBios_sys_b0_1b;
3403 //biosB0[0x1c] = psxBios_sys_b0_1c;
3404 //biosB0[0x1d] = psxBios_sys_b0_1d;
3405 //biosB0[0x1e] = psxBios_sys_b0_1e;
3406 //biosB0[0x1f] = psxBios_sys_b0_1f;
3407 biosB0[0x20] = psxBios_UnDeliverEvent;
3408 //biosB0[0x21] = psxBios_sys_b0_21;
3409 //biosB0[0x22] = psxBios_sys_b0_22;
3410 //biosB0[0x23] = psxBios_sys_b0_23;
3411 //biosB0[0x24] = psxBios_sys_b0_24;
3412 //biosB0[0x25] = psxBios_sys_b0_25;
3413 //biosB0[0x26] = psxBios_sys_b0_26;
3414 //biosB0[0x27] = psxBios_sys_b0_27;
3415 //biosB0[0x28] = psxBios_sys_b0_28;
3416 //biosB0[0x29] = psxBios_sys_b0_29;
3417 //biosB0[0x2a] = psxBios_sys_b0_2a;
3418 //biosB0[0x2b] = psxBios_sys_b0_2b;
3419 //biosB0[0x2c] = psxBios_sys_b0_2c;
3420 //biosB0[0x2d] = psxBios_sys_b0_2d;
3421 //biosB0[0x2e] = psxBios_sys_b0_2e;
3422 //biosB0[0x2f] = psxBios_sys_b0_2f;
3423 //biosB0[0x30] = psxBios_sys_b0_30;
3424 //biosB0[0x31] = psxBios_sys_b0_31;
3425 biosB0[0x32] = psxBios_open;
3426 biosB0[0x33] = psxBios_lseek;
3427 biosB0[0x34] = psxBios_read;
3428 biosB0[0x35] = psxBios_write;
3429 biosB0[0x36] = psxBios_close;
3430 //biosB0[0x37] = psxBios_ioctl;
3431 //biosB0[0x38] = psxBios_exit;
3432 //biosB0[0x39] = psxBios_sys_b0_39;
3433 //biosB0[0x3a] = psxBios_getc;
3434 //biosB0[0x3b] = psxBios_putc;
3435 biosB0[0x3c] = psxBios_getchar;
3436 biosB0[0x3d] = psxBios_putchar;
3437 //biosB0[0x3e] = psxBios_gets;
3438 biosB0[0x3f] = psxBios_puts;
3439 //biosB0[0x40] = psxBios_cd;
3440 biosB0[0x41] = psxBios_format;
3441 biosB0[0x42] = psxBios_firstfile;
3442 biosB0[0x43] = psxBios_nextfile;
3443 biosB0[0x44] = psxBios_rename;
3444 biosB0[0x45] = psxBios_delete;
3445 //biosB0[0x46] = psxBios_undelete;
3446 //biosB0[0x47] = psxBios_AddDevice;
3447 //biosB0[0x48] = psxBios_RemoteDevice;
3448 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3449 biosB0[0x4a] = psxBios_InitCARD;
3450 biosB0[0x4b] = psxBios_StartCARD;
3451 biosB0[0x4c] = psxBios_StopCARD;
3452 //biosB0[0x4d] = psxBios_sys_b0_4d;
3453 biosB0[0x4e] = psxBios__card_write;
3454 biosB0[0x4f] = psxBios__card_read;
3455 biosB0[0x50] = psxBios__new_card;
3456 biosB0[0x51] = psxBios_Krom2RawAdd;
3457 //biosB0[0x52] = psxBios_sys_b0_52;
3458 //biosB0[0x53] = psxBios_sys_b0_53;
3459 //biosB0[0x54] = psxBios__get_errno;
3460 biosB0[0x55] = psxBios__get_error;
3461 biosB0[0x56] = psxBios_GetC0Table;
3462 biosB0[0x57] = psxBios_GetB0Table;
3463 biosB0[0x58] = psxBios__card_chan;
3464 //biosB0[0x59] = psxBios_sys_b0_59;
3465 //biosB0[0x5a] = psxBios_sys_b0_5a;
3466 biosB0[0x5b] = psxBios_ChangeClearPad;
3467 biosB0[0x5c] = psxBios__card_status;
3468 biosB0[0x5d] = psxBios__card_wait;
3469 //*******************C0 CALLS****************************
3470 biosC0[0x00] = psxBios_InitRCnt;
3471 biosC0[0x01] = psxBios_InitException;
3472 biosC0[0x02] = psxBios_SysEnqIntRP;
3473 biosC0[0x03] = psxBios_SysDeqIntRP;
3474 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3475 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3476 //biosC0[0x06] = psxBios_ExceptionHandler;
3477 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3478 biosC0[0x08] = psxBios_SysInitMemory;
3479 //biosC0[0x09] = psxBios_SysInitKMem;
3480 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3481 //biosC0[0x0b] = psxBios_SystemError;
3482 biosC0[0x0c] = psxBios_InitDefInt;
3483 //biosC0[0x0d] = psxBios_sys_c0_0d;
3484 //biosC0[0x0e] = psxBios_sys_c0_0e;
3485 //biosC0[0x0f] = psxBios_sys_c0_0f;
3486 //biosC0[0x10] = psxBios_sys_c0_10;
3487 //biosC0[0x11] = psxBios_sys_c0_11;
3488 //biosC0[0x12] = psxBios_InstallDevices;
3489 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3490 //biosC0[0x14] = psxBios_sys_c0_14;
3491 //biosC0[0x15] = psxBios__cdevinput;
3492 //biosC0[0x16] = psxBios__cdevscan;
3493 //biosC0[0x17] = psxBios__circgetc;
3494 //biosC0[0x18] = psxBios__circputc;
3495 //biosC0[0x19] = psxBios_ioabort;
3496 //biosC0[0x1a] = psxBios_sys_c0_1a
3497 //biosC0[0x1b] = psxBios_KernelRedirect;
3498 //biosC0[0x1c] = psxBios_PatchAOTable;
3499 //************** THE END ***************************************
3502 memset(FDesc, 0, sizeof(FDesc));
3505 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3507 // somewhat pretend to be a SCPH1001 BIOS
3508 // some games look for these and take an exception if they're missing
3509 rom32 = (u32 *)psxR;
3510 rom32[0x100/4] = SWAP32(0x19951204);
3511 rom32[0x104/4] = SWAP32(3);
3512 strcpy(psxR + 0x108, "PCSX authors");
3513 strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3514 strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3515 strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
3518 len = 0x80000 - 0x66000;
3519 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3520 len = 0x80000 - 0x69d68;
3521 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3523 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3524 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3525 Here are some examples of games not working with this fix in place :
3526 R-type won't get past the Irem logo if not implemented.
3527 Crash Team Racing will softlock after the Sony logo.
3530 ram32 = (u32 *)psxM;
3531 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3532 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3533 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3534 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3536 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3537 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3539 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3540 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3541 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3542 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3544 ram32[0x00a0/4] = HLEOP(hleop_a0);
3545 ram32[0x00b0/4] = HLEOP(hleop_b0);
3546 ram32[0x00c0/4] = HLEOP(hleop_c0);
3550 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3551 strcpy((char *)&ram32[0xeff0/4], "bu");
3553 // default exception handler chains
3554 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3555 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3556 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3557 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3558 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3559 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3560 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3561 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3565 // fill the api jumptables with fake entries as some games patch them
3566 // (or rather the funcs listed there)
3567 ptr = (u32 *)&psxM[A_A0_TABLE];
3568 for (i = 0; i < 256; i++)
3569 ptr[i] = SWAP32(0x1000);
3571 ptr = (u32 *)&psxM[A_B0_TABLE];
3572 for (i = 0; i < 256; i++)
3573 ptr[i] = SWAP32(0x2000);
3574 // B(5b) is special because games patch (sometimes even jump to)
3575 // code at fixed offsets from it, nocash lists offsets:
3576 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3577 // call: +7a0=4b70, +884=4c54, +894=4c64
3578 ptr[0x5b] = SWAP32(0x43d0);
3579 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3581 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3582 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3583 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3585 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3586 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3588 ptr = (u32 *)&psxM[A_C0_TABLE];
3589 for (i = 0; i < 256/2; i++)
3590 ptr[i] = SWAP32(0x3000);
3591 ptr[6] = SWAP32(A_EXCEPTION);
3594 ram32[0x1000/4] = HLEOP(hleop_dummy);
3595 ram32[0x2000/4] = HLEOP(hleop_dummy);
3596 ram32[0x3000/4] = HLEOP(hleop_dummy);
3597 ram32[0x4c54/4] = HLEOP(hleop_dummy); // for B12_InitPad?
3598 ram32[0x8000/4] = HLEOP(hleop_execret);
3600 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3601 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3602 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3603 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3604 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3605 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3608 void psxBiosShutdown() {
3611 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3612 if (tcb_cnt != 4 || evcb_cnt != 16)
3613 setup_tt(tcb_cnt, evcb_cnt);
3616 #define psxBios_PADpoll(pad) { \
3617 PAD##pad##_startPoll(pad); \
3618 pad_buf##pad[0] = 0; \
3619 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3620 if (!(pad_buf##pad[1] & 0x0f)) { \
3623 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3625 PAD##pad##_poll(0); \
3627 while (bufcount--) { \
3628 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3632 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3636 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3637 psxBios_ReturnFromException();
3643 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3644 // so this is only partially implemented
3645 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3647 u32 cdrom_dma_ack_enable = 1; // a000b93c
3648 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3651 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3654 //PSXBIOS_LOG("%s\n", __func__);
3656 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3657 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3658 //if (--cdrom_irq_counter == 0) // 0xa0009180
3659 // DeliverEvent(0xf0000003, 0x10);
3663 mips_return_c(ret, 20);
3666 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3668 u32 cdrom_irq_ack_enable = 1; // a000b938
3669 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3672 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3675 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3676 PSXBIOS_LOG("%s TODO\n", __func__);
3679 mips_return_c(ret, 20);
3682 void hleExc0_2_2_syscall() // not in any A/B/C table
3684 u32 code = (psxRegs.CP0.n.Cause & 0x3c) >> 2;
3685 u32 tcbPtr = loadRam32(A_TT_PCB);
3686 TCB *tcb = loadRam32ptr(tcbPtr);
3688 if (code != R3000E_Syscall) {
3690 DeliverEvent(0xf0000010, 0x1000);
3691 //psxBios_SystemErrorUnresolvedException();
3693 mips_return_c(0, 17);
3697 //printf("%s c=%d a0=%d\n", __func__, code, a0);
3698 tcb->epc += SWAP32(4);
3703 case 1: { // EnterCritical - disable irqs
3704 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3705 tcb->reg[2] = SWAP32(was_enabled);
3706 tcb->sr &= SWAP32(~0x404);
3709 case 2: // ExitCritical - enable irqs
3710 tcb->sr |= SWAP32(0x404);
3713 case 3: { // ChangeThreadSubFunction
3714 u32 tcbPtr = loadRam32(A_TT_PCB);
3715 storeRam32(tcbPtr, a1);
3719 DeliverEvent(0xf0000010, 0x4000);
3723 psxBios_ReturnFromException();
3726 void hleExc1_0_1(void)
3728 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3729 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3732 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3735 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3736 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3739 mips_return_c(ret, 22);
3742 void hleExc1_0_2(void)
3744 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3747 void hleExc1_1_1(void)
3749 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3750 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3753 void hleExc1_1_2(void)
3755 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3758 void hleExc1_2_1(void)
3760 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3761 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3764 void hleExc1_2_2(void)
3766 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3769 void hleExc1_3_1(void)
3771 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3772 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3775 void hleExc1_3_2(void)
3777 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3780 void hleExc3_0_2_defint(void)
3782 static const struct {
3793 { 6, 6 }, // rcnt2 (bug)
3798 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3799 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3800 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3805 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3808 void hleExcPadCard1(void)
3810 if (loadRam32(A_PAD_IRQR_ENA)) {
3811 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3812 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3818 if (loadRam32(A_PAD_DR_DST))
3821 if (loadRam32(A_PAD_ACK_VBL))
3822 psxHwWrite16(0x1f801070, ~1);
3823 if (loadRam32(A_CARD_IRQR_ENA)) {
3827 mips_return_c(0, 18);
3830 void hleExcPadCard2(void)
3832 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3833 mips_return_c(ret, 15);
3836 void psxBiosException() {
3837 u32 tcbPtr = loadRam32(A_TT_PCB);
3838 u32 *chains = loadRam32ptr(A_TT_ExCB);
3839 TCB *tcb = loadRam32ptr(tcbPtr);
3845 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3846 for (i = 4; i < 32; i++) {
3849 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3851 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3852 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3853 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3854 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3855 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3856 sp = fp = loadRam32(A_EXC_SP);
3860 // do the chains (always 4)
3861 for (c = lim = 0; c < 4; c++) {
3862 if (chains[c * 2] == 0)
3864 ptr = SWAP32(chains[c * 2]);
3865 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3866 chain = castRam32ptr(ptr);
3871 softCallInException(SWAP32(chain[2]));
3872 if (returned_from_exception())
3875 if (v0 == 0 || chain[1] == 0)
3877 softCallInException(SWAP32(chain[1]));
3878 if (returned_from_exception())
3884 // return from exception (custom or default)
3886 ptr = loadRam32(A_EEXIT_PTR);
3887 if (ptr != A_EEXIT_DEF) {
3888 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3889 longjmp_load(jmp_buf);
3894 psxBios_ReturnFromException();
3897 #define bfreeze(ptr, size) { \
3898 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3899 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3903 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3904 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3906 #define bfreezepsxMptr(ptr, type) { \
3908 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3909 else psxRu32ref(base) = 0; \
3911 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3912 else (ptr) = NULL; \
3914 base += sizeof(u32); \
3917 void psxBiosFreeze(int Mode) {