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];
268 static int card_io_delay;
270 // fixed RAM offsets, SCPH1001 compatible
271 #define A_TT_ExCB 0x0100
272 #define A_TT_PCB 0x0108
273 #define A_TT_TCB 0x0110
274 #define A_TT_EvCB 0x0120
275 #define A_A0_TABLE 0x0200
276 #define A_B0_TABLE 0x0874
277 #define A_C0_TABLE 0x0674
278 #define A_SYSCALL 0x0650
279 #define A_EXCEPTION 0x0c80
280 #define A_EXC_SP 0x6cf0
281 #define A_EEXIT_DEF 0x6cf4
282 #define A_CARD_ISLOT 0x7264 // 0 or 1, toggled by card vint handler
283 #define A_KMALLOC_PTR 0x7460
284 #define A_KMALLOC_SIZE 0x7464
285 #define A_KMALLOC_END 0x7468
286 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
287 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
288 #define A_CARD_IRQR_ENA 0x74bc // same for card
289 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
290 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
291 #define A_PAD_IN_LEN 0x74d8
292 #define A_PAD_OUT_LEN 0x74e0
293 #define A_PAD_DR_DST 0x74c4
294 #define A_CARD_ACHAN 0x7500 // currently active port in 0xPortSlot format
295 #define A_CARD_HANDLER 0x7528 // ptr to irq handler
296 #define A_CARD_STATUS1 0x7568
297 #define A_CARD_STATUS2 0x7569
298 #define A_PAD_DR_BUF1 0x7570
299 #define A_PAD_DR_BUF2 0x7598
300 #define A_EEXIT_PTR 0x75d0
301 #define A_EXC_STACK 0x85d8 // exception stack top
302 #define A_RCNT_VBL_ACK 0x8600
303 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
304 #define A_HEAP_BASE 0x9000
305 #define A_HEAP_SIZE 0x9004
306 #define A_HEAP_END 0x9008
307 #define A_HEAP_INIT_FLG 0x900c
308 #define A_RND_SEED 0x9010
309 #define A_HEAP_FRSTCHNK 0xb060
310 #define A_HEAP_CURCHNK 0xb064
311 #define A_CONF_TCB 0xb940
312 #define A_CONF_EvCB 0xb944
313 #define A_CONF_SP 0xb948
314 #define A_CD_EVENTS 0xb9b8
315 #define A_EXC_GP 0xf450
317 #define A_A0_TRAPS 0x1010
318 #define A_B0_TRAPS 0x2010
319 #define A_C0_TRAPS 0x3010
320 #define A_B0_5B_TRAP 0x43d0
322 #define CARD_HARDLER_WRITE 0x51F4
323 #define CARD_HARDLER_WRITEM 0x51F5 // fake, for psxBios_write()
324 #define CARD_HARDLER_READ 0x5688
325 #define CARD_HARDLER_READM 0x5689 // fake, for psxBios_read()
326 #define CARD_HARDLER_INFO 0x5B64
328 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
330 static u8 loadRam8(u32 addr)
332 assert(!(addr & 0x5f800000));
333 return psxM[addr & 0x1fffff];
336 static u32 loadRam32(u32 addr)
338 assert(!(addr & 0x5f800000));
339 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
342 static void *castRam8ptr(u32 addr)
344 assert(!(addr & 0x5f800000));
345 return psxM + (addr & 0x1fffff);
348 static void *castRam32ptr(u32 addr)
350 assert(!(addr & 0x5f800003));
351 return psxM + (addr & 0x1ffffc);
354 static void *loadRam8ptr(u32 addr)
356 return castRam8ptr(loadRam32(addr));
359 static void *loadRam32ptr(u32 addr)
361 return castRam32ptr(loadRam32(addr));
364 static void storeRam8(u32 addr, u8 d)
366 assert(!(addr & 0x5f800000));
367 *((u8 *)psxM + (addr & 0x1fffff)) = d;
370 static void storeRam32(u32 addr, u32 d)
372 assert(!(addr & 0x5f800000));
373 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
376 static void mips_return(u32 val)
382 static void mips_return_void(void)
387 static void use_cycles(u32 cycle)
389 psxRegs.cycle += cycle * 2;
392 static void mips_return_c(u32 val, u32 cycle)
398 static void mips_return_void_c(u32 cycle)
404 static int returned_from_exception(void)
406 // 0x80000080 means it took another exception just after return
407 return pc0 == k0 || pc0 == 0x80000080;
410 static inline void softCall(u32 pc) {
412 u32 ssr = psxRegs.CP0.n.SR;
416 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
418 assert(psxRegs.cpuInRecursion <= 1);
419 psxRegs.cpuInRecursion++;
420 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
422 while (pc0 != 0x80001000 && ++lim < 0x100000)
423 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
425 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
426 psxRegs.cpuInRecursion--;
429 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
431 psxRegs.CP0.n.SR |= ssr & 0x404;
434 static inline void softCallInException(u32 pc) {
439 assert(ra != 0x80001000);
440 if (ra == 0x80001000)
444 psxRegs.cpuInRecursion++;
445 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
447 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 0x100000)
448 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
450 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
451 psxRegs.cpuInRecursion--;
454 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
455 if (pc0 == 0x80001000)
459 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
460 static void EnableEvent(u32 ev, int do_log);
461 static u32 DeliverEvent(u32 class, u32 spec);
462 static u32 UnDeliverEvent(u32 class, u32 spec);
463 static void CloseEvent(u32 ev);
465 static int card_buf_io(int is_write, int port, void *buf, u32 size)
467 char *mcdptr = port ? Mcd2Data : Mcd1Data;
468 FileDesc *desc = &FDesc[2 + port];
469 u32 offset = 8192 * desc->mcfile + desc->offset;
471 PSXBIOS_LOG("card_%s_buf %d,%d: ofs=%x(%x) sz=%x (%s)\n",
472 is_write ? "write" : "read", port, desc->mcfile,
473 desc->offset, offset, size, mcdptr + 128 * desc->mcfile + 0xa);
474 if (!(loadRam8(A_CARD_STATUS1 + port) & 1)) {
475 PSXBIOS_LOG(" ...busy %x\n", loadRam8(A_CARD_STATUS1 + port));
478 UnDeliverEvent(0xf4000001, 0x0004);
479 UnDeliverEvent(0xf4000001, 0x8000);
480 UnDeliverEvent(0xf4000001, 0x2000);
481 UnDeliverEvent(0xf4000001, 0x0100);
483 if (offset >= 128*1024u) {
484 log_unhandled("card offs %x(%x)\n", desc->offset, offset);
485 DeliverEvent(0xf4000001, 0x8000); // ?
488 if (offset + size >= 128*1024u) {
489 log_unhandled("card offs+size %x+%x\n", offset, size);
490 size = 128*1024 - offset;
493 memcpy(mcdptr + offset, buf, size);
495 SaveMcd(Config.Mcd1, Mcd1Data, offset, size);
497 SaveMcd(Config.Mcd2, Mcd2Data, offset, size);
500 size_t ram_offset = (s8 *)buf - psxM;
501 memcpy(buf, mcdptr + offset, size);
502 if (ram_offset < 0x200000)
503 psxCpu->Clear(ram_offset, (size + 3) / 4);
505 desc->offset += size;
506 if (desc->mode & 0x8000) { // async
507 storeRam8(A_CARD_STATUS1 + port, is_write ? 4 : 2); // busy
508 storeRam32(A_CARD_HANDLER,
509 is_write ? CARD_HARDLER_WRITEM : CARD_HARDLER_READM);
510 card_io_delay = 2 + size / 1024; // hack
519 // System calls A0 */
521 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
522 /* For some strange reason, the returned character is sign-expanded; */
523 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
524 static void psxBios_getc(void) // 0x03, 0x35
529 PSXBIOS_LOG("psxBios_%s %d\n", biosA0n[0x03], a0);
533 else if (a0 == 2 || a0 == 3) {
534 card_buf_io(0, a0 - 2, buf, 1);
538 mips_return_c(ret, 100);
541 /* Copy of psxBios_write, except size is 1. */
542 static void psxBios_putc(void) // 0x09, 0x3B
544 u8 buf[1] = { (u8)a0 };
547 if (a1 != 1) // not stdout
548 PSXBIOS_LOG("psxBios_%s '%c' %d\n", biosA0n[0x09], (char)a0, a1);
550 if (a1 == 1) { // stdout
551 if (Config.PsxOut) printf("%c", (char)a0);
553 else if (a1 == 2 || a1 == 3) {
554 ret = card_buf_io(1, a1 - 2, buf, 1);
557 mips_return_c(ret, 100);
560 static u32 do_todigit(u32 c)
563 if (c >= 0x30 && c < 0x3A) {
566 else if (c > 0x60 && c < 0x7B) {
569 else if (c > 0x40 && c < 0x5B) {
572 else if (c >= 0x80) {
573 log_unhandled("todigit %02x\n", c);
584 static void psxBios_todigit(void) // 0x0a
586 mips_return(do_todigit(a0));
587 PSXBIOS_LOG("psxBios_%s '%c' -> %u\n", biosA0n[0x0a], a0, v0);
590 static void do_strtol(char *p, void *end_, u32 base, int can_neg) {
595 if (p == INVALID_PTR) {
600 for (; (0x09 <= *p && *p <= '\r') || *p == ' '; p++)
603 for (; *p == '-'; f = 1, p++)
606 if (base == 0 || base > 36)
610 case 'b': case 'B': base = 2; break;
611 case 'x': case 'X': base = 16; break;
614 else if (*p == 'o' || *p == 'O') {
619 for (; (t = do_todigit(*p)) < base; p++) {
625 if (end != INVALID_PTR)
626 *end = SWAP32(a0 + (p - Ra0));
627 mips_return_c(n, 100);
630 static void psxBios_strtoul() { // 0x0c
631 do_strtol(a0 ? Ra0 : INVALID_PTR, a1 ? Ra1 : INVALID_PTR, a2, 0);
632 PSXBIOS_LOG("psxBios_%s %s (%x), %x, %x -> 0x%x\n",
633 biosA0n[0x0c], a0 ? Ra0 : NULL, a0, a1, a2, v0);
636 static void psxBios_strtol() { // 0x0d
637 do_strtol(a0 ? Ra0 : INVALID_PTR, a1 ? Ra1 : INVALID_PTR, a2, 1);
638 PSXBIOS_LOG("psxBios_%s %s (%x), %x, %x -> 0x%x\n",
639 biosA0n[0x0d], a0 ? Ra0 : NULL, a0, a1, a2, v0);
642 void psxBios_abs() { // 0x0e
643 if ((s32)a0 < 0) v0 = -(s32)a0;
648 void psxBios_labs() { // 0x0f
652 void psxBios_atoi() { // 0x10
654 char *p = (char *)Ra0;
656 if (p == INVALID_PTR) {
663 case ' ': case '\t': continue;
670 while (*p >= '0' && *p <= '9') {
671 n = n * 10 + *p++ - '0';
676 PSXBIOS_LOG("psxBios_%s %s (%x) -> 0x%x\n", biosA0n[0x10], Ra0, a0, v0);
679 void psxBios_atol() { // 0x11
689 static void psxBios_setjmp() { // 0x13
690 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
693 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
695 jmp_buf->ra_ = SWAP32(ra);
696 jmp_buf->sp_ = SWAP32(sp);
697 jmp_buf->fp_ = SWAP32(fp);
698 for (i = 0; i < 8; i++) // s0-s7
699 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
700 jmp_buf->gp_ = SWAP32(gp);
702 mips_return_c(0, 15);
705 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
709 ra = SWAP32(jmp_buf->ra_);
710 sp = SWAP32(jmp_buf->sp_);
711 fp = SWAP32(jmp_buf->fp_);
712 for (i = 0; i < 8; i++) // s0-s7
713 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
714 gp = SWAP32(jmp_buf->gp_);;
717 void psxBios_longjmp() { // 0x14
718 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
720 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
721 longjmp_load(jmp_buf);
722 mips_return_c(a1, 15);
725 void psxBios_strcat() { // 0x15
729 PSXBIOS_LOG("psxBios_%s %s (%x), %s (%x)\n", biosA0n[0x15], Ra0, a0, Ra1, a1);
730 if (a0 == 0 || a1 == 0 || p2 == INVALID_PTR)
735 while (loadRam8(p1)) {
739 for (; *p2; p1++, p2++)
743 mips_return_c(a0, 22);
746 void psxBios_strncat() { // 0x16
747 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
751 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
753 if (a0 == 0 || a1 == 0)
761 while ((*p1++ = *p2++) != '\0') {
771 void psxBios_strcmp() { // 0x17
772 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
774 if (a0 == 0 && a1 == 0)
780 else if (a0 == 0 && a1 != 0)
786 else if (a0 != 0 && a1 == 0)
793 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
796 while (*p1 == *p2++) {
815 void psxBios_strncmp() { // 0x18
816 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
818 if (a0 == 0 && a1 == 0)
824 else if (a0 == 0 && a1 != 0)
830 else if (a0 != 0 && a1 == 0)
837 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
840 while (--n >= 0 && *p1 == *p2++) {
844 v1 = a2 - ((a2-n) - 1);
852 v0 = (n < 0 ? 0 : *p1 - *--p2);
854 v1 = a2 - ((a2-n) - 1);
860 void psxBios_strcpy() { // 0x19
861 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
862 PSXBIOS_LOG("psxBios_%s %x, %s (%x)\n", biosA0n[0x19], a0, p2, a1);
863 if (a0 == 0 || a1 == 0)
869 while ((*p1++ = *p2++) != '\0');
874 void psxBios_strncpy() { // 0x1a
875 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
877 if (a0 == 0 || a1 == 0)
883 for (i = 0; i < n; i++) {
884 if ((*p1++ = *p2++) == '\0') {
896 void psxBios_strlen() { // 0x1b
897 char *p = (char *)Ra0;
908 void psxBios_index() { // 0x1c
909 char *p = (char *)Ra0;
919 v0 = a0 + (p - (char *)Ra0);
923 } while (*p++ != '\0');
928 void psxBios_rindex() { // 0x1d
929 char *p = (char *)Ra0;
939 v0 = a0 + (p - (char *)Ra0);
940 } while (*p++ != '\0');
945 void psxBios_strchr() { // 0x1e
949 void psxBios_strrchr() { // 0x1f
953 void psxBios_strpbrk() { // 0x20
954 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
956 while ((c = *p1++) != '\0') {
957 for (scanp = p2; (sc = *scanp++) != '\0';) {
959 v0 = a0 + (p1 - 1 - (char *)Ra0);
966 // BUG: return a0 instead of NULL if not found
970 void psxBios_strspn() { // 0x21
973 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
974 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
975 if (*p2 == '\0') break;
978 v0 = p1 - (char *)Ra0; pc0 = ra;
981 void psxBios_strcspn() { // 0x22
984 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
985 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
986 if (*p2 != '\0') break;
989 v0 = p1 - (char *)Ra0; pc0 = ra;
992 void psxBios_strtok() { // 0x23
993 char *pcA0 = (char *)Ra0;
994 char *pcRet = strtok(pcA0, (char *)Ra1);
996 v0 = a0 + pcRet - pcA0;
1002 void psxBios_strstr() { // 0x24
1003 char *p = (char *)Ra0, *p1, *p2;
1004 PSXBIOS_LOG("psxBios_%s %s (%x), %s (%x)\n", biosA0n[0x24], p, a0, Ra1, a1);
1006 while (*p != '\0') {
1010 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
1015 v0 = a0 + (p - (char *)Ra0);
1017 PSXBIOS_LOG(" -> %x\n", v0);
1021 // bug: skips the whole matched substring + 1
1028 void psxBios_toupper() { // 0x25
1029 v0 = (s8)(a0 & 0xff);
1030 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
1034 void psxBios_tolower() { // 0x26
1035 v0 = (s8)(a0 & 0xff);
1036 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
1040 static void do_memset(u32 dst, u32 v, s32 len)
1046 if (db != INVALID_PTR)
1050 psxCpu->Clear(dst, (len + 3) / 4);
1053 static void do_memcpy(u32 dst, u32 src, s32 len)
1055 u32 d = dst, s = src;
1058 const u8 *sb = PSXM(s);
1060 if (db != INVALID_PTR && sb != INVALID_PTR)
1065 psxCpu->Clear(dst, (len + 3) / 4);
1068 static void psxBios_memcpy();
1070 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
1071 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
1072 u32 ret = a0, cycles = 0;
1073 if (a0 == 0) // ...but it checks src this time
1075 mips_return_c(0, 4);
1080 do_memcpy(a1, a0, a2);
1086 mips_return_c(ret, cycles + 5);
1089 static void psxBios_bzero() { // 0x28
1090 /* Same as memset here (See memset below) */
1091 u32 ret = a0, cycles;
1092 if (a0 == 0 || (s32)a1 <= 0)
1094 mips_return_c(0, 6);
1097 do_memset(a0, 0, a1);
1101 // todo: many more cycles due to uncached bios mem
1102 mips_return_c(ret, cycles + 5);
1105 void psxBios_bcmp() { // 0x29
1106 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
1108 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
1110 while ((s32)a2-- > 0) {
1111 if (*p1++ != *p2++) {
1112 v0 = *p1 - *p2; // BUG: compare the NEXT byte
1121 static void psxBios_memcpy() { // 0x2a
1122 u32 ret = a0, cycles = 0;
1125 mips_return_c(0, 4);
1130 do_memcpy(a0, a1, a2);
1136 mips_return_c(ret, cycles + 5);
1139 static void psxBios_memset() { // 0x2b
1140 u32 ret = a0, cycles;
1141 if (a0 == 0 || (s32)a2 <= 0)
1143 mips_return_c(0, 6);
1146 do_memset(a0, a1, a2);
1150 // todo: many more cycles due to uncached bios mem
1151 mips_return_c(ret, cycles + 5);
1154 void psxBios_memmove() { // 0x2c
1155 u32 ret = a0, cycles = 0;
1158 mips_return_c(0, 4);
1162 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1163 u32 dst = a0, len = a2 + 1;
1166 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1167 const u8 *sb = PSXM(a1);
1169 if (db != INVALID_PTR && sb != INVALID_PTR)
1175 psxCpu->Clear(dst, (len + 3) / 4);
1176 cycles = 10 + len * 8;
1177 } else if ((s32)a2 > 0) {
1178 do_memcpy(a0, a1, a2);
1184 mips_return_c(ret, cycles + 5);
1187 void psxBios_memcmp() { // 0x2d
1191 void psxBios_memchr() { // 0x2e
1192 char *p = (char *)Ra0;
1194 if (a0 == 0 || a2 > 0x7FFFFFFF)
1200 while ((s32)a2-- > 0) {
1201 if (*p++ != (s8)a1) continue;
1202 v0 = a0 + (p - (char *)Ra0 - 1);
1210 static void psxBios_rand() { // 0x2f
1211 u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1212 storeRam32(A_RND_SEED, s);
1214 mips_return_c((s >> 16) & 0x7fff, 12+37);
1217 static void psxBios_srand() { // 0x30
1218 storeRam32(A_RND_SEED, a0);
1219 mips_return_void_c(3);
1222 static u32 qscmpfunc, qswidth;
1224 static inline int qscmp(char *a, char *b) {
1227 a0 = sa0 + (a - (char *)PSXM(sa0));
1228 a1 = sa0 + (b - (char *)PSXM(sa0));
1230 softCall(qscmpfunc);
1236 static inline void qexchange(char *i, char *j) {
1247 static inline void q3exchange(char *i, char *j, char *k) {
1259 static void qsort_main(char *a, char *l) {
1260 char *i, *j, *lp, *hp;
1265 if ((n = l - a) <= qswidth)
1267 n = qswidth * (n / (2 * qswidth));
1273 if ((c = qscmp(i, lp)) == 0) {
1274 qexchange(i, lp -= qswidth);
1285 if ((c = qscmp(hp, j)) == 0) {
1286 qexchange(hp += qswidth, j);
1291 q3exchange(i, hp += qswidth, j);
1305 if (lp - a >= l - hp) {
1306 qsort_main(hp + qswidth, l);
1315 q3exchange(j, lp -= qswidth, i);
1320 void psxBios_qsort() { // 0x31
1323 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1328 static int malloc_heap_grow(u32 size) {
1329 u32 heap_addr, heap_end, heap_addr_new;
1331 heap_addr = loadRam32(A_HEAP_BASE);
1332 heap_end = loadRam32(A_HEAP_END);
1333 heap_addr_new = heap_addr + size + 4;
1334 if (heap_addr_new >= heap_end)
1336 storeRam32(A_HEAP_BASE, heap_addr_new);
1337 storeRam32(heap_addr - 4, size | 1);
1338 storeRam32(heap_addr + size, ~1); // terminator
1342 static void psxBios_malloc() { // 0x33
1343 u32 size = (a0 + 3) & ~3;
1344 u32 limit = 32*1024;
1348 PSXBIOS_LOG("psxBios_%s %d\n", biosA0n[0x33], a0);
1350 if (!loadRam32(A_HEAP_INIT_FLG)) {
1351 u32 heap_addr = loadRam32(A_HEAP_BASE);
1352 storeRam32(heap_addr, ~1);
1353 storeRam32(A_HEAP_FRSTCHNK, heap_addr);
1354 storeRam32(A_HEAP_CURCHNK, heap_addr);
1355 storeRam32(A_HEAP_BASE, heap_addr + 4);
1356 if (malloc_heap_grow(size)) {
1357 PSXBIOS_LOG("malloc: init OOM\n");
1358 mips_return_c(0, 20);
1361 storeRam32(A_HEAP_INIT_FLG, 1);
1364 for (i = 0; tries > 0 && i < limit; i++)
1366 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1367 u32 chunk_hdr = loadRam32(chunk);
1368 u32 next_chunk = chunk + 4 + (chunk_hdr & ~3);
1369 u32 next_chunk_hdr = loadRam32(next_chunk);
1371 //printf(" c %08x %08x\n", chunk, chunk_hdr);
1372 if (chunk_hdr & 1) {
1374 if (chunk_hdr > (size | 1)) {
1376 u32 p2size = (chunk_hdr & ~3) - size - 4;
1377 storeRam32(chunk + 4 + size, p2size | 1);
1378 chunk_hdr = size | 1;
1380 if (chunk_hdr == (size | 1)) {
1381 storeRam32(chunk, size);
1385 if (next_chunk_hdr == ~1) {
1386 // rm useless last free block
1387 storeRam32(A_HEAP_BASE, chunk + 4);
1388 storeRam32(chunk, ~1);
1391 if (next_chunk_hdr & 1) {
1393 u32 msize = (chunk_hdr & ~3) + 4 + (next_chunk_hdr & ~3);
1394 storeRam32(chunk, msize | 1);
1398 if (chunk_hdr == ~1) {
1401 storeRam32(A_HEAP_CURCHNK, loadRam32(A_HEAP_FRSTCHNK));
1405 // go to the next chunk
1406 storeRam32(A_HEAP_CURCHNK, next_chunk);
1411 PSXBIOS_LOG("malloc: limit OOM\n");
1414 else if (tries == 0 && malloc_heap_grow(size)) {
1415 PSXBIOS_LOG("malloc: grow OOM s=%d end=%08x/%08x\n",
1416 size, loadRam32(A_HEAP_BASE), loadRam32(A_HEAP_END));
1420 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1421 storeRam32(chunk, loadRam32(chunk) & ~3);
1425 PSXBIOS_LOG(" -> %08x\n", ret);
1426 mips_return_c(ret, 40);
1429 static void psxBios_free() { // 0x34
1430 PSXBIOS_LOG("psxBios_%s %x (%d bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1431 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1432 mips_return_void_c(5);
1435 static void psxBios_calloc() { // 0x37
1437 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1439 a0 = size = a0 * a1;
1443 a0 = ret; a1 = size;
1446 mips_return_c(ret, 21);
1449 void psxBios_realloc() { // 0x38
1453 PSXBIOS_LOG("psxBios_%s %08x %d\n", biosA0n[0x38], a0, a1);
1456 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1461 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1466 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1467 /* Note that it is not quite implemented this way here. */
1477 /* InitHeap(void *block , int n) */
1478 static void psxBios_InitHeap() { // 0x39
1479 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1481 storeRam32(A_HEAP_BASE, a0);
1482 storeRam32(A_HEAP_SIZE, a1);
1483 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1484 storeRam32(A_HEAP_INIT_FLG, 0);
1487 mips_return_void_c(14);
1490 void psxBios_getchar() { //0x3b
1491 v0 = getchar(); pc0 = ra;
1494 static void psxBios_printf_psxout() { // 0x3f
1497 u32 save[4] = { 0, };
1503 if (psp != INVALID_PTR) {
1504 memcpy(save, psp, 4 * 4);
1505 psxMu32ref(sp) = SWAP32((u32)a0);
1506 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1507 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1508 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1520 tmp2[j++] = Ra0[i]; goto _start;
1522 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1533 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1537 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1543 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1545 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1547 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1549 *ptmp++ = Ra0[i]; break;
1559 if (psp != INVALID_PTR)
1560 memcpy(psp, save, 4 * 4);
1563 SysPrintf("%s", tmp);
1566 void psxBios_printf() { // 0x3f
1567 psxBios_printf_psxout();
1571 static void psxBios_cd() { // 0x40
1572 const char *p, *dir = Ra0;
1573 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x40], a0, dir);
1574 if (dir != INVALID_PTR) {
1575 if ((p = strchr(dir, ':')))
1579 snprintf(cdir, sizeof(cdir), "%s", dir);
1581 mips_return_c(1, 100);
1584 static void psxBios_format() { // 0x41
1585 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x41], a0, Ra0);
1586 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1588 CreateMcd(Config.Mcd1);
1589 LoadMcd(1, Config.Mcd1);
1592 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1594 CreateMcd(Config.Mcd2);
1595 LoadMcd(2, Config.Mcd2);
1605 static void psxBios_SystemErrorUnresolvedException() {
1606 if (floodchk != 0x12340a40) { // prevent log flood
1607 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1608 floodchk = 0x12340a40;
1610 mips_return_void_c(1000);
1613 static void FlushCache() {
1614 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1615 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1617 // runs from uncached mem so tons of cycles
1621 // you likely want to mask irqs before calling these
1622 static u8 cdrom_sync(int do_ack)
1625 if (psxRegs.interrupt & (1u << PSXINT_CDR)) {
1626 if ((s32)(psxRegs.cycle - event_cycles[PSXINT_CDR]) < 0)
1627 psxRegs.cycle = event_cycles[PSXINT_CDR] + 1;
1628 irq_test(&psxRegs.CP0);
1632 r = cdrRead3() & 0x1f;
1633 cdrWrite3(0x5f); // ack; clear params
1638 static void cdrom_cmd_and_wait(u8 cmd, int arg_cnt, int resp_cnt, ...)
1644 va_start(ap, resp_cnt);
1645 while (arg_cnt-- > 0)
1646 cdrWrite2(va_arg(ap, u32));
1651 u8 r = cdrom_sync(1);
1652 assert(r == 3); (void)r;
1656 u8 r = cdrom_sync(1);
1657 assert(r == 2); (void)r;
1663 * long Load(char *name, struct EXEC *header);
1666 void psxBios_Load() { // 0x42
1667 u8 time[3] = { 2, 0, 0x16 };
1675 PSXBIOS_LOG("psxBios_%s %x(%s), %x\n", biosA0n[0x42], a0, pa0, a1);
1676 if (pa0 == INVALID_PTR || pa1 == INVALID_PTR) {
1680 if ((p = strchr(pa0, ':')))
1685 snprintf(path, sizeof(path), "%s\\%s", cdir, (char *)pa0);
1687 snprintf(path, sizeof(path), "%s", (char *)pa0);
1689 if (LoadCdromFile(path, &eheader, time) == 0) {
1690 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1691 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1695 PSXBIOS_LOG(" -> %d\n", v0);
1699 // set the cdrom to a state of just after exe read
1700 psxRegs.CP0.n.SR &= ~0x404;
1703 cdrWrite2(0x1f); // unmask
1704 cdrom_cmd_and_wait(0x0e, 1, 1, 0x80u); // CdlSetmode
1705 cdrom_cmd_and_wait(0x02, 3, 1, time[0], time[1], time[2]); // CdlSetloc
1706 cdrom_cmd_and_wait(0x15, 0, 2); // CdlSeekL
1707 psxHwWrite16(0x1f801070, ~4);
1708 MTC0(&psxRegs, 12, psxRegs.CP0.n.SR | 0x404);
1712 * int Exec(struct EXEC *header , int argc , char **argv);
1715 void psxBios_Exec() { // 43
1716 EXEC *header = (EXEC *)castRam32ptr(a0);
1720 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1722 header->_sp = SWAP32(sp);
1723 header->_fp = SWAP32(fp);
1724 header->_sp = SWAP32(sp);
1725 header->_gp = SWAP32(gp);
1726 header->ret = SWAP32(ra);
1727 header->base = SWAP32(s0);
1729 ptr = SWAP32(header->b_addr);
1730 len = SWAP32(header->b_size);
1736 if (header->S_addr != 0)
1737 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1739 gp = SWAP32(header->gp0);
1747 pc0 = SWAP32(header->_pc0);
1750 static void psxBios_FlushCache() { // 44
1751 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1756 void psxBios_GPU_dw() { // 0x46
1761 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1764 GPU_writeData(0xa0000000);
1765 GPU_writeData((a1<<0x10)|(a0&0xffff));
1766 GPU_writeData((a3<<0x10)|(a2&0xffff));
1768 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1771 GPU_writeData(SWAPu32(*ptr++));
1777 static void gpu_sync() {
1778 // not implemented...
1779 // might be problematic to do because of Config.GpuListWalking
1780 if (psxRegs.interrupt & (1u << PSXINT_GPUDMA))
1781 log_unhandled("gpu_sync with active dma\n");
1782 mips_return_c(0, 21);
1785 void psxBios_mem2vram() { // 0x47
1787 gpuSyncPluginSR(); // flush
1788 GPU_writeData(0xa0000000);
1789 GPU_writeData((a1<<0x10)|(a0&0xffff));
1790 GPU_writeData((a3<<0x10)|(a2&0xffff));
1791 size = ((((a2 * a3) / 2) >> 4) << 16);
1792 GPU_writeStatus(0x04000002);
1793 psxHwWrite32(0x1f8010f4,0);
1794 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1795 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1796 psxHwWrite32(0x1f8010a4, size | 0x10);
1797 psxHwWrite32(0x1f8010a8,0x01000201);
1802 void psxBios_SendGPU() { // 0x48
1803 GPU_writeStatus(a0);
1808 void psxBios_GPU_cw() { // 0x49
1815 void psxBios_GPU_cwb() { // 0x4a
1816 u32 *ptr = (u32*)Ra0;
1821 GPU_writeData(SWAPu32(*ptr++));
1827 void psxBios_GPU_SendPackets() { //4b:
1829 GPU_writeStatus(0x04000002);
1830 psxHwWrite32(0x1f8010f4,0);
1831 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1832 psxHwWrite32(0x1f8010a0,a0);
1833 psxHwWrite32(0x1f8010a4,0);
1834 psxHwWrite32(0x1f8010a8,0x010000401);
1838 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1839 psxHwWrite32(0x1f8010a8,0x00000401);
1840 GPU_writeData(0x0400000);
1841 GPU_writeData(0x0200000);
1842 GPU_writeData(0x0100000);
1847 void psxBios_GPU_GetGPUStatus() { // 0x4d
1848 v0 = GPU_readStatus();
1854 void psxBios_LoadExec() { // 51
1855 EXEC *header = (EXEC*)PSXM(0xf000);
1859 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1861 s_addr = a1; s_size = a2;
1866 header->S_addr = s_addr;
1867 header->s_size = s_size;
1869 a0 = 0xf000; a1 = 0; a2 = 0;
1873 static void psxBios__bu_init() { // 70
1874 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1876 DeliverEvent(0xf0000011, 0x0004);
1877 DeliverEvent(0xf4000001, 0x0004);
1882 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1883 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1884 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1886 static void psxBios_EnqueueCdIntr_(void)
1888 u32 *ram32 = (u32 *)psxM;
1890 // traps should already be installed by write_chain()
1891 ram32[0x91d0/4] = 0;
1892 ram32[0x91d4/4] = SWAP32(0xbfc0506c);
1893 ram32[0x91d8/4] = SWAP32(0xbfc04dec);
1894 psxBios_SysEnqIntRP_(0, 0x91d0);
1895 ram32[0x91e0/4] = 0;
1896 ram32[0x91e4/4] = SWAP32(0xbfc050a4);
1897 ram32[0x91e8/4] = SWAP32(0xbfc04fbc);
1898 psxBios_SysEnqIntRP_(0, 0x91e0);
1902 static void setup_cd_irq_and_events(void)
1904 u16 specs[] = { 0x10, 0x20, 0x40, 0x80, 0x8000 };
1907 psxBios_EnqueueCdIntr_();
1909 for (i = 0; i < sizeof(specs) / sizeof(specs[0]); i++) {
1910 u32 h = OpenEvent(0xf0000003, specs[i], EvMdMARK, 0);
1912 storeRam32(A_CD_EVENTS + i * 4, h);
1917 static void psxBios_CdReset_() {
1918 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
1922 cdrWrite2(0x1f); // unmask
1923 cdrom_cmd_and_wait(0x0a, 0, 2); // CdlReset
1924 cdrom_cmd_and_wait(0x0e, 1, 1, 0x80u); // CdlSetmode
1926 // todo(?): should read something (iso root directory?)
1927 // from { 0, 2, 16 } to somewhere and pause
1930 psxHwWrite16(0x1f801070, ~4);
1931 MTC0(&psxRegs, 12, psxRegs.CP0.n.SR | 0x404);
1932 DeliverEvent(0xf0000003, 0x0020);
1935 static void psxBios_CdInit() { // 54, 71
1936 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1937 setup_cd_irq_and_events();
1941 // this function takes pretty much forever
1942 mips_return_c(0, 50000*11);
1945 static void psxBios_DequeueCdIntr_() {
1946 psxBios_SysDeqIntRP_(0, 0x91d0);
1947 psxBios_SysDeqIntRP_(0, 0x91e0);
1951 static void psxBios_CdReset() { // 95
1952 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x95]);
1956 static void psxBios_EnqueueCdIntr() { // a2
1957 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa2]);
1958 psxBios_EnqueueCdIntr_();
1959 // return value comes from SysEnqIntRP() insternal call
1962 static void psxBios_DequeueCdIntr() { // a3
1963 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1964 psxBios_DequeueCdIntr_();
1967 static void psxBios_CdRemove() { // 56, 72
1968 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1970 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1971 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1972 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1973 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1974 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1975 psxBios_DequeueCdIntr_();
1977 // EnterCriticalSection - should be done at the beginning,
1978 // but this way is much easier to implement
1984 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1986 static void psxBios_SetConf() { // 9c
1987 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1988 setup_tt(a1, a0, a2);
1989 psxRegs.CP0.n.SR |= 0x401;
1990 mips_return_void_c(500);
1993 static void psxBios_GetConf() { // 9d
1994 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1995 storeRam32(a0, loadRam32(A_CONF_EvCB));
1996 storeRam32(a1, loadRam32(A_CONF_TCB));
1997 storeRam32(a2, loadRam32(A_CONF_SP));
1998 mips_return_void_c(10);
2001 void psxBios_SetMem() { // 9f
2002 u32 new = psxHu32(0x1060);
2005 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
2010 psxHu32ref(0x1060) = SWAP32(new);
2011 psxMu32ref(0x060) = a0;
2012 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
2016 psxHu32ref(0x1060) = SWAP32(new | 0x300);
2017 psxMu32ref(0x060) = a0;
2018 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
2021 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
2028 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
2029 static void psxBios_get_cd_status() // a6
2031 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
2036 static void psxBios_GetSystemInfo() { // b4
2038 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
2039 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
2042 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
2043 case 2: ret = 0xbfc0012c; break;
2044 case 5: ret = loadRam32(0x60) << 10; break;
2046 mips_return_c(ret, 20);
2049 /* System calls B0 */
2051 static u32 psxBios_SysMalloc_(u32 size);
2053 static void psxBios_SysMalloc() { // B 00
2054 u32 ret = psxBios_SysMalloc_(a0);
2056 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
2057 mips_return_c(ret, 33);
2060 void psxBios_SetRCnt() { // 02
2062 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
2069 psxRcntWtarget(a0, a1);
2070 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
2071 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
2072 if (a2&0x0010) mode|= 0x001; // Timer stop mode
2073 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
2074 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
2076 psxRcntWmode(a0, mode);
2081 void psxBios_GetRCnt() { // 03
2083 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
2088 case 0: v0 = psxRcntRcount0(); break;
2089 case 1: v0 = psxRcntRcount1(); break;
2090 case 2: v0 = psxRcntRcount2(); break;
2091 case 3: v0 = 0; break;
2096 void psxBios_StartRCnt() { // 04
2098 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
2102 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
2103 else psxHu32ref(0x1074)|= SWAPu32(0x1);
2107 void psxBios_StopRCnt() { // 05
2109 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
2113 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
2114 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
2118 void psxBios_ResetRCnt() { // 06
2120 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
2125 psxRcntWmode(a0, 0);
2126 psxRcntWtarget(a0, 0);
2127 psxRcntWcount(a0, 0);
2132 static u32 DeliverEvent(u32 class, u32 spec) {
2133 EvCB *ev, *ev_first = (EvCB *)loadRam32ptr(A_TT_EvCB);
2134 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
2135 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
2136 u32 i, lim = evcb_len / 0x1c;
2138 //printf("%s %08x %x\n", __func__, class, spec);
2139 for (i = 0, ev = ev_first; i < lim; i++, ev++) {
2141 if (SWAP32(ev->status) != EvStACTIVE)
2144 if (SWAP32(ev->class) != class)
2147 if (SWAP32(ev->spec) != spec)
2150 ret = SWAP32(ev->mode);
2151 if (ret == EvMdMARK) {
2152 if (ev->status != SWAP32(EvStALREADY))
2153 PSXBIOS_EV_LOG("DeliverEvent %08x %x (%08zx) set\n",
2154 class, spec, (ev - ev_first) | 0xf1000000u);
2155 ev->status = SWAP32(EvStALREADY);
2159 if (ret == EvMdCALL) {
2160 ret = SWAP32(ev->fhandler);
2161 PSXBIOS_EV_LOG("DeliverEvent %08x %x (%08zx) cb %x\n",
2162 class, spec, (ev - ev_first) | 0xf1000000u, ret);
2175 static u32 UnDeliverEvent(u32 class, u32 spec) {
2176 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2177 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
2178 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
2179 u32 i, lim = evcb_len / 0x1c;
2181 for (i = 0; i < lim; i++, ev++) {
2183 if (SWAP32(ev->status) != EvStALREADY)
2186 if (SWAP32(ev->class) != class)
2189 if (SWAP32(ev->spec) != spec)
2192 if (SWAP32(ev->mode) == EvMdMARK)
2193 ev->status = SWAP32(EvStACTIVE);
2199 static void psxBios_DeliverEvent() { // 07
2201 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
2203 ret = DeliverEvent(a0, a1);
2207 static s32 get_free_EvCB_slot() {
2208 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2209 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
2212 for (i = 0; i < lim; i++, ev++) {
2214 if (ev->status == SWAP32(EvStUNUSED))
2220 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2221 u32 ret = get_free_EvCB_slot();
2222 if ((s32)ret >= 0) {
2223 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2224 ev->class = SWAP32(class);
2225 ev->status = SWAP32(EvStDISABLED);
2226 ev->spec = SWAP32(spec);
2227 ev->mode = SWAP32(mode);
2228 ev->fhandler = SWAP32(func);
2234 static void psxBios_OpenEvent() { // 08
2235 u32 ret = OpenEvent(a0, a1, a2, a3);
2236 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2237 biosB0n[0x08], a0, a1, a2, a3, ret);
2238 mips_return_c(ret, 36);
2241 static void CloseEvent(u32 ev)
2243 u32 base = loadRam32(A_TT_EvCB);
2244 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2247 static void psxBios_CloseEvent() { // 09
2248 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2249 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2251 mips_return_c(1, 10);
2254 static void psxBios_WaitEvent() { // 0a
2255 u32 base = loadRam32(A_TT_EvCB);
2256 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2257 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2260 if (status == EvStALREADY) {
2261 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2265 if (status != EvStACTIVE)
2267 mips_return_c(0, 2);
2271 // retrigger this hlecall after the next emulation event
2273 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2274 psxRegs.cycle = next_interupt;
2278 static void psxBios_TestEvent() { // 0b
2279 u32 base = loadRam32(A_TT_EvCB);
2280 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2283 if (psxRegs.cycle - floodchk > 16*1024u) { // prevent log flood
2284 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2285 floodchk = psxRegs.cycle;
2287 if (status == EvStALREADY) {
2288 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2292 mips_return_c(ret, 15);
2295 static void EnableEvent(u32 ev, int do_log) {
2296 u32 base = loadRam32(A_TT_EvCB);
2297 u32 status = loadRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4);
2299 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], ev, status);
2300 if (status != EvStUNUSED)
2301 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2304 static void psxBios_EnableEvent() { // 0c
2306 mips_return_c(1, 15);
2309 static void psxBios_DisableEvent() { // 0d
2310 u32 base = loadRam32(A_TT_EvCB);
2311 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2312 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2313 if (status != EvStUNUSED)
2314 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2316 mips_return_c(1, 15);
2320 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2323 void psxBios_OpenTh() { // 0e
2324 TCB *tcb = loadRam32ptr(A_TT_TCB);
2325 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2328 for (th = 1; th < limit; th++)
2330 if (tcb[th].status != SWAP32(0x4000)) break;
2334 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2335 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2337 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2339 mips_return_c(0xffffffff, 20);
2342 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2344 tcb[th].status = SWAP32(0x4000);
2345 tcb[th].mode = SWAP32(0x1000);
2346 tcb[th].epc = SWAP32(a0);
2347 tcb[th].reg[30] = SWAP32(a1); // fp
2348 tcb[th].reg[29] = SWAP32(a1); // sp
2349 tcb[th].reg[28] = SWAP32(a2); // gp
2351 mips_return_c(0xff000000 + th, 34);
2355 * int CloseTh(long thread);
2358 static void psxBios_CloseTh() { // 0f
2359 u32 tcb = loadRam32(A_TT_TCB);
2360 u32 th = a0 & 0xffff;
2362 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2363 // in the usual bios fashion no checks, just write and return 1
2364 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2366 mips_return_c(1, 11);
2370 * int ChangeTh(long thread);
2373 void psxBios_ChangeTh() { // 10
2374 u32 tcbBase = loadRam32(A_TT_TCB);
2375 u32 th = a0 & 0xffff;
2377 // this is quite spammy
2378 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2380 // without doing any argument checks, just issue a syscall
2381 // (like the real bios does)
2383 a1 = tcbBase + th * sizeof(TCB);
2388 void psxBios_InitPAD() { // 0x12
2389 u32 i, *ram32 = (u32 *)psxM;
2390 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2392 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2393 ram32[A_PAD_DR_DST/4] = 0;
2394 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2395 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2396 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2397 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2398 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2399 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2400 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2401 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2403 for (i = 0; i < a1; i++) {
2405 storeRam8(a0 + i, 0);
2407 for (i = 0; i < a3; i++) {
2409 storeRam8(a2 + i, 0);
2411 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2413 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2415 mips_return_c(1, 200);
2418 void psxBios_StartPAD() { // 13
2419 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2421 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2422 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2423 psxHwWrite16(0x1f801070, ~1);
2424 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2425 storeRam32(A_PAD_ACK_VBL, 1);
2426 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2427 psxRegs.CP0.n.SR |= 0x401;
2429 mips_return_c(1, 300);
2432 void psxBios_StopPAD() { // 14
2433 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2434 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2435 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2436 psxRegs.CP0.n.SR |= 0x401;
2437 mips_return_void_c(200);
2440 static void psxBios_PAD_init() { // 15
2442 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2443 if (a0 == 0x20000000 || a0 == 0x20000001)
2446 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2447 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2450 storeRam32(A_PAD_DR_DST, dst);
2453 mips_return_c(ret, 100);
2456 static u32 psxBios_PAD_dr_() {
2457 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2458 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2459 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2460 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2461 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2463 dst[0] = buf1[3], dst[1] = buf1[2];
2464 if (buf1[1] == 0x23) {
2465 dst[0] |= 0xc7, dst[1] |= 7;
2466 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2467 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2470 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2472 dst[2] = buf2[3], dst[3] = buf2[2];
2473 if (buf2[1] == 0x23) {
2474 dst[2] |= 0xc7, dst[3] |= 7;
2475 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2476 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2480 return SWAP32(*(u32 *)dst);
2483 static void psxBios_PAD_dr() { // 16
2484 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2485 u32 ret = psxBios_PAD_dr_();
2489 static void psxBios_ReturnFromException() { // 17
2490 u32 tcbPtr = loadRam32(A_TT_PCB);
2491 const TCB *tcb = loadRam32ptr(tcbPtr);
2495 for (i = 1; i < 32; i++)
2496 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2497 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2498 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2499 sr = SWAP32(tcb->sr);
2501 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2502 pc0 = k0 = SWAP32(tcb->epc);
2504 // the interpreter wants to know about sr changes, so do a MTC0
2505 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2506 MTC0(&psxRegs, 12, sr);
2512 void psxBios_ResetEntryInt() { // 18
2513 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2515 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2516 mips_return_void_c(5);
2519 void psxBios_HookEntryInt() { // 19
2520 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2522 storeRam32(A_EEXIT_PTR, a0);
2523 mips_return_void_c(3);
2526 static void psxBios_UnDeliverEvent() { // 0x20
2528 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2530 ret = UnDeliverEvent(a0, a1);
2534 static void buopen(int mcd, char *ptr, char *cfg)
2537 char *mcd_data = ptr;
2539 strcpy(FDesc[1 + mcd].name, Ra0+5);
2540 FDesc[1 + mcd].offset = 0;
2541 FDesc[1 + mcd].mode = a1;
2543 for (i=1; i<16; i++) {
2544 const char *fptr = mcd_data + 128 * i;
2545 if ((*fptr & 0xF0) != 0x50) continue;
2546 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2547 FDesc[1 + mcd].mcfile = i;
2549 PSXBIOS_LOG("open %s -> %d\n", fptr+0xa, v0);
2552 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2553 for (i=1; i<16; i++) {
2554 int j, xor, nblk = a1 >> 16;
2556 char *fptr = mcd_data + 128 * i;
2558 if ((*fptr & 0xF0) != 0xa0) continue;
2560 FDesc[1 + mcd].mcfile = i;
2563 fptr[5] = 0x20 * nblk;
2566 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2567 pptr = fptr2 = fptr;
2568 for(j=2; j<=nblk; j++) {
2570 for(i++; i<16; i++) {
2573 memset(fptr2, 0, 128);
2574 fptr2[0] = j < nblk ? 0x52 : 0x53;
2577 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2582 /* shouldn't this return ENOSPC if i == 16? */
2584 pptr[8] = pptr[9] = 0xff;
2585 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2587 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2589 /* just go ahead and resave them all */
2590 SaveMcd(cfg, ptr, 128, 128 * 15);
2593 /* shouldn't this return ENOSPC if i == 16? */
2598 * int open(char *name , int mode);
2601 void psxBios_open() { // 0x32
2604 PSXBIOS_LOG("psxBios_%s %s(%x) %x\n", biosB0n[0x32], Ra0, a0, a1);
2608 if (pa0 != INVALID_PTR) {
2609 if (!strncmp(pa0, "bu00", 4)) {
2610 buopen(1, Mcd1Data, Config.Mcd1);
2613 if (!strncmp(pa0, "bu10", 4)) {
2614 buopen(2, Mcd2Data, Config.Mcd2);
2622 * int lseek(int fd , int offset , int whence);
2625 void psxBios_lseek() { // 0x33
2627 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2632 FDesc[a0].offset = a1;
2634 // DeliverEvent(0xf0000011, 0x0004);
2635 // DeliverEvent(0xf4000001, 0x0004);
2639 FDesc[a0].offset+= a1;
2640 v0 = FDesc[a0].offset;
2649 * int read(int fd , void *buf , int nbytes);
2652 static void psxBios_read() { // 0x34
2656 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2658 if (pa1 == INVALID_PTR)
2660 else if (a0 == 2 || a0 == 3)
2661 ret = card_buf_io(0, a0 - 2, pa1, a2);
2663 mips_return_c(ret, 100);
2667 * int write(int fd , void *buf , int nbytes);
2670 static void psxBios_write() { // 0x35/0x03
2674 if (a0 != 1) // not stdout
2675 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2677 if (pa1 == INVALID_PTR)
2679 else if (a0 == 1) { // stdout
2683 if (Config.PsxOut) while (a2 > 0) {
2684 SysPrintf("%c", *ptr++); a2--;
2688 else if (a0 == 2 || a0 == 3)
2689 ret = card_buf_io(1, a0 - 2, pa1, a2);
2691 mips_return_c(ret, 100);
2694 static void psxBios_write_psxout() {
2695 if (a0 == 1) { // stdout
2696 const char *ptr = Ra1;
2699 if (ptr != INVALID_PTR)
2701 SysPrintf("%c", *ptr++);
2705 static void psxBios_putchar_psxout() { // 3d
2706 SysPrintf("%c", (char)a0);
2709 static void psxBios_puts_psxout() { // 3e/3f
2710 SysPrintf("%s", Ra0);
2714 * int close(int fd);
2717 void psxBios_close() { // 0x36
2719 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2726 void psxBios_putchar() { // 3d
2727 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2731 void psxBios_puts() { // 3e/3f
2732 if (Config.PsxOut) SysPrintf("%s", Ra0);
2736 static void bufile(const u8 *mcd_data, u32 dir_) {
2737 struct DIRENTRY *dir = (struct DIRENTRY *)PSXM(dir_);
2738 const char *pfile = ffile + 5;
2739 const u8 *data = mcd_data;
2740 int i = 0, match = 0;
2745 if (dir == INVALID_PTR)
2748 for (; nfile <= 15 && !match; nfile++) {
2751 head = nfile * 0x40;
2752 data = mcd_data + 128 * nfile;
2753 name = (const char *)data + 0x0a;
2754 if ((data[0] & 0xF0) != 0x50) continue;
2755 /* Bug link files show up as free block. */
2756 if (!name[0]) continue;
2758 for (i = 0; i < 20; i++) {
2759 if (pfile[i] == name[i] || pfile[i] == '?')
2760 dir->name[i] = name[i];
2761 else if (pfile[i] == '*') {
2762 int len = strlen(name + i);
2765 memcpy(dir->name + i, name + i, len + 1);
2776 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2777 nfile, dir->name, pfile, name, match);
2779 for (; nfile <= 15; nfile++, blocks++) {
2780 const u8 *data2 = mcd_data + 128 * nfile;
2781 const char *name = (const char *)data2 + 0x0a;
2782 if ((data2[0] & 0xF0) != 0x50 || name[0])
2786 // nul char of full lenth name seems to overwrite .attr
2787 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2788 dir->size = 8192 * blocks;
2792 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2793 dir->attr, dir->size, dir->next, dir->head);
2797 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2800 static void psxBios_firstfile() { // 42
2803 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2806 if (pa0 != INVALID_PTR)
2808 snprintf(ffile, sizeof(ffile), "%s", pa0);
2810 strcpy(ffile + 5, "*"); // maybe?
2812 if (!strncmp(pa0, "bu00", 4)) {
2813 // firstfile() calls _card_read() internally, so deliver it's event
2814 DeliverEvent(0xf0000011, 0x0004);
2815 bufile((u8 *)Mcd1Data, a1);
2816 } else if (!strncmp(pa0, "bu10", 4)) {
2817 // firstfile() calls _card_read() internally, so deliver it's event
2818 DeliverEvent(0xf0000011, 0x0004);
2819 bufile((u8 *)Mcd2Data, a1);
2827 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2830 void psxBios_nextfile() { // 43
2831 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2834 if (!strncmp(ffile, "bu00", 4))
2835 bufile((u8 *)Mcd1Data, a0);
2836 else if (!strncmp(ffile, "bu10", 4))
2837 bufile((u8 *)Mcd2Data, a0);
2842 #define burename(mcd) { \
2843 for (i=1; i<16; i++) { \
2844 int namelen, j, xor = 0; \
2845 ptr = Mcd##mcd##Data + 128 * i; \
2846 if ((*ptr & 0xF0) != 0x50) continue; \
2847 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2848 namelen = strlen(Ra1+5); \
2849 memcpy(ptr+0xa, Ra1+5, namelen); \
2850 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2851 for (j=0; j<127; j++) xor^= ptr[j]; \
2853 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2860 * int rename(char *old, char *new);
2863 void psxBios_rename() { // 44
2870 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2875 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2876 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2880 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2889 #define budelete(mcd) { \
2890 for (i=1; i<16; i++) { \
2891 ptr = Mcd##mcd##Data + 128 * i; \
2892 if ((*ptr & 0xF0) != 0x50) continue; \
2893 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2894 *ptr = (*ptr & 0xf) | 0xA0; \
2895 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2896 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2903 * int delete(char *name);
2906 void psxBios_delete() { // 45
2912 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2917 if (pa0 != INVALID_PTR) {
2918 if (!strncmp(pa0, "bu00", 4)) {
2922 if (!strncmp(pa0, "bu10", 4)) {
2930 void psxBios_InitCARD() { // 4a
2931 u8 *ram8 = (u8 *)psxM;
2932 u32 *ram32 = (u32 *)psxM;
2933 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2934 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2936 ram8[A_CARD_ISLOT] = 0;
2937 ram8[A_CARD_STATUS1] = 1;
2938 ram8[A_CARD_STATUS2] = 1;
2939 // (maybe) todo: early_card_irq, etc
2941 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2943 psxBios_FlushCache();
2944 mips_return_c(0, 34+13+15+6);
2947 void psxBios_StartCARD() { // 4b
2948 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2949 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2950 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2952 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2953 storeRam32(A_PAD_ACK_VBL, 1);
2954 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2955 storeRam32(A_CARD_IRQR_ENA, 1);
2956 psxRegs.CP0.n.SR |= 0x401;
2958 mips_return_c(1, 200);
2961 void psxBios_StopCARD() { // 4c
2962 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2963 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2964 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2965 storeRam32(A_CARD_IRQR_ENA, 0);
2966 psxRegs.CP0.n.SR |= 0x401;
2967 mips_return_void_c(200);
2970 void psxBios__card_write() { // 0x4e
2974 PSXBIOS_LOG("psxBios_%s %02x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2975 // function also accepts sector 400h (a bug),
2976 // but what actually happens then?
2979 /* Invalid sectors */
2983 storeRam32(A_CARD_ACHAN, a0);
2986 if (pa2 != INVALID_PTR && a1 < 0x400) {
2988 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2989 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2991 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2992 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2996 storeRam8(A_CARD_STATUS1 + port, 4); // busy/write
2997 storeRam32(A_CARD_HANDLER, CARD_HARDLER_WRITE);
3002 static void psxBios__card_read() { // 0x4f
3006 PSXBIOS_LOG("psxBios_%s %x,%x,%x\n", biosB0n[0x4f], a0, a1, a2);
3009 /* Invalid sectors */
3013 storeRam32(A_CARD_ACHAN, a0);
3016 if (pa2 != INVALID_PTR && a1 < 0x400) {
3018 memcpy(pa2, Mcd1Data + a1 * 128, 128);
3020 memcpy(pa2, Mcd2Data + a1 * 128, 128);
3024 storeRam8(A_CARD_STATUS1 + port, 2); // busy/read
3025 storeRam32(A_CARD_HANDLER, CARD_HARDLER_READ);
3030 void psxBios__new_card() { // 0x50
3032 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
3038 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
3039 void psxBios__get_error(void) // 55
3041 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
3046 void psxBios_Krom2RawAdd() { // 0x51
3049 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
3050 const u32 table_8140[][2] = {
3051 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
3052 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
3053 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
3054 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
3055 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
3056 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
3057 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
3058 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
3059 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
3063 const u32 table_889f[][2] = {
3064 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
3065 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
3066 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
3067 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
3068 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
3069 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
3070 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
3071 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
3075 if (a0 >= 0x8140 && a0 <= 0x84be) {
3076 while (table_8140[i][0] <= a0) i++;
3077 a0 -= table_8140[i - 1][0];
3078 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
3079 } else if (a0 >= 0x889f && a0 <= 0x9872) {
3080 while (table_889f[i][0] <= a0) i++;
3081 a0 -= table_889f[i - 1][0];
3082 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
3090 void psxBios_GetC0Table() { // 56
3091 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
3092 log_unhandled("GetC0Table @%08x\n", ra);
3094 mips_return_c(A_C0_TABLE, 3);
3097 void psxBios_GetB0Table() { // 57
3098 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
3099 log_unhandled("GetB0Table @%08x\n", ra);
3101 mips_return_c(A_B0_TABLE, 3);
3104 static void psxBios__card_chan() { // 0x58
3105 // todo: should return active slot channel
3106 // (active - which was last processed by irq code)
3107 u32 ret = loadRam32(A_CARD_ACHAN);
3108 PSXBIOS_LOG("psxBios_%s -> %02x\n", biosB0n[0x58], ret);
3110 mips_return_c(ret, 8);
3113 static void psxBios_ChangeClearPad() { // 5b
3115 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
3116 ret = loadRam32(A_PAD_ACK_VBL);
3117 storeRam32(A_PAD_ACK_VBL, a0);
3119 mips_return_c(ret, 6);
3122 static void psxBios__card_status() { // 5c
3123 u8 s = loadRam8(A_CARD_STATUS1 + a0);
3124 PSXBIOS_LOG("psxBios_%s %x -> %x\n", biosB0n[0x5c], a0, s);
3126 mips_return_c(s, 5);
3129 static void psxBios__card_wait() { // 5d
3130 u8 s = loadRam8(A_CARD_STATUS1 + a0);
3131 PSXBIOS_LOG("psxBios_%s %x -> %x\n", biosB0n[0x5d], a0, s);
3135 log_unhandled("%s %x\n", __func__, s);
3137 mips_return_c(s, 11);
3140 static void psxBios__card_info() { // A ab
3141 PSXBIOS_LOG("psxBios_%s %02x\n", biosA0n[0xab], a0);
3143 storeRam32(A_CARD_ACHAN, a0);
3150 if (McdDisable[port & 1])
3154 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
3159 if (McdDisable[0] && McdDisable[1])
3163 // deliver from card_vint_handler()
3164 storeRam8(A_CARD_STATUS1 + port, 8); // busy/info
3165 storeRam32(A_CARD_HANDLER, CARD_HARDLER_INFO);
3167 DeliverEvent(0xf4000001, ret);
3168 DeliverEvent(0xf0000011, 0x0004); // ?
3173 static void psxBios__card_load() { // A ac
3174 PSXBIOS_LOG("psxBios_%s %02x\n", biosA0n[0xac], a0);
3176 storeRam32(A_CARD_ACHAN, a0);
3178 // DeliverEvent(0xf0000011, 0x0004);
3179 DeliverEvent(0xf4000001, 0x0004);
3184 static void card_vint_handler(void) {
3188 if (card_io_delay) {
3192 UnDeliverEvent(0xf0000011, 0x0004);
3193 UnDeliverEvent(0xf0000011, 0x8000);
3194 UnDeliverEvent(0xf0000011, 0x0100);
3195 UnDeliverEvent(0xf0000011, 0x0200);
3196 UnDeliverEvent(0xf0000011, 0x2000);
3199 select = loadRam8(A_CARD_ISLOT);
3200 select = (select ^ 1) & 1;
3201 storeRam8(A_CARD_ISLOT, select);
3203 select = loadRam8(A_CARD_ACHAN) >> 4;
3204 storeRam8(A_CARD_ISLOT, select);
3206 status = loadRam8(A_CARD_STATUS1 + select);
3210 //psxBios_SysDeqIntRP_(0, 0x7540);
3211 //psxBios_SysDeqIntRP_(0, 0x7540);
3212 //card_state_machine = 0;
3213 //card_error_flag = 0;
3214 handler = loadRam32(A_CARD_HANDLER);
3216 case CARD_HARDLER_INFO:
3217 DeliverEvent(0xf4000001, 4);
3218 DeliverEvent(0xf0000011, 4);
3219 storeRam8(A_CARD_STATUS1 + select, 1);
3220 storeRam32(A_CARD_HANDLER, 0);
3222 case CARD_HARDLER_WRITEM:
3223 case CARD_HARDLER_READM:
3224 DeliverEvent(0xf4000001, 4);
3226 case CARD_HARDLER_WRITE:
3227 case CARD_HARDLER_READ:
3228 DeliverEvent(0xf0000011, 4);
3229 storeRam8(A_CARD_STATUS1 + select, 1);
3230 storeRam32(A_CARD_HANDLER, 0);
3235 log_unhandled("%s: unhandled handler %x\n", __func__, handler);
3236 DeliverEvent(0xf0000011, 0x8000);
3237 storeRam8(A_CARD_STATUS1 + select, 1);
3238 storeRam32(A_CARD_HANDLER, 0);
3242 /* System calls C0 */
3244 static void psxBios_InitRCnt() { // 00
3246 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
3247 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
3248 for (i = 0; i < 3; i++) {
3249 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
3250 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
3251 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
3253 for (i = 0; i < 4; i++)
3254 psxBios_SysEnqIntRP_(a0, 0x6d58 + i * 0x10);
3255 mips_return_c(0, 9);
3258 static void psxBios_InitException() { // 01
3259 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
3260 psxBios_SysEnqIntRP_(a0, 0x6da8);
3261 mips_return_c(0, 9);
3265 * int SysEnqIntRP(int index , long *queue);
3268 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
3269 u32 old, base = loadRam32(A_TT_ExCB);
3271 old = loadRam32(base + (priority << 3));
3272 storeRam32(base + (priority << 3), chain_eptr);
3273 storeRam32(chain_eptr, old);
3274 mips_return_c(0, 9);
3277 static void psxBios_SysEnqIntRP() { // 02
3278 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
3279 psxBios_SysEnqIntRP_(a0, a1);
3283 * int SysDeqIntRP(int index , long *queue);
3286 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
3287 u32 ptr, next, base = loadRam32(A_TT_ExCB);
3288 u32 lim = 0, ret = 0;
3290 // as in original: no arg checks of any kind, bug if a1 == 0
3291 ptr = loadRam32(base + (priority << 3));
3293 next = loadRam32(ptr);
3294 if (ptr == chain_rm_eptr) {
3295 storeRam32(base + (priority << 3), next);
3300 while (next && next != chain_rm_eptr && lim++ < 100) {
3302 next = loadRam32(ptr);
3305 if (next == chain_rm_eptr) {
3306 next = loadRam32(next);
3307 storeRam32(ptr, next);
3314 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
3316 mips_return_c(ret, 12);
3319 static void psxBios_SysDeqIntRP() { // 03
3320 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3321 psxBios_SysDeqIntRP_(a0, a1);
3324 static void psxBios_get_free_EvCB_slot() { // 04
3325 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3326 s32 ret = get_free_EvCB_slot();
3327 mips_return_c(ret, 0);
3330 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3331 storeRam32(base, 0);
3332 storeRam32(A_KMALLOC_PTR, base);
3333 storeRam32(A_KMALLOC_SIZE, size);
3334 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3337 // this should be much more complicated, but maybe that'll be enough
3338 static u32 psxBios_SysMalloc_(u32 size) {
3339 u32 ptr = loadRam32(A_KMALLOC_PTR);
3341 size = (size + 3) & ~3;
3342 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3343 storeRam32(ptr, size);
3347 static void psxBios_SysInitMemory() { // 08
3348 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3350 psxBios_SysInitMemory_(a0, a1);
3351 mips_return_void_c(12);
3354 static void psxBios_ChangeClearRCnt() { // 0a
3357 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3359 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3360 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3361 mips_return_c(ret, 8);
3364 static void psxBios_InitDefInt() { // 0c
3365 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3366 // should also clear the autoack table
3367 psxBios_SysEnqIntRP_(a0, 0x6d98);
3368 mips_return_c(0, 20 + 6*2);
3371 void psxBios_dummy() {
3372 u32 pc = (pc0 & 0x1fffff) - 4;
3373 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3374 : pc == 0xc0 ? biosC0n : NULL;
3375 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3376 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3377 (void)pc; (void)ntab;
3378 mips_return_c(0, 100);
3381 void (*biosA0[256])();
3382 // C0 and B0 overlap (end of C0 is start of B0)
3383 void (*biosC0[256+128])();
3384 void (**biosB0)() = biosC0 + 128;
3386 static void setup_mips_code()
3389 ptr = (u32 *)&psxM[A_SYSCALL];
3390 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3391 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3392 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3394 ptr = (u32 *)&psxM[A_EXCEPTION];
3395 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3396 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3397 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3398 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3399 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3400 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3401 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3402 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3403 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3404 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3406 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3407 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3408 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3410 ptr[0xb0/4] = HLEOP(hleop_exception);
3413 static const struct {
3417 { 0xbfc050a4, hleop_exc0_0_1 },
3418 { 0xbfc04fbc, hleop_exc0_0_2 },
3419 { 0xbfc0506c, hleop_exc0_1_1 },
3420 { 0xbfc04dec, hleop_exc0_1_2 },
3421 { 0x1a00, hleop_exc0_2_2 },
3422 { 0x19c8, hleop_exc1_0_1 },
3423 { 0x18bc, hleop_exc1_0_2 },
3424 { 0x1990, hleop_exc1_1_1 },
3425 { 0x1858, hleop_exc1_1_2 },
3426 { 0x1958, hleop_exc1_2_1 },
3427 { 0x17f4, hleop_exc1_2_2 },
3428 { 0x1920, hleop_exc1_3_1 },
3429 { 0x1794, hleop_exc1_3_2 },
3430 { 0x2458, hleop_exc3_0_2 },
3431 { 0x49bc, hleop_exc_padcard1 }, // hleExcPadCard1
3432 { 0x4a4c, hleop_exc_padcard2 },
3435 static int chain_hle_op(u32 handler)
3439 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3440 if (chainfns[i].addr == handler)
3441 return chainfns[i].op;
3445 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3447 d[0] = SWAPu32(next);
3448 d[1] = SWAPu32(handler1);
3449 d[2] = SWAPu32(handler2);
3451 // install the hle traps
3452 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3453 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3456 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3458 u32 *ram32 = (u32 *)psxM;
3459 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3460 u32 p_excb, p_evcb, p_pcb, p_tcb;
3463 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3465 // the real bios doesn't care, but we just don't
3466 // want to crash in case of garbage parameters
3467 if (tcb_cnt > 1024) tcb_cnt = 1024;
3468 if (evcb_cnt > 1024) evcb_cnt = 1024;
3469 s_evcb = 0x1c * evcb_cnt;
3470 s_tcb = 0xc0 * tcb_cnt;
3472 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3473 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3474 p_excb = psxBios_SysMalloc_(s_excb);
3475 p_evcb = psxBios_SysMalloc_(s_evcb);
3476 p_pcb = psxBios_SysMalloc_(s_pcb);
3477 p_tcb = psxBios_SysMalloc_(s_tcb);
3479 // "table of tables". Some games modify it
3480 assert(A_TT_ExCB == 0x0100);
3481 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3482 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3483 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3484 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3485 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3486 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3487 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3488 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3489 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3490 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3491 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3492 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3494 storeRam32(p_excb + 0*4, 0x0000); // chain0
3495 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3496 storeRam32(p_excb + 4*4, 0x0000); // chain2
3497 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3499 storeRam32(p_pcb, p_tcb);
3500 storeRam32(p_tcb, 0x4000); // first TCB
3501 for (i = 1; i < tcb_cnt; i++)
3502 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3504 psxBios_SysEnqIntRP_(0, 0x6da8);
3505 setup_cd_irq_and_events();
3507 storeRam32(A_CONF_EvCB, evcb_cnt);
3508 storeRam32(A_CONF_TCB, tcb_cnt);
3509 storeRam32(A_CONF_SP, stack);
3512 static const u32 gpu_ctl_def[] = {
3513 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3514 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3517 static const u32 gpu_data_def[] = {
3518 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3519 0xe5001000, 0xe6000000,
3520 0x02000000, 0x00000000, 0x01ff03ff
3524 static const u16 spu_config[] = {
3525 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3526 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3527 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3528 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3529 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3530 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3531 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3532 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3535 void psxBiosSetupBootState(void)
3537 boolean hle = Config.HLE;
3538 u32 *hw = (u32 *)psxH;
3541 // see also SetBootRegs()
3544 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3545 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3547 k0 = 0xbfc0d968; k1 = 0xf1c;
3548 ra = 0xf0001234; // just to easily detect attempts to return
3549 psxRegs.CP0.n.Cause = 0x20;
3550 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3552 hw[0x1000/4] = SWAP32(0x1f000000);
3553 hw[0x1004/4] = SWAP32(0x1f802000);
3554 hw[0x1008/4] = SWAP32(0x0013243f);
3555 hw[0x100c/4] = SWAP32(0x00003022);
3556 hw[0x1010/4] = SWAP32(0x0013243f);
3557 hw[0x1014/4] = SWAP32(0x200931e1);
3558 hw[0x1018/4] = SWAP32(0x00020943);
3559 hw[0x101c/4] = SWAP32(0x00070777);
3560 hw[0x1020/4] = SWAP32(0x0000132c);
3561 hw[0x1060/4] = SWAP32(0x00000b88);
3562 hw[0x1070/4] = SWAP32(0x00000001);
3563 hw[0x1074/4] = SWAP32(0x0000000c);
3564 hw[0x2040/4] = SWAP32(0x00000900);
3567 hw[0x10a0/4] = SWAP32(0x00ffffff);
3568 hw[0x10a8/4] = SWAP32(0x00000401);
3569 hw[0x10b0/4] = SWAP32(0x0008b000);
3570 hw[0x10b4/4] = SWAP32(0x00010200);
3571 hw[0x10e0/4] = SWAP32(0x000eccf4);
3572 hw[0x10e4/4] = SWAP32(0x00000400);
3573 hw[0x10e8/4] = SWAP32(0x00000002);
3574 hw[0x10f0/4] = SWAP32(0x00009099);
3575 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3584 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3585 GPU_writeStatus(gpu_ctl_def[i]);
3586 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3587 GPU_writeData(gpu_data_def[i]);
3590 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3591 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3594 static void hleExc0_0_1();
3595 static void hleExc0_0_2();
3596 static void hleExc0_1_1();
3597 static void hleExc0_1_2();
3599 #include "sjisfont.h"
3601 void psxBiosInit() {
3602 u32 *ptr, *ram32, *rom32;
3607 psxRegs.biosBranchCheck = ~0;
3609 memset(psxM, 0, 0x10000);
3610 for(i = 0; i < 256; i++) {
3615 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3616 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3617 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3618 biosA0[0x3f] = psxBios_printf_psxout;
3621 char verstr[0x24+1];
3622 rom32 = (u32 *)psxR;
3623 memcpy(verstr, psxR + 0x12c, 0x24);
3625 SysPrintf("BIOS: %08x, '%s', '%c'\n", SWAP32(rom32[0x100/4]),
3626 verstr, psxR[0x7ff52]);
3630 for(i = 0; i < 256; i++) {
3631 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3632 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3633 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3636 biosA0[0x00] = psxBios_open;
3637 biosA0[0x01] = psxBios_lseek;
3638 biosA0[0x02] = psxBios_read;
3639 biosA0[0x03] = psxBios_write;
3640 biosA0[0x04] = psxBios_close;
3641 //biosA0[0x05] = psxBios_ioctl;
3642 //biosA0[0x06] = psxBios_exit;
3643 //biosA0[0x07] = psxBios_sys_a0_07;
3644 biosA0[0x08] = psxBios_getc;
3645 biosA0[0x09] = psxBios_putc;
3646 biosA0[0x0a] = psxBios_todigit;
3647 //biosA0[0x0b] = psxBios_atof;
3648 biosA0[0x0c] = psxBios_strtoul;
3649 biosA0[0x0d] = psxBios_strtol;
3650 biosA0[0x0e] = psxBios_abs;
3651 biosA0[0x0f] = psxBios_labs;
3652 biosA0[0x10] = psxBios_atoi;
3653 biosA0[0x11] = psxBios_atol;
3654 //biosA0[0x12] = psxBios_atob;
3655 biosA0[0x13] = psxBios_setjmp;
3656 biosA0[0x14] = psxBios_longjmp;
3657 biosA0[0x15] = psxBios_strcat;
3658 biosA0[0x16] = psxBios_strncat;
3659 biosA0[0x17] = psxBios_strcmp;
3660 biosA0[0x18] = psxBios_strncmp;
3661 biosA0[0x19] = psxBios_strcpy;
3662 biosA0[0x1a] = psxBios_strncpy;
3663 biosA0[0x1b] = psxBios_strlen;
3664 biosA0[0x1c] = psxBios_index;
3665 biosA0[0x1d] = psxBios_rindex;
3666 biosA0[0x1e] = psxBios_strchr;
3667 biosA0[0x1f] = psxBios_strrchr;
3668 biosA0[0x20] = psxBios_strpbrk;
3669 biosA0[0x21] = psxBios_strspn;
3670 biosA0[0x22] = psxBios_strcspn;
3671 biosA0[0x23] = psxBios_strtok;
3672 biosA0[0x24] = psxBios_strstr;
3673 biosA0[0x25] = psxBios_toupper;
3674 biosA0[0x26] = psxBios_tolower;
3675 biosA0[0x27] = psxBios_bcopy;
3676 biosA0[0x28] = psxBios_bzero;
3677 biosA0[0x29] = psxBios_bcmp;
3678 biosA0[0x2a] = psxBios_memcpy;
3679 biosA0[0x2b] = psxBios_memset;
3680 biosA0[0x2c] = psxBios_memmove;
3681 biosA0[0x2d] = psxBios_memcmp;
3682 biosA0[0x2e] = psxBios_memchr;
3683 biosA0[0x2f] = psxBios_rand;
3684 biosA0[0x30] = psxBios_srand;
3685 biosA0[0x31] = psxBios_qsort;
3686 //biosA0[0x32] = psxBios_strtod;
3687 biosA0[0x33] = psxBios_malloc;
3688 biosA0[0x34] = psxBios_free;
3689 //biosA0[0x35] = psxBios_lsearch;
3690 //biosA0[0x36] = psxBios_bsearch;
3691 biosA0[0x37] = psxBios_calloc;
3692 biosA0[0x38] = psxBios_realloc;
3693 biosA0[0x39] = psxBios_InitHeap;
3694 //biosA0[0x3a] = psxBios__exit;
3695 biosA0[0x3b] = psxBios_getchar;
3696 biosA0[0x3c] = psxBios_putchar;
3697 //biosA0[0x3d] = psxBios_gets;
3698 biosA0[0x3e] = psxBios_puts;
3699 biosA0[0x3f] = psxBios_printf;
3700 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3701 //biosA0[0x41] = psxBios_LoadTest;
3702 biosA0[0x42] = psxBios_Load;
3703 biosA0[0x43] = psxBios_Exec;
3704 biosA0[0x44] = psxBios_FlushCache;
3705 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3706 biosA0[0x46] = psxBios_GPU_dw;
3707 biosA0[0x47] = psxBios_mem2vram;
3708 biosA0[0x48] = psxBios_SendGPU;
3709 biosA0[0x49] = psxBios_GPU_cw;
3710 biosA0[0x4a] = psxBios_GPU_cwb;
3711 biosA0[0x4b] = psxBios_GPU_SendPackets;
3712 biosA0[0x4c] = psxBios_sys_a0_4c;
3713 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3714 //biosA0[0x4e] = psxBios_GPU_sync;
3715 //biosA0[0x4f] = psxBios_sys_a0_4f;
3716 //biosA0[0x50] = psxBios_sys_a0_50;
3717 biosA0[0x51] = psxBios_LoadExec;
3718 //biosA0[0x52] = psxBios_GetSysSp;
3719 //biosA0[0x53] = psxBios_sys_a0_53;
3720 biosA0[0x54] = psxBios_CdInit;
3721 biosA0[0x55] = psxBios__bu_init;
3722 biosA0[0x56] = psxBios_CdRemove;
3723 //biosA0[0x57] = psxBios_sys_a0_57;
3724 //biosA0[0x58] = psxBios_sys_a0_58;
3725 //biosA0[0x59] = psxBios_sys_a0_59;
3726 //biosA0[0x5a] = psxBios_sys_a0_5a;
3727 //biosA0[0x5b] = psxBios_dev_tty_init;
3728 //biosA0[0x5c] = psxBios_dev_tty_open;
3729 //biosA0[0x5d] = psxBios_sys_a0_5d;
3730 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3731 //biosA0[0x5f] = psxBios_dev_cd_open;
3732 //biosA0[0x60] = psxBios_dev_cd_read;
3733 //biosA0[0x61] = psxBios_dev_cd_close;
3734 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3735 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3736 //biosA0[0x64] = psxBios_dev_cd_chdir;
3737 //biosA0[0x65] = psxBios_dev_card_open;
3738 //biosA0[0x66] = psxBios_dev_card_read;
3739 //biosA0[0x67] = psxBios_dev_card_write;
3740 //biosA0[0x68] = psxBios_dev_card_close;
3741 //biosA0[0x69] = psxBios_dev_card_firstfile;
3742 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3743 //biosA0[0x6b] = psxBios_dev_card_erase;
3744 //biosA0[0x6c] = psxBios_dev_card_undelete;
3745 //biosA0[0x6d] = psxBios_dev_card_format;
3746 //biosA0[0x6e] = psxBios_dev_card_rename;
3747 //biosA0[0x6f] = psxBios_dev_card_6f;
3748 biosA0[0x70] = psxBios__bu_init;
3749 biosA0[0x71] = psxBios_CdInit;
3750 biosA0[0x72] = psxBios_CdRemove;
3751 //biosA0[0x73] = psxBios_sys_a0_73;
3752 //biosA0[0x74] = psxBios_sys_a0_74;
3753 //biosA0[0x75] = psxBios_sys_a0_75;
3754 //biosA0[0x76] = psxBios_sys_a0_76;
3755 //biosA0[0x77] = psxBios_sys_a0_77;
3756 //biosA0[0x78] = psxBios__96_CdSeekL;
3757 //biosA0[0x79] = psxBios_sys_a0_79;
3758 //biosA0[0x7a] = psxBios_sys_a0_7a;
3759 //biosA0[0x7b] = psxBios_sys_a0_7b;
3760 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3761 //biosA0[0x7d] = psxBios_sys_a0_7d;
3762 //biosA0[0x7e] = psxBios__96_CdRead;
3763 //biosA0[0x7f] = psxBios_sys_a0_7f;
3764 //biosA0[0x80] = psxBios_sys_a0_80;
3765 //biosA0[0x81] = psxBios_sys_a0_81;
3766 //biosA0[0x82] = psxBios_sys_a0_82;
3767 //biosA0[0x83] = psxBios_sys_a0_83;
3768 //biosA0[0x84] = psxBios_sys_a0_84;
3769 //biosA0[0x85] = psxBios__96_CdStop;
3770 //biosA0[0x86] = psxBios_sys_a0_86;
3771 //biosA0[0x87] = psxBios_sys_a0_87;
3772 //biosA0[0x88] = psxBios_sys_a0_88;
3773 //biosA0[0x89] = psxBios_sys_a0_89;
3774 //biosA0[0x8a] = psxBios_sys_a0_8a;
3775 //biosA0[0x8b] = psxBios_sys_a0_8b;
3776 //biosA0[0x8c] = psxBios_sys_a0_8c;
3777 //biosA0[0x8d] = psxBios_sys_a0_8d;
3778 //biosA0[0x8e] = psxBios_sys_a0_8e;
3779 //biosA0[0x8f] = psxBios_sys_a0_8f;
3780 biosA0[0x90] = hleExc0_1_2;
3781 biosA0[0x91] = hleExc0_0_2;
3782 biosA0[0x92] = hleExc0_1_1;
3783 biosA0[0x93] = hleExc0_0_1;
3784 //biosA0[0x94] = psxBios_sys_a0_94;
3785 biosA0[0x95] = psxBios_CdReset;
3786 //biosA0[0x96] = psxBios_AddCDROMDevice;
3787 //biosA0[0x97] = psxBios_AddMemCardDevide;
3788 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3789 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3790 //biosA0[0x9a] = psxBios_sys_a0_9a;
3791 //biosA0[0x9b] = psxBios_sys_a0_9b;
3792 biosA0[0x9c] = psxBios_SetConf;
3793 biosA0[0x9d] = psxBios_GetConf;
3794 //biosA0[0x9e] = psxBios_sys_a0_9e;
3795 biosA0[0x9f] = psxBios_SetMem;
3796 //biosA0[0xa0] = psxBios__boot;
3797 //biosA0[0xa1] = psxBios_SystemError;
3798 biosA0[0xa2] = psxBios_EnqueueCdIntr;
3799 biosA0[0xa3] = psxBios_DequeueCdIntr;
3800 //biosA0[0xa4] = psxBios_sys_a0_a4;
3801 //biosA0[0xa5] = psxBios_ReadSector;
3802 biosA0[0xa6] = psxBios_get_cd_status;
3803 //biosA0[0xa7] = psxBios_bufs_cb_0;
3804 //biosA0[0xa8] = psxBios_bufs_cb_1;
3805 //biosA0[0xa9] = psxBios_bufs_cb_2;
3806 //biosA0[0xaa] = psxBios_bufs_cb_3;
3807 biosA0[0xab] = psxBios__card_info;
3808 biosA0[0xac] = psxBios__card_load;
3809 //biosA0[0axd] = psxBios__card_auto;
3810 //biosA0[0xae] = psxBios_bufs_cd_4;
3811 //biosA0[0xaf] = psxBios_sys_a0_af;
3812 //biosA0[0xb0] = psxBios_sys_a0_b0;
3813 //biosA0[0xb1] = psxBios_sys_a0_b1;
3814 //biosA0[0xb2] = psxBios_do_a_long_jmp
3815 //biosA0[0xb3] = psxBios_sys_a0_b3;
3816 biosA0[0xb4] = psxBios_GetSystemInfo;
3817 //*******************B0 CALLS****************************
3818 biosB0[0x00] = psxBios_SysMalloc;
3819 //biosB0[0x01] = psxBios_sys_b0_01;
3820 biosB0[0x02] = psxBios_SetRCnt;
3821 biosB0[0x03] = psxBios_GetRCnt;
3822 biosB0[0x04] = psxBios_StartRCnt;
3823 biosB0[0x05] = psxBios_StopRCnt;
3824 biosB0[0x06] = psxBios_ResetRCnt;
3825 biosB0[0x07] = psxBios_DeliverEvent;
3826 biosB0[0x08] = psxBios_OpenEvent;
3827 biosB0[0x09] = psxBios_CloseEvent;
3828 biosB0[0x0a] = psxBios_WaitEvent;
3829 biosB0[0x0b] = psxBios_TestEvent;
3830 biosB0[0x0c] = psxBios_EnableEvent;
3831 biosB0[0x0d] = psxBios_DisableEvent;
3832 biosB0[0x0e] = psxBios_OpenTh;
3833 biosB0[0x0f] = psxBios_CloseTh;
3834 biosB0[0x10] = psxBios_ChangeTh;
3835 //biosB0[0x11] = psxBios_psxBios_b0_11;
3836 biosB0[0x12] = psxBios_InitPAD;
3837 biosB0[0x13] = psxBios_StartPAD;
3838 biosB0[0x14] = psxBios_StopPAD;
3839 biosB0[0x15] = psxBios_PAD_init;
3840 biosB0[0x16] = psxBios_PAD_dr;
3841 biosB0[0x17] = psxBios_ReturnFromException;
3842 biosB0[0x18] = psxBios_ResetEntryInt;
3843 biosB0[0x19] = psxBios_HookEntryInt;
3844 //biosB0[0x1a] = psxBios_sys_b0_1a;
3845 //biosB0[0x1b] = psxBios_sys_b0_1b;
3846 //biosB0[0x1c] = psxBios_sys_b0_1c;
3847 //biosB0[0x1d] = psxBios_sys_b0_1d;
3848 //biosB0[0x1e] = psxBios_sys_b0_1e;
3849 //biosB0[0x1f] = psxBios_sys_b0_1f;
3850 biosB0[0x20] = psxBios_UnDeliverEvent;
3851 //biosB0[0x21] = psxBios_sys_b0_21;
3852 //biosB0[0x22] = psxBios_sys_b0_22;
3853 //biosB0[0x23] = psxBios_sys_b0_23;
3854 //biosB0[0x24] = psxBios_sys_b0_24;
3855 //biosB0[0x25] = psxBios_sys_b0_25;
3856 //biosB0[0x26] = psxBios_sys_b0_26;
3857 //biosB0[0x27] = psxBios_sys_b0_27;
3858 //biosB0[0x28] = psxBios_sys_b0_28;
3859 //biosB0[0x29] = psxBios_sys_b0_29;
3860 //biosB0[0x2a] = psxBios_sys_b0_2a;
3861 //biosB0[0x2b] = psxBios_sys_b0_2b;
3862 //biosB0[0x2c] = psxBios_sys_b0_2c;
3863 //biosB0[0x2d] = psxBios_sys_b0_2d;
3864 //biosB0[0x2e] = psxBios_sys_b0_2e;
3865 //biosB0[0x2f] = psxBios_sys_b0_2f;
3866 //biosB0[0x30] = psxBios_sys_b0_30;
3867 //biosB0[0x31] = psxBios_sys_b0_31;
3868 biosB0[0x32] = psxBios_open;
3869 biosB0[0x33] = psxBios_lseek;
3870 biosB0[0x34] = psxBios_read;
3871 biosB0[0x35] = psxBios_write;
3872 biosB0[0x36] = psxBios_close;
3873 //biosB0[0x37] = psxBios_ioctl;
3874 //biosB0[0x38] = psxBios_exit;
3875 //biosB0[0x39] = psxBios_sys_b0_39;
3876 biosB0[0x3a] = psxBios_getc;
3877 biosB0[0x3b] = psxBios_putc;
3878 biosB0[0x3c] = psxBios_getchar;
3879 biosB0[0x3d] = psxBios_putchar;
3880 //biosB0[0x3e] = psxBios_gets;
3881 biosB0[0x3f] = psxBios_puts;
3882 biosB0[0x40] = psxBios_cd;
3883 biosB0[0x41] = psxBios_format;
3884 biosB0[0x42] = psxBios_firstfile;
3885 biosB0[0x43] = psxBios_nextfile;
3886 biosB0[0x44] = psxBios_rename;
3887 biosB0[0x45] = psxBios_delete;
3888 //biosB0[0x46] = psxBios_undelete;
3889 //biosB0[0x47] = psxBios_AddDevice;
3890 //biosB0[0x48] = psxBios_RemoteDevice;
3891 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3892 biosB0[0x4a] = psxBios_InitCARD;
3893 biosB0[0x4b] = psxBios_StartCARD;
3894 biosB0[0x4c] = psxBios_StopCARD;
3895 //biosB0[0x4d] = psxBios_sys_b0_4d;
3896 biosB0[0x4e] = psxBios__card_write;
3897 biosB0[0x4f] = psxBios__card_read;
3898 biosB0[0x50] = psxBios__new_card;
3899 biosB0[0x51] = psxBios_Krom2RawAdd;
3900 //biosB0[0x52] = psxBios_sys_b0_52;
3901 //biosB0[0x53] = psxBios_sys_b0_53;
3902 //biosB0[0x54] = psxBios__get_errno;
3903 biosB0[0x55] = psxBios__get_error;
3904 biosB0[0x56] = psxBios_GetC0Table;
3905 biosB0[0x57] = psxBios_GetB0Table;
3906 biosB0[0x58] = psxBios__card_chan;
3907 //biosB0[0x59] = psxBios_sys_b0_59;
3908 //biosB0[0x5a] = psxBios_sys_b0_5a;
3909 biosB0[0x5b] = psxBios_ChangeClearPad;
3910 biosB0[0x5c] = psxBios__card_status;
3911 biosB0[0x5d] = psxBios__card_wait;
3912 //*******************C0 CALLS****************************
3913 biosC0[0x00] = psxBios_InitRCnt;
3914 biosC0[0x01] = psxBios_InitException;
3915 biosC0[0x02] = psxBios_SysEnqIntRP;
3916 biosC0[0x03] = psxBios_SysDeqIntRP;
3917 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3918 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3919 //biosC0[0x06] = psxBios_ExceptionHandler;
3920 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3921 biosC0[0x08] = psxBios_SysInitMemory;
3922 //biosC0[0x09] = psxBios_SysInitKMem;
3923 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3924 //biosC0[0x0b] = psxBios_SystemError;
3925 biosC0[0x0c] = psxBios_InitDefInt;
3926 //biosC0[0x0d] = psxBios_sys_c0_0d;
3927 //biosC0[0x0e] = psxBios_sys_c0_0e;
3928 //biosC0[0x0f] = psxBios_sys_c0_0f;
3929 //biosC0[0x10] = psxBios_sys_c0_10;
3930 //biosC0[0x11] = psxBios_sys_c0_11;
3931 //biosC0[0x12] = psxBios_InstallDevices;
3932 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3933 //biosC0[0x14] = psxBios_sys_c0_14;
3934 //biosC0[0x15] = psxBios__cdevinput;
3935 //biosC0[0x16] = psxBios__cdevscan;
3936 //biosC0[0x17] = psxBios__circgetc;
3937 //biosC0[0x18] = psxBios__circputc;
3938 //biosC0[0x19] = psxBios_ioabort;
3939 //biosC0[0x1a] = psxBios_sys_c0_1a
3940 //biosC0[0x1b] = psxBios_KernelRedirect;
3941 //biosC0[0x1c] = psxBios_PatchAOTable;
3942 //************** THE END ***************************************
3945 memset(FDesc, 0, sizeof(FDesc));
3946 memset(cdir, 0, sizeof(cdir));
3949 // somewhat pretend to be a SCPH1001 BIOS
3950 // some games look for these and take an exception if they're missing
3951 rom32 = (u32 *)psxR;
3952 rom32[0x100/4] = SWAP32(0x19951204);
3953 rom32[0x104/4] = SWAP32(3);
3954 romc = (char *)psxR;
3955 strcpy(romc + 0x108, "PCSX authors");
3956 strcpy(romc + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3957 strcpy(romc + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3958 strcpy(romc + 0x7ff54, "GPL-2.0-or-later");
3961 len = 0x80000 - 0x66000;
3962 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3963 len = 0x80000 - 0x69d68;
3964 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3966 // trap attempts to call bios directly
3967 rom32[0x00000/4] = HLEOP(hleop_dummy);
3968 rom32[0x00180/4] = HLEOP(hleop_dummy);
3969 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3970 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3971 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3973 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3974 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3975 Here are some examples of games not working with this fix in place :
3976 R-type won't get past the Irem logo if not implemented.
3977 Crash Team Racing will softlock after the Sony logo.
3980 ram32 = (u32 *)psxM;
3981 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3982 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3983 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3984 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3986 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3987 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3989 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3990 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3991 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3992 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3994 ram32[0x00a0/4] = HLEOP(hleop_a0);
3995 ram32[0x00b0/4] = HLEOP(hleop_b0);
3996 ram32[0x00c0/4] = HLEOP(hleop_c0);
3998 setup_tt(4, 16, 0x801fff00);
3999 DeliverEvent(0xf0000003, 0x0010);
4001 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
4002 strcpy((char *)&ram32[0xeff0/4], "bu");
4004 // default exception handler chains
4005 // see also setup_cd_irq_and_events()
4006 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
4007 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
4008 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
4009 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
4010 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
4011 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
4012 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
4013 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
4017 // fill the api jumptables with fake entries as some games patch them
4018 // (or rather the funcs listed there)
4019 // also trap the destination as some "Cheats Edition" thing overrides the
4020 // dispatcher with a wrapper and then jumps to the table entries directly
4021 ptr = (u32 *)&psxM[A_A0_TABLE];
4022 for (i = 0; i < 256; i++) {
4023 ptr[i] = SWAP32(A_A0_TRAPS + i*4);
4024 ram32[A_A0_TRAPS/4 + i] = HLEOP(hleop_a0t);
4026 ptr = (u32 *)&psxM[A_B0_TABLE];
4027 for (i = 0; i < 256; i++) {
4028 ptr[i] = SWAP32(A_B0_TRAPS + i*4);
4029 ram32[A_B0_TRAPS/4 + i] = HLEOP(hleop_b0t);
4031 // B(5b) is special because games patch (sometimes even jump to)
4032 // code at fixed offsets from it, nocash lists offsets:
4033 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
4034 // call: +7a0=4b70, +884=4c54, +894=4c64
4035 ptr[0x5b] = SWAP32(A_B0_5B_TRAP); // 0x43d0
4036 ram32[A_B0_5B_TRAP/4] = HLEOP(hleop_b0t);
4038 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
4040 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
4041 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
4042 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
4044 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
4045 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
4047 ptr = (u32 *)&psxM[A_C0_TABLE];
4048 for (i = 0; i < 256/2; i++) {
4049 ptr[i] = SWAP32(A_C0_TRAPS + i*4);
4050 ram32[A_C0_TRAPS/4 + i] = HLEOP(hleop_c0t);
4052 ptr[6] = SWAP32(A_EXCEPTION);
4055 ram32[A_A0_TRAPS/4 - 1] = HLEOP(hleop_dummy);
4056 ram32[A_B0_TRAPS/4 - 1] = HLEOP(hleop_dummy);
4057 ram32[A_C0_TRAPS/4 - 1] = HLEOP(hleop_dummy);
4058 ram32[0x7ffc/4] = HLEOP(hleop_dummy);
4059 ram32[0x8000/4] = HLEOP(hleop_execret);
4061 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
4062 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
4063 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
4064 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
4065 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
4066 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
4067 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
4070 void psxBiosShutdown() {
4073 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
4076 if (tcb_cnt != 4 || evcb_cnt != 16) {
4077 setup_tt(tcb_cnt, evcb_cnt, stack);
4078 DeliverEvent(0xf0000003, 0x0010);
4080 storeRam32(A_CONF_SP, stack);
4083 #define psxBios_PADpoll(pad) { \
4084 int i, more_data = 0; \
4085 PAD##pad##_startPoll(pad); \
4086 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
4087 pad_buf##pad[0] = more_data ? 0 : 0xff; \
4088 PAD##pad##_poll(0, &more_data); \
4090 while (more_data) { \
4091 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
4095 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
4099 psxHwWrite16(0x1f801070, ~(1u << irqbit));
4100 psxBios_ReturnFromException();
4106 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
4107 // so this is only partially implemented
4108 static void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
4110 u32 cdrom_dma_ack_enable = 1; // a000b93c
4111 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
4114 static void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
4117 //PSXBIOS_LOG("%s\n", __func__);
4119 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
4120 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
4121 //if (--cdrom_irq_counter == 0) // 0xa0009180
4122 // DeliverEvent(0xf0000003, 0x10);
4126 mips_return_c(ret, 20);
4129 static void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
4131 u32 cdrom_irq_ack_enable = 1; // a000b938
4132 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
4135 static void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
4138 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
4139 PSXBIOS_LOG("%s TODO\n", __func__);
4142 mips_return_c(ret, 20);
4145 static void hleExc0_2_2_syscall() // not in any A/B/C table
4147 u32 tcbPtr = loadRam32(A_TT_PCB);
4148 TCB *tcb = loadRam32ptr(tcbPtr);
4149 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
4151 if (code != R3000E_Syscall) {
4153 DeliverEvent(0xf0000010, 0x1000);
4154 //psxBios_SystemErrorUnresolvedException();
4156 mips_return_c(0, 17);
4160 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
4161 tcb->epc += SWAP32(4);
4162 switch (SWAP32(tcb->reg[4])) { // a0
4166 case 1: { // EnterCritical - disable irqs
4167 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
4168 tcb->reg[2] = SWAP32(was_enabled);
4169 tcb->sr &= SWAP32(~0x404);
4172 case 2: // ExitCritical - enable irqs
4173 tcb->sr |= SWAP32(0x404);
4176 case 3: { // ChangeThreadSubFunction
4177 u32 tcbPtr = loadRam32(A_TT_PCB);
4178 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
4182 DeliverEvent(0xf0000010, 0x4000);
4186 psxBios_ReturnFromException();
4189 static void hleExc1_0_1(void)
4191 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
4192 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
4195 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
4198 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
4199 DeliverEvent(0xf2000000 + ev_index, 0x0002);
4202 mips_return_c(ret, 22);
4205 static void hleExc1_0_2(void)
4207 handle_chain_1_x_2(3, 0); // IRQ0 vblank
4210 static void hleExc1_1_1(void)
4212 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
4213 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
4216 static void hleExc1_1_2(void)
4218 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
4221 static void hleExc1_2_1(void)
4223 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
4224 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
4227 static void hleExc1_2_2(void)
4229 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
4232 static void hleExc1_3_1(void)
4234 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
4235 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
4238 static void hleExc1_3_2(void)
4240 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
4243 static void hleExc3_0_2_defint(void)
4245 static const struct {
4256 { 6, 6 }, // rcnt2 (bug)
4261 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
4262 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
4263 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
4268 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
4271 static void hleExcPadCard1(void)
4273 if (loadRam32(A_PAD_IRQR_ENA)) {
4274 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
4275 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
4280 if (loadRam32(A_PAD_DR_DST))
4283 if (loadRam32(A_PAD_ACK_VBL))
4284 psxHwWrite16(0x1f801070, ~1);
4285 if (loadRam32(A_CARD_IRQR_ENA))
4286 card_vint_handler();
4288 mips_return_c(0, 18);
4291 static void hleExcPadCard2(void)
4293 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
4294 mips_return_c(ret, 15);
4297 void psxBiosException() {
4298 u32 tcbPtr = loadRam32(A_TT_PCB);
4299 u32 *chains = loadRam32ptr(A_TT_ExCB);
4300 TCB *tcb = loadRam32ptr(tcbPtr);
4306 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
4307 for (i = 4; i < 31; i++) {
4310 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
4312 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
4313 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
4314 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
4315 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
4316 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
4317 sp = fp = loadRam32(A_EXC_SP);
4320 assert(!psxRegs.cpuInRecursion);
4322 // do the chains (always 4)
4323 for (c = lim = 0; c < 4; c++) {
4324 if (chains[c * 2] == 0)
4326 ptr = SWAP32(chains[c * 2]);
4327 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
4328 chain = castRam32ptr(ptr);
4333 softCallInException(SWAP32(chain[2]));
4334 if (returned_from_exception())
4337 if (v0 == 0 || chain[1] == 0)
4339 softCallInException(SWAP32(chain[1]));
4340 if (returned_from_exception())
4346 // return from exception (custom or default)
4348 ptr = loadRam32(A_EEXIT_PTR);
4349 if (ptr != A_EEXIT_DEF) {
4350 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4351 longjmp_load(jmp_buf);
4356 psxBios_ReturnFromException();
4360 static void hleDummy() {
4361 log_unhandled("hleDummy called @%08x ra=%08x\n", psxRegs.pc - 4, ra);
4363 psxRegs.cycle += 1000;
4368 static void hleA0() {
4369 u32 call = t1 & 0xff;
4370 u32 entry = loadRam32(A_A0_TABLE + call * 4);
4373 if (call < 192 && entry != A_A0_TRAPS + call * 4) {
4374 PSXBIOS_LOG("custom A%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4375 call, biosA0n[call], a0, entry, ra);
4378 PSXBIOS_LOG(" -> %08x\n", v0);
4380 else if (biosA0[call])
4383 //printf("A(%02x) -> %x\n", call, v0);
4387 static void hleB0() {
4388 u32 call = t1 & 0xff;
4389 u32 entry = loadRam32(A_B0_TABLE + call * 4);
4394 is_custom = entry != A_B0_5B_TRAP;
4396 is_custom = entry != A_B0_TRAPS + call * 4;
4398 PSXBIOS_LOG("custom B%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4399 call, biosB0n[call], a0, entry, ra);
4402 PSXBIOS_LOG(" -> %08x\n", v0);
4404 else if (biosB0[call])
4407 //printf("B(%02x) -> %x\n", call, v0);
4411 static void hleC0() {
4412 u32 call = t1 & 0xff;
4413 u32 entry = loadRam32(A_C0_TABLE + call * 4);
4416 if (call < 128 && entry != A_C0_TRAPS + call * 4) {
4417 PSXBIOS_LOG("custom C%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4418 call, biosC0n[call], a0, entry, ra);
4421 PSXBIOS_LOG(" -> %08x\n", v0);
4423 else if (biosC0[call])
4426 //printf("C(%02x) -> %x\n", call, v0);
4430 static void hleA0t() {
4431 u32 call = (pc0 - A_A0_TRAPS) / 4 - 1;
4432 if (call >= 256u || !biosA0[call]) {
4433 log_unhandled("unexpected A trap @%08x ra=%08x\n", pc0 - 4, ra);
4434 mips_return_void_c(1000);
4439 //printf("A(%02x) -> %x\n", call, v0);
4443 static void hleB0t() {
4444 u32 call = (pc0 - A_B0_TRAPS) / 4 - 1;
4445 if (pc0 - 4 == A_B0_5B_TRAP)
4447 if (call >= 256u || !biosB0[call]) {
4448 log_unhandled("unexpected B trap @%08x ra=%08x\n", pc0 - 4, ra);
4449 mips_return_void_c(1000);
4454 //printf("B(%02x) -> %x\n", call, v0);
4458 static void hleC0t() {
4459 u32 call = (pc0 - A_C0_TRAPS) / 4 - 1;
4460 if (call >= 128u || !biosC0[call]) {
4461 log_unhandled("unexpected C trap @%08x ra=%08x\n", pc0 - 4, ra);
4462 mips_return_void_c(1000);
4467 //printf("C(%02x) -> %x\n", call, v0);
4471 // currently not used
4472 static void hleBootstrap() {
4477 static void hleExecRet() {
4478 const EXEC *header = (EXEC *)PSXM(s0);
4480 PSXBIOS_LOG("ExecRet %x: %x\n", s0, header->ret);
4482 ra = SWAP32(header->ret);
4483 sp = SWAP32(header->_sp);
4484 fp = SWAP32(header->_fp);
4485 gp = SWAP32(header->_gp);
4486 s0 = SWAP32(header->base);
4492 void (* const psxHLEt[hleop_count_])() = {
4493 hleDummy, hleA0, hleB0, hleC0,
4494 hleBootstrap, hleExecRet, psxBiosException, hleDummy,
4495 hleExc0_0_1, hleExc0_0_2,
4496 hleExc0_1_1, hleExc0_1_2, hleExc0_2_2_syscall,
4497 hleExc1_0_1, hleExc1_0_2,
4498 hleExc1_1_1, hleExc1_1_2,
4499 hleExc1_2_1, hleExc1_2_2,
4500 hleExc1_3_1, hleExc1_3_2,
4502 hleExcPadCard1, hleExcPadCard2,
4503 hleA0t, hleB0t, hleC0t,
4506 void psxBiosCheckExe(u32 t_addr, u32 t_size, int loading_state)
4508 // lw $v0, 0x10($sp)
4511 // sw $v0, 0x10($sp)
4512 // lw $v0, 0x10($sp)
4514 // bne $v0, $v1, not_timeout
4517 static const u8 pattern[] = {
4518 0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
4519 0xFF, 0xFF, 0x42, 0x24, 0x10, 0x00, 0xA2, 0xAF,
4520 0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
4521 0x0C, 0x00, 0x43, 0x14, 0x00, 0x00, 0x00, 0x00,
4523 u32 start = t_addr & 0x1ffffc;
4524 u32 end = (start + t_size) & 0x1ffffc;
4525 u32 buf[sizeof(pattern) / sizeof(u32)];
4526 const u32 *r32 = (u32 *)(psxM + start);
4534 memcpy(buf, pattern, sizeof(buf));
4535 for (i = 0; i < t_size / 4; i += j + 1) {
4536 for (j = 0; j < sizeof(buf) / sizeof(buf[0]); j++)
4537 if (r32[i + j] != buf[j])
4539 if (j != sizeof(buf) / sizeof(buf[0]))
4542 if ((SWAP32(r32[i + j]) >> 16) != 0x3c04) // lui
4545 SysPrintf("HLE vsync @%08x\n", start + i * 4);
4546 psxRegs.biosBranchCheck = (t_addr & 0xa01ffffc) + i * 4;
4550 void psxBiosCheckBranch(void)
4554 static u32 cycles_prev, v0_prev;
4555 u32 cycles_passed, waste_cycles;
4556 u32 loops, v0_expect = v0_prev - 1;
4560 cycles_passed = psxRegs.cycle - cycles_prev;
4561 cycles_prev = psxRegs.cycle;
4563 if (cycles_passed < 10 || cycles_passed > 50 || v0 != v0_expect)
4566 waste_cycles = schedule_timeslice() - psxRegs.cycle;
4567 loops = waste_cycles / cycles_passed;
4571 psxRegs.cycle += loops * cycles_passed;
4572 //printf("c %4u %d\n", loops, cycles_passed);
4576 #define bfreeze(ptr, size) { \
4577 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4578 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4582 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4583 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4585 void psxBiosFreeze(int Mode) {
4592 bfreezel(&card_io_delay);