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.
40 #if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
41 #pragma GCC diagnostic ignored "-Wpointer-sign"
45 #define SysPrintf if (Config.PsxOut) printf
47 char *biosA0n[256] = {
49 "open", "lseek", "read", "write",
50 "close", "ioctl", "exit", "sys_a0_07",
51 "getc", "putc", "todigit", "atof",
52 "strtoul", "strtol", "abs", "labs",
54 "atoi", "atol", "atob", "setjmp",
55 "longjmp", "strcat", "strncat", "strcmp",
56 "strncmp", "strcpy", "strncpy", "strlen",
57 "index", "rindex", "strchr", "strrchr",
59 "strpbrk", "strspn", "strcspn", "strtok",
60 "strstr", "toupper", "tolower", "bcopy",
61 "bzero", "bcmp", "memcpy", "memset",
62 "memmove", "memcmp", "memchr", "rand",
64 "srand", "qsort", "strtod", "malloc",
65 "free", "lsearch", "bsearch", "calloc",
66 "realloc", "InitHeap", "_exit", "getchar",
67 "putchar", "gets", "puts", "printf",
69 "sys_a0_40", "LoadTest", "Load", "Exec",
70 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
71 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
72 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
74 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
75 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
76 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
77 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
79 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
80 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
81 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
82 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
84 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
85 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
86 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
87 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
89 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
90 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
91 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
92 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
94 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
95 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
96 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
97 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
99 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
100 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
101 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
102 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
104 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
108 char *biosB0n[256] = {
110 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
111 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
112 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
113 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
115 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
116 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
117 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
118 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
120 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
121 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
122 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
123 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
125 "sys_b0_30", "sys_b0_31", "open", "lseek",
126 "read", "write", "close", "ioctl",
127 "exit", "sys_b0_39", "getc", "putc",
128 "getchar", "putchar", "gets", "puts",
130 "cd", "format", "firstfile", "nextfile",
131 "rename", "delete", "undelete", "AddDevice",
132 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
133 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
135 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
136 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
137 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
138 "_card_status", "_card_wait",
141 char *biosC0n[256] = {
143 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
144 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
145 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
146 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
148 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
149 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
150 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
154 //#define r0 (psxRegs.GPR.n.r0)
155 #define at (psxRegs.GPR.n.at)
156 #define v0 (psxRegs.GPR.n.v0)
157 #define v1 (psxRegs.GPR.n.v1)
158 #define a0 (psxRegs.GPR.n.a0)
159 #define a1 (psxRegs.GPR.n.a1)
160 #define a2 (psxRegs.GPR.n.a2)
161 #define a3 (psxRegs.GPR.n.a3)
162 #define t0 (psxRegs.GPR.n.t0)
163 #define t1 (psxRegs.GPR.n.t1)
164 #define t2 (psxRegs.GPR.n.t2)
165 #define t3 (psxRegs.GPR.n.t3)
166 #define t4 (psxRegs.GPR.n.t4)
167 #define t5 (psxRegs.GPR.n.t5)
168 #define t6 (psxRegs.GPR.n.t6)
169 #define t7 (psxRegs.GPR.n.t7)
170 #define t8 (psxRegs.GPR.n.t8)
171 #define t9 (psxRegs.GPR.n.t9)
172 #define s0 (psxRegs.GPR.n.s0)
173 #define s1 (psxRegs.GPR.n.s1)
174 #define s2 (psxRegs.GPR.n.s2)
175 #define s3 (psxRegs.GPR.n.s3)
176 #define s4 (psxRegs.GPR.n.s4)
177 #define s5 (psxRegs.GPR.n.s5)
178 #define s6 (psxRegs.GPR.n.s6)
179 #define s7 (psxRegs.GPR.n.s7)
180 #define k0 (psxRegs.GPR.n.k0)
181 #define k1 (psxRegs.GPR.n.k1)
182 #define gp (psxRegs.GPR.n.gp)
183 #define sp (psxRegs.GPR.n.sp)
184 #define fp (psxRegs.GPR.n.fp)
185 #define ra (psxRegs.GPR.n.ra)
186 #define pc0 (psxRegs.pc)
188 #define Ra0 ((char *)PSXM(a0))
189 #define Ra1 ((char *)PSXM(a1))
190 #define Ra2 ((char *)PSXM(a2))
191 #define Ra3 ((char *)PSXM(a3))
192 #define Rv0 ((char *)PSXM(v0))
193 #define Rsp ((char *)PSXM(sp))
204 #define EvStUNUSED 0x0000
205 #define EvStDISABLED 0x1000
206 #define EvStACTIVE 0x2000
207 #define EvStALREADY 0x4000
209 #define EvMdCALL 0x1000
210 #define EvMdMARK 0x2000
233 u32 _sp, _fp, _gp, ret, base;
253 static int *pad_buf = NULL;
254 static u32 heap_size = 0;
255 static u32 *heap_addr = NULL;
256 static u32 *heap_end = NULL;
257 static FileDesc FDesc[32];
258 static u32 card_active_chan = 0;
260 // fixed RAM offsets, SCPH1001 compatible
261 #define A_TT_ExCB 0x0100
262 #define A_TT_PCB 0x0108
263 #define A_TT_TCB 0x0110
264 #define A_TT_EvCB 0x0120
265 #define A_A0_TABLE 0x0200
266 #define A_B0_TABLE 0x0874
267 #define A_C0_TABLE 0x0674
268 #define A_SYSCALL 0x0650
269 #define A_EXCEPTION 0x0c80
270 #define A_EXC_SP 0x6cf0
271 #define A_EEXIT_DEF 0x6cf4
272 #define A_KMALLOC_PTR 0x7460
273 #define A_KMALLOC_SIZE 0x7464
274 #define A_KMALLOC_END 0x7468
275 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry
276 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
277 #define A_CARD_IRQR_ENA 0x74bc // same for card
278 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
279 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
280 #define A_PAD_IN_LEN 0x74d8
281 #define A_PAD_OUT_LEN 0x74e0
282 #define A_EEXIT_PTR 0x75d0
283 #define A_EXC_STACK 0x85d8 // exception stack top
284 #define A_RCNT_VBL_ACK 0x8600
285 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
286 #define A_CD_EVENTS 0xb9b8
287 #define A_EXC_GP 0xf450
289 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
291 static u32 loadRam32(u32 addr)
293 assert(!(addr & 0x5f800000));
294 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
297 static void *castRam8ptr(u32 addr)
299 assert(!(addr & 0x5f800000));
300 return psxM + (addr & 0x1fffff);
303 static void *castRam32ptr(u32 addr)
305 assert(!(addr & 0x5f800003));
306 return psxM + (addr & 0x1ffffc);
309 static void *loadRam8ptr(u32 addr)
311 return castRam8ptr(loadRam32(addr));
314 static void *loadRam32ptr(u32 addr)
316 return castRam32ptr(loadRam32(addr));
319 static void storeRam8(u32 addr, u8 d)
321 assert(!(addr & 0x5f800000));
322 *((u8 *)psxM + (addr & 0x1fffff)) = d;
325 static void storeRam32(u32 addr, u32 d)
327 assert(!(addr & 0x5f800000));
328 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
331 static void mips_return(u32 val)
337 static void use_cycles(u32 cycle)
339 psxRegs.cycle += cycle * 2;
342 static void mips_return_c(u32 val, u32 cycle)
348 static void mips_return_void_c(u32 cycle)
354 static int returned_from_exception(void)
356 // 0x80000080 means it took another exception just after return
357 return pc0 == k0 || pc0 == 0x80000080;
360 static inline void softCall(u32 pc) {
362 u32 ssr = psxRegs.CP0.n.SR;
365 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
367 while (pc0 != 0x80001000)
368 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
371 psxRegs.CP0.n.SR = ssr;
374 static inline void softCallInException(u32 pc) {
379 while (!returned_from_exception() && pc0 != 0x80001000)
380 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
382 if (pc0 == 0x80001000)
386 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
387 static u32 DeliverEvent(u32 class, u32 spec);
388 static u32 UnDeliverEvent(u32 class, u32 spec);
389 static void CloseEvent(u32 ev);
394 // System calls A0 */
397 #define buread(Ra1, mcd, length) { \
398 SysPrintf("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
399 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
400 memcpy(Ra1, ptr, length); \
401 if (FDesc[1 + mcd].mode & 0x8000) { \
402 DeliverEvent(0xf0000011, 0x0004); \
403 DeliverEvent(0xf4000001, 0x0004); \
406 FDesc[1 + mcd].offset += v0; \
409 #define buwrite(Ra1, mcd, length) { \
410 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
411 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
412 ptr = Mcd##mcd##Data + offset; \
413 memcpy(ptr, Ra1, length); \
414 FDesc[1 + mcd].offset += length; \
415 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
416 if (FDesc[1 + mcd].mode & 0x8000) { \
417 DeliverEvent(0xf0000011, 0x0004); \
418 DeliverEvent(0xf4000001, 0x0004); \
424 //#define PSXBIOS_LOG printf
425 #define PSXBIOS_LOG(...)
428 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
429 /* For some strange reason, the returned character is sign-expanded; */
430 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
431 /* TODO FIX ME : Properly implement this behaviour */
432 void psxBios_getc(void) // 0x03, 0x35
437 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
441 if (pa1 != INVALID_PTR) {
443 case 2: buread(pa1, 1, 1); break;
444 case 3: buread(pa1, 2, 1); break;
451 /* Copy of psxBios_write, except size is 1. */
452 void psxBios_putc(void) // 0x09, 0x3B
457 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
460 if (pa1 == INVALID_PTR) {
465 if (a0 == 1) { // stdout
466 char *ptr = (char *)pa1;
470 printf("%c", *ptr++); a2--;
476 case 2: buwrite(pa1, 1, 1); break;
477 case 3: buwrite(pa1, 2, 1); break;
483 void psxBios_todigit(void) // 0x0a
487 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
490 if (c >= 0x30 && c < 0x3A) {
493 else if (c > 0x60 && c < 0x7B) {
496 else if (c > 0x40 && c < 0x5B) {
499 else if (c >= 0x80) {
510 void psxBios_abs() { // 0x0e
511 if ((s32)a0 < 0) v0 = -(s32)a0;
516 void psxBios_labs() { // 0x0f
520 void psxBios_atoi() { // 0x10
522 char *p = (char *)Ra0;
526 case ' ': case '\t': continue;
533 while (*p >= '0' && *p <= '9') {
534 n = n * 10 + *p++ - '0';
541 void psxBios_atol() { // 0x11
551 static void psxBios_setjmp() { // 0x13
552 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
555 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
557 jmp_buf->ra_ = SWAP32(ra);
558 jmp_buf->sp_ = SWAP32(sp);
559 jmp_buf->fp_ = SWAP32(fp);
560 for (i = 0; i < 8; i++) // s0-s7
561 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
562 jmp_buf->gp_ = SWAP32(gp);
564 mips_return_c(0, 15);
567 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
571 ra = SWAP32(jmp_buf->ra_);
572 sp = SWAP32(jmp_buf->sp_);
573 fp = SWAP32(jmp_buf->fp_);
574 for (i = 0; i < 8; i++) // s0-s7
575 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
576 gp = SWAP32(jmp_buf->gp_);;
579 void psxBios_longjmp() { // 0x14
580 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
582 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
583 longjmp_load(jmp_buf);
584 mips_return_c(a1, 15);
587 void psxBios_strcat() { // 0x15
588 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
591 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
593 if (a0 == 0 || a1 == 0)
601 while ((*p1++ = *p2++) != '\0');
606 void psxBios_strncat() { // 0x16
607 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
611 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
613 if (a0 == 0 || a1 == 0)
621 while ((*p1++ = *p2++) != '\0') {
631 void psxBios_strcmp() { // 0x17
632 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
634 if (a0 == 0 && a1 == 0)
640 else if (a0 == 0 && a1 != 0)
646 else if (a0 != 0 && a1 == 0)
653 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
656 while (*p1 == *p2++) {
675 void psxBios_strncmp() { // 0x18
676 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
678 if (a0 == 0 && a1 == 0)
684 else if (a0 == 0 && a1 != 0)
690 else if (a0 != 0 && a1 == 0)
697 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
700 while (--n >= 0 && *p1 == *p2++) {
704 v1 = a2 - ((a2-n) - 1);
712 v0 = (n < 0 ? 0 : *p1 - *--p2);
714 v1 = a2 - ((a2-n) - 1);
720 void psxBios_strcpy() { // 0x19
721 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
722 if (a0 == 0 || a1 == 0)
728 while ((*p1++ = *p2++) != '\0');
733 void psxBios_strncpy() { // 0x1a
734 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
736 if (a0 == 0 || a1 == 0)
742 for (i = 0; i < n; i++) {
743 if ((*p1++ = *p2++) == '\0') {
755 void psxBios_strlen() { // 0x1b
756 char *p = (char *)Ra0;
767 void psxBios_index() { // 0x1c
768 char *p = (char *)Ra0;
778 v0 = a0 + (p - (char *)Ra0);
782 } while (*p++ != '\0');
787 void psxBios_rindex() { // 0x1d
788 char *p = (char *)Ra0;
798 v0 = a0 + (p - (char *)Ra0);
799 } while (*p++ != '\0');
804 void psxBios_strchr() { // 0x1e
808 void psxBios_strrchr() { // 0x1f
812 void psxBios_strpbrk() { // 0x20
813 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
815 while ((c = *p1++) != '\0') {
816 for (scanp = p2; (sc = *scanp++) != '\0';) {
818 v0 = a0 + (p1 - 1 - (char *)Ra0);
825 // BUG: return a0 instead of NULL if not found
829 void psxBios_strspn() { // 0x21
832 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
833 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
834 if (*p2 == '\0') break;
837 v0 = p1 - (char *)Ra0; pc0 = ra;
840 void psxBios_strcspn() { // 0x22
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_strtok() { // 0x23
852 char *pcA0 = (char *)Ra0;
853 char *pcRet = strtok(pcA0, (char *)Ra1);
855 v0 = a0 + pcRet - pcA0;
861 void psxBios_strstr() { // 0x24
862 char *p = (char *)Ra0, *p1, *p2;
868 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
873 v0 = a0 + (p - (char *)Ra0);
884 void psxBios_toupper() { // 0x25
885 v0 = (s8)(a0 & 0xff);
886 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
890 void psxBios_tolower() { // 0x26
891 v0 = (s8)(a0 & 0xff);
892 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
896 void psxBios_bcopy() { // 0x27
897 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
899 if (a0 == 0 || a2 > 0x7FFFFFFF)
904 while ((s32)a2-- > 0) *p1++ = *p2++;
909 void psxBios_bzero() { // 0x28
910 char *p = (char *)Ra0;
912 /* Same as memset here (See memset below) */
913 if (a1 > 0x7FFFFFFF || a1 == 0)
924 while ((s32)a1-- > 0) *p++ = '\0';
929 void psxBios_bcmp() { // 0x29
930 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
932 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
934 while ((s32)a2-- > 0) {
935 if (*p1++ != *p2++) {
936 v0 = *p1 - *p2; // BUG: compare the NEXT byte
945 void psxBios_memcpy() { // 0x2a
946 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
948 if (a0 == 0 || a2 > 0x7FFFFFFF)
953 while ((s32)a2-- > 0) {
960 void psxBios_memset() { // 0x2b
961 char *p = (char *)Ra0;
963 if (a2 > 0x7FFFFFFF || a2 == 0)
974 while ((s32)a2-- > 0) *p++ = (char)a1;
979 void psxBios_memmove() { // 0x2c
980 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
982 if (a0 == 0 || a2 > 0x7FFFFFFF)
987 if (p2 <= p1 && p2 + a2 > p1) {
988 a2++; // BUG: copy one more byte here
991 while ((s32)a2-- > 0) *--p1 = *--p2;
993 while ((s32)a2-- > 0) *p1++ = *p2++;
998 void psxBios_memcmp() { // 0x2d
1002 void psxBios_memchr() { // 0x2e
1003 char *p = (char *)Ra0;
1005 if (a0 == 0 || a2 > 0x7FFFFFFF)
1011 while ((s32)a2-- > 0) {
1012 if (*p++ != (s8)a1) continue;
1013 v0 = a0 + (p - (char *)Ra0 - 1);
1021 void psxBios_rand() { // 0x2f
1022 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1023 v0 = (s >> 16) & 0x7fff;
1024 psxMu32ref(0x9010) = SWAPu32(s);
1028 void psxBios_srand() { // 0x30
1029 psxMu32ref(0x9010) = SWAPu32(a0);
1033 static u32 qscmpfunc, qswidth;
1035 static inline int qscmp(char *a, char *b) {
1038 a0 = sa0 + (a - (char *)PSXM(sa0));
1039 a1 = sa0 + (b - (char *)PSXM(sa0));
1041 softCall(qscmpfunc);
1047 static inline void qexchange(char *i, char *j) {
1058 static inline void q3exchange(char *i, char *j, char *k) {
1070 static void qsort_main(char *a, char *l) {
1071 char *i, *j, *lp, *hp;
1076 if ((n = l - a) <= qswidth)
1078 n = qswidth * (n / (2 * qswidth));
1084 if ((c = qscmp(i, lp)) == 0) {
1085 qexchange(i, lp -= qswidth);
1096 if ((c = qscmp(hp, j)) == 0) {
1097 qexchange(hp += qswidth, j);
1102 q3exchange(i, hp += qswidth, j);
1116 if (lp - a >= l - hp) {
1117 qsort_main(hp + qswidth, l);
1126 q3exchange(j, lp -= qswidth, i);
1131 void psxBios_qsort() { // 0x31
1134 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1139 void psxBios_malloc() { // 0x33
1140 u32 *chunk, *newchunk = NULL;
1141 unsigned int dsize = 0, csize, cstat;
1144 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1146 if (!a0 || (!heap_size || !heap_addr)) {
1152 // scan through heap and combine free chunks of space
1155 while(chunk < heap_end) {
1156 // get size and status of actual chunk
1157 csize = ((u32)*chunk) & 0xfffffffc;
1158 cstat = ((u32)*chunk) & 1;
1160 // most probably broken heap descriptor
1161 // this fixes Burning Road
1164 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1169 // it's a free chunk
1174 colflag = 1; // let's begin a new collection of free memory
1176 else dsize += (csize+4); // add the new size including header
1178 // not a free chunk: did we start a collection ?
1180 if(colflag == 1) { // collection is over
1182 *newchunk = SWAP32(dsize | 1);
1187 chunk = (u32*)((uptr)chunk + csize + 4);
1189 // if neccessary free memory on end of heap
1191 *newchunk = SWAP32(dsize | 1);
1194 csize = ((u32)*chunk) & 0xfffffffc;
1195 cstat = ((u32)*chunk) & 1;
1196 dsize = (a0 + 3) & 0xfffffffc;
1198 // exit on uninitialized heap
1199 if (chunk == NULL) {
1200 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1206 // search an unused chunk that is big enough until the end of the heap
1207 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1208 chunk = (u32*)((uptr)chunk + csize + 4);
1210 // catch out of memory
1211 if(chunk >= heap_end) {
1212 printf("malloc %x,%x: Out of memory error!\n",
1218 csize = ((u32)*chunk) & 0xfffffffc;
1219 cstat = ((u32)*chunk) & 1;
1223 if(dsize == csize) {
1224 // chunk has same size
1225 *chunk &= 0xfffffffc;
1226 } else if (dsize > csize) {
1231 *chunk = SWAP32(dsize);
1232 newchunk = (u32*)((uptr)chunk + dsize + 4);
1233 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1236 // return pointer to allocated memory
1237 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1239 //printf ("malloc %x,%x\n", v0, a0);
1243 void psxBios_free() { // 0x34
1246 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1249 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1252 *(u32*)(Ra0-4) |= 1; // set chunk to free
1256 void psxBios_calloc() { // 0x37
1259 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1269 void psxBios_realloc() { // 0x38
1273 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1277 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1282 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1287 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1288 /* Note that it is not quite implemented this way here. */
1298 /* InitHeap(void *block , int n) */
1299 void psxBios_InitHeap() { // 0x39
1303 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1306 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1311 heap_addr = (u32 *)Ra0;
1313 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1314 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1315 //*heap_addr = SWAP32(size | 1);
1317 SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1322 void psxBios_getchar() { //0x3b
1323 v0 = getchar(); pc0 = ra;
1326 static void psxBios_printf_psxout() { // 0x3f
1335 if (psp != INVALID_PTR) {
1336 memcpy(save, psp, 4 * 4);
1337 psxMu32ref(sp) = SWAP32((u32)a0);
1338 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1339 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1340 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1352 tmp2[j++] = Ra0[i]; goto _start;
1354 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1365 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1369 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1375 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1377 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1379 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1381 *ptmp++ = Ra0[i]; break;
1391 if (psp != INVALID_PTR)
1392 memcpy(psp, save, 4 * 4);
1394 SysPrintf("%s", tmp);
1397 void psxBios_printf() { // 0x3f
1398 psxBios_printf_psxout();
1402 void psxBios_format() { // 0x41
1403 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1405 CreateMcd(Config.Mcd1);
1406 LoadMcd(1, Config.Mcd1);
1409 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1411 CreateMcd(Config.Mcd2);
1412 LoadMcd(2, Config.Mcd2);
1422 static void psxBios_SystemErrorUnresolvedException() {
1423 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1424 SysPrintf("psxBios_%s\n", biosA0n[0x40]);
1425 storeRam32(0xfffc, 0x12345678);
1427 mips_return_void_c(1000);
1431 * long Load(char *name, struct EXEC *header);
1434 void psxBios_Load() { // 0x42
1439 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1440 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1443 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1449 * int Exec(struct EXEC *header , int argc , char **argv);
1452 void psxBios_Exec() { // 43
1453 EXEC *header = (EXEC*)Ra0;
1457 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1467 if (header->S_addr != 0) {
1468 tmp = header->S_addr + header->s_size;
1484 void psxBios_FlushCache() { // 44
1486 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1488 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1489 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1493 void psxBios_GPU_dw() { // 0x46
1498 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1501 GPU_writeData(0xa0000000);
1502 GPU_writeData((a1<<0x10)|(a0&0xffff));
1503 GPU_writeData((a3<<0x10)|(a2&0xffff));
1505 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1508 GPU_writeData(SWAPu32(*ptr++));
1514 void psxBios_mem2vram() { // 0x47
1517 GPU_writeData(0xa0000000);
1518 GPU_writeData((a1<<0x10)|(a0&0xffff));
1519 GPU_writeData((a3<<0x10)|(a2&0xffff));
1520 size = ((((a2 * a3) / 2) >> 4) << 16);
1521 GPU_writeStatus(0x04000002);
1522 psxHwWrite32(0x1f8010f4,0);
1523 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1524 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1525 psxHwWrite32(0x1f8010a4, size | 0x10);
1526 psxHwWrite32(0x1f8010a8,0x01000201);
1531 void psxBios_SendGPU() { // 0x48
1532 GPU_writeStatus(a0);
1537 void psxBios_GPU_cw() { // 0x49
1544 void psxBios_GPU_cwb() { // 0x4a
1545 u32 *ptr = (u32*)Ra0;
1550 GPU_writeData(SWAPu32(*ptr++));
1556 void psxBios_GPU_SendPackets() { //4b:
1558 GPU_writeStatus(0x04000002);
1559 psxHwWrite32(0x1f8010f4,0);
1560 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1561 psxHwWrite32(0x1f8010a0,a0);
1562 psxHwWrite32(0x1f8010a4,0);
1563 psxHwWrite32(0x1f8010a8,0x010000401);
1567 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1568 psxHwWrite32(0x1f8010a8,0x00000401);
1569 GPU_writeData(0x0400000);
1570 GPU_writeData(0x0200000);
1571 GPU_writeData(0x0100000);
1576 void psxBios_GPU_GetGPUStatus() { // 0x4d
1577 v0 = GPU_readStatus();
1583 void psxBios_LoadExec() { // 51
1584 EXEC *header = (EXEC*)PSXM(0xf000);
1588 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1590 s_addr = a1; s_size = a2;
1595 header->S_addr = s_addr;
1596 header->s_size = s_size;
1598 a0 = 0xf000; a1 = 0; a2 = 0;
1602 void psxBios__bu_init() { // 70
1604 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1607 DeliverEvent(0xf0000011, 0x0004);
1608 DeliverEvent(0xf4000001, 0x0004);
1613 void psxBios__96_init() { // 71
1615 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1621 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1622 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1623 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1625 static void psxBios_DequeueCdIntr_() {
1626 psxBios_SysDeqIntRP_(0, 0x91d0);
1627 psxBios_SysDeqIntRP_(0, 0x91e0);
1631 static void psxBios_DequeueCdIntr() { // a3
1632 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1633 psxBios_DequeueCdIntr_();
1636 static void psxBios_CdRemove() { // 56, 72
1637 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1639 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1640 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1641 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1642 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1643 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1644 psxBios_DequeueCdIntr_();
1646 // EnterCriticalSection - should be done at the beginning,
1647 // but this way is much easier to implement
1653 void psxBios_SetMem() { // 9f
1654 u32 new = psxHu32(0x1060);
1657 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1662 psxHu32ref(0x1060) = SWAP32(new);
1663 psxMu32ref(0x060) = a0;
1664 SysPrintf("Change effective memory : %d MBytes\n",a0);
1668 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1669 psxMu32ref(0x060) = a0;
1670 SysPrintf("Change effective memory : %d MBytes\n",a0);
1673 SysPrintf("Effective memory must be 2/8 MBytes\n");
1680 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1681 void psxBios_get_cd_status(void) //a6
1687 void psxBios__card_info() { // ab
1689 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1692 card_active_chan = a0;
1693 port = card_active_chan >> 4;
1699 if (McdDisable[port & 1])
1704 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1710 if (McdDisable[0] && McdDisable[1])
1713 DeliverEvent(0xf0000011, 0x0004);
1714 // DeliverEvent(0xf4000001, 0x0004);
1715 DeliverEvent(0xf4000001, ret);
1719 void psxBios__card_load() { // ac
1721 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1724 card_active_chan = a0;
1726 // DeliverEvent(0xf0000011, 0x0004);
1727 DeliverEvent(0xf4000001, 0x0004);
1732 /* System calls B0 */
1734 static u32 psxBios_SysMalloc_(u32 size);
1736 static void psxBios_SysMalloc() { // B 00
1737 u32 ret = psxBios_SysMalloc_(a0);
1739 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1740 mips_return_c(ret, 33);
1743 void psxBios_SetRCnt() { // 02
1745 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1752 psxRcntWtarget(a0, a1);
1753 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1754 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1755 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1756 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1757 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1759 psxRcntWmode(a0, mode);
1764 void psxBios_GetRCnt() { // 03
1766 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1770 if (a0 != 3) v0 = psxRcntRcount(a0);
1775 void psxBios_StartRCnt() { // 04
1777 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1781 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1782 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1786 void psxBios_StopRCnt() { // 05
1788 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1792 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1793 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1797 void psxBios_ResetRCnt() { // 06
1799 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1804 psxRcntWmode(a0, 0);
1805 psxRcntWtarget(a0, 0);
1806 psxRcntWcount(a0, 0);
1811 static u32 DeliverEvent(u32 class, u32 spec) {
1812 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1813 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1814 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1815 u32 i, lim = evcb_len / 0x1c;
1817 for (i = 0; i < lim; i++, ev++) {
1819 if (SWAP32(ev->status) != EvStACTIVE)
1822 if (SWAP32(ev->class) != class)
1825 if (SWAP32(ev->spec) != spec)
1828 ret = SWAP32(ev->mode);
1829 if (ret == EvMdMARK) {
1830 ev->status = SWAP32(EvStALREADY);
1834 if (ret == EvMdCALL) {
1835 ret = SWAP32(ev->fhandler);
1847 static u32 UnDeliverEvent(u32 class, u32 spec) {
1848 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1849 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1850 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1851 u32 i, lim = evcb_len / 0x1c;
1853 for (i = 0; i < lim; i++, ev++) {
1855 if (SWAP32(ev->status) != EvStALREADY)
1858 if (SWAP32(ev->class) != class)
1861 if (SWAP32(ev->spec) != spec)
1864 if (SWAP32(ev->mode) == EvMdMARK)
1865 ev->status = SWAP32(EvStACTIVE);
1871 static void psxBios_DeliverEvent() { // 07
1873 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1875 ret = DeliverEvent(a0, a1);
1879 static s32 get_free_EvCB_slot() {
1880 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1881 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1884 for (i = 0; i < lim; i++, ev++) {
1886 if (ev->status == SWAP32(EvStUNUSED))
1892 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
1893 u32 ret = get_free_EvCB_slot();
1894 if ((s32)ret >= 0) {
1895 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
1896 ev->class = SWAP32(class);
1897 ev->status = SWAP32(EvStDISABLED);
1898 ev->spec = SWAP32(spec);
1899 ev->mode = SWAP32(mode);
1900 ev->fhandler = SWAP32(func);
1906 static void psxBios_OpenEvent() { // 08
1907 u32 ret = OpenEvent(a0, a1, a2, a3);
1908 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
1909 biosB0n[0x08], a0, a1, a2, a3, ret);
1910 mips_return_c(ret, 36);
1913 static void CloseEvent(u32 ev)
1915 u32 base = loadRam32(A_TT_EvCB);
1916 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
1919 static void psxBios_CloseEvent() { // 09
1920 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
1921 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
1923 mips_return_c(1, 10);
1926 static void psxBios_WaitEvent() { // 0a
1927 u32 base = loadRam32(A_TT_EvCB);
1928 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1929 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
1932 if (status == EvStALREADY) {
1933 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1937 if (status != EvStACTIVE)
1939 mips_return_c(0, 2);
1943 // retrigger this hlecall after the next emulation event
1945 if ((s32)(next_interupt - psxRegs.cycle) > 0)
1946 psxRegs.cycle = next_interupt;
1950 static void psxBios_TestEvent() { // 0b
1951 u32 base = loadRam32(A_TT_EvCB);
1952 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1954 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
1955 if (status == EvStALREADY) {
1956 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1960 mips_return_c(ret, 15);
1963 static void psxBios_EnableEvent() { // 0c
1964 u32 base = loadRam32(A_TT_EvCB);
1965 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1966 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
1967 if (status != EvStUNUSED)
1968 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
1970 mips_return_c(1, 15);
1973 static void psxBios_DisableEvent() { // 0d
1974 u32 base = loadRam32(A_TT_EvCB);
1975 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
1976 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
1977 if (status != EvStUNUSED)
1978 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
1980 mips_return_c(1, 15);
1984 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1987 void psxBios_OpenTh() { // 0e
1988 TCB *tcb = loadRam32ptr(A_TT_TCB);
1989 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
1992 for (th = 1; th < limit; th++)
1994 if (tcb[th].status != SWAP32(0x4000)) break;
1998 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1999 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2001 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2003 mips_return_c(0xffffffff, 20);
2006 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
2008 tcb[th].status = SWAP32(0x4000);
2009 tcb[th].mode = SWAP32(0x1000);
2010 tcb[th].epc = SWAP32(a0);
2011 tcb[th].reg[30] = SWAP32(a1); // fp
2012 tcb[th].reg[29] = SWAP32(a1); // sp
2013 tcb[th].reg[28] = SWAP32(a2); // gp
2015 mips_return_c(0xff000000 + th, 34);
2019 * int CloseTh(long thread);
2022 void psxBios_CloseTh() { // 0f
2023 TCB *tcb = loadRam32ptr(A_TT_TCB);
2024 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2028 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2030 /* The return value is always 1 (even if the handle was already closed). */
2032 if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2033 tcb[th].status = SWAP32(0x1000);
2040 * int ChangeTh(long thread);
2043 void psxBios_ChangeTh() { // 10
2044 u32 tcbBase = loadRam32(A_TT_TCB);
2045 u32 th = a0 & 0xffff;
2048 // PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
2050 // without doing any argument checks, just issue a syscall
2051 // (like the real bios does)
2053 a1 = tcbBase + th * sizeof(TCB);
2058 void psxBios_InitPAD() { // 0x12
2059 u32 i, *ram32 = (u32 *)psxM;
2060 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2062 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2063 // PAD_dr_enable = 0;
2064 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2065 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2066 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2067 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2068 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2069 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2070 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2071 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2073 for (i = 0; i < a1; i++) {
2075 storeRam8(a0 + i, 0);
2077 for (i = 0; i < a3; i++) {
2079 storeRam8(a2 + i, 0);
2081 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2083 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2085 mips_return_c(1, 200);
2088 void psxBios_StartPAD() { // 13
2089 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2091 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2092 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2093 psxHwWrite16(0x1f801070, ~1);
2094 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2095 storeRam32(A_PAD_ACK_VBL, 1);
2096 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2097 psxRegs.CP0.n.SR |= 0x401;
2099 mips_return_c(1, 300);
2102 void psxBios_StopPAD() { // 14
2103 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2104 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2105 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2106 psxRegs.CP0.n.SR |= 0x401;
2107 mips_return_void_c(200);
2110 void psxBios_PAD_init() { // 15
2112 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2114 if (!(a0 == 0x20000000 || a0 == 0x20000001))
2120 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
2121 pad_buf = (int *)Ra1;
2123 psxRegs.CP0.n.SR |= 0x401;
2128 void psxBios_PAD_dr() { // 16
2130 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2136 static void psxBios_ReturnFromException() { // 17
2137 u32 tcbPtr = loadRam32(A_TT_PCB);
2138 const TCB *tcb = loadRam32ptr(tcbPtr);
2141 for (i = 1; i < 32; i++)
2142 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2143 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2144 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2145 psxRegs.CP0.n.SR = SWAP32(tcb->sr);
2147 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2148 pc0 = k0 = SWAP32(tcb->epc);
2150 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
2155 void psxBios_ResetEntryInt() { // 18
2156 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2158 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2159 mips_return_void_c(5);
2162 void psxBios_HookEntryInt() { // 19
2163 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2165 storeRam32(A_EEXIT_PTR, a0);
2166 mips_return_void_c(3);
2169 static void psxBios_UnDeliverEvent() { // 0x20
2171 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2173 ret = UnDeliverEvent(a0, a1);
2177 char ffile[64], *pfile;
2180 static void buopen(int mcd, char *ptr, char *cfg)
2183 char *mcd_data = ptr;
2185 strcpy(FDesc[1 + mcd].name, Ra0+5);
2186 FDesc[1 + mcd].offset = 0;
2187 FDesc[1 + mcd].mode = a1;
2189 for (i=1; i<16; i++) {
2190 const char *fptr = mcd_data + 128 * i;
2191 if ((*fptr & 0xF0) != 0x50) continue;
2192 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2193 FDesc[1 + mcd].mcfile = i;
2194 SysPrintf("open %s\n", fptr+0xa);
2198 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2199 for (i=1; i<16; i++) {
2200 int j, xor, nblk = a1 >> 16;
2202 char *fptr = mcd_data + 128 * i;
2204 if ((*fptr & 0xF0) != 0xa0) continue;
2206 FDesc[1 + mcd].mcfile = i;
2209 fptr[5] = 0x20 * nblk;
2212 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2213 pptr = fptr2 = fptr;
2214 for(j=2; j<=nblk; j++) {
2216 for(i++; i<16; i++) {
2219 memset(fptr2, 0, 128);
2220 fptr2[0] = j < nblk ? 0x52 : 0x53;
2223 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2228 /* shouldn't this return ENOSPC if i == 16? */
2230 pptr[8] = pptr[9] = 0xff;
2231 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2233 SysPrintf("openC %s %d\n", ptr, nblk);
2235 /* just go ahead and resave them all */
2236 SaveMcd(cfg, ptr, 128, 128 * 15);
2239 /* shouldn't this return ENOSPC if i == 16? */
2244 * int open(char *name , int mode);
2247 void psxBios_open() { // 0x32
2251 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2256 if (pa0 != INVALID_PTR) {
2257 if (!strncmp(pa0, "bu00", 4)) {
2258 buopen(1, Mcd1Data, Config.Mcd1);
2261 if (!strncmp(pa0, "bu10", 4)) {
2262 buopen(2, Mcd2Data, Config.Mcd2);
2270 * int lseek(int fd , int offset , int whence);
2273 void psxBios_lseek() { // 0x33
2275 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2280 FDesc[a0].offset = a1;
2282 // DeliverEvent(0xf0000011, 0x0004);
2283 // DeliverEvent(0xf4000001, 0x0004);
2287 FDesc[a0].offset+= a1;
2288 v0 = FDesc[a0].offset;
2297 * int read(int fd , void *buf , int nbytes);
2300 void psxBios_read() { // 0x34
2305 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2310 if (pa1 != INVALID_PTR) {
2312 case 2: buread(pa1, 1, a2); break;
2313 case 3: buread(pa1, 2, a2); break;
2321 * int write(int fd , void *buf , int nbytes);
2324 void psxBios_write() { // 0x35/0x03
2329 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2333 if (pa1 == INVALID_PTR) {
2338 if (a0 == 1) { // stdout
2343 SysPrintf("%c", *ptr++); a2--;
2349 case 2: buwrite(pa1, 1, a2); break;
2350 case 3: buwrite(pa1, 2, a2); break;
2356 static void psxBios_write_psxout() {
2357 if (a0 == 1) { // stdout
2358 const char *ptr = Ra1;
2361 if (ptr != INVALID_PTR)
2363 SysPrintf("%c", *ptr++);
2367 static void psxBios_putchar_psxout() { // 3d
2368 SysPrintf("%c", (char)a0);
2371 static void psxBios_puts_psxout() { // 3e/3f
2372 SysPrintf("%s", Ra0);
2376 * int close(int fd);
2379 void psxBios_close() { // 0x36
2381 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2388 void psxBios_putchar() { // 3d
2389 SysPrintf("%c", (char)a0);
2393 void psxBios_puts() { // 3e/3f
2394 SysPrintf("%s", Ra0);
2399 /* To avoid any issues with different behaviour when using the libc's own strlen instead.
2400 * We want to mimic the PSX's behaviour in this case for bufile. */
2401 static size_t strlen_internal(char* p)
2403 size_t size_of_array = 0;
2404 while (*p++) size_of_array++;
2405 return size_of_array;
2408 #define bufile(mcd) { \
2409 size_t size_of_name = strlen_internal(dir->name); \
2410 while (nfile < 16) { \
2413 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2415 if ((*ptr & 0xF0) != 0x50) continue; \
2416 /* Bug link files show up as free block. */ \
2417 if (!ptr[0xa]) continue; \
2419 if (pfile[0] == 0) { \
2420 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2421 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2422 } else for (i=0; i<20; i++) { \
2423 if (pfile[i] == ptr[i]) { \
2424 dir->name[i] = ptr[i]; continue; } \
2425 if (pfile[i] == '?') { \
2426 dir->name[i] = ptr[i]; continue; } \
2427 if (pfile[i] == '*') { \
2428 strcpy(dir->name+i, ptr+i); break; } \
2431 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2432 if (match == 0) { continue; } \
2440 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2443 void psxBios_firstfile() { // 42
2444 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2451 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2456 if (pa0 != INVALID_PTR) {
2460 if (!strncmp(pa0, "bu00", 4)) {
2461 // firstfile() calls _card_read() internally, so deliver it's event
2462 DeliverEvent(0xf0000011, 0x0004);
2464 } else if (!strncmp(pa0, "bu10", 4)) {
2465 // firstfile() calls _card_read() internally, so deliver it's event
2466 DeliverEvent(0xf0000011, 0x0004);
2475 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2478 void psxBios_nextfile() { // 43
2479 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2485 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2490 if (!strncmp(ffile, "bu00", 4)) {
2494 if (!strncmp(ffile, "bu10", 4)) {
2501 #define burename(mcd) { \
2502 for (i=1; i<16; i++) { \
2503 int namelen, j, xor = 0; \
2504 ptr = Mcd##mcd##Data + 128 * i; \
2505 if ((*ptr & 0xF0) != 0x50) continue; \
2506 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2507 namelen = strlen(Ra1+5); \
2508 memcpy(ptr+0xa, Ra1+5, namelen); \
2509 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2510 for (j=0; j<127; j++) xor^= ptr[j]; \
2512 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2519 * int rename(char *old, char *new);
2522 void psxBios_rename() { // 44
2529 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2534 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2535 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2539 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2548 #define budelete(mcd) { \
2549 for (i=1; i<16; i++) { \
2550 ptr = Mcd##mcd##Data + 128 * i; \
2551 if ((*ptr & 0xF0) != 0x50) continue; \
2552 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2553 *ptr = (*ptr & 0xf) | 0xA0; \
2554 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2555 SysPrintf("delete %s\n", ptr+0xa); \
2562 * int delete(char *name);
2565 void psxBios_delete() { // 45
2571 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2576 if (pa0 != INVALID_PTR) {
2577 if (!strncmp(pa0, "bu00", 4)) {
2581 if (!strncmp(pa0, "bu10", 4)) {
2589 void psxBios_InitCARD() { // 4a
2590 u32 *ram32 = (u32 *)psxM;
2591 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2592 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2593 // (maybe) todo: early_card_irq, FlushCache etc
2595 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2597 mips_return_c(0, 300);
2600 void psxBios_StartCARD() { // 4b
2601 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2602 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2603 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2605 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2606 storeRam32(A_PAD_ACK_VBL, 1);
2607 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2608 storeRam32(A_CARD_IRQR_ENA, 1);
2609 psxRegs.CP0.n.SR |= 0x401;
2611 mips_return_c(1, 200);
2614 void psxBios_StopCARD() { // 4c
2615 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2616 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2617 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2618 storeRam32(A_CARD_IRQR_ENA, 0);
2619 psxRegs.CP0.n.SR |= 0x401;
2620 mips_return_void_c(200);
2623 void psxBios__card_write() { // 0x4e
2628 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2631 Function also accepts sector 400h (a bug).
2632 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2636 /* Invalid sectors */
2640 card_active_chan = a0;
2643 if (pa2 != INVALID_PTR) {
2645 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2646 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2648 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2649 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2653 DeliverEvent(0xf0000011, 0x0004);
2654 // DeliverEvent(0xf4000001, 0x0004);
2659 void psxBios__card_read() { // 0x4f
2664 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2667 Function also accepts sector 400h (a bug).
2668 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2672 /* Invalid sectors */
2676 card_active_chan = a0;
2679 if (pa2 != INVALID_PTR) {
2681 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2683 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2687 DeliverEvent(0xf0000011, 0x0004);
2688 // DeliverEvent(0xf4000001, 0x0004);
2693 void psxBios__new_card() { // 0x50
2695 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2701 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2702 void psxBios__get_error(void) // 55
2704 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2709 void psxBios_Krom2RawAdd() { // 0x51
2712 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2713 const u32 table_8140[][2] = {
2714 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2715 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2716 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2717 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2718 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2719 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2720 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2721 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2722 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2726 const u32 table_889f[][2] = {
2727 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2728 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2729 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2730 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2731 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2732 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2733 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2734 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2738 if (a0 >= 0x8140 && a0 <= 0x84be) {
2739 while (table_8140[i][0] <= a0) i++;
2740 a0 -= table_8140[i - 1][0];
2741 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2742 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2743 while (table_889f[i][0] <= a0) i++;
2744 a0 -= table_889f[i - 1][0];
2745 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2753 void psxBios_GetC0Table() { // 56
2754 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2755 log_unhandled("GetC0Table @%08x\n", ra);
2757 mips_return_c(A_C0_TABLE, 3);
2760 void psxBios_GetB0Table() { // 57
2761 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2762 log_unhandled("GetB0Table @%08x\n", ra);
2764 mips_return_c(A_B0_TABLE, 3);
2767 void psxBios__card_chan() { // 0x58
2769 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2772 v0 = card_active_chan;
2776 static void psxBios_ChangeClearPad() { // 5b
2778 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2779 ret = loadRam32(A_PAD_ACK_VBL);
2780 storeRam32(A_PAD_ACK_VBL, a0);
2782 mips_return_c(ret, 6);
2785 void psxBios__card_status() { // 5c
2787 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2790 v0 = card_active_chan;
2794 void psxBios__card_wait() { // 5d
2796 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2803 /* System calls C0 */
2805 static void psxBios_InitRCnt() { // 00
2807 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2808 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2809 for (i = 0; i < 3; i++) {
2810 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2811 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2812 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2814 psxBios_SysEnqIntRP_(a0, 0x6d88);
2815 mips_return_c(0, 9);
2818 static void psxBios_InitException() { // 01
2819 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2820 psxBios_SysEnqIntRP_(a0, 0x6da8);
2821 mips_return_c(0, 9);
2825 * int SysEnqIntRP(int index , long *queue);
2828 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2829 u32 old, base = loadRam32(A_TT_ExCB);
2831 old = loadRam32(base + (priority << 3));
2832 storeRam32(base + (priority << 3), chain_eptr);
2833 storeRam32(chain_eptr, old);
2834 mips_return_c(0, 9);
2837 static void psxBios_SysEnqIntRP() { // 02
2838 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2839 psxBios_SysEnqIntRP_(a0, a1);
2843 * int SysDeqIntRP(int index , long *queue);
2846 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2847 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2848 u32 lim = 0, ret = 0;
2850 // as in original: no arg checks of any kind, bug if a1 == 0
2851 ptr = loadRam32(base + (priority << 3));
2853 next = loadRam32(ptr);
2854 if (ptr == chain_rm_eptr) {
2855 storeRam32(base + (priority << 3), next);
2860 while (next && next != chain_rm_eptr && lim++ < 100) {
2862 next = loadRam32(ptr);
2865 if (next == chain_rm_eptr) {
2866 next = loadRam32(next);
2867 storeRam32(ptr, next);
2874 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2876 mips_return_c(ret, 12);
2879 static void psxBios_SysDeqIntRP() { // 03
2880 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2881 psxBios_SysDeqIntRP_(a0, a1);
2884 static void psxBios_get_free_EvCB_slot() { // 04
2885 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
2886 s32 ret = get_free_EvCB_slot();
2887 mips_return_c(ret, 0);
2890 static void psxBios_SysInitMemory_(u32 base, u32 size) {
2891 storeRam32(base, 0);
2892 storeRam32(A_KMALLOC_PTR, base);
2893 storeRam32(A_KMALLOC_SIZE, size);
2894 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2897 // this should be much more complicated, but maybe that'll be enough
2898 static u32 psxBios_SysMalloc_(u32 size) {
2899 u32 ptr = loadRam32(A_KMALLOC_PTR);
2901 size = (size + 3) & ~3;
2902 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2903 storeRam32(ptr, size);
2907 static void psxBios_SysInitMemory() { // 08
2908 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2910 psxBios_SysInitMemory_(a0, a1);
2911 mips_return_void_c(12);
2914 static void psxBios_ChangeClearRCnt() { // 0a
2917 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2919 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
2920 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
2921 mips_return_c(ret, 8);
2924 static void psxBios_InitDefInt() { // 0c
2925 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
2926 // should also clear the autoack table
2927 psxBios_SysEnqIntRP_(a0, 0x6d98);
2928 mips_return_c(0, 20 + 6*2);
2931 void psxBios_dummy() {
2932 u32 pc = (pc0 & 0x1fffff) - 4;
2933 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
2934 : pc == 0xc0 ? biosC0n : NULL;
2935 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
2936 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
2937 (void)pc; (void)ntab;
2938 mips_return_c(0, 100);
2941 void (*biosA0[256])();
2942 // C0 and B0 overlap (end of C0 is start of B0)
2943 void (*biosC0[256+128])();
2944 void (**biosB0)() = biosC0 + 128;
2946 static void setup_mips_code()
2949 ptr = (u32 *)&psxM[A_SYSCALL];
2950 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
2951 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
2952 ptr[0x08/4] = SWAPu32(0x00000000); // nop
2954 ptr = (u32 *)&psxM[A_EXCEPTION];
2955 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
2956 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
2957 ptr[0x14/4] = SWAPu32(0x00000000); // nop
2958 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
2959 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
2960 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
2961 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
2962 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
2963 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
2964 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
2966 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
2967 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
2968 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
2970 ptr[0xb0/4] = HLEOP(hleop_exception);
2973 static const struct {
2977 { 0xbfc050a4, hleop_exc0_0_1 },
2978 { 0xbfc04fbc, hleop_exc0_0_2 },
2979 { 0xbfc0506c, hleop_exc0_1_1 },
2980 { 0xbfc04dec, hleop_exc0_1_2 },
2981 { 0x1a00, hleop_exc0_2_2 },
2982 { 0x19c8, hleop_exc1_0_1 },
2983 { 0x18bc, hleop_exc1_0_2 },
2984 { 0x1990, hleop_exc1_1_1 },
2985 { 0x1858, hleop_exc1_1_2 },
2986 { 0x1958, hleop_exc1_2_1 },
2987 { 0x17f4, hleop_exc1_2_2 },
2988 { 0x1920, hleop_exc1_3_1 },
2989 { 0x1794, hleop_exc1_3_2 },
2990 { 0x2458, hleop_exc3_0_2 },
2991 { 0x49bc, hleop_exc_padcard1 },
2992 { 0x4a4c, hleop_exc_padcard2 },
2995 static int chain_hle_op(u32 handler)
2999 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3000 if (chainfns[i].addr == handler)
3001 return chainfns[i].op;
3005 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3007 d[0] = SWAPu32(next);
3008 d[1] = SWAPu32(handler1);
3009 d[2] = SWAPu32(handler2);
3011 // install the hle traps
3012 PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3013 PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3016 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
3018 u32 *ram32 = (u32 *)psxM;
3019 u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
3020 u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
3021 u32 p_excb, p_evcb, p_pcb, p_tcb;
3023 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3024 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3025 p_excb = psxBios_SysMalloc_(s_excb);
3026 p_evcb = psxBios_SysMalloc_(s_evcb);
3027 p_pcb = psxBios_SysMalloc_(s_pcb);
3028 p_tcb = psxBios_SysMalloc_(s_tcb);
3030 // "table of tables". Some games modify it
3031 assert(A_TT_ExCB == 0x0100);
3032 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3033 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3034 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3035 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3036 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3037 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3038 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3039 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3040 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3041 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3042 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3043 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3045 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3046 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3047 storeRam32(p_excb + 4*4, 0x0000); // chain2
3048 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3050 storeRam32(p_pcb, p_tcb);
3051 storeRam32(p_tcb, 0x4000); // first TCB
3054 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3055 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3056 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3057 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3058 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3059 DeliverEvent(0xf0000003, 0x0010);
3062 static const u32 gpu_ctl_def[] = {
3063 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3064 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3067 static const u32 gpu_data_def[] = {
3068 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3069 0xe5001000, 0xe6000000,
3070 0x02000000, 0x00000000, 0x01ff03ff
3074 static const u16 spu_config[] = {
3075 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3076 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3077 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3078 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3079 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3080 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3081 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3082 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3085 void psxBiosSetupBootState(void)
3087 boolean hle = Config.HLE;
3088 u32 *hw = (u32 *)psxH;
3091 // see also SetBootRegs()
3094 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3095 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3097 k0 = 0xbfc0d968; k1 = 0xf1c;
3098 ra = 0xf0001234; // just to easily detect attempts to return
3099 psxRegs.CP0.n.Cause = 0x20;
3100 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3102 hw[0x1000/4] = SWAP32(0x1f000000);
3103 hw[0x1004/4] = SWAP32(0x1f802000);
3104 hw[0x1008/4] = SWAP32(0x0013243f);
3105 hw[0x100c/4] = SWAP32(0x00003022);
3106 hw[0x1010/4] = SWAP32(0x0013243f);
3107 hw[0x1014/4] = SWAP32(0x200931e1);
3108 hw[0x1018/4] = SWAP32(0x00020943);
3109 hw[0x101c/4] = SWAP32(0x00070777);
3110 hw[0x1020/4] = SWAP32(0x0000132c);
3111 hw[0x1060/4] = SWAP32(0x00000b88);
3112 hw[0x1070/4] = SWAP32(0x00000001);
3113 hw[0x1074/4] = SWAP32(0x0000000c);
3114 hw[0x2040/4] = SWAP32(0x00000900);
3117 hw[0x10a0/4] = SWAP32(0x00ffffff);
3118 hw[0x10a8/4] = SWAP32(0x00000401);
3119 hw[0x10b0/4] = SWAP32(0x0008b000);
3120 hw[0x10b4/4] = SWAP32(0x00010200);
3121 hw[0x10e0/4] = SWAP32(0x000eccf4);
3122 hw[0x10e4/4] = SWAP32(0x00000400);
3123 hw[0x10e8/4] = SWAP32(0x00000002);
3124 hw[0x10f0/4] = SWAP32(0x00009099);
3125 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3134 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3135 GPU_writeStatus(gpu_ctl_def[i]);
3136 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3137 GPU_writeData(gpu_data_def[i]);
3138 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3141 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3142 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3145 #include "sjisfont.h"
3147 void psxBiosInit() {
3148 u32 *ptr, *ram32, *rom32;
3152 memset(psxM, 0, 0x10000);
3153 for(i = 0; i < 256; i++) {
3158 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3159 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3160 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3161 biosA0[0x3f] = psxBios_printf_psxout;
3163 if (!Config.HLE) return;
3165 for(i = 0; i < 256; i++) {
3166 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3167 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3168 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3171 biosA0[0x00] = psxBios_open;
3172 biosA0[0x01] = psxBios_lseek;
3173 biosA0[0x02] = psxBios_read;
3174 biosA0[0x03] = psxBios_write;
3175 biosA0[0x04] = psxBios_close;
3176 //biosA0[0x05] = psxBios_ioctl;
3177 //biosA0[0x06] = psxBios_exit;
3178 //biosA0[0x07] = psxBios_sys_a0_07;
3179 biosA0[0x08] = psxBios_getc;
3180 biosA0[0x09] = psxBios_putc;
3181 biosA0[0x0a] = psxBios_todigit;
3182 //biosA0[0x0b] = psxBios_atof;
3183 //biosA0[0x0c] = psxBios_strtoul;
3184 //biosA0[0x0d] = psxBios_strtol;
3185 biosA0[0x0e] = psxBios_abs;
3186 biosA0[0x0f] = psxBios_labs;
3187 biosA0[0x10] = psxBios_atoi;
3188 biosA0[0x11] = psxBios_atol;
3189 //biosA0[0x12] = psxBios_atob;
3190 biosA0[0x13] = psxBios_setjmp;
3191 biosA0[0x14] = psxBios_longjmp;
3192 biosA0[0x15] = psxBios_strcat;
3193 biosA0[0x16] = psxBios_strncat;
3194 biosA0[0x17] = psxBios_strcmp;
3195 biosA0[0x18] = psxBios_strncmp;
3196 biosA0[0x19] = psxBios_strcpy;
3197 biosA0[0x1a] = psxBios_strncpy;
3198 biosA0[0x1b] = psxBios_strlen;
3199 biosA0[0x1c] = psxBios_index;
3200 biosA0[0x1d] = psxBios_rindex;
3201 biosA0[0x1e] = psxBios_strchr;
3202 biosA0[0x1f] = psxBios_strrchr;
3203 biosA0[0x20] = psxBios_strpbrk;
3204 biosA0[0x21] = psxBios_strspn;
3205 biosA0[0x22] = psxBios_strcspn;
3206 biosA0[0x23] = psxBios_strtok;
3207 biosA0[0x24] = psxBios_strstr;
3208 biosA0[0x25] = psxBios_toupper;
3209 biosA0[0x26] = psxBios_tolower;
3210 biosA0[0x27] = psxBios_bcopy;
3211 biosA0[0x28] = psxBios_bzero;
3212 biosA0[0x29] = psxBios_bcmp;
3213 biosA0[0x2a] = psxBios_memcpy;
3214 biosA0[0x2b] = psxBios_memset;
3215 biosA0[0x2c] = psxBios_memmove;
3216 biosA0[0x2d] = psxBios_memcmp;
3217 biosA0[0x2e] = psxBios_memchr;
3218 biosA0[0x2f] = psxBios_rand;
3219 biosA0[0x30] = psxBios_srand;
3220 biosA0[0x31] = psxBios_qsort;
3221 //biosA0[0x32] = psxBios_strtod;
3222 biosA0[0x33] = psxBios_malloc;
3223 biosA0[0x34] = psxBios_free;
3224 //biosA0[0x35] = psxBios_lsearch;
3225 //biosA0[0x36] = psxBios_bsearch;
3226 biosA0[0x37] = psxBios_calloc;
3227 biosA0[0x38] = psxBios_realloc;
3228 biosA0[0x39] = psxBios_InitHeap;
3229 //biosA0[0x3a] = psxBios__exit;
3230 biosA0[0x3b] = psxBios_getchar;
3231 biosA0[0x3c] = psxBios_putchar;
3232 //biosA0[0x3d] = psxBios_gets;
3233 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3234 //biosA0[0x41] = psxBios_LoadTest;
3235 biosA0[0x42] = psxBios_Load;
3236 biosA0[0x43] = psxBios_Exec;
3237 biosA0[0x44] = psxBios_FlushCache;
3238 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3239 biosA0[0x46] = psxBios_GPU_dw;
3240 biosA0[0x47] = psxBios_mem2vram;
3241 biosA0[0x48] = psxBios_SendGPU;
3242 biosA0[0x49] = psxBios_GPU_cw;
3243 biosA0[0x4a] = psxBios_GPU_cwb;
3244 biosA0[0x4b] = psxBios_GPU_SendPackets;
3245 biosA0[0x4c] = psxBios_sys_a0_4c;
3246 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3247 //biosA0[0x4e] = psxBios_GPU_sync;
3248 //biosA0[0x4f] = psxBios_sys_a0_4f;
3249 //biosA0[0x50] = psxBios_sys_a0_50;
3250 biosA0[0x51] = psxBios_LoadExec;
3251 //biosA0[0x52] = psxBios_GetSysSp;
3252 //biosA0[0x53] = psxBios_sys_a0_53;
3253 //biosA0[0x54] = psxBios__96_init_a54;
3254 //biosA0[0x55] = psxBios__bu_init_a55;
3255 biosA0[0x56] = psxBios_CdRemove;
3256 //biosA0[0x57] = psxBios_sys_a0_57;
3257 //biosA0[0x58] = psxBios_sys_a0_58;
3258 //biosA0[0x59] = psxBios_sys_a0_59;
3259 //biosA0[0x5a] = psxBios_sys_a0_5a;
3260 //biosA0[0x5b] = psxBios_dev_tty_init;
3261 //biosA0[0x5c] = psxBios_dev_tty_open;
3262 //biosA0[0x5d] = psxBios_sys_a0_5d;
3263 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3264 //biosA0[0x5f] = psxBios_dev_cd_open;
3265 //biosA0[0x60] = psxBios_dev_cd_read;
3266 //biosA0[0x61] = psxBios_dev_cd_close;
3267 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3268 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3269 //biosA0[0x64] = psxBios_dev_cd_chdir;
3270 //biosA0[0x65] = psxBios_dev_card_open;
3271 //biosA0[0x66] = psxBios_dev_card_read;
3272 //biosA0[0x67] = psxBios_dev_card_write;
3273 //biosA0[0x68] = psxBios_dev_card_close;
3274 //biosA0[0x69] = psxBios_dev_card_firstfile;
3275 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3276 //biosA0[0x6b] = psxBios_dev_card_erase;
3277 //biosA0[0x6c] = psxBios_dev_card_undelete;
3278 //biosA0[0x6d] = psxBios_dev_card_format;
3279 //biosA0[0x6e] = psxBios_dev_card_rename;
3280 //biosA0[0x6f] = psxBios_dev_card_6f;
3281 biosA0[0x70] = psxBios__bu_init;
3282 biosA0[0x71] = psxBios__96_init;
3283 biosA0[0x72] = psxBios_CdRemove;
3284 //biosA0[0x73] = psxBios_sys_a0_73;
3285 //biosA0[0x74] = psxBios_sys_a0_74;
3286 //biosA0[0x75] = psxBios_sys_a0_75;
3287 //biosA0[0x76] = psxBios_sys_a0_76;
3288 //biosA0[0x77] = psxBios_sys_a0_77;
3289 //biosA0[0x78] = psxBios__96_CdSeekL;
3290 //biosA0[0x79] = psxBios_sys_a0_79;
3291 //biosA0[0x7a] = psxBios_sys_a0_7a;
3292 //biosA0[0x7b] = psxBios_sys_a0_7b;
3293 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3294 //biosA0[0x7d] = psxBios_sys_a0_7d;
3295 //biosA0[0x7e] = psxBios__96_CdRead;
3296 //biosA0[0x7f] = psxBios_sys_a0_7f;
3297 //biosA0[0x80] = psxBios_sys_a0_80;
3298 //biosA0[0x81] = psxBios_sys_a0_81;
3299 //biosA0[0x82] = psxBios_sys_a0_82;
3300 //biosA0[0x83] = psxBios_sys_a0_83;
3301 //biosA0[0x84] = psxBios_sys_a0_84;
3302 //biosA0[0x85] = psxBios__96_CdStop;
3303 //biosA0[0x86] = psxBios_sys_a0_86;
3304 //biosA0[0x87] = psxBios_sys_a0_87;
3305 //biosA0[0x88] = psxBios_sys_a0_88;
3306 //biosA0[0x89] = psxBios_sys_a0_89;
3307 //biosA0[0x8a] = psxBios_sys_a0_8a;
3308 //biosA0[0x8b] = psxBios_sys_a0_8b;
3309 //biosA0[0x8c] = psxBios_sys_a0_8c;
3310 //biosA0[0x8d] = psxBios_sys_a0_8d;
3311 //biosA0[0x8e] = psxBios_sys_a0_8e;
3312 //biosA0[0x8f] = psxBios_sys_a0_8f;
3313 biosA0[0x90] = hleExc0_1_2;
3314 biosA0[0x91] = hleExc0_0_2;
3315 biosA0[0x92] = hleExc0_1_1;
3316 biosA0[0x93] = hleExc0_0_1;
3317 //biosA0[0x94] = psxBios_sys_a0_94;
3318 //biosA0[0x95] = psxBios_sys_a0_95;
3319 //biosA0[0x96] = psxBios_AddCDROMDevice;
3320 //biosA0[0x97] = psxBios_AddMemCardDevide;
3321 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3322 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3323 //biosA0[0x9a] = psxBios_sys_a0_9a;
3324 //biosA0[0x9b] = psxBios_sys_a0_9b;
3325 //biosA0[0x9c] = psxBios_SetConf;
3326 //biosA0[0x9d] = psxBios_GetConf;
3327 //biosA0[0x9e] = psxBios_sys_a0_9e;
3328 biosA0[0x9f] = psxBios_SetMem;
3329 //biosA0[0xa0] = psxBios__boot;
3330 //biosA0[0xa1] = psxBios_SystemError;
3331 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3332 biosA0[0xa3] = psxBios_DequeueCdIntr;
3333 //biosA0[0xa4] = psxBios_sys_a0_a4;
3334 //biosA0[0xa5] = psxBios_ReadSector;
3335 biosA0[0xa6] = psxBios_get_cd_status;
3336 //biosA0[0xa7] = psxBios_bufs_cb_0;
3337 //biosA0[0xa8] = psxBios_bufs_cb_1;
3338 //biosA0[0xa9] = psxBios_bufs_cb_2;
3339 //biosA0[0xaa] = psxBios_bufs_cb_3;
3340 biosA0[0xab] = psxBios__card_info;
3341 biosA0[0xac] = psxBios__card_load;
3342 //biosA0[0axd] = psxBios__card_auto;
3343 //biosA0[0xae] = psxBios_bufs_cd_4;
3344 //biosA0[0xaf] = psxBios_sys_a0_af;
3345 //biosA0[0xb0] = psxBios_sys_a0_b0;
3346 //biosA0[0xb1] = psxBios_sys_a0_b1;
3347 //biosA0[0xb2] = psxBios_do_a_long_jmp
3348 //biosA0[0xb3] = psxBios_sys_a0_b3;
3349 //biosA0[0xb4] = psxBios_sub_function;
3350 //*******************B0 CALLS****************************
3351 biosB0[0x00] = psxBios_SysMalloc;
3352 //biosB0[0x01] = psxBios_sys_b0_01;
3353 biosB0[0x02] = psxBios_SetRCnt;
3354 biosB0[0x03] = psxBios_GetRCnt;
3355 biosB0[0x04] = psxBios_StartRCnt;
3356 biosB0[0x05] = psxBios_StopRCnt;
3357 biosB0[0x06] = psxBios_ResetRCnt;
3358 biosB0[0x07] = psxBios_DeliverEvent;
3359 biosB0[0x08] = psxBios_OpenEvent;
3360 biosB0[0x09] = psxBios_CloseEvent;
3361 biosB0[0x0a] = psxBios_WaitEvent;
3362 biosB0[0x0b] = psxBios_TestEvent;
3363 biosB0[0x0c] = psxBios_EnableEvent;
3364 biosB0[0x0d] = psxBios_DisableEvent;
3365 biosB0[0x0e] = psxBios_OpenTh;
3366 biosB0[0x0f] = psxBios_CloseTh;
3367 biosB0[0x10] = psxBios_ChangeTh;
3368 //biosB0[0x11] = psxBios_psxBios_b0_11;
3369 biosB0[0x12] = psxBios_InitPAD;
3370 biosB0[0x13] = psxBios_StartPAD;
3371 biosB0[0x14] = psxBios_StopPAD;
3372 biosB0[0x15] = psxBios_PAD_init;
3373 biosB0[0x16] = psxBios_PAD_dr;
3374 biosB0[0x17] = psxBios_ReturnFromException;
3375 biosB0[0x18] = psxBios_ResetEntryInt;
3376 biosB0[0x19] = psxBios_HookEntryInt;
3377 //biosB0[0x1a] = psxBios_sys_b0_1a;
3378 //biosB0[0x1b] = psxBios_sys_b0_1b;
3379 //biosB0[0x1c] = psxBios_sys_b0_1c;
3380 //biosB0[0x1d] = psxBios_sys_b0_1d;
3381 //biosB0[0x1e] = psxBios_sys_b0_1e;
3382 //biosB0[0x1f] = psxBios_sys_b0_1f;
3383 biosB0[0x20] = psxBios_UnDeliverEvent;
3384 //biosB0[0x21] = psxBios_sys_b0_21;
3385 //biosB0[0x22] = psxBios_sys_b0_22;
3386 //biosB0[0x23] = psxBios_sys_b0_23;
3387 //biosB0[0x24] = psxBios_sys_b0_24;
3388 //biosB0[0x25] = psxBios_sys_b0_25;
3389 //biosB0[0x26] = psxBios_sys_b0_26;
3390 //biosB0[0x27] = psxBios_sys_b0_27;
3391 //biosB0[0x28] = psxBios_sys_b0_28;
3392 //biosB0[0x29] = psxBios_sys_b0_29;
3393 //biosB0[0x2a] = psxBios_sys_b0_2a;
3394 //biosB0[0x2b] = psxBios_sys_b0_2b;
3395 //biosB0[0x2c] = psxBios_sys_b0_2c;
3396 //biosB0[0x2d] = psxBios_sys_b0_2d;
3397 //biosB0[0x2e] = psxBios_sys_b0_2e;
3398 //biosB0[0x2f] = psxBios_sys_b0_2f;
3399 //biosB0[0x30] = psxBios_sys_b0_30;
3400 //biosB0[0x31] = psxBios_sys_b0_31;
3401 biosB0[0x32] = psxBios_open;
3402 biosB0[0x33] = psxBios_lseek;
3403 biosB0[0x34] = psxBios_read;
3404 biosB0[0x35] = psxBios_write;
3405 biosB0[0x36] = psxBios_close;
3406 //biosB0[0x37] = psxBios_ioctl;
3407 //biosB0[0x38] = psxBios_exit;
3408 //biosB0[0x39] = psxBios_sys_b0_39;
3409 //biosB0[0x3a] = psxBios_getc;
3410 //biosB0[0x3b] = psxBios_putc;
3411 biosB0[0x3c] = psxBios_getchar;
3412 //biosB0[0x3e] = psxBios_gets;
3413 //biosB0[0x40] = psxBios_cd;
3414 biosB0[0x41] = psxBios_format;
3415 biosB0[0x42] = psxBios_firstfile;
3416 biosB0[0x43] = psxBios_nextfile;
3417 biosB0[0x44] = psxBios_rename;
3418 biosB0[0x45] = psxBios_delete;
3419 //biosB0[0x46] = psxBios_undelete;
3420 //biosB0[0x47] = psxBios_AddDevice;
3421 //biosB0[0x48] = psxBios_RemoteDevice;
3422 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3423 biosB0[0x4a] = psxBios_InitCARD;
3424 biosB0[0x4b] = psxBios_StartCARD;
3425 biosB0[0x4c] = psxBios_StopCARD;
3426 //biosB0[0x4d] = psxBios_sys_b0_4d;
3427 biosB0[0x4e] = psxBios__card_write;
3428 biosB0[0x4f] = psxBios__card_read;
3429 biosB0[0x50] = psxBios__new_card;
3430 biosB0[0x51] = psxBios_Krom2RawAdd;
3431 //biosB0[0x52] = psxBios_sys_b0_52;
3432 //biosB0[0x53] = psxBios_sys_b0_53;
3433 //biosB0[0x54] = psxBios__get_errno;
3434 biosB0[0x55] = psxBios__get_error;
3435 biosB0[0x56] = psxBios_GetC0Table;
3436 biosB0[0x57] = psxBios_GetB0Table;
3437 biosB0[0x58] = psxBios__card_chan;
3438 //biosB0[0x59] = psxBios_sys_b0_59;
3439 //biosB0[0x5a] = psxBios_sys_b0_5a;
3440 biosB0[0x5b] = psxBios_ChangeClearPad;
3441 biosB0[0x5c] = psxBios__card_status;
3442 biosB0[0x5d] = psxBios__card_wait;
3443 //*******************C0 CALLS****************************
3444 biosC0[0x00] = psxBios_InitRCnt;
3445 biosC0[0x01] = psxBios_InitException;
3446 biosC0[0x02] = psxBios_SysEnqIntRP;
3447 biosC0[0x03] = psxBios_SysDeqIntRP;
3448 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3449 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3450 //biosC0[0x06] = psxBios_ExceptionHandler;
3451 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3452 biosC0[0x08] = psxBios_SysInitMemory;
3453 //biosC0[0x09] = psxBios_SysInitKMem;
3454 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3455 //biosC0[0x0b] = psxBios_SystemError;
3456 biosC0[0x0c] = psxBios_InitDefInt;
3457 //biosC0[0x0d] = psxBios_sys_c0_0d;
3458 //biosC0[0x0e] = psxBios_sys_c0_0e;
3459 //biosC0[0x0f] = psxBios_sys_c0_0f;
3460 //biosC0[0x10] = psxBios_sys_c0_10;
3461 //biosC0[0x11] = psxBios_sys_c0_11;
3462 //biosC0[0x12] = psxBios_InstallDevices;
3463 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3464 //biosC0[0x14] = psxBios_sys_c0_14;
3465 //biosC0[0x15] = psxBios__cdevinput;
3466 //biosC0[0x16] = psxBios__cdevscan;
3467 //biosC0[0x17] = psxBios__circgetc;
3468 //biosC0[0x18] = psxBios__circputc;
3469 //biosC0[0x19] = psxBios_ioabort;
3470 //biosC0[0x1a] = psxBios_sys_c0_1a
3471 //biosC0[0x1b] = psxBios_KernelRedirect;
3472 //biosC0[0x1c] = psxBios_PatchAOTable;
3473 //************** THE END ***************************************
3480 memset(FDesc, 0, sizeof(FDesc));
3481 card_active_chan = 0;
3484 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3486 rom32 = (u32 *)psxR;
3487 rom32[0x100/4] = SWAP32(0x19951204);
3488 rom32[0x104/4] = SWAP32(3);
3489 strcpy(psxR + 0x108, "PCSX authors");
3490 strcpy(psxR + 0x12c, "PCSX HLE");
3493 len = 0x80000 - 0x66000;
3494 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3495 len = 0x80000 - 0x69d68;
3496 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3498 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3499 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3500 Here are some examples of games not working with this fix in place :
3501 R-type won't get past the Irem logo if not implemented.
3502 Crash Team Racing will softlock after the Sony logo.
3505 ram32 = (u32 *)psxM;
3506 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3507 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3508 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3509 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3511 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3512 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3514 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3515 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3516 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3517 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3519 ram32[0x00a0/4] = HLEOP(hleop_a0);
3520 ram32[0x00b0/4] = HLEOP(hleop_b0);
3521 ram32[0x00c0/4] = HLEOP(hleop_c0);
3525 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3526 strcpy((char *)&ram32[0xeff0/4], "bu");
3528 // default exception handler chains
3529 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3530 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3531 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3532 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3533 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3534 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3535 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3536 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3540 // fill the api jumptables with fake entries as some games patch them
3541 // (or rather the funcs listed there)
3542 ptr = (u32 *)&psxM[A_A0_TABLE];
3543 for (i = 0; i < 256; i++)
3544 ptr[i] = SWAP32(0x1000);
3546 ptr = (u32 *)&psxM[A_B0_TABLE];
3547 for (i = 0; i < 256; i++)
3548 ptr[i] = SWAP32(0x2000);
3549 // B(5b) is special because games patch (sometimes even jump to)
3550 // code at fixed offsets from it, nocash lists offsets:
3551 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3552 // call: +7a0=4b70, +884=4c54, +894=4c64
3553 ptr[0x5b] = SWAP32(0x43d0);
3554 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3556 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3557 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3558 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3560 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3561 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3563 ptr = (u32 *)&psxM[A_C0_TABLE];
3564 for (i = 0; i < 256/2; i++)
3565 ptr[i] = SWAP32(0x3000);
3566 ptr[6] = SWAP32(A_EXCEPTION);
3569 ram32[0x1000/4] = HLEOP(hleop_dummy);
3570 ram32[0x2000/4] = HLEOP(hleop_dummy);
3571 ram32[0x3000/4] = HLEOP(hleop_dummy);
3572 ram32[0x4c54/4] = HLEOP(hleop_dummy); // for B12_InitPad?
3573 ram32[0x8000/4] = HLEOP(hleop_execret);
3575 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3576 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3577 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3578 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3579 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3580 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3583 void psxBiosShutdown() {
3586 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3587 if (tcb_cnt != 4 || evcb_cnt != 16)
3588 setup_tt(tcb_cnt, evcb_cnt);
3591 #define psxBios_PADpoll(pad) { \
3592 PAD##pad##_startPoll(pad); \
3593 pad_buf##pad[0] = 0; \
3594 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3595 if (!(pad_buf##pad[1] & 0x0f)) { \
3598 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3600 PAD##pad##_poll(0); \
3602 while (bufcount--) { \
3603 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3607 static void biosPadHLE() {
3608 if (pad_buf != NULL) {
3609 u32 *buf = (u32*)pad_buf;
3612 if (PAD1_poll(0x42) == 0x23) {
3614 *buf = PAD1_poll(0) << 8;
3615 *buf |= PAD1_poll(0);
3617 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3618 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3621 *buf = PAD1_poll(0) << 8;
3622 *buf|= PAD1_poll(0);
3626 if (PAD2_poll(0x42) == 0x23) {
3628 *buf |= PAD2_poll(0) << 24;
3629 *buf |= PAD2_poll(0) << 16;
3631 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3632 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3635 *buf |= PAD2_poll(0) << 24;
3636 *buf |= PAD2_poll(0) << 16;
3641 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3645 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3646 psxBios_ReturnFromException();
3652 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3653 // so this is only partially implemented
3654 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3656 u32 cdrom_dma_ack_enable = 1; // a000b93c
3657 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3660 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3663 //PSXBIOS_LOG("%s\n", __func__);
3665 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3666 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3667 //if (--cdrom_irq_counter == 0) // 0xa0009180
3668 // DeliverEvent(0xf0000003, 0x10);
3672 mips_return_c(ret, 20);
3675 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3677 u32 cdrom_irq_ack_enable = 1; // a000b938
3678 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3681 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3684 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3685 PSXBIOS_LOG("%s TODO\n", __func__);
3688 mips_return_c(ret, 20);
3691 void hleExc0_2_2_syscall() // not in any A/B/C table
3693 u32 code = (psxRegs.CP0.n.Cause & 0x3c) >> 2;
3694 u32 tcbPtr = loadRam32(A_TT_PCB);
3695 TCB *tcb = loadRam32ptr(tcbPtr);
3697 if (code != R3000E_Syscall) {
3699 DeliverEvent(0xf0000010, 0x1000);
3700 psxBios_SystemErrorUnresolvedException();
3702 mips_return_c(0, 17);
3706 //printf("%s c=%d a0=%d\n", __func__, code, a0);
3707 tcb->epc += SWAP32(4);
3712 case 1: { // EnterCritical - disable irqs
3713 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3714 tcb->reg[2] = SWAP32(was_enabled);
3715 tcb->sr &= SWAP32(~0x404);
3718 case 2: // ExitCritical - enable irqs
3719 tcb->sr |= SWAP32(0x404);
3722 case 3: { // ChangeThreadSubFunction
3723 u32 tcbPtr = loadRam32(A_TT_PCB);
3724 storeRam32(tcbPtr, a1);
3728 DeliverEvent(0xf0000010, 0x4000);
3732 psxBios_ReturnFromException();
3735 void hleExc1_0_1(void)
3737 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3738 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3741 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3744 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3745 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3748 mips_return_c(ret, 22);
3751 void hleExc1_0_2(void)
3753 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3756 void hleExc1_1_1(void)
3758 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3759 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3762 void hleExc1_1_2(void)
3764 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3767 void hleExc1_2_1(void)
3769 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3770 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3773 void hleExc1_2_2(void)
3775 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3778 void hleExc1_3_1(void)
3780 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3781 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3784 void hleExc1_3_2(void)
3786 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3789 void hleExc3_0_2_defint(void)
3791 static const struct {
3802 { 6, 6 }, // rcnt2 (bug)
3807 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3808 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3809 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3814 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3817 void hleExcPadCard1(void)
3819 if (loadRam32(A_PAD_IRQR_ENA)) {
3820 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3821 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3829 if (loadRam32(A_PAD_ACK_VBL))
3830 psxHwWrite16(0x1f801070, ~1);
3831 if (loadRam32(A_CARD_IRQR_ENA)) {
3835 mips_return_c(0, 18);
3838 void hleExcPadCard2(void)
3840 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3841 mips_return_c(ret, 15);
3844 void psxBiosException() {
3845 u32 tcbPtr = loadRam32(A_TT_PCB);
3846 u32 *chains = loadRam32ptr(A_TT_ExCB);
3847 TCB *tcb = loadRam32ptr(tcbPtr);
3853 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3854 for (i = 4; i < 32; i++) {
3857 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3859 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3860 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3861 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3862 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3863 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3864 sp = fp = loadRam32(A_EXC_SP);
3868 // do the chains (always 4)
3869 for (c = lim = 0; c < 4; c++) {
3870 if (chains[c * 2] == 0)
3872 ptr = SWAP32(chains[c * 2]);
3873 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3874 chain = castRam32ptr(ptr);
3879 softCallInException(SWAP32(chain[2]));
3880 if (returned_from_exception())
3883 if (v0 == 0 || chain[1] == 0)
3885 softCallInException(SWAP32(chain[1]));
3886 if (returned_from_exception())
3892 // return from exception (custom or default)
3894 ptr = loadRam32(A_EEXIT_PTR);
3895 if (ptr != A_EEXIT_DEF) {
3896 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3897 longjmp_load(jmp_buf);
3902 psxBios_ReturnFromException();
3905 #define bfreeze(ptr, size) { \
3906 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3907 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3911 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3912 #define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3914 #define bfreezepsxMptr(ptr, type) { \
3916 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3917 else psxRu32ref(base) = 0; \
3919 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3920 else (ptr) = NULL; \
3922 base += sizeof(u32); \
3925 void psxBiosFreeze(int Mode) {
3928 bfreezepsxMptr(pad_buf, int);
3929 bfreezepsxMptr(heap_addr, u32);
3931 bfreezel(&card_active_chan);
3932 bfreezel(&heap_size);