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"
39 #include "psxevents.h"
45 //#define PSXBIOS_LOG printf
46 #define PSXBIOS_LOG(...)
48 #ifndef PSXBIOS_EV_LOG
49 //#define PSXBIOS_EV_LOG printf
50 #define PSXBIOS_EV_LOG(...)
53 #define PTR_1 (void *)(size_t)1
55 char *biosA0n[256] = {
57 "open", "lseek", "read", "write",
58 "close", "ioctl", "exit", "sys_a0_07",
59 "getc", "putc", "todigit", "atof",
60 "strtoul", "strtol", "abs", "labs",
62 "atoi", "atol", "atob", "setjmp",
63 "longjmp", "strcat", "strncat", "strcmp",
64 "strncmp", "strcpy", "strncpy", "strlen",
65 "index", "rindex", "strchr", "strrchr",
67 "strpbrk", "strspn", "strcspn", "strtok",
68 "strstr", "toupper", "tolower", "bcopy",
69 "bzero", "bcmp", "memcpy", "memset",
70 "memmove", "memcmp", "memchr", "rand",
72 "srand", "qsort", "strtod", "malloc",
73 "free", "lsearch", "bsearch", "calloc",
74 "realloc", "InitHeap", "_exit", "getchar",
75 "putchar", "gets", "puts", "printf",
77 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
78 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
79 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
80 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
82 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
83 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
84 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
85 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
87 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
88 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
89 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
90 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
92 "_bu_init", "CdInit", "CdRemove", "sys_a0_73",
93 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
94 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
95 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
97 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
98 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
99 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
100 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
102 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
103 "sys_a0_94", "CdReset", "AddCDROMDevice", "AddMemCardDevide",
104 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
105 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
107 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
108 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
109 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
110 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
112 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
116 char *biosB0n[256] = {
118 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
119 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
120 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
121 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
123 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
124 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromException",
125 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
126 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
128 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
129 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
130 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
131 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
133 "sys_b0_30", "sys_b0_31", "open", "lseek",
134 "read", "write", "close", "ioctl",
135 "exit", "sys_b0_39", "getc", "putc",
136 "getchar", "putchar", "gets", "puts",
138 "cd", "format", "firstfile", "nextfile",
139 "rename", "delete", "undelete", "AddDevice",
140 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
141 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
143 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
144 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
145 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
146 "_card_status", "_card_wait",
149 char *biosC0n[256] = {
151 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
152 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
153 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
154 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
156 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
157 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
158 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
162 //#define r0 (psxRegs.GPR.n.r0)
163 #define at (psxRegs.GPR.n.at)
164 #define v0 (psxRegs.GPR.n.v0)
165 #define v1 (psxRegs.GPR.n.v1)
166 #define a0 (psxRegs.GPR.n.a0)
167 #define a1 (psxRegs.GPR.n.a1)
168 #define a2 (psxRegs.GPR.n.a2)
169 #define a3 (psxRegs.GPR.n.a3)
170 #define t0 (psxRegs.GPR.n.t0)
171 #define t1 (psxRegs.GPR.n.t1)
172 #define t2 (psxRegs.GPR.n.t2)
173 #define t3 (psxRegs.GPR.n.t3)
174 #define t4 (psxRegs.GPR.n.t4)
175 #define t5 (psxRegs.GPR.n.t5)
176 #define t6 (psxRegs.GPR.n.t6)
177 #define t7 (psxRegs.GPR.n.t7)
178 #define t8 (psxRegs.GPR.n.t8)
179 #define t9 (psxRegs.GPR.n.t9)
180 #define s0 (psxRegs.GPR.n.s0)
181 #define s1 (psxRegs.GPR.n.s1)
182 #define s2 (psxRegs.GPR.n.s2)
183 #define s3 (psxRegs.GPR.n.s3)
184 #define s4 (psxRegs.GPR.n.s4)
185 #define s5 (psxRegs.GPR.n.s5)
186 #define s6 (psxRegs.GPR.n.s6)
187 #define s7 (psxRegs.GPR.n.s7)
188 #define k0 (psxRegs.GPR.n.k0)
189 #define k1 (psxRegs.GPR.n.k1)
190 #define gp (psxRegs.GPR.n.gp)
191 #define sp (psxRegs.GPR.n.sp)
192 #define fp (psxRegs.GPR.n.fp)
193 #define ra (psxRegs.GPR.n.ra)
194 #define pc0 (psxRegs.pc)
196 #define Ra0 ((char *)PSXM(a0))
197 #define Ra1 ((char *)PSXM(a1))
198 #define Ra2 ((char *)PSXM(a2))
199 #define Ra3 ((char *)PSXM(a3))
200 #define Rv0 ((char *)PSXM(v0))
201 #define Rsp ((char *)PSXM(sp))
212 #define EvStUNUSED 0x0000
213 #define EvStDISABLED 0x1000
214 #define EvStACTIVE 0x2000
215 #define EvStALREADY 0x4000
217 #define EvMdCALL 0x1000
218 #define EvMdMARK 0x2000
241 u32 _sp, _fp, _gp, ret, base;
261 // todo: FileDesc layout is wrong
262 // todo: get rid of these globals
263 static FileDesc FDesc[32];
264 static char ffile[64];
266 static char cdir[8*8+8];
269 // fixed RAM offsets, SCPH1001 compatible
270 #define A_TT_ExCB 0x0100
271 #define A_TT_PCB 0x0108
272 #define A_TT_TCB 0x0110
273 #define A_TT_EvCB 0x0120
274 #define A_A0_TABLE 0x0200
275 #define A_B0_TABLE 0x0874
276 #define A_C0_TABLE 0x0674
277 #define A_SYSCALL 0x0650
278 #define A_EXCEPTION 0x0c80
279 #define A_EXC_SP 0x6cf0
280 #define A_EEXIT_DEF 0x6cf4
281 #define A_CARD_ISLOT 0x7264 // 0 or 1, toggled by card vint handler
282 #define A_KMALLOC_PTR 0x7460
283 #define A_KMALLOC_SIZE 0x7464
284 #define A_KMALLOC_END 0x7468
285 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
286 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
287 #define A_CARD_IRQR_ENA 0x74bc // same for card
288 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
289 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
290 #define A_PAD_IN_LEN 0x74d8
291 #define A_PAD_OUT_LEN 0x74e0
292 #define A_PAD_DR_DST 0x74c4
293 #define A_CARD_ACHAN 0x7500 // currently active port in 0xPortSlot format
294 #define A_CARD_HANDLER 0x7528 // ptr to irq handler
295 #define A_CARD_STATUS1 0x7568
296 #define A_CARD_STATUS2 0x7569
297 #define A_PAD_DR_BUF1 0x7570
298 #define A_PAD_DR_BUF2 0x7598
299 #define A_EEXIT_PTR 0x75d0
300 #define A_EXC_STACK 0x85d8 // exception stack top
301 #define A_RCNT_VBL_ACK 0x8600
302 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
303 #define A_HEAP_BASE 0x9000
304 #define A_HEAP_SIZE 0x9004
305 #define A_HEAP_END 0x9008
306 #define A_HEAP_INIT_FLG 0x900c
307 #define A_RND_SEED 0x9010
308 #define A_HEAP_FRSTCHNK 0xb060
309 #define A_HEAP_CURCHNK 0xb064
310 #define A_CONF_TCB 0xb940
311 #define A_CONF_EvCB 0xb944
312 #define A_CONF_SP 0xb948
313 #define A_CD_EVENTS 0xb9b8
314 #define A_EXC_GP 0xf450
316 #define A_A0_TRAPS 0x1010
317 #define A_B0_TRAPS 0x2010
318 #define A_C0_TRAPS 0x3010
319 #define A_B0_5B_TRAP 0x43d0
321 #define CARD_HARDLER_WRITE 0x51F4
322 #define CARD_HARDLER_READ 0x5688
323 #define CARD_HARDLER_INFO 0x5B64
325 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
327 static u8 loadRam8(u32 addr)
329 assert(!(addr & 0x5f800000));
330 return psxM[addr & 0x1fffff];
333 static u32 loadRam32(u32 addr)
335 assert(!(addr & 0x5f800000));
336 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
339 static void *castRam8ptr(u32 addr)
341 assert(!(addr & 0x5f800000));
342 return psxM + (addr & 0x1fffff);
345 static void *castRam32ptr(u32 addr)
347 assert(!(addr & 0x5f800003));
348 return psxM + (addr & 0x1ffffc);
351 static void *loadRam8ptr(u32 addr)
353 return castRam8ptr(loadRam32(addr));
356 static void *loadRam32ptr(u32 addr)
358 return castRam32ptr(loadRam32(addr));
361 static void storeRam8(u32 addr, u8 d)
363 assert(!(addr & 0x5f800000));
364 *((u8 *)psxM + (addr & 0x1fffff)) = d;
367 static void storeRam32(u32 addr, u32 d)
369 assert(!(addr & 0x5f800000));
370 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
373 static void mips_return(u32 val)
379 static void mips_return_void(void)
384 static void use_cycles(u32 cycle)
386 psxRegs.cycle += cycle * 2;
389 static void mips_return_c(u32 val, u32 cycle)
395 static void mips_return_void_c(u32 cycle)
401 static int returned_from_exception(void)
403 // 0x80000080 means it took another exception just after return
404 return pc0 == k0 || pc0 == 0x80000080;
407 static inline void softCall(u32 pc) {
409 u32 ssr = psxRegs.CP0.n.SR;
413 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
415 assert(psxRegs.cpuInRecursion <= 1);
416 psxRegs.cpuInRecursion++;
417 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
419 while (pc0 != 0x80001000 && ++lim < 0x100000)
420 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
422 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
423 psxRegs.cpuInRecursion--;
426 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
428 psxRegs.CP0.n.SR |= ssr & 0x404;
431 static inline void softCallInException(u32 pc) {
436 assert(ra != 0x80001000);
437 if (ra == 0x80001000)
441 psxRegs.cpuInRecursion++;
442 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
444 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 0x100000)
445 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
447 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
448 psxRegs.cpuInRecursion--;
451 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
452 if (pc0 == 0x80001000)
456 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
457 static void EnableEvent(u32 ev, int do_log);
458 static u32 DeliverEvent(u32 class, u32 spec);
459 static u32 UnDeliverEvent(u32 class, u32 spec);
460 static void CloseEvent(u32 ev);
465 // System calls A0 */
468 #define buread(Ra1, mcd, length) { \
469 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); \
470 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
471 memcpy(Ra1, ptr, length); \
472 psxCpu->Clear(a1, (length + 3) / 4); \
473 if (FDesc[1 + mcd].mode & 0x8000) { \
474 DeliverEvent(0xf0000011, 0x0004); \
475 DeliverEvent(0xf4000001, 0x0004); \
478 FDesc[1 + mcd].offset += v0; \
481 #define buwrite(Ra1, mcd, length) { \
482 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
483 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
484 ptr = Mcd##mcd##Data + offset; \
485 memcpy(ptr, Ra1, length); \
486 FDesc[1 + mcd].offset += length; \
487 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
488 if (FDesc[1 + mcd].mode & 0x8000) { \
489 DeliverEvent(0xf0000011, 0x0004); \
490 DeliverEvent(0xf4000001, 0x0004); \
495 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
496 /* For some strange reason, the returned character is sign-expanded; */
497 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
498 /* TODO FIX ME : Properly implement this behaviour */
499 void psxBios_getc(void) // 0x03, 0x35
504 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
508 if (pa1 != INVALID_PTR) {
510 case 2: buread(pa1, 1, 1); break;
511 case 3: buread(pa1, 2, 1); break;
518 /* Copy of psxBios_write, except size is 1. */
519 void psxBios_putc(void) // 0x09, 0x3B
524 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
527 if (pa1 == INVALID_PTR) {
532 if (a0 == 1) { // stdout
533 char *ptr = (char *)pa1;
537 printf("%c", *ptr++); a2--;
543 case 2: buwrite(pa1, 1, 1); break;
544 case 3: buwrite(pa1, 2, 1); break;
550 static u32 do_todigit(u32 c)
553 if (c >= 0x30 && c < 0x3A) {
556 else if (c > 0x60 && c < 0x7B) {
559 else if (c > 0x40 && c < 0x5B) {
562 else if (c >= 0x80) {
563 log_unhandled("todigit %02x\n", c);
574 static void psxBios_todigit(void) // 0x0a
576 mips_return(do_todigit(a0));
577 PSXBIOS_LOG("psxBios_%s '%c' -> %u\n", biosA0n[0x0a], a0, v0);
580 static void do_strtol(char *p, void *end_, u32 base, int can_neg) {
585 if (p == INVALID_PTR) {
590 for (; (0x09 <= *p && *p <= '\r') || *p == ' '; p++)
593 for (; *p == '-'; f = 1, p++)
596 if (base == 0 || base > 36)
600 case 'b': case 'B': base = 2; break;
601 case 'x': case 'X': base = 16; break;
604 else if (*p == 'o' || *p == 'O') {
609 for (; (t = do_todigit(*p)) < base; p++) {
615 if (end != INVALID_PTR)
616 *end = SWAP32(a0 + (p - Ra0));
617 mips_return_c(n, 100);
620 static void psxBios_strtoul() { // 0x0c
621 do_strtol(a0 ? Ra0 : INVALID_PTR, a1 ? Ra1 : INVALID_PTR, a2, 0);
622 PSXBIOS_LOG("psxBios_%s %s (%x), %x, %x -> 0x%x\n",
623 biosA0n[0x0c], a0 ? Ra0 : NULL, a0, a1, a2, v0);
626 static void psxBios_strtol() { // 0x0d
627 do_strtol(a0 ? Ra0 : INVALID_PTR, a1 ? Ra1 : INVALID_PTR, a2, 1);
628 PSXBIOS_LOG("psxBios_%s %s (%x), %x, %x -> 0x%x\n",
629 biosA0n[0x0d], a0 ? Ra0 : NULL, a0, a1, a2, v0);
632 void psxBios_abs() { // 0x0e
633 if ((s32)a0 < 0) v0 = -(s32)a0;
638 void psxBios_labs() { // 0x0f
642 void psxBios_atoi() { // 0x10
644 char *p = (char *)Ra0;
646 if (p == INVALID_PTR) {
653 case ' ': case '\t': continue;
660 while (*p >= '0' && *p <= '9') {
661 n = n * 10 + *p++ - '0';
666 PSXBIOS_LOG("psxBios_%s %s (%x) -> 0x%x\n", biosA0n[0x10], Ra0, a0, v0);
669 void psxBios_atol() { // 0x11
679 static void psxBios_setjmp() { // 0x13
680 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
683 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
685 jmp_buf->ra_ = SWAP32(ra);
686 jmp_buf->sp_ = SWAP32(sp);
687 jmp_buf->fp_ = SWAP32(fp);
688 for (i = 0; i < 8; i++) // s0-s7
689 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
690 jmp_buf->gp_ = SWAP32(gp);
692 mips_return_c(0, 15);
695 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
699 ra = SWAP32(jmp_buf->ra_);
700 sp = SWAP32(jmp_buf->sp_);
701 fp = SWAP32(jmp_buf->fp_);
702 for (i = 0; i < 8; i++) // s0-s7
703 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
704 gp = SWAP32(jmp_buf->gp_);;
707 void psxBios_longjmp() { // 0x14
708 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
710 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
711 longjmp_load(jmp_buf);
712 mips_return_c(a1, 15);
715 void psxBios_strcat() { // 0x15
719 PSXBIOS_LOG("psxBios_%s %s (%x), %s (%x)\n", biosA0n[0x15], Ra0, a0, Ra1, a1);
720 if (a0 == 0 || a1 == 0 || p2 == INVALID_PTR)
725 while (loadRam8(p1)) {
729 for (; *p2; p1++, p2++)
733 mips_return_c(a0, 22);
736 void psxBios_strncat() { // 0x16
737 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
741 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
743 if (a0 == 0 || a1 == 0)
751 while ((*p1++ = *p2++) != '\0') {
761 void psxBios_strcmp() { // 0x17
762 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
764 if (a0 == 0 && a1 == 0)
770 else if (a0 == 0 && a1 != 0)
776 else if (a0 != 0 && a1 == 0)
783 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
786 while (*p1 == *p2++) {
805 void psxBios_strncmp() { // 0x18
806 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
808 if (a0 == 0 && a1 == 0)
814 else if (a0 == 0 && a1 != 0)
820 else if (a0 != 0 && a1 == 0)
827 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
830 while (--n >= 0 && *p1 == *p2++) {
834 v1 = a2 - ((a2-n) - 1);
842 v0 = (n < 0 ? 0 : *p1 - *--p2);
844 v1 = a2 - ((a2-n) - 1);
850 void psxBios_strcpy() { // 0x19
851 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
852 PSXBIOS_LOG("psxBios_%s %x, %s (%x)\n", biosA0n[0x19], a0, p2, a1);
853 if (a0 == 0 || a1 == 0)
859 while ((*p1++ = *p2++) != '\0');
864 void psxBios_strncpy() { // 0x1a
865 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
867 if (a0 == 0 || a1 == 0)
873 for (i = 0; i < n; i++) {
874 if ((*p1++ = *p2++) == '\0') {
886 void psxBios_strlen() { // 0x1b
887 char *p = (char *)Ra0;
898 void psxBios_index() { // 0x1c
899 char *p = (char *)Ra0;
909 v0 = a0 + (p - (char *)Ra0);
913 } while (*p++ != '\0');
918 void psxBios_rindex() { // 0x1d
919 char *p = (char *)Ra0;
929 v0 = a0 + (p - (char *)Ra0);
930 } while (*p++ != '\0');
935 void psxBios_strchr() { // 0x1e
939 void psxBios_strrchr() { // 0x1f
943 void psxBios_strpbrk() { // 0x20
944 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
946 while ((c = *p1++) != '\0') {
947 for (scanp = p2; (sc = *scanp++) != '\0';) {
949 v0 = a0 + (p1 - 1 - (char *)Ra0);
956 // BUG: return a0 instead of NULL if not found
960 void psxBios_strspn() { // 0x21
963 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
964 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
965 if (*p2 == '\0') break;
968 v0 = p1 - (char *)Ra0; pc0 = ra;
971 void psxBios_strcspn() { // 0x22
974 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
975 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
976 if (*p2 != '\0') break;
979 v0 = p1 - (char *)Ra0; pc0 = ra;
982 void psxBios_strtok() { // 0x23
983 char *pcA0 = (char *)Ra0;
984 char *pcRet = strtok(pcA0, (char *)Ra1);
986 v0 = a0 + pcRet - pcA0;
992 void psxBios_strstr() { // 0x24
993 char *p = (char *)Ra0, *p1, *p2;
994 PSXBIOS_LOG("psxBios_%s %s (%x), %s (%x)\n", biosA0n[0x24], p, a0, Ra1, a1);
1000 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
1005 v0 = a0 + (p - (char *)Ra0);
1007 PSXBIOS_LOG(" -> %x\n", v0);
1011 // bug: skips the whole matched substring + 1
1018 void psxBios_toupper() { // 0x25
1019 v0 = (s8)(a0 & 0xff);
1020 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
1024 void psxBios_tolower() { // 0x26
1025 v0 = (s8)(a0 & 0xff);
1026 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
1030 static void do_memset(u32 dst, u32 v, s32 len)
1036 if (db != INVALID_PTR)
1040 psxCpu->Clear(dst, (len + 3) / 4);
1043 static void do_memcpy(u32 dst, u32 src, s32 len)
1045 u32 d = dst, s = src;
1048 const u8 *sb = PSXM(s);
1050 if (db != INVALID_PTR && sb != INVALID_PTR)
1055 psxCpu->Clear(dst, (len + 3) / 4);
1058 static void psxBios_memcpy();
1060 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
1061 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
1062 u32 ret = a0, cycles = 0;
1063 if (a0 == 0) // ...but it checks src this time
1065 mips_return_c(0, 4);
1070 do_memcpy(a1, a0, a2);
1076 mips_return_c(ret, cycles + 5);
1079 static void psxBios_bzero() { // 0x28
1080 /* Same as memset here (See memset below) */
1081 u32 ret = a0, cycles;
1082 if (a0 == 0 || (s32)a1 <= 0)
1084 mips_return_c(0, 6);
1087 do_memset(a0, 0, a1);
1091 // todo: many more cycles due to uncached bios mem
1092 mips_return_c(ret, cycles + 5);
1095 void psxBios_bcmp() { // 0x29
1096 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
1098 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
1100 while ((s32)a2-- > 0) {
1101 if (*p1++ != *p2++) {
1102 v0 = *p1 - *p2; // BUG: compare the NEXT byte
1111 static void psxBios_memcpy() { // 0x2a
1112 u32 ret = a0, cycles = 0;
1115 mips_return_c(0, 4);
1120 do_memcpy(a0, a1, a2);
1126 mips_return_c(ret, cycles + 5);
1129 static void psxBios_memset() { // 0x2b
1130 u32 ret = a0, cycles;
1131 if (a0 == 0 || (s32)a2 <= 0)
1133 mips_return_c(0, 6);
1136 do_memset(a0, a1, a2);
1140 // todo: many more cycles due to uncached bios mem
1141 mips_return_c(ret, cycles + 5);
1144 void psxBios_memmove() { // 0x2c
1145 u32 ret = a0, cycles = 0;
1148 mips_return_c(0, 4);
1152 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1153 u32 dst = a0, len = a2 + 1;
1156 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1157 const u8 *sb = PSXM(a1);
1159 if (db != INVALID_PTR && sb != INVALID_PTR)
1165 psxCpu->Clear(dst, (len + 3) / 4);
1166 cycles = 10 + len * 8;
1167 } else if ((s32)a2 > 0) {
1168 do_memcpy(a0, a1, a2);
1174 mips_return_c(ret, cycles + 5);
1177 void psxBios_memcmp() { // 0x2d
1181 void psxBios_memchr() { // 0x2e
1182 char *p = (char *)Ra0;
1184 if (a0 == 0 || a2 > 0x7FFFFFFF)
1190 while ((s32)a2-- > 0) {
1191 if (*p++ != (s8)a1) continue;
1192 v0 = a0 + (p - (char *)Ra0 - 1);
1200 static void psxBios_rand() { // 0x2f
1201 u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1202 storeRam32(A_RND_SEED, s);
1204 mips_return_c((s >> 16) & 0x7fff, 12+37);
1207 static void psxBios_srand() { // 0x30
1208 storeRam32(A_RND_SEED, a0);
1209 mips_return_void_c(3);
1212 static u32 qscmpfunc, qswidth;
1214 static inline int qscmp(char *a, char *b) {
1217 a0 = sa0 + (a - (char *)PSXM(sa0));
1218 a1 = sa0 + (b - (char *)PSXM(sa0));
1220 softCall(qscmpfunc);
1226 static inline void qexchange(char *i, char *j) {
1237 static inline void q3exchange(char *i, char *j, char *k) {
1249 static void qsort_main(char *a, char *l) {
1250 char *i, *j, *lp, *hp;
1255 if ((n = l - a) <= qswidth)
1257 n = qswidth * (n / (2 * qswidth));
1263 if ((c = qscmp(i, lp)) == 0) {
1264 qexchange(i, lp -= qswidth);
1275 if ((c = qscmp(hp, j)) == 0) {
1276 qexchange(hp += qswidth, j);
1281 q3exchange(i, hp += qswidth, j);
1295 if (lp - a >= l - hp) {
1296 qsort_main(hp + qswidth, l);
1305 q3exchange(j, lp -= qswidth, i);
1310 void psxBios_qsort() { // 0x31
1313 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1318 static int malloc_heap_grow(u32 size) {
1319 u32 heap_addr, heap_end, heap_addr_new;
1321 heap_addr = loadRam32(A_HEAP_BASE);
1322 heap_end = loadRam32(A_HEAP_END);
1323 heap_addr_new = heap_addr + 4 + size;
1324 if (heap_addr_new >= heap_end)
1326 storeRam32(A_HEAP_BASE, heap_addr_new);
1327 storeRam32(heap_addr - 4, size | 1);
1328 storeRam32(heap_addr + size, ~1); // terminator
1332 static void psxBios_malloc() { // 0x33
1333 u32 size = (a0 + 3) & ~3;
1334 u32 limit = 32*1024;
1338 PSXBIOS_LOG("psxBios_%s %d\n", biosA0n[0x33], a0);
1340 if (!loadRam32(A_HEAP_INIT_FLG)) {
1341 u32 heap_addr = loadRam32(A_HEAP_BASE);
1342 storeRam32(heap_addr, ~1);
1343 storeRam32(A_HEAP_FRSTCHNK, heap_addr);
1344 storeRam32(A_HEAP_CURCHNK, heap_addr);
1345 storeRam32(A_HEAP_BASE, heap_addr + 4);
1346 if (malloc_heap_grow(size)) {
1347 PSXBIOS_LOG("malloc: init OOM\n");
1348 mips_return_c(0, 20);
1351 storeRam32(A_HEAP_INIT_FLG, 1);
1354 for (i = 0; tries > 0 && i < limit; i++)
1356 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1357 u32 chunk_hdr = loadRam32(chunk);
1358 u32 next_chunk = chunk + 4 + (chunk_hdr & ~3);
1359 u32 next_chunk_hdr = loadRam32(next_chunk);
1361 //printf(" c %08x %08x\n", chunk, chunk_hdr);
1362 if (chunk_hdr & 1) {
1364 if (chunk_hdr > (size | 1)) {
1366 u32 p2size = (chunk_hdr & ~3) - size - 4;
1367 storeRam32(chunk + 4 + size, p2size | 1);
1368 chunk_hdr = size | 1;
1370 if (chunk_hdr == (size | 1)) {
1371 storeRam32(chunk, size);
1375 if (next_chunk_hdr & 1) {
1377 u32 msize = (chunk_hdr & ~3) + 4 + (next_chunk_hdr & ~3);
1378 storeRam32(chunk, msize | 1);
1382 if (chunk_hdr == ~1) {
1385 storeRam32(A_HEAP_CURCHNK, loadRam32(A_HEAP_FRSTCHNK));
1389 // go to the next chunk
1390 storeRam32(A_HEAP_CURCHNK, next_chunk);
1396 else if (tries == 0 && malloc_heap_grow(size))
1399 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1400 storeRam32(chunk, loadRam32(chunk) & ~3);
1404 PSXBIOS_LOG(" -> %08x\n", ret);
1405 mips_return_c(ret, 40);
1408 static void psxBios_free() { // 0x34
1409 PSXBIOS_LOG("psxBios_%s %x (%d bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1410 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1411 mips_return_void_c(5);
1414 static void psxBios_calloc() { // 0x37
1416 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1418 a0 = size = a0 * a1;
1422 a0 = ret; a1 = size;
1425 mips_return_c(ret, 21);
1428 void psxBios_realloc() { // 0x38
1432 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1436 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1441 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1446 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1447 /* Note that it is not quite implemented this way here. */
1457 /* InitHeap(void *block , int n) */
1458 static void psxBios_InitHeap() { // 0x39
1459 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1461 storeRam32(A_HEAP_BASE, a0);
1462 storeRam32(A_HEAP_SIZE, a1);
1463 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1464 storeRam32(A_HEAP_INIT_FLG, 0);
1467 mips_return_void_c(14);
1470 void psxBios_getchar() { //0x3b
1471 v0 = getchar(); pc0 = ra;
1474 static void psxBios_printf_psxout() { // 0x3f
1477 u32 save[4] = { 0, };
1483 if (psp != INVALID_PTR) {
1484 memcpy(save, psp, 4 * 4);
1485 psxMu32ref(sp) = SWAP32((u32)a0);
1486 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1487 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1488 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1500 tmp2[j++] = Ra0[i]; goto _start;
1502 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1513 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1517 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1523 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1525 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1527 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1529 *ptmp++ = Ra0[i]; break;
1539 if (psp != INVALID_PTR)
1540 memcpy(psp, save, 4 * 4);
1543 SysPrintf("%s", tmp);
1546 void psxBios_printf() { // 0x3f
1547 psxBios_printf_psxout();
1551 static void psxBios_cd() { // 0x40
1552 const char *p, *dir = Ra0;
1553 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x40], a0, dir);
1554 if (dir != INVALID_PTR) {
1555 if ((p = strchr(dir, ':')))
1559 snprintf(cdir, sizeof(cdir), "%s", dir);
1561 mips_return_c(1, 100);
1564 static void psxBios_format() { // 0x41
1565 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x41], a0, Ra0);
1566 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1568 CreateMcd(Config.Mcd1);
1569 LoadMcd(1, Config.Mcd1);
1572 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1574 CreateMcd(Config.Mcd2);
1575 LoadMcd(2, Config.Mcd2);
1585 static void psxBios_SystemErrorUnresolvedException() {
1586 if (floodchk != 0x12340a40) { // prevent log flood
1587 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1588 floodchk = 0x12340a40;
1590 mips_return_void_c(1000);
1593 static void FlushCache() {
1594 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1595 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1597 // runs from uncached mem so tons of cycles
1601 // you likely want to mask irqs before calling these
1602 static u8 cdrom_sync(int do_ack)
1605 if (psxRegs.interrupt & (1u << PSXINT_CDR)) {
1606 if ((s32)(psxRegs.cycle - event_cycles[PSXINT_CDR]) < 0)
1607 psxRegs.cycle = event_cycles[PSXINT_CDR] + 1;
1608 irq_test(&psxRegs.CP0);
1612 r = cdrRead3() & 0x1f;
1613 cdrWrite3(0x5f); // ack; clear params
1618 static void cdrom_cmd_and_wait(u8 cmd, int arg_cnt, int resp_cnt, ...)
1624 va_start(ap, resp_cnt);
1625 while (arg_cnt-- > 0)
1626 cdrWrite2(va_arg(ap, u32));
1631 u8 r = cdrom_sync(1);
1632 assert(r == 3); (void)r;
1636 u8 r = cdrom_sync(1);
1637 assert(r == 2); (void)r;
1643 * long Load(char *name, struct EXEC *header);
1646 void psxBios_Load() { // 0x42
1647 u8 time[3] = { 2, 0, 0x16 };
1655 PSXBIOS_LOG("psxBios_%s %x(%s), %x\n", biosA0n[0x42], a0, pa0, a1);
1656 if (pa0 == INVALID_PTR || pa1 == INVALID_PTR) {
1660 if ((p = strchr(pa0, ':')))
1665 snprintf(path, sizeof(path), "%s\\%s", cdir, (char *)pa0);
1667 snprintf(path, sizeof(path), "%s", (char *)pa0);
1669 if (LoadCdromFile(path, &eheader, time) == 0) {
1670 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1671 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1675 PSXBIOS_LOG(" -> %d\n", v0);
1679 // set the cdrom to a state of just after exe read
1680 psxRegs.CP0.n.SR &= ~0x404;
1683 cdrWrite2(0x1f); // unmask
1684 cdrom_cmd_and_wait(0x0e, 1, 1, 0x80u); // CdlSetmode
1685 cdrom_cmd_and_wait(0x02, 3, 1, time[0], time[1], time[2]); // CdlSetloc
1686 cdrom_cmd_and_wait(0x15, 0, 2); // CdlSeekL
1687 psxHwWrite16(0x1f801070, ~4);
1688 MTC0(&psxRegs, 12, psxRegs.CP0.n.SR | 0x404);
1692 * int Exec(struct EXEC *header , int argc , char **argv);
1695 void psxBios_Exec() { // 43
1696 EXEC *header = (EXEC *)castRam32ptr(a0);
1700 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1702 header->_sp = SWAP32(sp);
1703 header->_fp = SWAP32(fp);
1704 header->_sp = SWAP32(sp);
1705 header->_gp = SWAP32(gp);
1706 header->ret = SWAP32(ra);
1707 header->base = SWAP32(s0);
1709 ptr = SWAP32(header->b_addr);
1710 len = SWAP32(header->b_size);
1716 if (header->S_addr != 0)
1717 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1719 gp = SWAP32(header->gp0);
1727 pc0 = SWAP32(header->_pc0);
1730 static void psxBios_FlushCache() { // 44
1731 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1736 void psxBios_GPU_dw() { // 0x46
1741 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1744 GPU_writeData(0xa0000000);
1745 GPU_writeData((a1<<0x10)|(a0&0xffff));
1746 GPU_writeData((a3<<0x10)|(a2&0xffff));
1748 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1751 GPU_writeData(SWAPu32(*ptr++));
1757 static void gpu_sync() {
1758 // not implemented...
1759 // might be problematic to do because of Config.GpuListWalking
1760 if (psxRegs.interrupt & (1u << PSXINT_GPUDMA))
1761 log_unhandled("gpu_sync with active dma\n");
1762 mips_return_c(0, 21);
1765 void psxBios_mem2vram() { // 0x47
1767 gpuSyncPluginSR(); // flush
1768 GPU_writeData(0xa0000000);
1769 GPU_writeData((a1<<0x10)|(a0&0xffff));
1770 GPU_writeData((a3<<0x10)|(a2&0xffff));
1771 size = ((((a2 * a3) / 2) >> 4) << 16);
1772 GPU_writeStatus(0x04000002);
1773 psxHwWrite32(0x1f8010f4,0);
1774 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1775 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1776 psxHwWrite32(0x1f8010a4, size | 0x10);
1777 psxHwWrite32(0x1f8010a8,0x01000201);
1782 void psxBios_SendGPU() { // 0x48
1783 GPU_writeStatus(a0);
1788 void psxBios_GPU_cw() { // 0x49
1795 void psxBios_GPU_cwb() { // 0x4a
1796 u32 *ptr = (u32*)Ra0;
1801 GPU_writeData(SWAPu32(*ptr++));
1807 void psxBios_GPU_SendPackets() { //4b:
1809 GPU_writeStatus(0x04000002);
1810 psxHwWrite32(0x1f8010f4,0);
1811 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1812 psxHwWrite32(0x1f8010a0,a0);
1813 psxHwWrite32(0x1f8010a4,0);
1814 psxHwWrite32(0x1f8010a8,0x010000401);
1818 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1819 psxHwWrite32(0x1f8010a8,0x00000401);
1820 GPU_writeData(0x0400000);
1821 GPU_writeData(0x0200000);
1822 GPU_writeData(0x0100000);
1827 void psxBios_GPU_GetGPUStatus() { // 0x4d
1828 v0 = GPU_readStatus();
1834 void psxBios_LoadExec() { // 51
1835 EXEC *header = (EXEC*)PSXM(0xf000);
1839 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1841 s_addr = a1; s_size = a2;
1846 header->S_addr = s_addr;
1847 header->s_size = s_size;
1849 a0 = 0xf000; a1 = 0; a2 = 0;
1853 static void psxBios__bu_init() { // 70
1854 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1856 DeliverEvent(0xf0000011, 0x0004);
1857 DeliverEvent(0xf4000001, 0x0004);
1862 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1863 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1864 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1866 static void psxBios_EnqueueCdIntr_(void)
1868 u32 *ram32 = (u32 *)psxM;
1870 // traps should already be installed by write_chain()
1871 ram32[0x91d0/4] = 0;
1872 ram32[0x91d4/4] = SWAP32(0xbfc0506c);
1873 ram32[0x91d8/4] = SWAP32(0xbfc04dec);
1874 psxBios_SysEnqIntRP_(0, 0x91d0);
1875 ram32[0x91e0/4] = 0;
1876 ram32[0x91e4/4] = SWAP32(0xbfc050a4);
1877 ram32[0x91e8/4] = SWAP32(0xbfc04fbc);
1878 psxBios_SysEnqIntRP_(0, 0x91e0);
1882 static void setup_cd_irq_and_events(void)
1884 u16 specs[] = { 0x10, 0x20, 0x40, 0x80, 0x8000 };
1887 psxBios_EnqueueCdIntr_();
1889 for (i = 0; i < sizeof(specs) / sizeof(specs[0]); i++) {
1890 u32 h = OpenEvent(0xf0000003, specs[i], EvMdMARK, 0);
1892 storeRam32(A_CD_EVENTS + i * 4, h);
1897 static void psxBios_CdReset_() {
1898 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
1902 cdrWrite2(0x1f); // unmask
1903 cdrom_cmd_and_wait(0x0a, 0, 2); // CdlReset
1904 cdrom_cmd_and_wait(0x0e, 1, 1, 0x80u); // CdlSetmode
1906 // todo(?): should read something (iso root directory?)
1907 // from { 0, 2, 16 } to somewhere and pause
1910 psxHwWrite16(0x1f801070, ~4);
1911 MTC0(&psxRegs, 12, psxRegs.CP0.n.SR | 0x404);
1912 DeliverEvent(0xf0000003, 0x0020);
1915 static void psxBios_CdInit() { // 54, 71
1916 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1917 setup_cd_irq_and_events();
1921 // this function takes pretty much forever
1922 mips_return_c(0, 50000*11);
1925 static void psxBios_DequeueCdIntr_() {
1926 psxBios_SysDeqIntRP_(0, 0x91d0);
1927 psxBios_SysDeqIntRP_(0, 0x91e0);
1931 static void psxBios_CdReset() { // 95
1932 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x95]);
1936 static void psxBios_EnqueueCdIntr() { // a2
1937 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa2]);
1938 psxBios_EnqueueCdIntr_();
1939 // return value comes from SysEnqIntRP() insternal call
1942 static void psxBios_DequeueCdIntr() { // a3
1943 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1944 psxBios_DequeueCdIntr_();
1947 static void psxBios_CdRemove() { // 56, 72
1948 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1950 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1951 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1952 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1953 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1954 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1955 psxBios_DequeueCdIntr_();
1957 // EnterCriticalSection - should be done at the beginning,
1958 // but this way is much easier to implement
1964 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1966 static void psxBios_SetConf() { // 9c
1967 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1968 setup_tt(a1, a0, a2);
1969 psxRegs.CP0.n.SR |= 0x401;
1970 mips_return_void_c(500);
1973 static void psxBios_GetConf() { // 9d
1974 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1975 storeRam32(a0, loadRam32(A_CONF_EvCB));
1976 storeRam32(a1, loadRam32(A_CONF_TCB));
1977 storeRam32(a2, loadRam32(A_CONF_SP));
1978 mips_return_void_c(10);
1981 void psxBios_SetMem() { // 9f
1982 u32 new = psxHu32(0x1060);
1985 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1990 psxHu32ref(0x1060) = SWAP32(new);
1991 psxMu32ref(0x060) = a0;
1992 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1996 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1997 psxMu32ref(0x060) = a0;
1998 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
2001 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
2008 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
2009 static void psxBios_get_cd_status() // a6
2011 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
2016 static void psxBios_GetSystemInfo() { // b4
2018 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
2019 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
2022 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
2023 case 2: ret = 0xbfc0012c; break;
2024 case 5: ret = loadRam32(0x60) << 10; break;
2026 mips_return_c(ret, 20);
2029 /* System calls B0 */
2031 static u32 psxBios_SysMalloc_(u32 size);
2033 static void psxBios_SysMalloc() { // B 00
2034 u32 ret = psxBios_SysMalloc_(a0);
2036 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
2037 mips_return_c(ret, 33);
2040 void psxBios_SetRCnt() { // 02
2042 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
2049 psxRcntWtarget(a0, a1);
2050 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
2051 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
2052 if (a2&0x0010) mode|= 0x001; // Timer stop mode
2053 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
2054 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
2056 psxRcntWmode(a0, mode);
2061 void psxBios_GetRCnt() { // 03
2063 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
2068 case 0: v0 = psxRcntRcount0(); break;
2069 case 1: v0 = psxRcntRcount1(); break;
2070 case 2: v0 = psxRcntRcount2(); break;
2071 case 3: v0 = 0; break;
2076 void psxBios_StartRCnt() { // 04
2078 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
2082 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
2083 else psxHu32ref(0x1074)|= SWAPu32(0x1);
2087 void psxBios_StopRCnt() { // 05
2089 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
2093 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
2094 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
2098 void psxBios_ResetRCnt() { // 06
2100 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
2105 psxRcntWmode(a0, 0);
2106 psxRcntWtarget(a0, 0);
2107 psxRcntWcount(a0, 0);
2112 static u32 DeliverEvent(u32 class, u32 spec) {
2113 EvCB *ev, *ev_first = (EvCB *)loadRam32ptr(A_TT_EvCB);
2114 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
2115 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
2116 u32 i, lim = evcb_len / 0x1c;
2118 //printf("%s %08x %x\n", __func__, class, spec);
2119 for (i = 0, ev = ev_first; i < lim; i++, ev++) {
2121 if (SWAP32(ev->status) != EvStACTIVE)
2124 if (SWAP32(ev->class) != class)
2127 if (SWAP32(ev->spec) != spec)
2130 ret = SWAP32(ev->mode);
2131 if (ret == EvMdMARK) {
2132 if (ev->status != SWAP32(EvStALREADY))
2133 PSXBIOS_EV_LOG("DeliverEvent %08x %x (%08zx) set\n",
2134 class, spec, (ev - ev_first) | 0xf1000000u);
2135 ev->status = SWAP32(EvStALREADY);
2139 if (ret == EvMdCALL) {
2140 ret = SWAP32(ev->fhandler);
2141 PSXBIOS_EV_LOG("DeliverEvent %08x %x (%08zx) cb %x\n",
2142 class, spec, (ev - ev_first) | 0xf1000000u, ret);
2155 static u32 UnDeliverEvent(u32 class, u32 spec) {
2156 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2157 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
2158 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
2159 u32 i, lim = evcb_len / 0x1c;
2161 for (i = 0; i < lim; i++, ev++) {
2163 if (SWAP32(ev->status) != EvStALREADY)
2166 if (SWAP32(ev->class) != class)
2169 if (SWAP32(ev->spec) != spec)
2172 if (SWAP32(ev->mode) == EvMdMARK)
2173 ev->status = SWAP32(EvStACTIVE);
2179 static void psxBios_DeliverEvent() { // 07
2181 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
2183 ret = DeliverEvent(a0, a1);
2187 static s32 get_free_EvCB_slot() {
2188 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2189 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
2192 for (i = 0; i < lim; i++, ev++) {
2194 if (ev->status == SWAP32(EvStUNUSED))
2200 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2201 u32 ret = get_free_EvCB_slot();
2202 if ((s32)ret >= 0) {
2203 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2204 ev->class = SWAP32(class);
2205 ev->status = SWAP32(EvStDISABLED);
2206 ev->spec = SWAP32(spec);
2207 ev->mode = SWAP32(mode);
2208 ev->fhandler = SWAP32(func);
2214 static void psxBios_OpenEvent() { // 08
2215 u32 ret = OpenEvent(a0, a1, a2, a3);
2216 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2217 biosB0n[0x08], a0, a1, a2, a3, ret);
2218 mips_return_c(ret, 36);
2221 static void CloseEvent(u32 ev)
2223 u32 base = loadRam32(A_TT_EvCB);
2224 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2227 static void psxBios_CloseEvent() { // 09
2228 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2229 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2231 mips_return_c(1, 10);
2234 static void psxBios_WaitEvent() { // 0a
2235 u32 base = loadRam32(A_TT_EvCB);
2236 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2237 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2240 if (status == EvStALREADY) {
2241 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2245 if (status != EvStACTIVE)
2247 mips_return_c(0, 2);
2251 // retrigger this hlecall after the next emulation event
2253 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2254 psxRegs.cycle = next_interupt;
2258 static void psxBios_TestEvent() { // 0b
2259 u32 base = loadRam32(A_TT_EvCB);
2260 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2263 if (psxRegs.cycle - floodchk > 16*1024u) { // prevent log flood
2264 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2265 floodchk = psxRegs.cycle;
2267 if (status == EvStALREADY) {
2268 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2272 mips_return_c(ret, 15);
2275 static void EnableEvent(u32 ev, int do_log) {
2276 u32 base = loadRam32(A_TT_EvCB);
2277 u32 status = loadRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4);
2279 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], ev, status);
2280 if (status != EvStUNUSED)
2281 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2284 static void psxBios_EnableEvent() { // 0c
2286 mips_return_c(1, 15);
2289 static void psxBios_DisableEvent() { // 0d
2290 u32 base = loadRam32(A_TT_EvCB);
2291 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2292 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2293 if (status != EvStUNUSED)
2294 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2296 mips_return_c(1, 15);
2300 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2303 void psxBios_OpenTh() { // 0e
2304 TCB *tcb = loadRam32ptr(A_TT_TCB);
2305 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2308 for (th = 1; th < limit; th++)
2310 if (tcb[th].status != SWAP32(0x4000)) break;
2314 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2315 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2317 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2319 mips_return_c(0xffffffff, 20);
2322 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2324 tcb[th].status = SWAP32(0x4000);
2325 tcb[th].mode = SWAP32(0x1000);
2326 tcb[th].epc = SWAP32(a0);
2327 tcb[th].reg[30] = SWAP32(a1); // fp
2328 tcb[th].reg[29] = SWAP32(a1); // sp
2329 tcb[th].reg[28] = SWAP32(a2); // gp
2331 mips_return_c(0xff000000 + th, 34);
2335 * int CloseTh(long thread);
2338 static void psxBios_CloseTh() { // 0f
2339 u32 tcb = loadRam32(A_TT_TCB);
2340 u32 th = a0 & 0xffff;
2342 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2343 // in the usual bios fashion no checks, just write and return 1
2344 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2346 mips_return_c(1, 11);
2350 * int ChangeTh(long thread);
2353 void psxBios_ChangeTh() { // 10
2354 u32 tcbBase = loadRam32(A_TT_TCB);
2355 u32 th = a0 & 0xffff;
2357 // this is quite spammy
2358 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2360 // without doing any argument checks, just issue a syscall
2361 // (like the real bios does)
2363 a1 = tcbBase + th * sizeof(TCB);
2368 void psxBios_InitPAD() { // 0x12
2369 u32 i, *ram32 = (u32 *)psxM;
2370 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2372 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2373 ram32[A_PAD_DR_DST/4] = 0;
2374 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2375 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2376 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2377 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2378 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2379 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2380 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2381 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2383 for (i = 0; i < a1; i++) {
2385 storeRam8(a0 + i, 0);
2387 for (i = 0; i < a3; i++) {
2389 storeRam8(a2 + i, 0);
2391 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2393 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2395 mips_return_c(1, 200);
2398 void psxBios_StartPAD() { // 13
2399 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2401 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2402 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2403 psxHwWrite16(0x1f801070, ~1);
2404 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2405 storeRam32(A_PAD_ACK_VBL, 1);
2406 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2407 psxRegs.CP0.n.SR |= 0x401;
2409 mips_return_c(1, 300);
2412 void psxBios_StopPAD() { // 14
2413 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2414 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2415 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2416 psxRegs.CP0.n.SR |= 0x401;
2417 mips_return_void_c(200);
2420 static void psxBios_PAD_init() { // 15
2422 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2423 if (a0 == 0x20000000 || a0 == 0x20000001)
2426 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2427 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2430 storeRam32(A_PAD_DR_DST, dst);
2433 mips_return_c(ret, 100);
2436 static u32 psxBios_PAD_dr_() {
2437 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2438 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2439 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2440 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2441 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2443 dst[0] = buf1[3], dst[1] = buf1[2];
2444 if (buf1[1] == 0x23) {
2445 dst[0] |= 0xc7, dst[1] |= 7;
2446 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2447 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2450 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2452 dst[2] = buf2[3], dst[3] = buf2[2];
2453 if (buf2[1] == 0x23) {
2454 dst[2] |= 0xc7, dst[3] |= 7;
2455 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2456 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2460 return SWAP32(*(u32 *)dst);
2463 static void psxBios_PAD_dr() { // 16
2464 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2465 u32 ret = psxBios_PAD_dr_();
2469 static void psxBios_ReturnFromException() { // 17
2470 u32 tcbPtr = loadRam32(A_TT_PCB);
2471 const TCB *tcb = loadRam32ptr(tcbPtr);
2475 for (i = 1; i < 32; i++)
2476 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2477 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2478 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2479 sr = SWAP32(tcb->sr);
2481 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2482 pc0 = k0 = SWAP32(tcb->epc);
2484 // the interpreter wants to know about sr changes, so do a MTC0
2485 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2486 MTC0(&psxRegs, 12, sr);
2492 void psxBios_ResetEntryInt() { // 18
2493 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2495 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2496 mips_return_void_c(5);
2499 void psxBios_HookEntryInt() { // 19
2500 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2502 storeRam32(A_EEXIT_PTR, a0);
2503 mips_return_void_c(3);
2506 static void psxBios_UnDeliverEvent() { // 0x20
2508 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2510 ret = UnDeliverEvent(a0, a1);
2514 static void buopen(int mcd, char *ptr, char *cfg)
2517 char *mcd_data = ptr;
2519 strcpy(FDesc[1 + mcd].name, Ra0+5);
2520 FDesc[1 + mcd].offset = 0;
2521 FDesc[1 + mcd].mode = a1;
2523 for (i=1; i<16; i++) {
2524 const char *fptr = mcd_data + 128 * i;
2525 if ((*fptr & 0xF0) != 0x50) continue;
2526 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2527 FDesc[1 + mcd].mcfile = i;
2528 PSXBIOS_LOG("open %s\n", fptr+0xa);
2532 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2533 for (i=1; i<16; i++) {
2534 int j, xor, nblk = a1 >> 16;
2536 char *fptr = mcd_data + 128 * i;
2538 if ((*fptr & 0xF0) != 0xa0) continue;
2540 FDesc[1 + mcd].mcfile = i;
2543 fptr[5] = 0x20 * nblk;
2546 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2547 pptr = fptr2 = fptr;
2548 for(j=2; j<=nblk; j++) {
2550 for(i++; i<16; i++) {
2553 memset(fptr2, 0, 128);
2554 fptr2[0] = j < nblk ? 0x52 : 0x53;
2557 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2562 /* shouldn't this return ENOSPC if i == 16? */
2564 pptr[8] = pptr[9] = 0xff;
2565 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2567 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2569 /* just go ahead and resave them all */
2570 SaveMcd(cfg, ptr, 128, 128 * 15);
2573 /* shouldn't this return ENOSPC if i == 16? */
2578 * int open(char *name , int mode);
2581 void psxBios_open() { // 0x32
2584 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2588 if (pa0 != INVALID_PTR) {
2589 if (!strncmp(pa0, "bu00", 4)) {
2590 buopen(1, Mcd1Data, Config.Mcd1);
2593 if (!strncmp(pa0, "bu10", 4)) {
2594 buopen(2, Mcd2Data, Config.Mcd2);
2602 * int lseek(int fd , int offset , int whence);
2605 void psxBios_lseek() { // 0x33
2607 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2612 FDesc[a0].offset = a1;
2614 // DeliverEvent(0xf0000011, 0x0004);
2615 // DeliverEvent(0xf4000001, 0x0004);
2619 FDesc[a0].offset+= a1;
2620 v0 = FDesc[a0].offset;
2629 * int read(int fd , void *buf , int nbytes);
2632 void psxBios_read() { // 0x34
2637 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2642 if (pa1 != INVALID_PTR) {
2644 case 2: buread(pa1, 1, a2); break;
2645 case 3: buread(pa1, 2, a2); break;
2653 * int write(int fd , void *buf , int nbytes);
2656 void psxBios_write() { // 0x35/0x03
2660 if (a0 != 1) // stdout
2661 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2664 if (pa1 == INVALID_PTR) {
2669 if (a0 == 1) { // stdout
2673 if (Config.PsxOut) while (a2 > 0) {
2674 SysPrintf("%c", *ptr++); a2--;
2680 case 2: buwrite(pa1, 1, a2); break;
2681 case 3: buwrite(pa1, 2, a2); break;
2687 static void psxBios_write_psxout() {
2688 if (a0 == 1) { // stdout
2689 const char *ptr = Ra1;
2692 if (ptr != INVALID_PTR)
2694 SysPrintf("%c", *ptr++);
2698 static void psxBios_putchar_psxout() { // 3d
2699 SysPrintf("%c", (char)a0);
2702 static void psxBios_puts_psxout() { // 3e/3f
2703 SysPrintf("%s", Ra0);
2707 * int close(int fd);
2710 void psxBios_close() { // 0x36
2712 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2719 void psxBios_putchar() { // 3d
2720 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2724 void psxBios_puts() { // 3e/3f
2725 if (Config.PsxOut) SysPrintf("%s", Ra0);
2729 static void bufile(const u8 *mcd_data, u32 dir_) {
2730 struct DIRENTRY *dir = (struct DIRENTRY *)PSXM(dir_);
2731 const char *pfile = ffile + 5;
2732 const u8 *data = mcd_data;
2733 int i = 0, match = 0;
2738 if (dir == INVALID_PTR)
2741 for (; nfile <= 15 && !match; nfile++) {
2744 head = nfile * 0x40;
2745 data = mcd_data + 128 * nfile;
2746 name = (const char *)data + 0x0a;
2747 if ((data[0] & 0xF0) != 0x50) continue;
2748 /* Bug link files show up as free block. */
2749 if (!name[0]) continue;
2751 for (i = 0; i < 20; i++) {
2752 if (pfile[i] == name[i] || pfile[i] == '?')
2753 dir->name[i] = name[i];
2754 else if (pfile[i] == '*') {
2755 int len = strlen(name + i);
2758 memcpy(dir->name + i, name + i, len + 1);
2769 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2770 nfile, dir->name, pfile, name, match);
2772 for (; nfile <= 15; nfile++, blocks++) {
2773 const u8 *data2 = mcd_data + 128 * nfile;
2774 const char *name = (const char *)data2 + 0x0a;
2775 if ((data2[0] & 0xF0) != 0x50 || name[0])
2779 // nul char of full lenth name seems to overwrite .attr
2780 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2781 dir->size = 8192 * blocks;
2785 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2786 dir->attr, dir->size, dir->next, dir->head);
2790 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2793 static void psxBios_firstfile() { // 42
2796 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2799 if (pa0 != INVALID_PTR)
2801 snprintf(ffile, sizeof(ffile), "%s", pa0);
2803 strcpy(ffile + 5, "*"); // maybe?
2805 if (!strncmp(pa0, "bu00", 4)) {
2806 // firstfile() calls _card_read() internally, so deliver it's event
2807 DeliverEvent(0xf0000011, 0x0004);
2808 bufile((u8 *)Mcd1Data, a1);
2809 } else if (!strncmp(pa0, "bu10", 4)) {
2810 // firstfile() calls _card_read() internally, so deliver it's event
2811 DeliverEvent(0xf0000011, 0x0004);
2812 bufile((u8 *)Mcd2Data, a1);
2820 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2823 void psxBios_nextfile() { // 43
2824 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2827 if (!strncmp(ffile, "bu00", 4))
2828 bufile((u8 *)Mcd1Data, a0);
2829 else if (!strncmp(ffile, "bu10", 4))
2830 bufile((u8 *)Mcd2Data, a0);
2835 #define burename(mcd) { \
2836 for (i=1; i<16; i++) { \
2837 int namelen, j, xor = 0; \
2838 ptr = Mcd##mcd##Data + 128 * i; \
2839 if ((*ptr & 0xF0) != 0x50) continue; \
2840 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2841 namelen = strlen(Ra1+5); \
2842 memcpy(ptr+0xa, Ra1+5, namelen); \
2843 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2844 for (j=0; j<127; j++) xor^= ptr[j]; \
2846 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2853 * int rename(char *old, char *new);
2856 void psxBios_rename() { // 44
2863 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2868 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2869 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2873 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2882 #define budelete(mcd) { \
2883 for (i=1; i<16; i++) { \
2884 ptr = Mcd##mcd##Data + 128 * i; \
2885 if ((*ptr & 0xF0) != 0x50) continue; \
2886 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2887 *ptr = (*ptr & 0xf) | 0xA0; \
2888 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2889 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2896 * int delete(char *name);
2899 void psxBios_delete() { // 45
2905 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2910 if (pa0 != INVALID_PTR) {
2911 if (!strncmp(pa0, "bu00", 4)) {
2915 if (!strncmp(pa0, "bu10", 4)) {
2923 void psxBios_InitCARD() { // 4a
2924 u8 *ram8 = (u8 *)psxM;
2925 u32 *ram32 = (u32 *)psxM;
2926 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2927 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2929 ram8[A_CARD_ISLOT] = 0;
2930 ram8[A_CARD_STATUS1] = 1;
2931 ram8[A_CARD_STATUS2] = 1;
2932 // (maybe) todo: early_card_irq, etc
2934 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2936 psxBios_FlushCache();
2937 mips_return_c(0, 34+13+15+6);
2940 void psxBios_StartCARD() { // 4b
2941 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2942 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2943 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2945 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2946 storeRam32(A_PAD_ACK_VBL, 1);
2947 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2948 storeRam32(A_CARD_IRQR_ENA, 1);
2949 psxRegs.CP0.n.SR |= 0x401;
2951 mips_return_c(1, 200);
2954 void psxBios_StopCARD() { // 4c
2955 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2956 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2957 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2958 storeRam32(A_CARD_IRQR_ENA, 0);
2959 psxRegs.CP0.n.SR |= 0x401;
2960 mips_return_void_c(200);
2963 void psxBios__card_write() { // 0x4e
2967 PSXBIOS_LOG("psxBios_%s %02x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2968 // function also accepts sector 400h (a bug),
2969 // but what actually happens then?
2972 /* Invalid sectors */
2976 storeRam32(A_CARD_ACHAN, a0);
2979 if (pa2 != INVALID_PTR && a1 < 0x400) {
2981 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2982 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2984 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2985 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2989 storeRam8(A_CARD_STATUS1 + port, 4); // busy/write
2990 storeRam32(A_CARD_HANDLER, CARD_HARDLER_READ);
2995 static void psxBios__card_read() { // 0x4f
2999 PSXBIOS_LOG("psxBios_%s %x,%x,%x\n", biosB0n[0x4f], a0, a1, a2);
3002 /* Invalid sectors */
3006 storeRam32(A_CARD_ACHAN, a0);
3009 if (pa2 != INVALID_PTR && a1 < 0x400) {
3011 memcpy(pa2, Mcd1Data + a1 * 128, 128);
3013 memcpy(pa2, Mcd2Data + a1 * 128, 128);
3017 storeRam8(A_CARD_STATUS1 + port, 2); // busy/read
3018 storeRam32(A_CARD_HANDLER, CARD_HARDLER_READ);
3023 void psxBios__new_card() { // 0x50
3025 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
3031 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
3032 void psxBios__get_error(void) // 55
3034 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
3039 void psxBios_Krom2RawAdd() { // 0x51
3042 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
3043 const u32 table_8140[][2] = {
3044 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
3045 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
3046 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
3047 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
3048 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
3049 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
3050 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
3051 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
3052 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
3056 const u32 table_889f[][2] = {
3057 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
3058 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
3059 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
3060 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
3061 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
3062 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
3063 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
3064 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
3068 if (a0 >= 0x8140 && a0 <= 0x84be) {
3069 while (table_8140[i][0] <= a0) i++;
3070 a0 -= table_8140[i - 1][0];
3071 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
3072 } else if (a0 >= 0x889f && a0 <= 0x9872) {
3073 while (table_889f[i][0] <= a0) i++;
3074 a0 -= table_889f[i - 1][0];
3075 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
3083 void psxBios_GetC0Table() { // 56
3084 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
3085 log_unhandled("GetC0Table @%08x\n", ra);
3087 mips_return_c(A_C0_TABLE, 3);
3090 void psxBios_GetB0Table() { // 57
3091 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
3092 log_unhandled("GetB0Table @%08x\n", ra);
3094 mips_return_c(A_B0_TABLE, 3);
3097 static void psxBios__card_chan() { // 0x58
3098 // todo: should return active slot channel
3099 // (active - which was last processed by irq code)
3100 u32 ret = loadRam32(A_CARD_ACHAN);
3101 PSXBIOS_LOG("psxBios_%s -> %02x\n", biosB0n[0x58], ret);
3103 mips_return_c(ret, 8);
3106 static void psxBios_ChangeClearPad() { // 5b
3108 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
3109 ret = loadRam32(A_PAD_ACK_VBL);
3110 storeRam32(A_PAD_ACK_VBL, a0);
3112 mips_return_c(ret, 6);
3115 static void psxBios__card_status() { // 5c
3116 u8 s = loadRam8(A_CARD_STATUS1 + a0);
3117 PSXBIOS_LOG("psxBios_%s %x -> %x\n", biosB0n[0x5c], a0, s);
3119 mips_return_c(s, 5);
3122 static void psxBios__card_wait() { // 5d
3123 u8 s = loadRam8(A_CARD_STATUS1 + a0);
3124 PSXBIOS_LOG("psxBios_%s %x -> %x\n", biosB0n[0x5d], a0, s);
3128 log_unhandled("%s %x\n", __func__, s);
3130 mips_return_c(s, 11);
3133 static void psxBios__card_info() { // A ab
3134 PSXBIOS_LOG("psxBios_%s %02x\n", biosA0n[0xab], a0);
3136 storeRam32(A_CARD_ACHAN, a0);
3143 if (McdDisable[port & 1])
3147 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
3152 if (McdDisable[0] && McdDisable[1])
3156 // deliver from card_vint_handler()
3157 storeRam8(A_CARD_STATUS1 + port, 8); // busy/info
3158 storeRam32(A_CARD_HANDLER, CARD_HARDLER_INFO);
3160 DeliverEvent(0xf4000001, ret);
3161 DeliverEvent(0xf0000011, 0x0004); // ?
3166 static void psxBios__card_load() { // A ac
3167 PSXBIOS_LOG("psxBios_%s %02x\n", biosA0n[0xac], a0);
3169 storeRam32(A_CARD_ACHAN, a0);
3171 // DeliverEvent(0xf0000011, 0x0004);
3172 DeliverEvent(0xf4000001, 0x0004);
3177 static void card_vint_handler(void) {
3180 UnDeliverEvent(0xf0000011, 0x0004);
3181 UnDeliverEvent(0xf0000011, 0x8000);
3182 UnDeliverEvent(0xf0000011, 0x0100);
3183 UnDeliverEvent(0xf0000011, 0x0200);
3184 UnDeliverEvent(0xf0000011, 0x2000);
3187 select = loadRam8(A_CARD_ISLOT);
3188 select = (select ^ 1) & 1;
3189 storeRam8(A_CARD_ISLOT, select);
3191 select = loadRam8(A_CARD_ACHAN) >> 4;
3192 storeRam8(A_CARD_ISLOT, select);
3194 status = loadRam8(A_CARD_STATUS1 + select);
3198 //psxBios_SysDeqIntRP_(0, 0x7540);
3199 //psxBios_SysDeqIntRP_(0, 0x7540);
3200 //card_state_machine = 0;
3201 //card_error_flag = 0;
3202 handler = loadRam32(A_CARD_HANDLER);
3204 case CARD_HARDLER_INFO:
3205 DeliverEvent(0xf4000001, 4);
3206 DeliverEvent(0xf0000011, 4);
3207 storeRam8(A_CARD_STATUS1 + select, 1);
3208 storeRam32(A_CARD_HANDLER, 0);
3210 case CARD_HARDLER_WRITE:
3211 case CARD_HARDLER_READ:
3212 DeliverEvent(0xf0000011, 4);
3213 storeRam8(A_CARD_STATUS1 + select, 1);
3214 storeRam32(A_CARD_HANDLER, 0);
3219 log_unhandled("%s: unhandled handler %x\n", __func__, handler);
3223 /* System calls C0 */
3225 static void psxBios_InitRCnt() { // 00
3227 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
3228 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
3229 for (i = 0; i < 3; i++) {
3230 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
3231 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
3232 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
3234 for (i = 0; i < 4; i++)
3235 psxBios_SysEnqIntRP_(a0, 0x6d58 + i * 0x10);
3236 mips_return_c(0, 9);
3239 static void psxBios_InitException() { // 01
3240 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
3241 psxBios_SysEnqIntRP_(a0, 0x6da8);
3242 mips_return_c(0, 9);
3246 * int SysEnqIntRP(int index , long *queue);
3249 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
3250 u32 old, base = loadRam32(A_TT_ExCB);
3252 old = loadRam32(base + (priority << 3));
3253 storeRam32(base + (priority << 3), chain_eptr);
3254 storeRam32(chain_eptr, old);
3255 mips_return_c(0, 9);
3258 static void psxBios_SysEnqIntRP() { // 02
3259 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
3260 psxBios_SysEnqIntRP_(a0, a1);
3264 * int SysDeqIntRP(int index , long *queue);
3267 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
3268 u32 ptr, next, base = loadRam32(A_TT_ExCB);
3269 u32 lim = 0, ret = 0;
3271 // as in original: no arg checks of any kind, bug if a1 == 0
3272 ptr = loadRam32(base + (priority << 3));
3274 next = loadRam32(ptr);
3275 if (ptr == chain_rm_eptr) {
3276 storeRam32(base + (priority << 3), next);
3281 while (next && next != chain_rm_eptr && lim++ < 100) {
3283 next = loadRam32(ptr);
3286 if (next == chain_rm_eptr) {
3287 next = loadRam32(next);
3288 storeRam32(ptr, next);
3295 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
3297 mips_return_c(ret, 12);
3300 static void psxBios_SysDeqIntRP() { // 03
3301 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3302 psxBios_SysDeqIntRP_(a0, a1);
3305 static void psxBios_get_free_EvCB_slot() { // 04
3306 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3307 s32 ret = get_free_EvCB_slot();
3308 mips_return_c(ret, 0);
3311 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3312 storeRam32(base, 0);
3313 storeRam32(A_KMALLOC_PTR, base);
3314 storeRam32(A_KMALLOC_SIZE, size);
3315 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3318 // this should be much more complicated, but maybe that'll be enough
3319 static u32 psxBios_SysMalloc_(u32 size) {
3320 u32 ptr = loadRam32(A_KMALLOC_PTR);
3322 size = (size + 3) & ~3;
3323 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3324 storeRam32(ptr, size);
3328 static void psxBios_SysInitMemory() { // 08
3329 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3331 psxBios_SysInitMemory_(a0, a1);
3332 mips_return_void_c(12);
3335 static void psxBios_ChangeClearRCnt() { // 0a
3338 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3340 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3341 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3342 mips_return_c(ret, 8);
3345 static void psxBios_InitDefInt() { // 0c
3346 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3347 // should also clear the autoack table
3348 psxBios_SysEnqIntRP_(a0, 0x6d98);
3349 mips_return_c(0, 20 + 6*2);
3352 void psxBios_dummy() {
3353 u32 pc = (pc0 & 0x1fffff) - 4;
3354 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3355 : pc == 0xc0 ? biosC0n : NULL;
3356 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3357 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3358 (void)pc; (void)ntab;
3359 mips_return_c(0, 100);
3362 void (*biosA0[256])();
3363 // C0 and B0 overlap (end of C0 is start of B0)
3364 void (*biosC0[256+128])();
3365 void (**biosB0)() = biosC0 + 128;
3367 static void setup_mips_code()
3370 ptr = (u32 *)&psxM[A_SYSCALL];
3371 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3372 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3373 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3375 ptr = (u32 *)&psxM[A_EXCEPTION];
3376 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3377 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3378 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3379 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3380 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3381 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3382 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3383 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3384 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3385 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3387 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3388 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3389 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3391 ptr[0xb0/4] = HLEOP(hleop_exception);
3394 static const struct {
3398 { 0xbfc050a4, hleop_exc0_0_1 },
3399 { 0xbfc04fbc, hleop_exc0_0_2 },
3400 { 0xbfc0506c, hleop_exc0_1_1 },
3401 { 0xbfc04dec, hleop_exc0_1_2 },
3402 { 0x1a00, hleop_exc0_2_2 },
3403 { 0x19c8, hleop_exc1_0_1 },
3404 { 0x18bc, hleop_exc1_0_2 },
3405 { 0x1990, hleop_exc1_1_1 },
3406 { 0x1858, hleop_exc1_1_2 },
3407 { 0x1958, hleop_exc1_2_1 },
3408 { 0x17f4, hleop_exc1_2_2 },
3409 { 0x1920, hleop_exc1_3_1 },
3410 { 0x1794, hleop_exc1_3_2 },
3411 { 0x2458, hleop_exc3_0_2 },
3412 { 0x49bc, hleop_exc_padcard1 }, // hleExcPadCard1
3413 { 0x4a4c, hleop_exc_padcard2 },
3416 static int chain_hle_op(u32 handler)
3420 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3421 if (chainfns[i].addr == handler)
3422 return chainfns[i].op;
3426 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3428 d[0] = SWAPu32(next);
3429 d[1] = SWAPu32(handler1);
3430 d[2] = SWAPu32(handler2);
3432 // install the hle traps
3433 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3434 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3437 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3439 u32 *ram32 = (u32 *)psxM;
3440 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3441 u32 p_excb, p_evcb, p_pcb, p_tcb;
3444 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3446 // the real bios doesn't care, but we just don't
3447 // want to crash in case of garbage parameters
3448 if (tcb_cnt > 1024) tcb_cnt = 1024;
3449 if (evcb_cnt > 1024) evcb_cnt = 1024;
3450 s_evcb = 0x1c * evcb_cnt;
3451 s_tcb = 0xc0 * tcb_cnt;
3453 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3454 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3455 p_excb = psxBios_SysMalloc_(s_excb);
3456 p_evcb = psxBios_SysMalloc_(s_evcb);
3457 p_pcb = psxBios_SysMalloc_(s_pcb);
3458 p_tcb = psxBios_SysMalloc_(s_tcb);
3460 // "table of tables". Some games modify it
3461 assert(A_TT_ExCB == 0x0100);
3462 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3463 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3464 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3465 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3466 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3467 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3468 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3469 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3470 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3471 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3472 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3473 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3475 storeRam32(p_excb + 0*4, 0x0000); // chain0
3476 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3477 storeRam32(p_excb + 4*4, 0x0000); // chain2
3478 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3480 storeRam32(p_pcb, p_tcb);
3481 storeRam32(p_tcb, 0x4000); // first TCB
3482 for (i = 1; i < tcb_cnt; i++)
3483 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3485 psxBios_SysEnqIntRP_(0, 0x6da8);
3486 setup_cd_irq_and_events();
3488 storeRam32(A_CONF_EvCB, evcb_cnt);
3489 storeRam32(A_CONF_TCB, tcb_cnt);
3490 storeRam32(A_CONF_SP, stack);
3493 static const u32 gpu_ctl_def[] = {
3494 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3495 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3498 static const u32 gpu_data_def[] = {
3499 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3500 0xe5001000, 0xe6000000,
3501 0x02000000, 0x00000000, 0x01ff03ff
3505 static const u16 spu_config[] = {
3506 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3507 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3508 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3509 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3510 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3511 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3512 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3513 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3516 void psxBiosSetupBootState(void)
3518 boolean hle = Config.HLE;
3519 u32 *hw = (u32 *)psxH;
3522 // see also SetBootRegs()
3525 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3526 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3528 k0 = 0xbfc0d968; k1 = 0xf1c;
3529 ra = 0xf0001234; // just to easily detect attempts to return
3530 psxRegs.CP0.n.Cause = 0x20;
3531 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3533 hw[0x1000/4] = SWAP32(0x1f000000);
3534 hw[0x1004/4] = SWAP32(0x1f802000);
3535 hw[0x1008/4] = SWAP32(0x0013243f);
3536 hw[0x100c/4] = SWAP32(0x00003022);
3537 hw[0x1010/4] = SWAP32(0x0013243f);
3538 hw[0x1014/4] = SWAP32(0x200931e1);
3539 hw[0x1018/4] = SWAP32(0x00020943);
3540 hw[0x101c/4] = SWAP32(0x00070777);
3541 hw[0x1020/4] = SWAP32(0x0000132c);
3542 hw[0x1060/4] = SWAP32(0x00000b88);
3543 hw[0x1070/4] = SWAP32(0x00000001);
3544 hw[0x1074/4] = SWAP32(0x0000000c);
3545 hw[0x2040/4] = SWAP32(0x00000900);
3548 hw[0x10a0/4] = SWAP32(0x00ffffff);
3549 hw[0x10a8/4] = SWAP32(0x00000401);
3550 hw[0x10b0/4] = SWAP32(0x0008b000);
3551 hw[0x10b4/4] = SWAP32(0x00010200);
3552 hw[0x10e0/4] = SWAP32(0x000eccf4);
3553 hw[0x10e4/4] = SWAP32(0x00000400);
3554 hw[0x10e8/4] = SWAP32(0x00000002);
3555 hw[0x10f0/4] = SWAP32(0x00009099);
3556 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3565 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3566 GPU_writeStatus(gpu_ctl_def[i]);
3567 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3568 GPU_writeData(gpu_data_def[i]);
3571 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3572 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3575 static void hleExc0_0_1();
3576 static void hleExc0_0_2();
3577 static void hleExc0_1_1();
3578 static void hleExc0_1_2();
3580 #include "sjisfont.h"
3582 void psxBiosInit() {
3583 u32 *ptr, *ram32, *rom32;
3588 psxRegs.biosBranchCheck = ~0;
3590 memset(psxM, 0, 0x10000);
3591 for(i = 0; i < 256; i++) {
3596 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3597 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3598 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3599 biosA0[0x3f] = psxBios_printf_psxout;
3602 char verstr[0x24+1];
3603 rom32 = (u32 *)psxR;
3604 memcpy(verstr, psxR + 0x12c, 0x24);
3606 SysPrintf("BIOS: %08x, '%s', '%c'\n", SWAP32(rom32[0x100/4]),
3607 verstr, psxR[0x7ff52]);
3611 for(i = 0; i < 256; i++) {
3612 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3613 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3614 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3617 biosA0[0x00] = psxBios_open;
3618 biosA0[0x01] = psxBios_lseek;
3619 biosA0[0x02] = psxBios_read;
3620 biosA0[0x03] = psxBios_write;
3621 biosA0[0x04] = psxBios_close;
3622 //biosA0[0x05] = psxBios_ioctl;
3623 //biosA0[0x06] = psxBios_exit;
3624 //biosA0[0x07] = psxBios_sys_a0_07;
3625 biosA0[0x08] = psxBios_getc;
3626 biosA0[0x09] = psxBios_putc;
3627 biosA0[0x0a] = psxBios_todigit;
3628 //biosA0[0x0b] = psxBios_atof;
3629 biosA0[0x0c] = psxBios_strtoul;
3630 biosA0[0x0d] = psxBios_strtol;
3631 biosA0[0x0e] = psxBios_abs;
3632 biosA0[0x0f] = psxBios_labs;
3633 biosA0[0x10] = psxBios_atoi;
3634 biosA0[0x11] = psxBios_atol;
3635 //biosA0[0x12] = psxBios_atob;
3636 biosA0[0x13] = psxBios_setjmp;
3637 biosA0[0x14] = psxBios_longjmp;
3638 biosA0[0x15] = psxBios_strcat;
3639 biosA0[0x16] = psxBios_strncat;
3640 biosA0[0x17] = psxBios_strcmp;
3641 biosA0[0x18] = psxBios_strncmp;
3642 biosA0[0x19] = psxBios_strcpy;
3643 biosA0[0x1a] = psxBios_strncpy;
3644 biosA0[0x1b] = psxBios_strlen;
3645 biosA0[0x1c] = psxBios_index;
3646 biosA0[0x1d] = psxBios_rindex;
3647 biosA0[0x1e] = psxBios_strchr;
3648 biosA0[0x1f] = psxBios_strrchr;
3649 biosA0[0x20] = psxBios_strpbrk;
3650 biosA0[0x21] = psxBios_strspn;
3651 biosA0[0x22] = psxBios_strcspn;
3652 biosA0[0x23] = psxBios_strtok;
3653 biosA0[0x24] = psxBios_strstr;
3654 biosA0[0x25] = psxBios_toupper;
3655 biosA0[0x26] = psxBios_tolower;
3656 biosA0[0x27] = psxBios_bcopy;
3657 biosA0[0x28] = psxBios_bzero;
3658 biosA0[0x29] = psxBios_bcmp;
3659 biosA0[0x2a] = psxBios_memcpy;
3660 biosA0[0x2b] = psxBios_memset;
3661 biosA0[0x2c] = psxBios_memmove;
3662 biosA0[0x2d] = psxBios_memcmp;
3663 biosA0[0x2e] = psxBios_memchr;
3664 biosA0[0x2f] = psxBios_rand;
3665 biosA0[0x30] = psxBios_srand;
3666 biosA0[0x31] = psxBios_qsort;
3667 //biosA0[0x32] = psxBios_strtod;
3668 biosA0[0x33] = psxBios_malloc;
3669 biosA0[0x34] = psxBios_free;
3670 //biosA0[0x35] = psxBios_lsearch;
3671 //biosA0[0x36] = psxBios_bsearch;
3672 biosA0[0x37] = psxBios_calloc;
3673 biosA0[0x38] = psxBios_realloc;
3674 biosA0[0x39] = psxBios_InitHeap;
3675 //biosA0[0x3a] = psxBios__exit;
3676 biosA0[0x3b] = psxBios_getchar;
3677 biosA0[0x3c] = psxBios_putchar;
3678 //biosA0[0x3d] = psxBios_gets;
3679 biosA0[0x3e] = psxBios_puts;
3680 biosA0[0x3f] = psxBios_printf;
3681 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3682 //biosA0[0x41] = psxBios_LoadTest;
3683 biosA0[0x42] = psxBios_Load;
3684 biosA0[0x43] = psxBios_Exec;
3685 biosA0[0x44] = psxBios_FlushCache;
3686 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3687 biosA0[0x46] = psxBios_GPU_dw;
3688 biosA0[0x47] = psxBios_mem2vram;
3689 biosA0[0x48] = psxBios_SendGPU;
3690 biosA0[0x49] = psxBios_GPU_cw;
3691 biosA0[0x4a] = psxBios_GPU_cwb;
3692 biosA0[0x4b] = psxBios_GPU_SendPackets;
3693 biosA0[0x4c] = psxBios_sys_a0_4c;
3694 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3695 //biosA0[0x4e] = psxBios_GPU_sync;
3696 //biosA0[0x4f] = psxBios_sys_a0_4f;
3697 //biosA0[0x50] = psxBios_sys_a0_50;
3698 biosA0[0x51] = psxBios_LoadExec;
3699 //biosA0[0x52] = psxBios_GetSysSp;
3700 //biosA0[0x53] = psxBios_sys_a0_53;
3701 biosA0[0x54] = psxBios_CdInit;
3702 biosA0[0x55] = psxBios__bu_init;
3703 biosA0[0x56] = psxBios_CdRemove;
3704 //biosA0[0x57] = psxBios_sys_a0_57;
3705 //biosA0[0x58] = psxBios_sys_a0_58;
3706 //biosA0[0x59] = psxBios_sys_a0_59;
3707 //biosA0[0x5a] = psxBios_sys_a0_5a;
3708 //biosA0[0x5b] = psxBios_dev_tty_init;
3709 //biosA0[0x5c] = psxBios_dev_tty_open;
3710 //biosA0[0x5d] = psxBios_sys_a0_5d;
3711 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3712 //biosA0[0x5f] = psxBios_dev_cd_open;
3713 //biosA0[0x60] = psxBios_dev_cd_read;
3714 //biosA0[0x61] = psxBios_dev_cd_close;
3715 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3716 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3717 //biosA0[0x64] = psxBios_dev_cd_chdir;
3718 //biosA0[0x65] = psxBios_dev_card_open;
3719 //biosA0[0x66] = psxBios_dev_card_read;
3720 //biosA0[0x67] = psxBios_dev_card_write;
3721 //biosA0[0x68] = psxBios_dev_card_close;
3722 //biosA0[0x69] = psxBios_dev_card_firstfile;
3723 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3724 //biosA0[0x6b] = psxBios_dev_card_erase;
3725 //biosA0[0x6c] = psxBios_dev_card_undelete;
3726 //biosA0[0x6d] = psxBios_dev_card_format;
3727 //biosA0[0x6e] = psxBios_dev_card_rename;
3728 //biosA0[0x6f] = psxBios_dev_card_6f;
3729 biosA0[0x70] = psxBios__bu_init;
3730 biosA0[0x71] = psxBios_CdInit;
3731 biosA0[0x72] = psxBios_CdRemove;
3732 //biosA0[0x73] = psxBios_sys_a0_73;
3733 //biosA0[0x74] = psxBios_sys_a0_74;
3734 //biosA0[0x75] = psxBios_sys_a0_75;
3735 //biosA0[0x76] = psxBios_sys_a0_76;
3736 //biosA0[0x77] = psxBios_sys_a0_77;
3737 //biosA0[0x78] = psxBios__96_CdSeekL;
3738 //biosA0[0x79] = psxBios_sys_a0_79;
3739 //biosA0[0x7a] = psxBios_sys_a0_7a;
3740 //biosA0[0x7b] = psxBios_sys_a0_7b;
3741 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3742 //biosA0[0x7d] = psxBios_sys_a0_7d;
3743 //biosA0[0x7e] = psxBios__96_CdRead;
3744 //biosA0[0x7f] = psxBios_sys_a0_7f;
3745 //biosA0[0x80] = psxBios_sys_a0_80;
3746 //biosA0[0x81] = psxBios_sys_a0_81;
3747 //biosA0[0x82] = psxBios_sys_a0_82;
3748 //biosA0[0x83] = psxBios_sys_a0_83;
3749 //biosA0[0x84] = psxBios_sys_a0_84;
3750 //biosA0[0x85] = psxBios__96_CdStop;
3751 //biosA0[0x86] = psxBios_sys_a0_86;
3752 //biosA0[0x87] = psxBios_sys_a0_87;
3753 //biosA0[0x88] = psxBios_sys_a0_88;
3754 //biosA0[0x89] = psxBios_sys_a0_89;
3755 //biosA0[0x8a] = psxBios_sys_a0_8a;
3756 //biosA0[0x8b] = psxBios_sys_a0_8b;
3757 //biosA0[0x8c] = psxBios_sys_a0_8c;
3758 //biosA0[0x8d] = psxBios_sys_a0_8d;
3759 //biosA0[0x8e] = psxBios_sys_a0_8e;
3760 //biosA0[0x8f] = psxBios_sys_a0_8f;
3761 biosA0[0x90] = hleExc0_1_2;
3762 biosA0[0x91] = hleExc0_0_2;
3763 biosA0[0x92] = hleExc0_1_1;
3764 biosA0[0x93] = hleExc0_0_1;
3765 //biosA0[0x94] = psxBios_sys_a0_94;
3766 biosA0[0x95] = psxBios_CdReset;
3767 //biosA0[0x96] = psxBios_AddCDROMDevice;
3768 //biosA0[0x97] = psxBios_AddMemCardDevide;
3769 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3770 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3771 //biosA0[0x9a] = psxBios_sys_a0_9a;
3772 //biosA0[0x9b] = psxBios_sys_a0_9b;
3773 biosA0[0x9c] = psxBios_SetConf;
3774 biosA0[0x9d] = psxBios_GetConf;
3775 //biosA0[0x9e] = psxBios_sys_a0_9e;
3776 biosA0[0x9f] = psxBios_SetMem;
3777 //biosA0[0xa0] = psxBios__boot;
3778 //biosA0[0xa1] = psxBios_SystemError;
3779 biosA0[0xa2] = psxBios_EnqueueCdIntr;
3780 biosA0[0xa3] = psxBios_DequeueCdIntr;
3781 //biosA0[0xa4] = psxBios_sys_a0_a4;
3782 //biosA0[0xa5] = psxBios_ReadSector;
3783 biosA0[0xa6] = psxBios_get_cd_status;
3784 //biosA0[0xa7] = psxBios_bufs_cb_0;
3785 //biosA0[0xa8] = psxBios_bufs_cb_1;
3786 //biosA0[0xa9] = psxBios_bufs_cb_2;
3787 //biosA0[0xaa] = psxBios_bufs_cb_3;
3788 biosA0[0xab] = psxBios__card_info;
3789 biosA0[0xac] = psxBios__card_load;
3790 //biosA0[0axd] = psxBios__card_auto;
3791 //biosA0[0xae] = psxBios_bufs_cd_4;
3792 //biosA0[0xaf] = psxBios_sys_a0_af;
3793 //biosA0[0xb0] = psxBios_sys_a0_b0;
3794 //biosA0[0xb1] = psxBios_sys_a0_b1;
3795 //biosA0[0xb2] = psxBios_do_a_long_jmp
3796 //biosA0[0xb3] = psxBios_sys_a0_b3;
3797 biosA0[0xb4] = psxBios_GetSystemInfo;
3798 //*******************B0 CALLS****************************
3799 biosB0[0x00] = psxBios_SysMalloc;
3800 //biosB0[0x01] = psxBios_sys_b0_01;
3801 biosB0[0x02] = psxBios_SetRCnt;
3802 biosB0[0x03] = psxBios_GetRCnt;
3803 biosB0[0x04] = psxBios_StartRCnt;
3804 biosB0[0x05] = psxBios_StopRCnt;
3805 biosB0[0x06] = psxBios_ResetRCnt;
3806 biosB0[0x07] = psxBios_DeliverEvent;
3807 biosB0[0x08] = psxBios_OpenEvent;
3808 biosB0[0x09] = psxBios_CloseEvent;
3809 biosB0[0x0a] = psxBios_WaitEvent;
3810 biosB0[0x0b] = psxBios_TestEvent;
3811 biosB0[0x0c] = psxBios_EnableEvent;
3812 biosB0[0x0d] = psxBios_DisableEvent;
3813 biosB0[0x0e] = psxBios_OpenTh;
3814 biosB0[0x0f] = psxBios_CloseTh;
3815 biosB0[0x10] = psxBios_ChangeTh;
3816 //biosB0[0x11] = psxBios_psxBios_b0_11;
3817 biosB0[0x12] = psxBios_InitPAD;
3818 biosB0[0x13] = psxBios_StartPAD;
3819 biosB0[0x14] = psxBios_StopPAD;
3820 biosB0[0x15] = psxBios_PAD_init;
3821 biosB0[0x16] = psxBios_PAD_dr;
3822 biosB0[0x17] = psxBios_ReturnFromException;
3823 biosB0[0x18] = psxBios_ResetEntryInt;
3824 biosB0[0x19] = psxBios_HookEntryInt;
3825 //biosB0[0x1a] = psxBios_sys_b0_1a;
3826 //biosB0[0x1b] = psxBios_sys_b0_1b;
3827 //biosB0[0x1c] = psxBios_sys_b0_1c;
3828 //biosB0[0x1d] = psxBios_sys_b0_1d;
3829 //biosB0[0x1e] = psxBios_sys_b0_1e;
3830 //biosB0[0x1f] = psxBios_sys_b0_1f;
3831 biosB0[0x20] = psxBios_UnDeliverEvent;
3832 //biosB0[0x21] = psxBios_sys_b0_21;
3833 //biosB0[0x22] = psxBios_sys_b0_22;
3834 //biosB0[0x23] = psxBios_sys_b0_23;
3835 //biosB0[0x24] = psxBios_sys_b0_24;
3836 //biosB0[0x25] = psxBios_sys_b0_25;
3837 //biosB0[0x26] = psxBios_sys_b0_26;
3838 //biosB0[0x27] = psxBios_sys_b0_27;
3839 //biosB0[0x28] = psxBios_sys_b0_28;
3840 //biosB0[0x29] = psxBios_sys_b0_29;
3841 //biosB0[0x2a] = psxBios_sys_b0_2a;
3842 //biosB0[0x2b] = psxBios_sys_b0_2b;
3843 //biosB0[0x2c] = psxBios_sys_b0_2c;
3844 //biosB0[0x2d] = psxBios_sys_b0_2d;
3845 //biosB0[0x2e] = psxBios_sys_b0_2e;
3846 //biosB0[0x2f] = psxBios_sys_b0_2f;
3847 //biosB0[0x30] = psxBios_sys_b0_30;
3848 //biosB0[0x31] = psxBios_sys_b0_31;
3849 biosB0[0x32] = psxBios_open;
3850 biosB0[0x33] = psxBios_lseek;
3851 biosB0[0x34] = psxBios_read;
3852 biosB0[0x35] = psxBios_write;
3853 biosB0[0x36] = psxBios_close;
3854 //biosB0[0x37] = psxBios_ioctl;
3855 //biosB0[0x38] = psxBios_exit;
3856 //biosB0[0x39] = psxBios_sys_b0_39;
3857 //biosB0[0x3a] = psxBios_getc;
3858 //biosB0[0x3b] = psxBios_putc;
3859 biosB0[0x3c] = psxBios_getchar;
3860 biosB0[0x3d] = psxBios_putchar;
3861 //biosB0[0x3e] = psxBios_gets;
3862 biosB0[0x3f] = psxBios_puts;
3863 biosB0[0x40] = psxBios_cd;
3864 biosB0[0x41] = psxBios_format;
3865 biosB0[0x42] = psxBios_firstfile;
3866 biosB0[0x43] = psxBios_nextfile;
3867 biosB0[0x44] = psxBios_rename;
3868 biosB0[0x45] = psxBios_delete;
3869 //biosB0[0x46] = psxBios_undelete;
3870 //biosB0[0x47] = psxBios_AddDevice;
3871 //biosB0[0x48] = psxBios_RemoteDevice;
3872 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3873 biosB0[0x4a] = psxBios_InitCARD;
3874 biosB0[0x4b] = psxBios_StartCARD;
3875 biosB0[0x4c] = psxBios_StopCARD;
3876 //biosB0[0x4d] = psxBios_sys_b0_4d;
3877 biosB0[0x4e] = psxBios__card_write;
3878 biosB0[0x4f] = psxBios__card_read;
3879 biosB0[0x50] = psxBios__new_card;
3880 biosB0[0x51] = psxBios_Krom2RawAdd;
3881 //biosB0[0x52] = psxBios_sys_b0_52;
3882 //biosB0[0x53] = psxBios_sys_b0_53;
3883 //biosB0[0x54] = psxBios__get_errno;
3884 biosB0[0x55] = psxBios__get_error;
3885 biosB0[0x56] = psxBios_GetC0Table;
3886 biosB0[0x57] = psxBios_GetB0Table;
3887 biosB0[0x58] = psxBios__card_chan;
3888 //biosB0[0x59] = psxBios_sys_b0_59;
3889 //biosB0[0x5a] = psxBios_sys_b0_5a;
3890 biosB0[0x5b] = psxBios_ChangeClearPad;
3891 biosB0[0x5c] = psxBios__card_status;
3892 biosB0[0x5d] = psxBios__card_wait;
3893 //*******************C0 CALLS****************************
3894 biosC0[0x00] = psxBios_InitRCnt;
3895 biosC0[0x01] = psxBios_InitException;
3896 biosC0[0x02] = psxBios_SysEnqIntRP;
3897 biosC0[0x03] = psxBios_SysDeqIntRP;
3898 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3899 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3900 //biosC0[0x06] = psxBios_ExceptionHandler;
3901 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3902 biosC0[0x08] = psxBios_SysInitMemory;
3903 //biosC0[0x09] = psxBios_SysInitKMem;
3904 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3905 //biosC0[0x0b] = psxBios_SystemError;
3906 biosC0[0x0c] = psxBios_InitDefInt;
3907 //biosC0[0x0d] = psxBios_sys_c0_0d;
3908 //biosC0[0x0e] = psxBios_sys_c0_0e;
3909 //biosC0[0x0f] = psxBios_sys_c0_0f;
3910 //biosC0[0x10] = psxBios_sys_c0_10;
3911 //biosC0[0x11] = psxBios_sys_c0_11;
3912 //biosC0[0x12] = psxBios_InstallDevices;
3913 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3914 //biosC0[0x14] = psxBios_sys_c0_14;
3915 //biosC0[0x15] = psxBios__cdevinput;
3916 //biosC0[0x16] = psxBios__cdevscan;
3917 //biosC0[0x17] = psxBios__circgetc;
3918 //biosC0[0x18] = psxBios__circputc;
3919 //biosC0[0x19] = psxBios_ioabort;
3920 //biosC0[0x1a] = psxBios_sys_c0_1a
3921 //biosC0[0x1b] = psxBios_KernelRedirect;
3922 //biosC0[0x1c] = psxBios_PatchAOTable;
3923 //************** THE END ***************************************
3926 memset(FDesc, 0, sizeof(FDesc));
3927 memset(cdir, 0, sizeof(cdir));
3930 // somewhat pretend to be a SCPH1001 BIOS
3931 // some games look for these and take an exception if they're missing
3932 rom32 = (u32 *)psxR;
3933 rom32[0x100/4] = SWAP32(0x19951204);
3934 rom32[0x104/4] = SWAP32(3);
3935 romc = (char *)psxR;
3936 strcpy(romc + 0x108, "PCSX authors");
3937 strcpy(romc + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3938 strcpy(romc + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3939 strcpy(romc + 0x7ff54, "GPL-2.0-or-later");
3942 len = 0x80000 - 0x66000;
3943 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3944 len = 0x80000 - 0x69d68;
3945 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3947 // trap attempts to call bios directly
3948 rom32[0x00000/4] = HLEOP(hleop_dummy);
3949 rom32[0x00180/4] = HLEOP(hleop_dummy);
3950 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3951 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3952 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3954 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3955 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3956 Here are some examples of games not working with this fix in place :
3957 R-type won't get past the Irem logo if not implemented.
3958 Crash Team Racing will softlock after the Sony logo.
3961 ram32 = (u32 *)psxM;
3962 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3963 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3964 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3965 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3967 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3968 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3970 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3971 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3972 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3973 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3975 ram32[0x00a0/4] = HLEOP(hleop_a0);
3976 ram32[0x00b0/4] = HLEOP(hleop_b0);
3977 ram32[0x00c0/4] = HLEOP(hleop_c0);
3979 setup_tt(4, 16, 0x801fff00);
3980 DeliverEvent(0xf0000003, 0x0010);
3982 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3983 strcpy((char *)&ram32[0xeff0/4], "bu");
3985 // default exception handler chains
3986 // see also setup_cd_irq_and_events()
3987 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3988 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3989 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3990 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3991 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3992 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3993 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3994 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3998 // fill the api jumptables with fake entries as some games patch them
3999 // (or rather the funcs listed there)
4000 // also trap the destination as some "Cheats Edition" thing overrides the
4001 // dispatcher with a wrapper and then jumps to the table entries directly
4002 ptr = (u32 *)&psxM[A_A0_TABLE];
4003 for (i = 0; i < 256; i++) {
4004 ptr[i] = SWAP32(A_A0_TRAPS + i*4);
4005 ram32[A_A0_TRAPS/4 + i] = HLEOP(hleop_a0t);
4007 ptr = (u32 *)&psxM[A_B0_TABLE];
4008 for (i = 0; i < 256; i++) {
4009 ptr[i] = SWAP32(A_B0_TRAPS + i*4);
4010 ram32[A_B0_TRAPS/4 + i] = HLEOP(hleop_b0t);
4012 // B(5b) is special because games patch (sometimes even jump to)
4013 // code at fixed offsets from it, nocash lists offsets:
4014 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
4015 // call: +7a0=4b70, +884=4c54, +894=4c64
4016 ptr[0x5b] = SWAP32(A_B0_5B_TRAP); // 0x43d0
4017 ram32[A_B0_5B_TRAP/4] = HLEOP(hleop_b0t);
4019 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
4021 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
4022 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
4023 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
4025 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
4026 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
4028 ptr = (u32 *)&psxM[A_C0_TABLE];
4029 for (i = 0; i < 256/2; i++) {
4030 ptr[i] = SWAP32(A_C0_TRAPS + i*4);
4031 ram32[A_C0_TRAPS/4 + i] = HLEOP(hleop_c0t);
4033 ptr[6] = SWAP32(A_EXCEPTION);
4036 ram32[A_A0_TRAPS/4 - 1] = HLEOP(hleop_dummy);
4037 ram32[A_B0_TRAPS/4 - 1] = HLEOP(hleop_dummy);
4038 ram32[A_C0_TRAPS/4 - 1] = HLEOP(hleop_dummy);
4039 ram32[0x7ffc/4] = HLEOP(hleop_dummy);
4040 ram32[0x8000/4] = HLEOP(hleop_execret);
4042 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
4043 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
4044 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
4045 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
4046 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
4047 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
4048 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
4051 void psxBiosShutdown() {
4054 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
4057 if (tcb_cnt != 4 || evcb_cnt != 16) {
4058 setup_tt(tcb_cnt, evcb_cnt, stack);
4059 DeliverEvent(0xf0000003, 0x0010);
4061 storeRam32(A_CONF_SP, stack);
4064 #define psxBios_PADpoll(pad) { \
4065 int i, more_data = 0; \
4066 PAD##pad##_startPoll(pad); \
4067 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
4068 pad_buf##pad[0] = more_data ? 0 : 0xff; \
4069 PAD##pad##_poll(0, &more_data); \
4071 while (more_data) { \
4072 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
4076 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
4080 psxHwWrite16(0x1f801070, ~(1u << irqbit));
4081 psxBios_ReturnFromException();
4087 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
4088 // so this is only partially implemented
4089 static void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
4091 u32 cdrom_dma_ack_enable = 1; // a000b93c
4092 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
4095 static void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
4098 //PSXBIOS_LOG("%s\n", __func__);
4100 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
4101 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
4102 //if (--cdrom_irq_counter == 0) // 0xa0009180
4103 // DeliverEvent(0xf0000003, 0x10);
4107 mips_return_c(ret, 20);
4110 static void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
4112 u32 cdrom_irq_ack_enable = 1; // a000b938
4113 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
4116 static void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
4119 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
4120 PSXBIOS_LOG("%s TODO\n", __func__);
4123 mips_return_c(ret, 20);
4126 static void hleExc0_2_2_syscall() // not in any A/B/C table
4128 u32 tcbPtr = loadRam32(A_TT_PCB);
4129 TCB *tcb = loadRam32ptr(tcbPtr);
4130 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
4132 if (code != R3000E_Syscall) {
4134 DeliverEvent(0xf0000010, 0x1000);
4135 //psxBios_SystemErrorUnresolvedException();
4137 mips_return_c(0, 17);
4141 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
4142 tcb->epc += SWAP32(4);
4143 switch (SWAP32(tcb->reg[4])) { // a0
4147 case 1: { // EnterCritical - disable irqs
4148 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
4149 tcb->reg[2] = SWAP32(was_enabled);
4150 tcb->sr &= SWAP32(~0x404);
4153 case 2: // ExitCritical - enable irqs
4154 tcb->sr |= SWAP32(0x404);
4157 case 3: { // ChangeThreadSubFunction
4158 u32 tcbPtr = loadRam32(A_TT_PCB);
4159 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
4163 DeliverEvent(0xf0000010, 0x4000);
4167 psxBios_ReturnFromException();
4170 static void hleExc1_0_1(void)
4172 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
4173 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
4176 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
4179 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
4180 DeliverEvent(0xf2000000 + ev_index, 0x0002);
4183 mips_return_c(ret, 22);
4186 static void hleExc1_0_2(void)
4188 handle_chain_1_x_2(3, 0); // IRQ0 vblank
4191 static void hleExc1_1_1(void)
4193 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
4194 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
4197 static void hleExc1_1_2(void)
4199 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
4202 static void hleExc1_2_1(void)
4204 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
4205 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
4208 static void hleExc1_2_2(void)
4210 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
4213 static void hleExc1_3_1(void)
4215 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
4216 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
4219 static void hleExc1_3_2(void)
4221 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
4224 static void hleExc3_0_2_defint(void)
4226 static const struct {
4237 { 6, 6 }, // rcnt2 (bug)
4242 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
4243 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
4244 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
4249 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
4252 static void hleExcPadCard1(void)
4254 if (loadRam32(A_PAD_IRQR_ENA)) {
4255 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
4256 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
4261 if (loadRam32(A_PAD_DR_DST))
4264 if (loadRam32(A_PAD_ACK_VBL))
4265 psxHwWrite16(0x1f801070, ~1);
4266 if (loadRam32(A_CARD_IRQR_ENA))
4267 card_vint_handler();
4269 mips_return_c(0, 18);
4272 static void hleExcPadCard2(void)
4274 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
4275 mips_return_c(ret, 15);
4278 void psxBiosException() {
4279 u32 tcbPtr = loadRam32(A_TT_PCB);
4280 u32 *chains = loadRam32ptr(A_TT_ExCB);
4281 TCB *tcb = loadRam32ptr(tcbPtr);
4287 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
4288 for (i = 4; i < 31; i++) {
4291 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
4293 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
4294 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
4295 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
4296 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
4297 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
4298 sp = fp = loadRam32(A_EXC_SP);
4301 assert(!psxRegs.cpuInRecursion);
4303 // do the chains (always 4)
4304 for (c = lim = 0; c < 4; c++) {
4305 if (chains[c * 2] == 0)
4307 ptr = SWAP32(chains[c * 2]);
4308 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
4309 chain = castRam32ptr(ptr);
4314 softCallInException(SWAP32(chain[2]));
4315 if (returned_from_exception())
4318 if (v0 == 0 || chain[1] == 0)
4320 softCallInException(SWAP32(chain[1]));
4321 if (returned_from_exception())
4327 // return from exception (custom or default)
4329 ptr = loadRam32(A_EEXIT_PTR);
4330 if (ptr != A_EEXIT_DEF) {
4331 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4332 longjmp_load(jmp_buf);
4337 psxBios_ReturnFromException();
4341 static void hleDummy() {
4342 log_unhandled("hleDummy called @%08x ra=%08x\n", psxRegs.pc - 4, ra);
4344 psxRegs.cycle += 1000;
4349 static void hleA0() {
4350 u32 call = t1 & 0xff;
4351 u32 entry = loadRam32(A_A0_TABLE + call * 4);
4354 if (call < 192 && entry != A_A0_TRAPS + call * 4) {
4355 PSXBIOS_LOG("custom A%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4356 call, biosA0n[call], a0, entry, ra);
4359 PSXBIOS_LOG(" -> %08x\n", v0);
4361 else if (biosA0[call])
4364 //printf("A(%02x) -> %x\n", call, v0);
4368 static void hleB0() {
4369 u32 call = t1 & 0xff;
4370 u32 entry = loadRam32(A_B0_TABLE + call * 4);
4375 is_custom = entry != A_B0_5B_TRAP;
4377 is_custom = entry != A_B0_TRAPS + call * 4;
4379 PSXBIOS_LOG("custom B%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4380 call, biosB0n[call], a0, entry, ra);
4383 PSXBIOS_LOG(" -> %08x\n", v0);
4385 else if (biosB0[call])
4388 //printf("B(%02x) -> %x\n", call, v0);
4392 static void hleC0() {
4393 u32 call = t1 & 0xff;
4394 u32 entry = loadRam32(A_C0_TABLE + call * 4);
4397 if (call < 128 && entry != A_C0_TRAPS + call * 4) {
4398 PSXBIOS_LOG("custom C%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4399 call, biosC0n[call], a0, entry, ra);
4402 PSXBIOS_LOG(" -> %08x\n", v0);
4404 else if (biosC0[call])
4407 //printf("C(%02x) -> %x\n", call, v0);
4411 static void hleA0t() {
4412 u32 call = (pc0 - A_A0_TRAPS) / 4 - 1;
4413 if (call >= 256u || !biosA0[call]) {
4414 log_unhandled("unexpected A trap @%08x ra=%08x\n", pc0 - 4, ra);
4415 mips_return_void_c(1000);
4420 //printf("A(%02x) -> %x\n", call, v0);
4424 static void hleB0t() {
4425 u32 call = (pc0 - A_B0_TRAPS) / 4 - 1;
4426 if (pc0 - 4 == A_B0_5B_TRAP)
4428 if (call >= 256u || !biosB0[call]) {
4429 log_unhandled("unexpected B trap @%08x ra=%08x\n", pc0 - 4, ra);
4430 mips_return_void_c(1000);
4435 //printf("B(%02x) -> %x\n", call, v0);
4439 static void hleC0t() {
4440 u32 call = (pc0 - A_C0_TRAPS) / 4 - 1;
4441 if (call >= 128u || !biosC0[call]) {
4442 log_unhandled("unexpected C trap @%08x ra=%08x\n", pc0 - 4, ra);
4443 mips_return_void_c(1000);
4448 //printf("C(%02x) -> %x\n", call, v0);
4452 // currently not used
4453 static void hleBootstrap() {
4458 static void hleExecRet() {
4459 const EXEC *header = (EXEC *)PSXM(s0);
4461 PSXBIOS_LOG("ExecRet %x: %x\n", s0, header->ret);
4463 ra = SWAP32(header->ret);
4464 sp = SWAP32(header->_sp);
4465 fp = SWAP32(header->_fp);
4466 gp = SWAP32(header->_gp);
4467 s0 = SWAP32(header->base);
4473 void (* const psxHLEt[hleop_count_])() = {
4474 hleDummy, hleA0, hleB0, hleC0,
4475 hleBootstrap, hleExecRet, psxBiosException, hleDummy,
4476 hleExc0_0_1, hleExc0_0_2,
4477 hleExc0_1_1, hleExc0_1_2, hleExc0_2_2_syscall,
4478 hleExc1_0_1, hleExc1_0_2,
4479 hleExc1_1_1, hleExc1_1_2,
4480 hleExc1_2_1, hleExc1_2_2,
4481 hleExc1_3_1, hleExc1_3_2,
4483 hleExcPadCard1, hleExcPadCard2,
4484 hleA0t, hleB0t, hleC0t,
4487 void psxBiosCheckExe(u32 t_addr, u32 t_size, int loading_state)
4489 // lw $v0, 0x10($sp)
4492 // sw $v0, 0x10($sp)
4493 // lw $v0, 0x10($sp)
4495 // bne $v0, $v1, not_timeout
4498 static const u8 pattern[] = {
4499 0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
4500 0xFF, 0xFF, 0x42, 0x24, 0x10, 0x00, 0xA2, 0xAF,
4501 0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
4502 0x0C, 0x00, 0x43, 0x14, 0x00, 0x00, 0x00, 0x00,
4504 u32 start = t_addr & 0x1ffffc;
4505 u32 end = (start + t_size) & 0x1ffffc;
4506 u32 buf[sizeof(pattern) / sizeof(u32)];
4507 const u32 *r32 = (u32 *)(psxM + start);
4515 memcpy(buf, pattern, sizeof(buf));
4516 for (i = 0; i < t_size / 4; i += j + 1) {
4517 for (j = 0; j < sizeof(buf) / sizeof(buf[0]); j++)
4518 if (r32[i + j] != buf[j])
4520 if (j != sizeof(buf) / sizeof(buf[0]))
4523 if ((SWAP32(r32[i + j]) >> 16) != 0x3c04) // lui
4526 SysPrintf("HLE vsync @%08x\n", start + i * 4);
4527 psxRegs.biosBranchCheck = (t_addr & 0xa01ffffc) + i * 4;
4531 void psxBiosCheckBranch(void)
4535 static u32 cycles_prev, v0_prev;
4536 u32 cycles_passed, waste_cycles;
4537 u32 loops, v0_expect = v0_prev - 1;
4541 cycles_passed = psxRegs.cycle - cycles_prev;
4542 cycles_prev = psxRegs.cycle;
4544 if (cycles_passed < 10 || cycles_passed > 50 || v0 != v0_expect)
4547 waste_cycles = schedule_timeslice() - psxRegs.cycle;
4548 loops = waste_cycles / cycles_passed;
4552 psxRegs.cycle += loops * cycles_passed;
4553 //printf("c %4u %d\n", loops, cycles_passed);
4557 #define bfreeze(ptr, size) { \
4558 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4559 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4563 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4564 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4566 void psxBiosFreeze(int Mode) {