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"
43 //#define PSXBIOS_LOG printf
44 #define PSXBIOS_LOG(...)
47 #define PTR_1 (void *)(size_t)1
49 char *biosA0n[256] = {
51 "open", "lseek", "read", "write",
52 "close", "ioctl", "exit", "sys_a0_07",
53 "getc", "putc", "todigit", "atof",
54 "strtoul", "strtol", "abs", "labs",
56 "atoi", "atol", "atob", "setjmp",
57 "longjmp", "strcat", "strncat", "strcmp",
58 "strncmp", "strcpy", "strncpy", "strlen",
59 "index", "rindex", "strchr", "strrchr",
61 "strpbrk", "strspn", "strcspn", "strtok",
62 "strstr", "toupper", "tolower", "bcopy",
63 "bzero", "bcmp", "memcpy", "memset",
64 "memmove", "memcmp", "memchr", "rand",
66 "srand", "qsort", "strtod", "malloc",
67 "free", "lsearch", "bsearch", "calloc",
68 "realloc", "InitHeap", "_exit", "getchar",
69 "putchar", "gets", "puts", "printf",
71 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
72 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
73 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
74 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
76 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
77 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
78 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
79 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
81 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
82 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
83 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
84 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
86 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
87 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
88 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
89 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
91 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
92 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
93 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
94 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
96 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
97 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
98 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
99 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
101 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
102 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
103 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
104 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
106 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
110 char *biosB0n[256] = {
112 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
113 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
114 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
115 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
117 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
118 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
119 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
120 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
122 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
123 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
124 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
125 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
127 "sys_b0_30", "sys_b0_31", "open", "lseek",
128 "read", "write", "close", "ioctl",
129 "exit", "sys_b0_39", "getc", "putc",
130 "getchar", "putchar", "gets", "puts",
132 "cd", "format", "firstfile", "nextfile",
133 "rename", "delete", "undelete", "AddDevice",
134 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
135 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
137 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
138 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
139 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
140 "_card_status", "_card_wait",
143 char *biosC0n[256] = {
145 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
146 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
147 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
148 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
150 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
151 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
152 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
156 //#define r0 (psxRegs.GPR.n.r0)
157 #define at (psxRegs.GPR.n.at)
158 #define v0 (psxRegs.GPR.n.v0)
159 #define v1 (psxRegs.GPR.n.v1)
160 #define a0 (psxRegs.GPR.n.a0)
161 #define a1 (psxRegs.GPR.n.a1)
162 #define a2 (psxRegs.GPR.n.a2)
163 #define a3 (psxRegs.GPR.n.a3)
164 #define t0 (psxRegs.GPR.n.t0)
165 #define t1 (psxRegs.GPR.n.t1)
166 #define t2 (psxRegs.GPR.n.t2)
167 #define t3 (psxRegs.GPR.n.t3)
168 #define t4 (psxRegs.GPR.n.t4)
169 #define t5 (psxRegs.GPR.n.t5)
170 #define t6 (psxRegs.GPR.n.t6)
171 #define t7 (psxRegs.GPR.n.t7)
172 #define t8 (psxRegs.GPR.n.t8)
173 #define t9 (psxRegs.GPR.n.t9)
174 #define s0 (psxRegs.GPR.n.s0)
175 #define s1 (psxRegs.GPR.n.s1)
176 #define s2 (psxRegs.GPR.n.s2)
177 #define s3 (psxRegs.GPR.n.s3)
178 #define s4 (psxRegs.GPR.n.s4)
179 #define s5 (psxRegs.GPR.n.s5)
180 #define s6 (psxRegs.GPR.n.s6)
181 #define s7 (psxRegs.GPR.n.s7)
182 #define k0 (psxRegs.GPR.n.k0)
183 #define k1 (psxRegs.GPR.n.k1)
184 #define gp (psxRegs.GPR.n.gp)
185 #define sp (psxRegs.GPR.n.sp)
186 #define fp (psxRegs.GPR.n.fp)
187 #define ra (psxRegs.GPR.n.ra)
188 #define pc0 (psxRegs.pc)
190 #define Ra0 ((char *)PSXM(a0))
191 #define Ra1 ((char *)PSXM(a1))
192 #define Ra2 ((char *)PSXM(a2))
193 #define Ra3 ((char *)PSXM(a3))
194 #define Rv0 ((char *)PSXM(v0))
195 #define Rsp ((char *)PSXM(sp))
206 #define EvStUNUSED 0x0000
207 #define EvStDISABLED 0x1000
208 #define EvStACTIVE 0x2000
209 #define EvStALREADY 0x4000
211 #define EvMdCALL 0x1000
212 #define EvMdMARK 0x2000
235 u32 _sp, _fp, _gp, ret, base;
255 // todo: FileDesc layout is wrong
256 // todo: get rid of these globals
257 static FileDesc FDesc[32];
258 static char ffile[64];
260 static char cdir[8*8+8];
263 // fixed RAM offsets, SCPH1001 compatible
264 #define A_TT_ExCB 0x0100
265 #define A_TT_PCB 0x0108
266 #define A_TT_TCB 0x0110
267 #define A_TT_EvCB 0x0120
268 #define A_A0_TABLE 0x0200
269 #define A_B0_TABLE 0x0874
270 #define A_C0_TABLE 0x0674
271 #define A_SYSCALL 0x0650
272 #define A_EXCEPTION 0x0c80
273 #define A_EXC_SP 0x6cf0
274 #define A_EEXIT_DEF 0x6cf4
275 #define A_KMALLOC_PTR 0x7460
276 #define A_KMALLOC_SIZE 0x7464
277 #define A_KMALLOC_END 0x7468
278 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
279 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
280 #define A_CARD_IRQR_ENA 0x74bc // same for card
281 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
282 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
283 #define A_PAD_IN_LEN 0x74d8
284 #define A_PAD_OUT_LEN 0x74e0
285 #define A_PAD_DR_DST 0x74c4
286 #define A_CARD_CHAN1 0x7500
287 #define A_PAD_DR_BUF1 0x7570
288 #define A_PAD_DR_BUF2 0x7598
289 #define A_EEXIT_PTR 0x75d0
290 #define A_EXC_STACK 0x85d8 // exception stack top
291 #define A_RCNT_VBL_ACK 0x8600
292 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
293 #define A_HEAP_BASE 0x9000
294 #define A_HEAP_SIZE 0x9004
295 #define A_HEAP_END 0x9008
296 #define A_HEAP_INIT_FLG 0x900c
297 #define A_RND_SEED 0x9010
298 #define A_HEAP_FRSTCHNK 0xb060
299 #define A_HEAP_CURCHNK 0xb064
300 #define A_CONF_TCB 0xb940
301 #define A_CONF_EvCB 0xb944
302 #define A_CONF_SP 0xb948
303 #define A_CD_EVENTS 0xb9b8
304 #define A_EXC_GP 0xf450
306 #define A_A0_TRAPS 0x1010
307 #define A_B0_TRAPS 0x2010
308 #define A_C0_TRAPS 0x3010
309 #define A_B0_5B_TRAP 0x43d0
311 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
313 static u8 loadRam8(u32 addr)
315 assert(!(addr & 0x5f800000));
316 return psxM[addr & 0x1fffff];
319 static u32 loadRam32(u32 addr)
321 assert(!(addr & 0x5f800000));
322 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
325 static void *castRam8ptr(u32 addr)
327 assert(!(addr & 0x5f800000));
328 return psxM + (addr & 0x1fffff);
331 static void *castRam32ptr(u32 addr)
333 assert(!(addr & 0x5f800003));
334 return psxM + (addr & 0x1ffffc);
337 static void *loadRam8ptr(u32 addr)
339 return castRam8ptr(loadRam32(addr));
342 static void *loadRam32ptr(u32 addr)
344 return castRam32ptr(loadRam32(addr));
347 static void storeRam8(u32 addr, u8 d)
349 assert(!(addr & 0x5f800000));
350 *((u8 *)psxM + (addr & 0x1fffff)) = d;
353 static void storeRam32(u32 addr, u32 d)
355 assert(!(addr & 0x5f800000));
356 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
359 static void mips_return(u32 val)
365 static void mips_return_void(void)
370 static void use_cycles(u32 cycle)
372 psxRegs.cycle += cycle * 2;
375 static void mips_return_c(u32 val, u32 cycle)
381 static void mips_return_void_c(u32 cycle)
387 static int returned_from_exception(void)
389 // 0x80000080 means it took another exception just after return
390 return pc0 == k0 || pc0 == 0x80000080;
393 static inline void softCall(u32 pc) {
395 u32 ssr = psxRegs.CP0.n.SR;
399 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
401 assert(psxRegs.cpuInRecursion <= 1);
402 psxRegs.cpuInRecursion++;
403 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
405 while (pc0 != 0x80001000 && ++lim < 0x100000)
406 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
408 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
409 psxRegs.cpuInRecursion--;
412 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
414 psxRegs.CP0.n.SR |= ssr & 0x404;
417 static inline void softCallInException(u32 pc) {
422 assert(ra != 0x80001000);
423 if (ra == 0x80001000)
427 psxRegs.cpuInRecursion++;
428 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
430 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 0x100000)
431 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
433 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
434 psxRegs.cpuInRecursion--;
437 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
438 if (pc0 == 0x80001000)
442 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
443 static u32 DeliverEvent(u32 class, u32 spec);
444 static u32 UnDeliverEvent(u32 class, u32 spec);
445 static void CloseEvent(u32 ev);
450 // System calls A0 */
453 #define buread(Ra1, mcd, length) { \
454 PSXBIOS_LOG("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
455 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
456 memcpy(Ra1, ptr, length); \
457 psxCpu->Clear(a1, (length + 3) / 4); \
458 if (FDesc[1 + mcd].mode & 0x8000) { \
459 DeliverEvent(0xf0000011, 0x0004); \
460 DeliverEvent(0xf4000001, 0x0004); \
463 FDesc[1 + mcd].offset += v0; \
466 #define buwrite(Ra1, mcd, length) { \
467 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
468 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
469 ptr = Mcd##mcd##Data + offset; \
470 memcpy(ptr, Ra1, length); \
471 FDesc[1 + mcd].offset += length; \
472 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
473 if (FDesc[1 + mcd].mode & 0x8000) { \
474 DeliverEvent(0xf0000011, 0x0004); \
475 DeliverEvent(0xf4000001, 0x0004); \
480 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
481 /* For some strange reason, the returned character is sign-expanded; */
482 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
483 /* TODO FIX ME : Properly implement this behaviour */
484 void psxBios_getc(void) // 0x03, 0x35
489 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
493 if (pa1 != INVALID_PTR) {
495 case 2: buread(pa1, 1, 1); break;
496 case 3: buread(pa1, 2, 1); break;
503 /* Copy of psxBios_write, except size is 1. */
504 void psxBios_putc(void) // 0x09, 0x3B
509 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
512 if (pa1 == INVALID_PTR) {
517 if (a0 == 1) { // stdout
518 char *ptr = (char *)pa1;
522 printf("%c", *ptr++); a2--;
528 case 2: buwrite(pa1, 1, 1); break;
529 case 3: buwrite(pa1, 2, 1); break;
535 static u32 do_todigit(u32 c)
538 if (c >= 0x30 && c < 0x3A) {
541 else if (c > 0x60 && c < 0x7B) {
544 else if (c > 0x40 && c < 0x5B) {
547 else if (c >= 0x80) {
548 log_unhandled("todigit %02x\n", c);
559 static void psxBios_todigit(void) // 0x0a
561 mips_return(do_todigit(a0));
562 PSXBIOS_LOG("psxBios_%s '%c' -> %u\n", biosA0n[0x0a], a0, v0);
565 static void do_strtol(char *p, void *end_, u32 base, int can_neg) {
570 if (p == INVALID_PTR) {
575 for (; (0x09 <= *p && *p <= '\r') || *p == ' '; p++)
578 for (; *p == '-'; f = 1, p++)
581 if (base == 0 || base > 36)
585 case 'b': case 'B': base = 2; break;
586 case 'x': case 'X': base = 16; break;
589 else if (*p == 'o' || *p == 'O') {
594 for (; (t = do_todigit(*p)) < base; p++) {
600 if (end != INVALID_PTR)
601 *end = SWAP32(a0 + (p - Ra0));
602 mips_return_c(n, 100);
605 static void psxBios_strtoul() { // 0x0c
606 do_strtol(a0 ? Ra0 : INVALID_PTR, a1 ? Ra1 : INVALID_PTR, a2, 0);
607 PSXBIOS_LOG("psxBios_%s %s (%x), %x, %x -> 0x%x\n",
608 biosA0n[0x0c], a0 ? Ra0 : NULL, a0, a1, a2, v0);
611 static void psxBios_strtol() { // 0x0d
612 do_strtol(a0 ? Ra0 : INVALID_PTR, a1 ? Ra1 : INVALID_PTR, a2, 1);
613 PSXBIOS_LOG("psxBios_%s %s (%x), %x, %x -> 0x%x\n",
614 biosA0n[0x0d], a0 ? Ra0 : NULL, a0, a1, a2, v0);
617 void psxBios_abs() { // 0x0e
618 if ((s32)a0 < 0) v0 = -(s32)a0;
623 void psxBios_labs() { // 0x0f
627 void psxBios_atoi() { // 0x10
629 char *p = (char *)Ra0;
631 if (p == INVALID_PTR) {
638 case ' ': case '\t': continue;
645 while (*p >= '0' && *p <= '9') {
646 n = n * 10 + *p++ - '0';
651 PSXBIOS_LOG("psxBios_%s %s (%x) -> 0x%x\n", biosA0n[0x10], Ra0, a0, v0);
654 void psxBios_atol() { // 0x11
664 static void psxBios_setjmp() { // 0x13
665 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
668 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
670 jmp_buf->ra_ = SWAP32(ra);
671 jmp_buf->sp_ = SWAP32(sp);
672 jmp_buf->fp_ = SWAP32(fp);
673 for (i = 0; i < 8; i++) // s0-s7
674 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
675 jmp_buf->gp_ = SWAP32(gp);
677 mips_return_c(0, 15);
680 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
684 ra = SWAP32(jmp_buf->ra_);
685 sp = SWAP32(jmp_buf->sp_);
686 fp = SWAP32(jmp_buf->fp_);
687 for (i = 0; i < 8; i++) // s0-s7
688 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
689 gp = SWAP32(jmp_buf->gp_);;
692 void psxBios_longjmp() { // 0x14
693 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
695 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
696 longjmp_load(jmp_buf);
697 mips_return_c(a1, 15);
700 void psxBios_strcat() { // 0x15
704 PSXBIOS_LOG("psxBios_%s %s (%x), %s (%x)\n", biosA0n[0x15], Ra0, a0, Ra1, a1);
705 if (a0 == 0 || a1 == 0 || p2 == INVALID_PTR)
710 while (loadRam8(p1)) {
714 for (; *p2; p1++, p2++)
718 mips_return_c(a0, 22);
721 void psxBios_strncat() { // 0x16
722 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
726 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
728 if (a0 == 0 || a1 == 0)
736 while ((*p1++ = *p2++) != '\0') {
746 void psxBios_strcmp() { // 0x17
747 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
749 if (a0 == 0 && a1 == 0)
755 else if (a0 == 0 && a1 != 0)
761 else if (a0 != 0 && a1 == 0)
768 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
771 while (*p1 == *p2++) {
790 void psxBios_strncmp() { // 0x18
791 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
793 if (a0 == 0 && a1 == 0)
799 else if (a0 == 0 && a1 != 0)
805 else if (a0 != 0 && a1 == 0)
812 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
815 while (--n >= 0 && *p1 == *p2++) {
819 v1 = a2 - ((a2-n) - 1);
827 v0 = (n < 0 ? 0 : *p1 - *--p2);
829 v1 = a2 - ((a2-n) - 1);
835 void psxBios_strcpy() { // 0x19
836 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
837 PSXBIOS_LOG("psxBios_%s %x, %s (%x)\n", biosA0n[0x19], a0, p2, a1);
838 if (a0 == 0 || a1 == 0)
844 while ((*p1++ = *p2++) != '\0');
849 void psxBios_strncpy() { // 0x1a
850 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
852 if (a0 == 0 || a1 == 0)
858 for (i = 0; i < n; i++) {
859 if ((*p1++ = *p2++) == '\0') {
871 void psxBios_strlen() { // 0x1b
872 char *p = (char *)Ra0;
883 void psxBios_index() { // 0x1c
884 char *p = (char *)Ra0;
894 v0 = a0 + (p - (char *)Ra0);
898 } while (*p++ != '\0');
903 void psxBios_rindex() { // 0x1d
904 char *p = (char *)Ra0;
914 v0 = a0 + (p - (char *)Ra0);
915 } while (*p++ != '\0');
920 void psxBios_strchr() { // 0x1e
924 void psxBios_strrchr() { // 0x1f
928 void psxBios_strpbrk() { // 0x20
929 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
931 while ((c = *p1++) != '\0') {
932 for (scanp = p2; (sc = *scanp++) != '\0';) {
934 v0 = a0 + (p1 - 1 - (char *)Ra0);
941 // BUG: return a0 instead of NULL if not found
945 void psxBios_strspn() { // 0x21
948 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
949 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
950 if (*p2 == '\0') break;
953 v0 = p1 - (char *)Ra0; pc0 = ra;
956 void psxBios_strcspn() { // 0x22
959 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
960 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
961 if (*p2 != '\0') break;
964 v0 = p1 - (char *)Ra0; pc0 = ra;
967 void psxBios_strtok() { // 0x23
968 char *pcA0 = (char *)Ra0;
969 char *pcRet = strtok(pcA0, (char *)Ra1);
971 v0 = a0 + pcRet - pcA0;
977 void psxBios_strstr() { // 0x24
978 char *p = (char *)Ra0, *p1, *p2;
979 PSXBIOS_LOG("psxBios_%s %s (%x), %s (%x)\n", biosA0n[0x24], p, a0, Ra1, a1);
985 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
990 v0 = a0 + (p - (char *)Ra0);
992 PSXBIOS_LOG(" -> %x\n", v0);
996 // bug: skips the whole matched substring + 1
1003 void psxBios_toupper() { // 0x25
1004 v0 = (s8)(a0 & 0xff);
1005 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
1009 void psxBios_tolower() { // 0x26
1010 v0 = (s8)(a0 & 0xff);
1011 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
1015 static void do_memset(u32 dst, u32 v, s32 len)
1021 if (db != INVALID_PTR)
1025 psxCpu->Clear(dst, (len + 3) / 4);
1028 static void do_memcpy(u32 dst, u32 src, s32 len)
1030 u32 d = dst, s = src;
1033 const u8 *sb = PSXM(s);
1035 if (db != INVALID_PTR && sb != INVALID_PTR)
1040 psxCpu->Clear(dst, (len + 3) / 4);
1043 static void psxBios_memcpy();
1045 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
1046 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
1047 u32 ret = a0, cycles = 0;
1048 if (a0 == 0) // ...but it checks src this time
1050 mips_return_c(0, 4);
1055 do_memcpy(a1, a0, a2);
1061 mips_return_c(ret, cycles + 5);
1064 static void psxBios_bzero() { // 0x28
1065 /* Same as memset here (See memset below) */
1066 u32 ret = a0, cycles;
1067 if (a0 == 0 || (s32)a1 <= 0)
1069 mips_return_c(0, 6);
1072 do_memset(a0, 0, a1);
1076 // todo: many more cycles due to uncached bios mem
1077 mips_return_c(ret, cycles + 5);
1080 void psxBios_bcmp() { // 0x29
1081 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
1083 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
1085 while ((s32)a2-- > 0) {
1086 if (*p1++ != *p2++) {
1087 v0 = *p1 - *p2; // BUG: compare the NEXT byte
1096 static void psxBios_memcpy() { // 0x2a
1097 u32 ret = a0, cycles = 0;
1100 mips_return_c(0, 4);
1105 do_memcpy(a0, a1, a2);
1111 mips_return_c(ret, cycles + 5);
1114 static void psxBios_memset() { // 0x2b
1115 u32 ret = a0, cycles;
1116 if (a0 == 0 || (s32)a2 <= 0)
1118 mips_return_c(0, 6);
1121 do_memset(a0, a1, a2);
1125 // todo: many more cycles due to uncached bios mem
1126 mips_return_c(ret, cycles + 5);
1129 void psxBios_memmove() { // 0x2c
1130 u32 ret = a0, cycles = 0;
1133 mips_return_c(0, 4);
1137 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1138 u32 dst = a0, len = a2 + 1;
1141 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1142 const u8 *sb = PSXM(a1);
1144 if (db != INVALID_PTR && sb != INVALID_PTR)
1150 psxCpu->Clear(dst, (len + 3) / 4);
1151 cycles = 10 + len * 8;
1152 } else if ((s32)a2 > 0) {
1153 do_memcpy(a0, a1, a2);
1159 mips_return_c(ret, cycles + 5);
1162 void psxBios_memcmp() { // 0x2d
1166 void psxBios_memchr() { // 0x2e
1167 char *p = (char *)Ra0;
1169 if (a0 == 0 || a2 > 0x7FFFFFFF)
1175 while ((s32)a2-- > 0) {
1176 if (*p++ != (s8)a1) continue;
1177 v0 = a0 + (p - (char *)Ra0 - 1);
1185 static void psxBios_rand() { // 0x2f
1186 u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1187 storeRam32(A_RND_SEED, s);
1189 mips_return_c((s >> 16) & 0x7fff, 12+37);
1192 static void psxBios_srand() { // 0x30
1193 storeRam32(A_RND_SEED, a0);
1194 mips_return_void_c(3);
1197 static u32 qscmpfunc, qswidth;
1199 static inline int qscmp(char *a, char *b) {
1202 a0 = sa0 + (a - (char *)PSXM(sa0));
1203 a1 = sa0 + (b - (char *)PSXM(sa0));
1205 softCall(qscmpfunc);
1211 static inline void qexchange(char *i, char *j) {
1222 static inline void q3exchange(char *i, char *j, char *k) {
1234 static void qsort_main(char *a, char *l) {
1235 char *i, *j, *lp, *hp;
1240 if ((n = l - a) <= qswidth)
1242 n = qswidth * (n / (2 * qswidth));
1248 if ((c = qscmp(i, lp)) == 0) {
1249 qexchange(i, lp -= qswidth);
1260 if ((c = qscmp(hp, j)) == 0) {
1261 qexchange(hp += qswidth, j);
1266 q3exchange(i, hp += qswidth, j);
1280 if (lp - a >= l - hp) {
1281 qsort_main(hp + qswidth, l);
1290 q3exchange(j, lp -= qswidth, i);
1295 void psxBios_qsort() { // 0x31
1298 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1303 static int malloc_heap_grow(u32 size) {
1304 u32 heap_addr, heap_end, heap_addr_new;
1306 heap_addr = loadRam32(A_HEAP_BASE);
1307 heap_end = loadRam32(A_HEAP_END);
1308 heap_addr_new = heap_addr + 4 + size;
1309 if (heap_addr_new >= heap_end)
1311 storeRam32(A_HEAP_BASE, heap_addr_new);
1312 storeRam32(heap_addr - 4, size | 1);
1313 storeRam32(heap_addr + size, ~1); // terminator
1317 static void psxBios_malloc() { // 0x33
1318 u32 size = (a0 + 3) & ~3;
1319 u32 limit = 32*1024;
1323 PSXBIOS_LOG("psxBios_%s %d\n", biosA0n[0x33], a0);
1325 if (!loadRam32(A_HEAP_INIT_FLG)) {
1326 u32 heap_addr = loadRam32(A_HEAP_BASE);
1327 storeRam32(heap_addr, ~1);
1328 storeRam32(A_HEAP_FRSTCHNK, heap_addr);
1329 storeRam32(A_HEAP_CURCHNK, heap_addr);
1330 storeRam32(A_HEAP_BASE, heap_addr + 4);
1331 if (malloc_heap_grow(size)) {
1332 PSXBIOS_LOG("malloc: init OOM\n");
1333 mips_return_c(0, 20);
1336 storeRam32(A_HEAP_INIT_FLG, 1);
1339 for (i = 0; tries > 0 && i < limit; i++)
1341 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1342 u32 chunk_hdr = loadRam32(chunk);
1343 u32 next_chunk = chunk + 4 + (chunk_hdr & ~3);
1344 u32 next_chunk_hdr = loadRam32(next_chunk);
1346 //printf(" c %08x %08x\n", chunk, chunk_hdr);
1347 if (chunk_hdr & 1) {
1349 if (chunk_hdr > (size | 1)) {
1351 u32 p2size = (chunk_hdr & ~3) - size - 4;
1352 storeRam32(chunk + 4 + size, p2size | 1);
1353 chunk_hdr = size | 1;
1355 if (chunk_hdr == (size | 1)) {
1356 storeRam32(chunk, size);
1360 if (next_chunk_hdr & 1) {
1362 u32 msize = (chunk_hdr & ~3) + 4 + (next_chunk_hdr & ~3);
1363 storeRam32(chunk, msize | 1);
1367 if (chunk_hdr == ~1) {
1370 storeRam32(A_HEAP_CURCHNK, loadRam32(A_HEAP_FRSTCHNK));
1374 // go to the next chunk
1375 storeRam32(A_HEAP_CURCHNK, next_chunk);
1381 else if (tries == 0 && malloc_heap_grow(size))
1384 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1385 storeRam32(chunk, loadRam32(chunk) & ~3);
1389 PSXBIOS_LOG(" -> %08x\n", ret);
1390 mips_return_c(ret, 40);
1393 static void psxBios_free() { // 0x34
1394 PSXBIOS_LOG("psxBios_%s %x (%d bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1395 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1396 mips_return_void_c(5);
1399 static void psxBios_calloc() { // 0x37
1401 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1403 a0 = size = a0 * a1;
1407 a0 = ret; a1 = size;
1410 mips_return_c(ret, 21);
1413 void psxBios_realloc() { // 0x38
1417 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1421 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1426 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1431 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1432 /* Note that it is not quite implemented this way here. */
1442 /* InitHeap(void *block , int n) */
1443 static void psxBios_InitHeap() { // 0x39
1444 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1446 storeRam32(A_HEAP_BASE, a0);
1447 storeRam32(A_HEAP_SIZE, a1);
1448 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1449 storeRam32(A_HEAP_INIT_FLG, 0);
1452 mips_return_void_c(14);
1455 void psxBios_getchar() { //0x3b
1456 v0 = getchar(); pc0 = ra;
1459 static void psxBios_printf_psxout() { // 0x3f
1462 u32 save[4] = { 0, };
1468 if (psp != INVALID_PTR) {
1469 memcpy(save, psp, 4 * 4);
1470 psxMu32ref(sp) = SWAP32((u32)a0);
1471 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1472 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1473 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1485 tmp2[j++] = Ra0[i]; goto _start;
1487 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1498 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1502 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1508 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1510 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1512 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1514 *ptmp++ = Ra0[i]; break;
1524 if (psp != INVALID_PTR)
1525 memcpy(psp, save, 4 * 4);
1528 SysPrintf("%s", tmp);
1531 void psxBios_printf() { // 0x3f
1532 psxBios_printf_psxout();
1536 static void psxBios_cd() { // 0x40
1537 const char *p, *dir = Ra0;
1538 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x40], a0, dir);
1539 if (dir != INVALID_PTR) {
1540 if ((p = strchr(dir, ':')))
1544 snprintf(cdir, sizeof(cdir), "%s", dir);
1546 mips_return_c(1, 100);
1549 static void psxBios_format() { // 0x41
1550 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x41], a0, Ra0);
1551 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1553 CreateMcd(Config.Mcd1);
1554 LoadMcd(1, Config.Mcd1);
1557 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1559 CreateMcd(Config.Mcd2);
1560 LoadMcd(2, Config.Mcd2);
1570 static void psxBios_SystemErrorUnresolvedException() {
1571 if (floodchk != 0x12340a40) { // prevent log flood
1572 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1573 floodchk = 0x12340a40;
1575 mips_return_void_c(1000);
1578 static void FlushCache() {
1579 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1580 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1582 // runs from uncached mem so tons of cycles
1587 * long Load(char *name, struct EXEC *header);
1590 void psxBios_Load() { // 0x42
1598 PSXBIOS_LOG("psxBios_%s %x(%s), %x\n", biosA0n[0x42], a0, pa0, a1);
1599 if (pa0 == INVALID_PTR || pa1 == INVALID_PTR) {
1603 if ((p = strchr(pa0, ':')))
1608 snprintf(path, sizeof(path), "%s\\%s", cdir, (char *)pa0);
1610 snprintf(path, sizeof(path), "%s", (char *)pa0);
1612 if (LoadCdromFile(path, &eheader) == 0) {
1613 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1614 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1618 PSXBIOS_LOG(" -> %d\n", v0);
1624 * int Exec(struct EXEC *header , int argc , char **argv);
1627 void psxBios_Exec() { // 43
1628 EXEC *header = (EXEC *)castRam32ptr(a0);
1632 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1634 header->_sp = SWAP32(sp);
1635 header->_fp = SWAP32(fp);
1636 header->_sp = SWAP32(sp);
1637 header->_gp = SWAP32(gp);
1638 header->ret = SWAP32(ra);
1639 header->base = SWAP32(s0);
1641 ptr = SWAP32(header->b_addr);
1642 len = SWAP32(header->b_size);
1648 if (header->S_addr != 0)
1649 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1651 gp = SWAP32(header->gp0);
1659 pc0 = SWAP32(header->_pc0);
1662 static void psxBios_FlushCache() { // 44
1663 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1668 void psxBios_GPU_dw() { // 0x46
1673 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1676 GPU_writeData(0xa0000000);
1677 GPU_writeData((a1<<0x10)|(a0&0xffff));
1678 GPU_writeData((a3<<0x10)|(a2&0xffff));
1680 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1683 GPU_writeData(SWAPu32(*ptr++));
1689 void psxBios_mem2vram() { // 0x47
1691 gpuSyncPluginSR(); // flush
1692 GPU_writeData(0xa0000000);
1693 GPU_writeData((a1<<0x10)|(a0&0xffff));
1694 GPU_writeData((a3<<0x10)|(a2&0xffff));
1695 size = ((((a2 * a3) / 2) >> 4) << 16);
1696 GPU_writeStatus(0x04000002);
1697 psxHwWrite32(0x1f8010f4,0);
1698 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1699 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1700 psxHwWrite32(0x1f8010a4, size | 0x10);
1701 psxHwWrite32(0x1f8010a8,0x01000201);
1706 void psxBios_SendGPU() { // 0x48
1707 GPU_writeStatus(a0);
1712 void psxBios_GPU_cw() { // 0x49
1719 void psxBios_GPU_cwb() { // 0x4a
1720 u32 *ptr = (u32*)Ra0;
1725 GPU_writeData(SWAPu32(*ptr++));
1731 void psxBios_GPU_SendPackets() { //4b:
1733 GPU_writeStatus(0x04000002);
1734 psxHwWrite32(0x1f8010f4,0);
1735 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1736 psxHwWrite32(0x1f8010a0,a0);
1737 psxHwWrite32(0x1f8010a4,0);
1738 psxHwWrite32(0x1f8010a8,0x010000401);
1742 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1743 psxHwWrite32(0x1f8010a8,0x00000401);
1744 GPU_writeData(0x0400000);
1745 GPU_writeData(0x0200000);
1746 GPU_writeData(0x0100000);
1751 void psxBios_GPU_GetGPUStatus() { // 0x4d
1752 v0 = GPU_readStatus();
1758 void psxBios_LoadExec() { // 51
1759 EXEC *header = (EXEC*)PSXM(0xf000);
1763 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1765 s_addr = a1; s_size = a2;
1770 header->S_addr = s_addr;
1771 header->s_size = s_size;
1773 a0 = 0xf000; a1 = 0; a2 = 0;
1777 void psxBios__bu_init() { // 70
1779 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1782 DeliverEvent(0xf0000011, 0x0004);
1783 DeliverEvent(0xf4000001, 0x0004);
1788 void psxBios__96_init() { // 71
1790 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1796 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1797 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1798 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1800 static void psxBios_DequeueCdIntr_() {
1801 psxBios_SysDeqIntRP_(0, 0x91d0);
1802 psxBios_SysDeqIntRP_(0, 0x91e0);
1806 static void psxBios_DequeueCdIntr() { // a3
1807 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1808 psxBios_DequeueCdIntr_();
1811 static void psxBios_CdRemove() { // 56, 72
1812 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1814 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1815 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1816 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1817 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1818 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1819 psxBios_DequeueCdIntr_();
1821 // EnterCriticalSection - should be done at the beginning,
1822 // but this way is much easier to implement
1828 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1830 static void psxBios_SetConf() { // 9c
1831 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1832 setup_tt(a1, a0, a2);
1833 psxRegs.CP0.n.SR |= 0x401;
1834 mips_return_void_c(500);
1837 static void psxBios_GetConf() { // 9d
1838 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1839 storeRam32(a0, loadRam32(A_CONF_EvCB));
1840 storeRam32(a1, loadRam32(A_CONF_TCB));
1841 storeRam32(a2, loadRam32(A_CONF_SP));
1842 mips_return_void_c(10);
1845 void psxBios_SetMem() { // 9f
1846 u32 new = psxHu32(0x1060);
1849 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1854 psxHu32ref(0x1060) = SWAP32(new);
1855 psxMu32ref(0x060) = a0;
1856 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1860 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1861 psxMu32ref(0x060) = a0;
1862 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1865 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1872 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1873 static void psxBios_get_cd_status() // a6
1875 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1880 static void psxBios__card_info() { // ab
1881 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1883 storeRam32(A_CARD_CHAN1, a0);
1890 if (McdDisable[port & 1])
1894 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1899 if (McdDisable[0] && McdDisable[1])
1902 DeliverEvent(0xf0000011, 0x0004);
1903 // DeliverEvent(0xf4000001, 0x0004);
1904 DeliverEvent(0xf4000001, ret);
1908 void psxBios__card_load() { // ac
1910 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1913 storeRam32(A_CARD_CHAN1, a0);
1915 // DeliverEvent(0xf0000011, 0x0004);
1916 DeliverEvent(0xf4000001, 0x0004);
1921 static void psxBios_GetSystemInfo() { // b4
1923 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1924 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1927 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1928 case 2: ret = 0xbfc0012c; break;
1929 case 5: ret = loadRam32(0x60) << 10; break;
1931 mips_return_c(ret, 20);
1934 /* System calls B0 */
1936 static u32 psxBios_SysMalloc_(u32 size);
1938 static void psxBios_SysMalloc() { // B 00
1939 u32 ret = psxBios_SysMalloc_(a0);
1941 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1942 mips_return_c(ret, 33);
1945 void psxBios_SetRCnt() { // 02
1947 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1954 psxRcntWtarget(a0, a1);
1955 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1956 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1957 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1958 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1959 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1961 psxRcntWmode(a0, mode);
1966 void psxBios_GetRCnt() { // 03
1968 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1973 case 0: v0 = psxRcntRcount0(); break;
1974 case 1: v0 = psxRcntRcount1(); break;
1975 case 2: v0 = psxRcntRcount2(); break;
1976 case 3: v0 = 0; break;
1981 void psxBios_StartRCnt() { // 04
1983 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1987 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1988 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1992 void psxBios_StopRCnt() { // 05
1994 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1998 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1999 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
2003 void psxBios_ResetRCnt() { // 06
2005 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
2010 psxRcntWmode(a0, 0);
2011 psxRcntWtarget(a0, 0);
2012 psxRcntWcount(a0, 0);
2017 static u32 DeliverEvent(u32 class, u32 spec) {
2018 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2019 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
2020 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
2021 u32 i, lim = evcb_len / 0x1c;
2023 //printf("%s %08x %x\n", __func__, class, spec);
2024 for (i = 0; i < lim; i++, ev++) {
2026 if (SWAP32(ev->status) != EvStACTIVE)
2029 if (SWAP32(ev->class) != class)
2032 if (SWAP32(ev->spec) != spec)
2035 ret = SWAP32(ev->mode);
2036 if (ret == EvMdMARK) {
2037 ev->status = SWAP32(EvStALREADY);
2041 if (ret == EvMdCALL) {
2042 ret = SWAP32(ev->fhandler);
2055 static u32 UnDeliverEvent(u32 class, u32 spec) {
2056 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2057 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
2058 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
2059 u32 i, lim = evcb_len / 0x1c;
2061 for (i = 0; i < lim; i++, ev++) {
2063 if (SWAP32(ev->status) != EvStALREADY)
2066 if (SWAP32(ev->class) != class)
2069 if (SWAP32(ev->spec) != spec)
2072 if (SWAP32(ev->mode) == EvMdMARK)
2073 ev->status = SWAP32(EvStACTIVE);
2079 static void psxBios_DeliverEvent() { // 07
2081 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
2083 ret = DeliverEvent(a0, a1);
2087 static s32 get_free_EvCB_slot() {
2088 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2089 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
2092 for (i = 0; i < lim; i++, ev++) {
2094 if (ev->status == SWAP32(EvStUNUSED))
2100 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2101 u32 ret = get_free_EvCB_slot();
2102 if ((s32)ret >= 0) {
2103 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2104 ev->class = SWAP32(class);
2105 ev->status = SWAP32(EvStDISABLED);
2106 ev->spec = SWAP32(spec);
2107 ev->mode = SWAP32(mode);
2108 ev->fhandler = SWAP32(func);
2114 static void psxBios_OpenEvent() { // 08
2115 u32 ret = OpenEvent(a0, a1, a2, a3);
2116 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2117 biosB0n[0x08], a0, a1, a2, a3, ret);
2118 mips_return_c(ret, 36);
2121 static void CloseEvent(u32 ev)
2123 u32 base = loadRam32(A_TT_EvCB);
2124 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2127 static void psxBios_CloseEvent() { // 09
2128 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2129 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2131 mips_return_c(1, 10);
2134 static void psxBios_WaitEvent() { // 0a
2135 u32 base = loadRam32(A_TT_EvCB);
2136 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2137 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2140 if (status == EvStALREADY) {
2141 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2145 if (status != EvStACTIVE)
2147 mips_return_c(0, 2);
2151 // retrigger this hlecall after the next emulation event
2153 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2154 psxRegs.cycle = next_interupt;
2158 static void psxBios_TestEvent() { // 0b
2159 u32 base = loadRam32(A_TT_EvCB);
2160 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2163 if (psxRegs.cycle - floodchk > 16*1024u) { // prevent log flood
2164 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2165 floodchk = psxRegs.cycle;
2167 if (status == EvStALREADY) {
2168 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2172 mips_return_c(ret, 15);
2175 static void psxBios_EnableEvent() { // 0c
2176 u32 base = loadRam32(A_TT_EvCB);
2177 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2178 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2179 if (status != EvStUNUSED)
2180 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2182 mips_return_c(1, 15);
2185 static void psxBios_DisableEvent() { // 0d
2186 u32 base = loadRam32(A_TT_EvCB);
2187 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2188 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2189 if (status != EvStUNUSED)
2190 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2192 mips_return_c(1, 15);
2196 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2199 void psxBios_OpenTh() { // 0e
2200 TCB *tcb = loadRam32ptr(A_TT_TCB);
2201 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2204 for (th = 1; th < limit; th++)
2206 if (tcb[th].status != SWAP32(0x4000)) break;
2210 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2211 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2213 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2215 mips_return_c(0xffffffff, 20);
2218 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2220 tcb[th].status = SWAP32(0x4000);
2221 tcb[th].mode = SWAP32(0x1000);
2222 tcb[th].epc = SWAP32(a0);
2223 tcb[th].reg[30] = SWAP32(a1); // fp
2224 tcb[th].reg[29] = SWAP32(a1); // sp
2225 tcb[th].reg[28] = SWAP32(a2); // gp
2227 mips_return_c(0xff000000 + th, 34);
2231 * int CloseTh(long thread);
2234 static void psxBios_CloseTh() { // 0f
2235 u32 tcb = loadRam32(A_TT_TCB);
2236 u32 th = a0 & 0xffff;
2238 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2239 // in the usual bios fashion no checks, just write and return 1
2240 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2242 mips_return_c(1, 11);
2246 * int ChangeTh(long thread);
2249 void psxBios_ChangeTh() { // 10
2250 u32 tcbBase = loadRam32(A_TT_TCB);
2251 u32 th = a0 & 0xffff;
2253 // this is quite spammy
2254 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2256 // without doing any argument checks, just issue a syscall
2257 // (like the real bios does)
2259 a1 = tcbBase + th * sizeof(TCB);
2264 void psxBios_InitPAD() { // 0x12
2265 u32 i, *ram32 = (u32 *)psxM;
2266 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2268 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2269 ram32[A_PAD_DR_DST/4] = 0;
2270 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2271 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2272 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2273 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2274 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2275 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2276 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2277 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2279 for (i = 0; i < a1; i++) {
2281 storeRam8(a0 + i, 0);
2283 for (i = 0; i < a3; i++) {
2285 storeRam8(a2 + i, 0);
2287 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2289 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2291 mips_return_c(1, 200);
2294 void psxBios_StartPAD() { // 13
2295 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2297 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2298 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2299 psxHwWrite16(0x1f801070, ~1);
2300 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2301 storeRam32(A_PAD_ACK_VBL, 1);
2302 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2303 psxRegs.CP0.n.SR |= 0x401;
2305 mips_return_c(1, 300);
2308 void psxBios_StopPAD() { // 14
2309 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2310 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2311 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2312 psxRegs.CP0.n.SR |= 0x401;
2313 mips_return_void_c(200);
2316 static void psxBios_PAD_init() { // 15
2318 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2319 if (a0 == 0x20000000 || a0 == 0x20000001)
2322 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2323 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2326 storeRam32(A_PAD_DR_DST, dst);
2329 mips_return_c(ret, 100);
2332 static u32 psxBios_PAD_dr_() {
2333 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2334 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2335 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2336 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2337 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2339 dst[0] = buf1[3], dst[1] = buf1[2];
2340 if (buf1[1] == 0x23) {
2341 dst[0] |= 0xc7, dst[1] |= 7;
2342 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2343 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2346 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2348 dst[2] = buf2[3], dst[3] = buf2[2];
2349 if (buf2[1] == 0x23) {
2350 dst[2] |= 0xc7, dst[3] |= 7;
2351 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2352 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2356 return SWAP32(*(u32 *)dst);
2359 static void psxBios_PAD_dr() { // 16
2360 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2361 u32 ret = psxBios_PAD_dr_();
2365 static void psxBios_ReturnFromException() { // 17
2366 u32 tcbPtr = loadRam32(A_TT_PCB);
2367 const TCB *tcb = loadRam32ptr(tcbPtr);
2371 for (i = 1; i < 32; i++)
2372 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2373 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2374 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2375 sr = SWAP32(tcb->sr);
2377 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2378 pc0 = k0 = SWAP32(tcb->epc);
2380 // the interpreter wants to know about sr changes, so do a MTC0
2381 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2382 MTC0(&psxRegs, 12, sr);
2388 void psxBios_ResetEntryInt() { // 18
2389 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2391 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2392 mips_return_void_c(5);
2395 void psxBios_HookEntryInt() { // 19
2396 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2398 storeRam32(A_EEXIT_PTR, a0);
2399 mips_return_void_c(3);
2402 static void psxBios_UnDeliverEvent() { // 0x20
2404 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2406 ret = UnDeliverEvent(a0, a1);
2410 static void buopen(int mcd, char *ptr, char *cfg)
2413 char *mcd_data = ptr;
2415 strcpy(FDesc[1 + mcd].name, Ra0+5);
2416 FDesc[1 + mcd].offset = 0;
2417 FDesc[1 + mcd].mode = a1;
2419 for (i=1; i<16; i++) {
2420 const char *fptr = mcd_data + 128 * i;
2421 if ((*fptr & 0xF0) != 0x50) continue;
2422 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2423 FDesc[1 + mcd].mcfile = i;
2424 PSXBIOS_LOG("open %s\n", fptr+0xa);
2428 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2429 for (i=1; i<16; i++) {
2430 int j, xor, nblk = a1 >> 16;
2432 char *fptr = mcd_data + 128 * i;
2434 if ((*fptr & 0xF0) != 0xa0) continue;
2436 FDesc[1 + mcd].mcfile = i;
2439 fptr[5] = 0x20 * nblk;
2442 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2443 pptr = fptr2 = fptr;
2444 for(j=2; j<=nblk; j++) {
2446 for(i++; i<16; i++) {
2449 memset(fptr2, 0, 128);
2450 fptr2[0] = j < nblk ? 0x52 : 0x53;
2453 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2458 /* shouldn't this return ENOSPC if i == 16? */
2460 pptr[8] = pptr[9] = 0xff;
2461 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2463 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2465 /* just go ahead and resave them all */
2466 SaveMcd(cfg, ptr, 128, 128 * 15);
2469 /* shouldn't this return ENOSPC if i == 16? */
2474 * int open(char *name , int mode);
2477 void psxBios_open() { // 0x32
2480 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2484 if (pa0 != INVALID_PTR) {
2485 if (!strncmp(pa0, "bu00", 4)) {
2486 buopen(1, Mcd1Data, Config.Mcd1);
2489 if (!strncmp(pa0, "bu10", 4)) {
2490 buopen(2, Mcd2Data, Config.Mcd2);
2498 * int lseek(int fd , int offset , int whence);
2501 void psxBios_lseek() { // 0x33
2503 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2508 FDesc[a0].offset = a1;
2510 // DeliverEvent(0xf0000011, 0x0004);
2511 // DeliverEvent(0xf4000001, 0x0004);
2515 FDesc[a0].offset+= a1;
2516 v0 = FDesc[a0].offset;
2525 * int read(int fd , void *buf , int nbytes);
2528 void psxBios_read() { // 0x34
2533 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2538 if (pa1 != INVALID_PTR) {
2540 case 2: buread(pa1, 1, a2); break;
2541 case 3: buread(pa1, 2, a2); break;
2549 * int write(int fd , void *buf , int nbytes);
2552 void psxBios_write() { // 0x35/0x03
2556 if (a0 != 1) // stdout
2557 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2560 if (pa1 == INVALID_PTR) {
2565 if (a0 == 1) { // stdout
2569 if (Config.PsxOut) while (a2 > 0) {
2570 SysPrintf("%c", *ptr++); a2--;
2576 case 2: buwrite(pa1, 1, a2); break;
2577 case 3: buwrite(pa1, 2, a2); break;
2583 static void psxBios_write_psxout() {
2584 if (a0 == 1) { // stdout
2585 const char *ptr = Ra1;
2588 if (ptr != INVALID_PTR)
2590 SysPrintf("%c", *ptr++);
2594 static void psxBios_putchar_psxout() { // 3d
2595 SysPrintf("%c", (char)a0);
2598 static void psxBios_puts_psxout() { // 3e/3f
2599 SysPrintf("%s", Ra0);
2603 * int close(int fd);
2606 void psxBios_close() { // 0x36
2608 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2615 void psxBios_putchar() { // 3d
2616 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2620 void psxBios_puts() { // 3e/3f
2621 if (Config.PsxOut) SysPrintf("%s", Ra0);
2625 static void bufile(const u8 *mcd_data, u32 dir_) {
2626 struct DIRENTRY *dir = (struct DIRENTRY *)PSXM(dir_);
2627 const char *pfile = ffile + 5;
2628 const u8 *data = mcd_data;
2629 int i = 0, match = 0;
2634 if (dir == INVALID_PTR)
2637 for (; nfile <= 15 && !match; nfile++) {
2640 head = nfile * 0x40;
2641 data = mcd_data + 128 * nfile;
2642 name = (const char *)data + 0x0a;
2643 if ((data[0] & 0xF0) != 0x50) continue;
2644 /* Bug link files show up as free block. */
2645 if (!name[0]) continue;
2647 for (i = 0; i < 20; i++) {
2648 if (pfile[i] == name[i] || pfile[i] == '?')
2649 dir->name[i] = name[i];
2650 else if (pfile[i] == '*') {
2651 int len = strlen(name + i);
2654 memcpy(dir->name + i, name + i, len + 1);
2665 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2666 nfile, dir->name, pfile, name, match);
2668 for (; nfile <= 15; nfile++, blocks++) {
2669 const u8 *data2 = mcd_data + 128 * nfile;
2670 const char *name = (const char *)data2 + 0x0a;
2671 if ((data2[0] & 0xF0) != 0x50 || name[0])
2675 // nul char of full lenth name seems to overwrite .attr
2676 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2677 dir->size = 8192 * blocks;
2681 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2682 dir->attr, dir->size, dir->next, dir->head);
2686 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2689 static void psxBios_firstfile() { // 42
2692 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2695 if (pa0 != INVALID_PTR)
2697 snprintf(ffile, sizeof(ffile), "%s", pa0);
2699 strcpy(ffile + 5, "*"); // maybe?
2701 if (!strncmp(pa0, "bu00", 4)) {
2702 // firstfile() calls _card_read() internally, so deliver it's event
2703 DeliverEvent(0xf0000011, 0x0004);
2704 bufile((u8 *)Mcd1Data, a1);
2705 } else if (!strncmp(pa0, "bu10", 4)) {
2706 // firstfile() calls _card_read() internally, so deliver it's event
2707 DeliverEvent(0xf0000011, 0x0004);
2708 bufile((u8 *)Mcd2Data, a1);
2716 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2719 void psxBios_nextfile() { // 43
2720 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2723 if (!strncmp(ffile, "bu00", 4))
2724 bufile((u8 *)Mcd1Data, a0);
2725 else if (!strncmp(ffile, "bu10", 4))
2726 bufile((u8 *)Mcd2Data, a0);
2731 #define burename(mcd) { \
2732 for (i=1; i<16; i++) { \
2733 int namelen, j, xor = 0; \
2734 ptr = Mcd##mcd##Data + 128 * i; \
2735 if ((*ptr & 0xF0) != 0x50) continue; \
2736 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2737 namelen = strlen(Ra1+5); \
2738 memcpy(ptr+0xa, Ra1+5, namelen); \
2739 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2740 for (j=0; j<127; j++) xor^= ptr[j]; \
2742 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2749 * int rename(char *old, char *new);
2752 void psxBios_rename() { // 44
2759 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2764 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2765 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2769 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2778 #define budelete(mcd) { \
2779 for (i=1; i<16; i++) { \
2780 ptr = Mcd##mcd##Data + 128 * i; \
2781 if ((*ptr & 0xF0) != 0x50) continue; \
2782 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2783 *ptr = (*ptr & 0xf) | 0xA0; \
2784 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2785 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2792 * int delete(char *name);
2795 void psxBios_delete() { // 45
2801 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2806 if (pa0 != INVALID_PTR) {
2807 if (!strncmp(pa0, "bu00", 4)) {
2811 if (!strncmp(pa0, "bu10", 4)) {
2819 void psxBios_InitCARD() { // 4a
2820 u32 *ram32 = (u32 *)psxM;
2821 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2822 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2823 // (maybe) todo: early_card_irq, etc
2825 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2827 psxBios_FlushCache();
2828 mips_return_c(0, 34+13+15+6);
2831 void psxBios_StartCARD() { // 4b
2832 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2833 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2834 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2836 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2837 storeRam32(A_PAD_ACK_VBL, 1);
2838 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2839 storeRam32(A_CARD_IRQR_ENA, 1);
2840 psxRegs.CP0.n.SR |= 0x401;
2842 mips_return_c(1, 200);
2845 void psxBios_StopCARD() { // 4c
2846 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2847 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2848 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2849 storeRam32(A_CARD_IRQR_ENA, 0);
2850 psxRegs.CP0.n.SR |= 0x401;
2851 mips_return_void_c(200);
2854 void psxBios__card_write() { // 0x4e
2859 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2862 Function also accepts sector 400h (a bug).
2863 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2867 /* Invalid sectors */
2871 storeRam32(A_CARD_CHAN1, a0);
2874 if (pa2 != INVALID_PTR) {
2876 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2877 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2879 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2880 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2884 DeliverEvent(0xf0000011, 0x0004);
2885 // DeliverEvent(0xf4000001, 0x0004);
2890 void psxBios__card_read() { // 0x4f
2895 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2898 Function also accepts sector 400h (a bug).
2899 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2903 /* Invalid sectors */
2907 storeRam32(A_CARD_CHAN1, a0);
2910 if (pa2 != INVALID_PTR) {
2912 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2914 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2918 DeliverEvent(0xf0000011, 0x0004);
2919 // DeliverEvent(0xf4000001, 0x0004);
2924 void psxBios__new_card() { // 0x50
2926 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2932 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2933 void psxBios__get_error(void) // 55
2935 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2940 void psxBios_Krom2RawAdd() { // 0x51
2943 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2944 const u32 table_8140[][2] = {
2945 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2946 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2947 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2948 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2949 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2950 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2951 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2952 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2953 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2957 const u32 table_889f[][2] = {
2958 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2959 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2960 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2961 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2962 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2963 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2964 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2965 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2969 if (a0 >= 0x8140 && a0 <= 0x84be) {
2970 while (table_8140[i][0] <= a0) i++;
2971 a0 -= table_8140[i - 1][0];
2972 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2973 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2974 while (table_889f[i][0] <= a0) i++;
2975 a0 -= table_889f[i - 1][0];
2976 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2984 void psxBios_GetC0Table() { // 56
2985 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2986 log_unhandled("GetC0Table @%08x\n", ra);
2988 mips_return_c(A_C0_TABLE, 3);
2991 void psxBios_GetB0Table() { // 57
2992 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2993 log_unhandled("GetB0Table @%08x\n", ra);
2995 mips_return_c(A_B0_TABLE, 3);
2998 static void psxBios__card_chan() { // 0x58
3000 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
3002 // todo: should return active slot chan
3003 // (active - which was last processed by irq code)
3004 ret = loadRam32(A_CARD_CHAN1);
3005 mips_return_c(ret, 8);
3008 static void psxBios_ChangeClearPad() { // 5b
3010 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
3011 ret = loadRam32(A_PAD_ACK_VBL);
3012 storeRam32(A_PAD_ACK_VBL, a0);
3014 mips_return_c(ret, 6);
3017 static void psxBios__card_status() { // 5c
3018 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
3024 static void psxBios__card_wait() { // 5d
3025 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
3031 /* System calls C0 */
3033 static void psxBios_InitRCnt() { // 00
3035 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
3036 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
3037 for (i = 0; i < 3; i++) {
3038 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
3039 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
3040 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
3042 psxBios_SysEnqIntRP_(a0, 0x6d88);
3043 mips_return_c(0, 9);
3046 static void psxBios_InitException() { // 01
3047 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
3048 psxBios_SysEnqIntRP_(a0, 0x6da8);
3049 mips_return_c(0, 9);
3053 * int SysEnqIntRP(int index , long *queue);
3056 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
3057 u32 old, base = loadRam32(A_TT_ExCB);
3059 old = loadRam32(base + (priority << 3));
3060 storeRam32(base + (priority << 3), chain_eptr);
3061 storeRam32(chain_eptr, old);
3062 mips_return_c(0, 9);
3065 static void psxBios_SysEnqIntRP() { // 02
3066 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
3067 psxBios_SysEnqIntRP_(a0, a1);
3071 * int SysDeqIntRP(int index , long *queue);
3074 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
3075 u32 ptr, next, base = loadRam32(A_TT_ExCB);
3076 u32 lim = 0, ret = 0;
3078 // as in original: no arg checks of any kind, bug if a1 == 0
3079 ptr = loadRam32(base + (priority << 3));
3081 next = loadRam32(ptr);
3082 if (ptr == chain_rm_eptr) {
3083 storeRam32(base + (priority << 3), next);
3088 while (next && next != chain_rm_eptr && lim++ < 100) {
3090 next = loadRam32(ptr);
3093 if (next == chain_rm_eptr) {
3094 next = loadRam32(next);
3095 storeRam32(ptr, next);
3102 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
3104 mips_return_c(ret, 12);
3107 static void psxBios_SysDeqIntRP() { // 03
3108 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3109 psxBios_SysDeqIntRP_(a0, a1);
3112 static void psxBios_get_free_EvCB_slot() { // 04
3113 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3114 s32 ret = get_free_EvCB_slot();
3115 mips_return_c(ret, 0);
3118 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3119 storeRam32(base, 0);
3120 storeRam32(A_KMALLOC_PTR, base);
3121 storeRam32(A_KMALLOC_SIZE, size);
3122 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3125 // this should be much more complicated, but maybe that'll be enough
3126 static u32 psxBios_SysMalloc_(u32 size) {
3127 u32 ptr = loadRam32(A_KMALLOC_PTR);
3129 size = (size + 3) & ~3;
3130 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3131 storeRam32(ptr, size);
3135 static void psxBios_SysInitMemory() { // 08
3136 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3138 psxBios_SysInitMemory_(a0, a1);
3139 mips_return_void_c(12);
3142 static void psxBios_ChangeClearRCnt() { // 0a
3145 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3147 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3148 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3149 mips_return_c(ret, 8);
3152 static void psxBios_InitDefInt() { // 0c
3153 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3154 // should also clear the autoack table
3155 psxBios_SysEnqIntRP_(a0, 0x6d98);
3156 mips_return_c(0, 20 + 6*2);
3159 void psxBios_dummy() {
3160 u32 pc = (pc0 & 0x1fffff) - 4;
3161 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3162 : pc == 0xc0 ? biosC0n : NULL;
3163 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3164 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3165 (void)pc; (void)ntab;
3166 mips_return_c(0, 100);
3169 void (*biosA0[256])();
3170 // C0 and B0 overlap (end of C0 is start of B0)
3171 void (*biosC0[256+128])();
3172 void (**biosB0)() = biosC0 + 128;
3174 static void setup_mips_code()
3177 ptr = (u32 *)&psxM[A_SYSCALL];
3178 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3179 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3180 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3182 ptr = (u32 *)&psxM[A_EXCEPTION];
3183 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3184 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3185 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3186 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3187 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3188 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3189 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3190 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3191 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3192 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3194 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3195 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3196 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3198 ptr[0xb0/4] = HLEOP(hleop_exception);
3201 static const struct {
3205 { 0xbfc050a4, hleop_exc0_0_1 },
3206 { 0xbfc04fbc, hleop_exc0_0_2 },
3207 { 0xbfc0506c, hleop_exc0_1_1 },
3208 { 0xbfc04dec, hleop_exc0_1_2 },
3209 { 0x1a00, hleop_exc0_2_2 },
3210 { 0x19c8, hleop_exc1_0_1 },
3211 { 0x18bc, hleop_exc1_0_2 },
3212 { 0x1990, hleop_exc1_1_1 },
3213 { 0x1858, hleop_exc1_1_2 },
3214 { 0x1958, hleop_exc1_2_1 },
3215 { 0x17f4, hleop_exc1_2_2 },
3216 { 0x1920, hleop_exc1_3_1 },
3217 { 0x1794, hleop_exc1_3_2 },
3218 { 0x2458, hleop_exc3_0_2 },
3219 { 0x49bc, hleop_exc_padcard1 },
3220 { 0x4a4c, hleop_exc_padcard2 },
3223 static int chain_hle_op(u32 handler)
3227 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3228 if (chainfns[i].addr == handler)
3229 return chainfns[i].op;
3233 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3235 d[0] = SWAPu32(next);
3236 d[1] = SWAPu32(handler1);
3237 d[2] = SWAPu32(handler2);
3239 // install the hle traps
3240 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3241 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3244 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3246 u32 *ram32 = (u32 *)psxM;
3247 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3248 u32 p_excb, p_evcb, p_pcb, p_tcb;
3251 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3253 // the real bios doesn't care, but we just don't
3254 // want to crash in case of garbage parameters
3255 if (tcb_cnt > 1024) tcb_cnt = 1024;
3256 if (evcb_cnt > 1024) evcb_cnt = 1024;
3257 s_evcb = 0x1c * evcb_cnt;
3258 s_tcb = 0xc0 * tcb_cnt;
3260 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3261 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3262 p_excb = psxBios_SysMalloc_(s_excb);
3263 p_evcb = psxBios_SysMalloc_(s_evcb);
3264 p_pcb = psxBios_SysMalloc_(s_pcb);
3265 p_tcb = psxBios_SysMalloc_(s_tcb);
3267 // "table of tables". Some games modify it
3268 assert(A_TT_ExCB == 0x0100);
3269 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3270 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3271 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3272 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3273 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3274 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3275 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3276 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3277 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3278 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3279 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3280 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3282 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3283 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3284 storeRam32(p_excb + 4*4, 0x0000); // chain2
3285 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3287 storeRam32(p_pcb, p_tcb);
3288 storeRam32(p_tcb, 0x4000); // first TCB
3289 for (i = 1; i < tcb_cnt; i++)
3290 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3293 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3294 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3295 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3296 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3297 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3299 storeRam32(A_CONF_EvCB, evcb_cnt);
3300 storeRam32(A_CONF_TCB, tcb_cnt);
3301 storeRam32(A_CONF_SP, stack);
3304 static const u32 gpu_ctl_def[] = {
3305 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3306 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3309 static const u32 gpu_data_def[] = {
3310 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3311 0xe5001000, 0xe6000000,
3312 0x02000000, 0x00000000, 0x01ff03ff
3316 static const u16 spu_config[] = {
3317 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3318 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3319 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3320 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3321 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3322 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3323 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3324 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3327 void psxBiosSetupBootState(void)
3329 boolean hle = Config.HLE;
3330 u32 *hw = (u32 *)psxH;
3333 // see also SetBootRegs()
3336 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3337 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3339 k0 = 0xbfc0d968; k1 = 0xf1c;
3340 ra = 0xf0001234; // just to easily detect attempts to return
3341 psxRegs.CP0.n.Cause = 0x20;
3342 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3344 hw[0x1000/4] = SWAP32(0x1f000000);
3345 hw[0x1004/4] = SWAP32(0x1f802000);
3346 hw[0x1008/4] = SWAP32(0x0013243f);
3347 hw[0x100c/4] = SWAP32(0x00003022);
3348 hw[0x1010/4] = SWAP32(0x0013243f);
3349 hw[0x1014/4] = SWAP32(0x200931e1);
3350 hw[0x1018/4] = SWAP32(0x00020943);
3351 hw[0x101c/4] = SWAP32(0x00070777);
3352 hw[0x1020/4] = SWAP32(0x0000132c);
3353 hw[0x1060/4] = SWAP32(0x00000b88);
3354 hw[0x1070/4] = SWAP32(0x00000001);
3355 hw[0x1074/4] = SWAP32(0x0000000c);
3356 hw[0x2040/4] = SWAP32(0x00000900);
3359 hw[0x10a0/4] = SWAP32(0x00ffffff);
3360 hw[0x10a8/4] = SWAP32(0x00000401);
3361 hw[0x10b0/4] = SWAP32(0x0008b000);
3362 hw[0x10b4/4] = SWAP32(0x00010200);
3363 hw[0x10e0/4] = SWAP32(0x000eccf4);
3364 hw[0x10e4/4] = SWAP32(0x00000400);
3365 hw[0x10e8/4] = SWAP32(0x00000002);
3366 hw[0x10f0/4] = SWAP32(0x00009099);
3367 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3376 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3377 GPU_writeStatus(gpu_ctl_def[i]);
3378 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3379 GPU_writeData(gpu_data_def[i]);
3382 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3383 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3386 static void hleExc0_0_1();
3387 static void hleExc0_0_2();
3388 static void hleExc0_1_1();
3389 static void hleExc0_1_2();
3391 #include "sjisfont.h"
3393 void psxBiosInit() {
3394 u32 *ptr, *ram32, *rom32;
3399 psxRegs.biosBranchCheck = ~0;
3401 memset(psxM, 0, 0x10000);
3402 for(i = 0; i < 256; i++) {
3407 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3408 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3409 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3410 biosA0[0x3f] = psxBios_printf_psxout;
3413 char verstr[0x24+1];
3414 rom32 = (u32 *)psxR;
3415 memcpy(verstr, psxR + 0x12c, 0x24);
3417 SysPrintf("BIOS: %08x, '%s', '%c'\n", SWAP32(rom32[0x100/4]),
3418 verstr, psxR[0x7ff52]);
3422 for(i = 0; i < 256; i++) {
3423 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3424 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3425 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3428 biosA0[0x00] = psxBios_open;
3429 biosA0[0x01] = psxBios_lseek;
3430 biosA0[0x02] = psxBios_read;
3431 biosA0[0x03] = psxBios_write;
3432 biosA0[0x04] = psxBios_close;
3433 //biosA0[0x05] = psxBios_ioctl;
3434 //biosA0[0x06] = psxBios_exit;
3435 //biosA0[0x07] = psxBios_sys_a0_07;
3436 biosA0[0x08] = psxBios_getc;
3437 biosA0[0x09] = psxBios_putc;
3438 biosA0[0x0a] = psxBios_todigit;
3439 //biosA0[0x0b] = psxBios_atof;
3440 biosA0[0x0c] = psxBios_strtoul;
3441 biosA0[0x0d] = psxBios_strtol;
3442 biosA0[0x0e] = psxBios_abs;
3443 biosA0[0x0f] = psxBios_labs;
3444 biosA0[0x10] = psxBios_atoi;
3445 biosA0[0x11] = psxBios_atol;
3446 //biosA0[0x12] = psxBios_atob;
3447 biosA0[0x13] = psxBios_setjmp;
3448 biosA0[0x14] = psxBios_longjmp;
3449 biosA0[0x15] = psxBios_strcat;
3450 biosA0[0x16] = psxBios_strncat;
3451 biosA0[0x17] = psxBios_strcmp;
3452 biosA0[0x18] = psxBios_strncmp;
3453 biosA0[0x19] = psxBios_strcpy;
3454 biosA0[0x1a] = psxBios_strncpy;
3455 biosA0[0x1b] = psxBios_strlen;
3456 biosA0[0x1c] = psxBios_index;
3457 biosA0[0x1d] = psxBios_rindex;
3458 biosA0[0x1e] = psxBios_strchr;
3459 biosA0[0x1f] = psxBios_strrchr;
3460 biosA0[0x20] = psxBios_strpbrk;
3461 biosA0[0x21] = psxBios_strspn;
3462 biosA0[0x22] = psxBios_strcspn;
3463 biosA0[0x23] = psxBios_strtok;
3464 biosA0[0x24] = psxBios_strstr;
3465 biosA0[0x25] = psxBios_toupper;
3466 biosA0[0x26] = psxBios_tolower;
3467 biosA0[0x27] = psxBios_bcopy;
3468 biosA0[0x28] = psxBios_bzero;
3469 biosA0[0x29] = psxBios_bcmp;
3470 biosA0[0x2a] = psxBios_memcpy;
3471 biosA0[0x2b] = psxBios_memset;
3472 biosA0[0x2c] = psxBios_memmove;
3473 biosA0[0x2d] = psxBios_memcmp;
3474 biosA0[0x2e] = psxBios_memchr;
3475 biosA0[0x2f] = psxBios_rand;
3476 biosA0[0x30] = psxBios_srand;
3477 biosA0[0x31] = psxBios_qsort;
3478 //biosA0[0x32] = psxBios_strtod;
3479 biosA0[0x33] = psxBios_malloc;
3480 biosA0[0x34] = psxBios_free;
3481 //biosA0[0x35] = psxBios_lsearch;
3482 //biosA0[0x36] = psxBios_bsearch;
3483 biosA0[0x37] = psxBios_calloc;
3484 biosA0[0x38] = psxBios_realloc;
3485 biosA0[0x39] = psxBios_InitHeap;
3486 //biosA0[0x3a] = psxBios__exit;
3487 biosA0[0x3b] = psxBios_getchar;
3488 biosA0[0x3c] = psxBios_putchar;
3489 //biosA0[0x3d] = psxBios_gets;
3490 biosA0[0x3e] = psxBios_puts;
3491 biosA0[0x3f] = psxBios_printf;
3492 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3493 //biosA0[0x41] = psxBios_LoadTest;
3494 biosA0[0x42] = psxBios_Load;
3495 biosA0[0x43] = psxBios_Exec;
3496 biosA0[0x44] = psxBios_FlushCache;
3497 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3498 biosA0[0x46] = psxBios_GPU_dw;
3499 biosA0[0x47] = psxBios_mem2vram;
3500 biosA0[0x48] = psxBios_SendGPU;
3501 biosA0[0x49] = psxBios_GPU_cw;
3502 biosA0[0x4a] = psxBios_GPU_cwb;
3503 biosA0[0x4b] = psxBios_GPU_SendPackets;
3504 biosA0[0x4c] = psxBios_sys_a0_4c;
3505 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3506 //biosA0[0x4e] = psxBios_GPU_sync;
3507 //biosA0[0x4f] = psxBios_sys_a0_4f;
3508 //biosA0[0x50] = psxBios_sys_a0_50;
3509 biosA0[0x51] = psxBios_LoadExec;
3510 //biosA0[0x52] = psxBios_GetSysSp;
3511 //biosA0[0x53] = psxBios_sys_a0_53;
3512 //biosA0[0x54] = psxBios__96_init_a54;
3513 //biosA0[0x55] = psxBios__bu_init_a55;
3514 biosA0[0x56] = psxBios_CdRemove;
3515 //biosA0[0x57] = psxBios_sys_a0_57;
3516 //biosA0[0x58] = psxBios_sys_a0_58;
3517 //biosA0[0x59] = psxBios_sys_a0_59;
3518 //biosA0[0x5a] = psxBios_sys_a0_5a;
3519 //biosA0[0x5b] = psxBios_dev_tty_init;
3520 //biosA0[0x5c] = psxBios_dev_tty_open;
3521 //biosA0[0x5d] = psxBios_sys_a0_5d;
3522 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3523 //biosA0[0x5f] = psxBios_dev_cd_open;
3524 //biosA0[0x60] = psxBios_dev_cd_read;
3525 //biosA0[0x61] = psxBios_dev_cd_close;
3526 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3527 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3528 //biosA0[0x64] = psxBios_dev_cd_chdir;
3529 //biosA0[0x65] = psxBios_dev_card_open;
3530 //biosA0[0x66] = psxBios_dev_card_read;
3531 //biosA0[0x67] = psxBios_dev_card_write;
3532 //biosA0[0x68] = psxBios_dev_card_close;
3533 //biosA0[0x69] = psxBios_dev_card_firstfile;
3534 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3535 //biosA0[0x6b] = psxBios_dev_card_erase;
3536 //biosA0[0x6c] = psxBios_dev_card_undelete;
3537 //biosA0[0x6d] = psxBios_dev_card_format;
3538 //biosA0[0x6e] = psxBios_dev_card_rename;
3539 //biosA0[0x6f] = psxBios_dev_card_6f;
3540 biosA0[0x70] = psxBios__bu_init;
3541 biosA0[0x71] = psxBios__96_init;
3542 biosA0[0x72] = psxBios_CdRemove;
3543 //biosA0[0x73] = psxBios_sys_a0_73;
3544 //biosA0[0x74] = psxBios_sys_a0_74;
3545 //biosA0[0x75] = psxBios_sys_a0_75;
3546 //biosA0[0x76] = psxBios_sys_a0_76;
3547 //biosA0[0x77] = psxBios_sys_a0_77;
3548 //biosA0[0x78] = psxBios__96_CdSeekL;
3549 //biosA0[0x79] = psxBios_sys_a0_79;
3550 //biosA0[0x7a] = psxBios_sys_a0_7a;
3551 //biosA0[0x7b] = psxBios_sys_a0_7b;
3552 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3553 //biosA0[0x7d] = psxBios_sys_a0_7d;
3554 //biosA0[0x7e] = psxBios__96_CdRead;
3555 //biosA0[0x7f] = psxBios_sys_a0_7f;
3556 //biosA0[0x80] = psxBios_sys_a0_80;
3557 //biosA0[0x81] = psxBios_sys_a0_81;
3558 //biosA0[0x82] = psxBios_sys_a0_82;
3559 //biosA0[0x83] = psxBios_sys_a0_83;
3560 //biosA0[0x84] = psxBios_sys_a0_84;
3561 //biosA0[0x85] = psxBios__96_CdStop;
3562 //biosA0[0x86] = psxBios_sys_a0_86;
3563 //biosA0[0x87] = psxBios_sys_a0_87;
3564 //biosA0[0x88] = psxBios_sys_a0_88;
3565 //biosA0[0x89] = psxBios_sys_a0_89;
3566 //biosA0[0x8a] = psxBios_sys_a0_8a;
3567 //biosA0[0x8b] = psxBios_sys_a0_8b;
3568 //biosA0[0x8c] = psxBios_sys_a0_8c;
3569 //biosA0[0x8d] = psxBios_sys_a0_8d;
3570 //biosA0[0x8e] = psxBios_sys_a0_8e;
3571 //biosA0[0x8f] = psxBios_sys_a0_8f;
3572 biosA0[0x90] = hleExc0_1_2;
3573 biosA0[0x91] = hleExc0_0_2;
3574 biosA0[0x92] = hleExc0_1_1;
3575 biosA0[0x93] = hleExc0_0_1;
3576 //biosA0[0x94] = psxBios_sys_a0_94;
3577 //biosA0[0x95] = psxBios_sys_a0_95;
3578 //biosA0[0x96] = psxBios_AddCDROMDevice;
3579 //biosA0[0x97] = psxBios_AddMemCardDevide;
3580 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3581 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3582 //biosA0[0x9a] = psxBios_sys_a0_9a;
3583 //biosA0[0x9b] = psxBios_sys_a0_9b;
3584 biosA0[0x9c] = psxBios_SetConf;
3585 biosA0[0x9d] = psxBios_GetConf;
3586 //biosA0[0x9e] = psxBios_sys_a0_9e;
3587 biosA0[0x9f] = psxBios_SetMem;
3588 //biosA0[0xa0] = psxBios__boot;
3589 //biosA0[0xa1] = psxBios_SystemError;
3590 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3591 biosA0[0xa3] = psxBios_DequeueCdIntr;
3592 //biosA0[0xa4] = psxBios_sys_a0_a4;
3593 //biosA0[0xa5] = psxBios_ReadSector;
3594 biosA0[0xa6] = psxBios_get_cd_status;
3595 //biosA0[0xa7] = psxBios_bufs_cb_0;
3596 //biosA0[0xa8] = psxBios_bufs_cb_1;
3597 //biosA0[0xa9] = psxBios_bufs_cb_2;
3598 //biosA0[0xaa] = psxBios_bufs_cb_3;
3599 biosA0[0xab] = psxBios__card_info;
3600 biosA0[0xac] = psxBios__card_load;
3601 //biosA0[0axd] = psxBios__card_auto;
3602 //biosA0[0xae] = psxBios_bufs_cd_4;
3603 //biosA0[0xaf] = psxBios_sys_a0_af;
3604 //biosA0[0xb0] = psxBios_sys_a0_b0;
3605 //biosA0[0xb1] = psxBios_sys_a0_b1;
3606 //biosA0[0xb2] = psxBios_do_a_long_jmp
3607 //biosA0[0xb3] = psxBios_sys_a0_b3;
3608 biosA0[0xb4] = psxBios_GetSystemInfo;
3609 //*******************B0 CALLS****************************
3610 biosB0[0x00] = psxBios_SysMalloc;
3611 //biosB0[0x01] = psxBios_sys_b0_01;
3612 biosB0[0x02] = psxBios_SetRCnt;
3613 biosB0[0x03] = psxBios_GetRCnt;
3614 biosB0[0x04] = psxBios_StartRCnt;
3615 biosB0[0x05] = psxBios_StopRCnt;
3616 biosB0[0x06] = psxBios_ResetRCnt;
3617 biosB0[0x07] = psxBios_DeliverEvent;
3618 biosB0[0x08] = psxBios_OpenEvent;
3619 biosB0[0x09] = psxBios_CloseEvent;
3620 biosB0[0x0a] = psxBios_WaitEvent;
3621 biosB0[0x0b] = psxBios_TestEvent;
3622 biosB0[0x0c] = psxBios_EnableEvent;
3623 biosB0[0x0d] = psxBios_DisableEvent;
3624 biosB0[0x0e] = psxBios_OpenTh;
3625 biosB0[0x0f] = psxBios_CloseTh;
3626 biosB0[0x10] = psxBios_ChangeTh;
3627 //biosB0[0x11] = psxBios_psxBios_b0_11;
3628 biosB0[0x12] = psxBios_InitPAD;
3629 biosB0[0x13] = psxBios_StartPAD;
3630 biosB0[0x14] = psxBios_StopPAD;
3631 biosB0[0x15] = psxBios_PAD_init;
3632 biosB0[0x16] = psxBios_PAD_dr;
3633 biosB0[0x17] = psxBios_ReturnFromException;
3634 biosB0[0x18] = psxBios_ResetEntryInt;
3635 biosB0[0x19] = psxBios_HookEntryInt;
3636 //biosB0[0x1a] = psxBios_sys_b0_1a;
3637 //biosB0[0x1b] = psxBios_sys_b0_1b;
3638 //biosB0[0x1c] = psxBios_sys_b0_1c;
3639 //biosB0[0x1d] = psxBios_sys_b0_1d;
3640 //biosB0[0x1e] = psxBios_sys_b0_1e;
3641 //biosB0[0x1f] = psxBios_sys_b0_1f;
3642 biosB0[0x20] = psxBios_UnDeliverEvent;
3643 //biosB0[0x21] = psxBios_sys_b0_21;
3644 //biosB0[0x22] = psxBios_sys_b0_22;
3645 //biosB0[0x23] = psxBios_sys_b0_23;
3646 //biosB0[0x24] = psxBios_sys_b0_24;
3647 //biosB0[0x25] = psxBios_sys_b0_25;
3648 //biosB0[0x26] = psxBios_sys_b0_26;
3649 //biosB0[0x27] = psxBios_sys_b0_27;
3650 //biosB0[0x28] = psxBios_sys_b0_28;
3651 //biosB0[0x29] = psxBios_sys_b0_29;
3652 //biosB0[0x2a] = psxBios_sys_b0_2a;
3653 //biosB0[0x2b] = psxBios_sys_b0_2b;
3654 //biosB0[0x2c] = psxBios_sys_b0_2c;
3655 //biosB0[0x2d] = psxBios_sys_b0_2d;
3656 //biosB0[0x2e] = psxBios_sys_b0_2e;
3657 //biosB0[0x2f] = psxBios_sys_b0_2f;
3658 //biosB0[0x30] = psxBios_sys_b0_30;
3659 //biosB0[0x31] = psxBios_sys_b0_31;
3660 biosB0[0x32] = psxBios_open;
3661 biosB0[0x33] = psxBios_lseek;
3662 biosB0[0x34] = psxBios_read;
3663 biosB0[0x35] = psxBios_write;
3664 biosB0[0x36] = psxBios_close;
3665 //biosB0[0x37] = psxBios_ioctl;
3666 //biosB0[0x38] = psxBios_exit;
3667 //biosB0[0x39] = psxBios_sys_b0_39;
3668 //biosB0[0x3a] = psxBios_getc;
3669 //biosB0[0x3b] = psxBios_putc;
3670 biosB0[0x3c] = psxBios_getchar;
3671 biosB0[0x3d] = psxBios_putchar;
3672 //biosB0[0x3e] = psxBios_gets;
3673 biosB0[0x3f] = psxBios_puts;
3674 biosB0[0x40] = psxBios_cd;
3675 biosB0[0x41] = psxBios_format;
3676 biosB0[0x42] = psxBios_firstfile;
3677 biosB0[0x43] = psxBios_nextfile;
3678 biosB0[0x44] = psxBios_rename;
3679 biosB0[0x45] = psxBios_delete;
3680 //biosB0[0x46] = psxBios_undelete;
3681 //biosB0[0x47] = psxBios_AddDevice;
3682 //biosB0[0x48] = psxBios_RemoteDevice;
3683 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3684 biosB0[0x4a] = psxBios_InitCARD;
3685 biosB0[0x4b] = psxBios_StartCARD;
3686 biosB0[0x4c] = psxBios_StopCARD;
3687 //biosB0[0x4d] = psxBios_sys_b0_4d;
3688 biosB0[0x4e] = psxBios__card_write;
3689 biosB0[0x4f] = psxBios__card_read;
3690 biosB0[0x50] = psxBios__new_card;
3691 biosB0[0x51] = psxBios_Krom2RawAdd;
3692 //biosB0[0x52] = psxBios_sys_b0_52;
3693 //biosB0[0x53] = psxBios_sys_b0_53;
3694 //biosB0[0x54] = psxBios__get_errno;
3695 biosB0[0x55] = psxBios__get_error;
3696 biosB0[0x56] = psxBios_GetC0Table;
3697 biosB0[0x57] = psxBios_GetB0Table;
3698 biosB0[0x58] = psxBios__card_chan;
3699 //biosB0[0x59] = psxBios_sys_b0_59;
3700 //biosB0[0x5a] = psxBios_sys_b0_5a;
3701 biosB0[0x5b] = psxBios_ChangeClearPad;
3702 biosB0[0x5c] = psxBios__card_status;
3703 biosB0[0x5d] = psxBios__card_wait;
3704 //*******************C0 CALLS****************************
3705 biosC0[0x00] = psxBios_InitRCnt;
3706 biosC0[0x01] = psxBios_InitException;
3707 biosC0[0x02] = psxBios_SysEnqIntRP;
3708 biosC0[0x03] = psxBios_SysDeqIntRP;
3709 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3710 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3711 //biosC0[0x06] = psxBios_ExceptionHandler;
3712 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3713 biosC0[0x08] = psxBios_SysInitMemory;
3714 //biosC0[0x09] = psxBios_SysInitKMem;
3715 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3716 //biosC0[0x0b] = psxBios_SystemError;
3717 biosC0[0x0c] = psxBios_InitDefInt;
3718 //biosC0[0x0d] = psxBios_sys_c0_0d;
3719 //biosC0[0x0e] = psxBios_sys_c0_0e;
3720 //biosC0[0x0f] = psxBios_sys_c0_0f;
3721 //biosC0[0x10] = psxBios_sys_c0_10;
3722 //biosC0[0x11] = psxBios_sys_c0_11;
3723 //biosC0[0x12] = psxBios_InstallDevices;
3724 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3725 //biosC0[0x14] = psxBios_sys_c0_14;
3726 //biosC0[0x15] = psxBios__cdevinput;
3727 //biosC0[0x16] = psxBios__cdevscan;
3728 //biosC0[0x17] = psxBios__circgetc;
3729 //biosC0[0x18] = psxBios__circputc;
3730 //biosC0[0x19] = psxBios_ioabort;
3731 //biosC0[0x1a] = psxBios_sys_c0_1a
3732 //biosC0[0x1b] = psxBios_KernelRedirect;
3733 //biosC0[0x1c] = psxBios_PatchAOTable;
3734 //************** THE END ***************************************
3737 memset(FDesc, 0, sizeof(FDesc));
3738 memset(cdir, 0, sizeof(cdir));
3741 // somewhat pretend to be a SCPH1001 BIOS
3742 // some games look for these and take an exception if they're missing
3743 rom32 = (u32 *)psxR;
3744 rom32[0x100/4] = SWAP32(0x19951204);
3745 rom32[0x104/4] = SWAP32(3);
3746 romc = (char *)psxR;
3747 strcpy(romc + 0x108, "PCSX authors");
3748 strcpy(romc + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3749 strcpy(romc + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3750 strcpy(romc + 0x7ff54, "GPL-2.0-or-later");
3753 len = 0x80000 - 0x66000;
3754 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3755 len = 0x80000 - 0x69d68;
3756 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3758 // trap attempts to call bios directly
3759 rom32[0x00000/4] = HLEOP(hleop_dummy);
3760 rom32[0x00180/4] = HLEOP(hleop_dummy);
3761 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3762 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3763 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3765 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3766 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3767 Here are some examples of games not working with this fix in place :
3768 R-type won't get past the Irem logo if not implemented.
3769 Crash Team Racing will softlock after the Sony logo.
3772 ram32 = (u32 *)psxM;
3773 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3774 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3775 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3776 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3778 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3779 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3781 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3782 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3783 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3784 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3786 ram32[0x00a0/4] = HLEOP(hleop_a0);
3787 ram32[0x00b0/4] = HLEOP(hleop_b0);
3788 ram32[0x00c0/4] = HLEOP(hleop_c0);
3790 setup_tt(4, 16, 0x801fff00);
3791 DeliverEvent(0xf0000003, 0x0010);
3793 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3794 strcpy((char *)&ram32[0xeff0/4], "bu");
3796 // default exception handler chains
3797 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3798 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3799 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3800 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3801 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3802 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3803 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3804 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3808 // fill the api jumptables with fake entries as some games patch them
3809 // (or rather the funcs listed there)
3810 // also trap the destination as some "Cheats Edition" thing overrides the
3811 // dispatcher with a wrapper and then jumps to the table entries directly
3812 ptr = (u32 *)&psxM[A_A0_TABLE];
3813 for (i = 0; i < 256; i++) {
3814 ptr[i] = SWAP32(A_A0_TRAPS + i*4);
3815 ram32[A_A0_TRAPS/4 + i] = HLEOP(hleop_a0t);
3817 ptr = (u32 *)&psxM[A_B0_TABLE];
3818 for (i = 0; i < 256; i++) {
3819 ptr[i] = SWAP32(A_B0_TRAPS + i*4);
3820 ram32[A_B0_TRAPS/4 + i] = HLEOP(hleop_b0t);
3822 // B(5b) is special because games patch (sometimes even jump to)
3823 // code at fixed offsets from it, nocash lists offsets:
3824 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3825 // call: +7a0=4b70, +884=4c54, +894=4c64
3826 ptr[0x5b] = SWAP32(A_B0_5B_TRAP); // 0x43d0
3827 ram32[A_B0_5B_TRAP/4] = HLEOP(hleop_b0t);
3829 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3831 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3832 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3833 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3835 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3836 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3838 ptr = (u32 *)&psxM[A_C0_TABLE];
3839 for (i = 0; i < 256/2; i++) {
3840 ptr[i] = SWAP32(A_C0_TRAPS + i*4);
3841 ram32[A_C0_TRAPS/4 + i] = HLEOP(hleop_c0t);
3843 ptr[6] = SWAP32(A_EXCEPTION);
3846 ram32[A_A0_TRAPS/4 - 1] = HLEOP(hleop_dummy);
3847 ram32[A_B0_TRAPS/4 - 1] = HLEOP(hleop_dummy);
3848 ram32[A_C0_TRAPS/4 - 1] = HLEOP(hleop_dummy);
3849 ram32[0x7ffc/4] = HLEOP(hleop_dummy);
3850 ram32[0x8000/4] = HLEOP(hleop_execret);
3852 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3853 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3854 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3855 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3856 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3857 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3858 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3861 void psxBiosShutdown() {
3864 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3867 if (tcb_cnt != 4 || evcb_cnt != 16) {
3868 setup_tt(tcb_cnt, evcb_cnt, stack);
3869 DeliverEvent(0xf0000003, 0x0010);
3871 storeRam32(A_CONF_SP, stack);
3874 #define psxBios_PADpoll(pad) { \
3875 int i, more_data = 0; \
3876 PAD##pad##_startPoll(pad); \
3877 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
3878 pad_buf##pad[0] = more_data ? 0 : 0xff; \
3879 PAD##pad##_poll(0, &more_data); \
3881 while (more_data) { \
3882 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
3886 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3890 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3891 psxBios_ReturnFromException();
3897 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3898 // so this is only partially implemented
3899 static void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3901 u32 cdrom_dma_ack_enable = 1; // a000b93c
3902 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3905 static void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3908 //PSXBIOS_LOG("%s\n", __func__);
3910 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3911 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3912 //if (--cdrom_irq_counter == 0) // 0xa0009180
3913 // DeliverEvent(0xf0000003, 0x10);
3917 mips_return_c(ret, 20);
3920 static void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3922 u32 cdrom_irq_ack_enable = 1; // a000b938
3923 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3926 static void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3929 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3930 PSXBIOS_LOG("%s TODO\n", __func__);
3933 mips_return_c(ret, 20);
3936 static void hleExc0_2_2_syscall() // not in any A/B/C table
3938 u32 tcbPtr = loadRam32(A_TT_PCB);
3939 TCB *tcb = loadRam32ptr(tcbPtr);
3940 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3942 if (code != R3000E_Syscall) {
3944 DeliverEvent(0xf0000010, 0x1000);
3945 //psxBios_SystemErrorUnresolvedException();
3947 mips_return_c(0, 17);
3951 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3952 tcb->epc += SWAP32(4);
3953 switch (SWAP32(tcb->reg[4])) { // a0
3957 case 1: { // EnterCritical - disable irqs
3958 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3959 tcb->reg[2] = SWAP32(was_enabled);
3960 tcb->sr &= SWAP32(~0x404);
3963 case 2: // ExitCritical - enable irqs
3964 tcb->sr |= SWAP32(0x404);
3967 case 3: { // ChangeThreadSubFunction
3968 u32 tcbPtr = loadRam32(A_TT_PCB);
3969 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3973 DeliverEvent(0xf0000010, 0x4000);
3977 psxBios_ReturnFromException();
3980 static void hleExc1_0_1(void)
3982 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3983 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3986 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3989 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3990 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3993 mips_return_c(ret, 22);
3996 static void hleExc1_0_2(void)
3998 handle_chain_1_x_2(3, 0); // IRQ0 vblank
4001 static void hleExc1_1_1(void)
4003 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
4004 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
4007 static void hleExc1_1_2(void)
4009 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
4012 static void hleExc1_2_1(void)
4014 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
4015 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
4018 static void hleExc1_2_2(void)
4020 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
4023 static void hleExc1_3_1(void)
4025 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
4026 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
4029 static void hleExc1_3_2(void)
4031 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
4034 static void hleExc3_0_2_defint(void)
4036 static const struct {
4047 { 6, 6 }, // rcnt2 (bug)
4052 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
4053 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
4054 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
4059 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
4062 static void hleExcPadCard1(void)
4064 if (loadRam32(A_PAD_IRQR_ENA)) {
4065 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
4066 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
4071 if (loadRam32(A_PAD_DR_DST))
4074 if (loadRam32(A_PAD_ACK_VBL))
4075 psxHwWrite16(0x1f801070, ~1);
4076 if (loadRam32(A_CARD_IRQR_ENA)) {
4080 mips_return_c(0, 18);
4083 static void hleExcPadCard2(void)
4085 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
4086 mips_return_c(ret, 15);
4089 void psxBiosException() {
4090 u32 tcbPtr = loadRam32(A_TT_PCB);
4091 u32 *chains = loadRam32ptr(A_TT_ExCB);
4092 TCB *tcb = loadRam32ptr(tcbPtr);
4098 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
4099 for (i = 4; i < 31; i++) {
4102 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
4104 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
4105 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
4106 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
4107 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
4108 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
4109 sp = fp = loadRam32(A_EXC_SP);
4112 assert(!psxRegs.cpuInRecursion);
4114 // do the chains (always 4)
4115 for (c = lim = 0; c < 4; c++) {
4116 if (chains[c * 2] == 0)
4118 ptr = SWAP32(chains[c * 2]);
4119 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
4120 chain = castRam32ptr(ptr);
4125 softCallInException(SWAP32(chain[2]));
4126 if (returned_from_exception())
4129 if (v0 == 0 || chain[1] == 0)
4131 softCallInException(SWAP32(chain[1]));
4132 if (returned_from_exception())
4138 // return from exception (custom or default)
4140 ptr = loadRam32(A_EEXIT_PTR);
4141 if (ptr != A_EEXIT_DEF) {
4142 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4143 longjmp_load(jmp_buf);
4148 psxBios_ReturnFromException();
4152 static void hleDummy() {
4153 log_unhandled("hleDummy called @%08x ra=%08x\n", psxRegs.pc - 4, ra);
4155 psxRegs.cycle += 1000;
4160 static void hleA0() {
4161 u32 call = t1 & 0xff;
4162 u32 entry = loadRam32(A_A0_TABLE + call * 4);
4165 if (call < 192 && entry != A_A0_TRAPS + call * 4) {
4166 PSXBIOS_LOG("custom A%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4167 call, biosA0n[call], a0, entry, ra);
4170 PSXBIOS_LOG(" -> %08x\n", v0);
4172 else if (biosA0[call])
4175 //printf("A(%02x) -> %x\n", call, v0);
4179 static void hleB0() {
4180 u32 call = t1 & 0xff;
4181 u32 entry = loadRam32(A_B0_TABLE + call * 4);
4186 is_custom = entry != A_B0_5B_TRAP;
4188 is_custom = entry != A_B0_TRAPS + call * 4;
4190 PSXBIOS_LOG("custom B%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4191 call, biosB0n[call], a0, entry, ra);
4194 PSXBIOS_LOG(" -> %08x\n", v0);
4196 else if (biosB0[call])
4199 //printf("B(%02x) -> %x\n", call, v0);
4203 static void hleC0() {
4204 u32 call = t1 & 0xff;
4205 u32 entry = loadRam32(A_C0_TABLE + call * 4);
4208 if (call < 128 && entry != A_C0_TRAPS + call * 4) {
4209 PSXBIOS_LOG("custom C%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4210 call, biosC0n[call], a0, entry, ra);
4213 PSXBIOS_LOG(" -> %08x\n", v0);
4215 else if (biosC0[call])
4218 //printf("C(%02x) -> %x\n", call, v0);
4222 static void hleA0t() {
4223 u32 call = (pc0 - A_A0_TRAPS) / 4 - 1;
4224 if (call >= 256u || !biosA0[call]) {
4225 log_unhandled("unexpected A trap @%08x ra=%08x\n", pc0 - 4, ra);
4226 mips_return_void_c(1000);
4231 //printf("A(%02x) -> %x\n", call, v0);
4235 static void hleB0t() {
4236 u32 call = (pc0 - A_B0_TRAPS) / 4 - 1;
4237 if (pc0 - 4 == A_B0_5B_TRAP)
4239 if (call >= 256u || !biosB0[call]) {
4240 log_unhandled("unexpected B trap @%08x ra=%08x\n", pc0 - 4, ra);
4241 mips_return_void_c(1000);
4246 //printf("B(%02x) -> %x\n", call, v0);
4250 static void hleC0t() {
4251 u32 call = (pc0 - A_C0_TRAPS) / 4 - 1;
4252 if (call >= 128u || !biosC0[call]) {
4253 log_unhandled("unexpected C trap @%08x ra=%08x\n", pc0 - 4, ra);
4254 mips_return_void_c(1000);
4259 //printf("C(%02x) -> %x\n", call, v0);
4263 // currently not used
4264 static void hleBootstrap() {
4269 static void hleExecRet() {
4270 const EXEC *header = (EXEC *)PSXM(s0);
4272 PSXBIOS_LOG("ExecRet %x: %x\n", s0, header->ret);
4274 ra = SWAP32(header->ret);
4275 sp = SWAP32(header->_sp);
4276 fp = SWAP32(header->_fp);
4277 gp = SWAP32(header->_gp);
4278 s0 = SWAP32(header->base);
4284 void (* const psxHLEt[hleop_count_])() = {
4285 hleDummy, hleA0, hleB0, hleC0,
4286 hleBootstrap, hleExecRet, psxBiosException, hleDummy,
4287 hleExc0_0_1, hleExc0_0_2,
4288 hleExc0_1_1, hleExc0_1_2, hleExc0_2_2_syscall,
4289 hleExc1_0_1, hleExc1_0_2,
4290 hleExc1_1_1, hleExc1_1_2,
4291 hleExc1_2_1, hleExc1_2_2,
4292 hleExc1_3_1, hleExc1_3_2,
4294 hleExcPadCard1, hleExcPadCard2,
4295 hleA0t, hleB0t, hleC0t,
4298 void psxBiosCheckExe(u32 t_addr, u32 t_size, int loading_state)
4300 // lw $v0, 0x10($sp)
4303 // sw $v0, 0x10($sp)
4304 // lw $v0, 0x10($sp)
4306 // bne $v0, $v1, not_timeout
4309 static const u8 pattern[] = {
4310 0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
4311 0xFF, 0xFF, 0x42, 0x24, 0x10, 0x00, 0xA2, 0xAF,
4312 0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
4313 0x0C, 0x00, 0x43, 0x14, 0x00, 0x00, 0x00, 0x00,
4315 u32 start = t_addr & 0x1ffffc;
4316 u32 end = (start + t_size) & 0x1ffffc;
4317 u32 buf[sizeof(pattern) / sizeof(u32)];
4318 const u32 *r32 = (u32 *)(psxM + start);
4326 memcpy(buf, pattern, sizeof(buf));
4327 for (i = 0; i < t_size / 4; i += j + 1) {
4328 for (j = 0; j < sizeof(buf) / sizeof(buf[0]); j++)
4329 if (r32[i + j] != buf[j])
4331 if (j != sizeof(buf) / sizeof(buf[0]))
4334 if ((SWAP32(r32[i + j]) >> 16) != 0x3c04) // lui
4337 SysPrintf("HLE vsync @%08x\n", start + i * 4);
4338 psxRegs.biosBranchCheck = (t_addr & 0xa01ffffc) + i * 4;
4342 void psxBiosCheckBranch(void)
4346 static u32 cycles_prev, v0_prev;
4347 u32 cycles_passed, waste_cycles;
4348 u32 loops, v0_expect = v0_prev - 1;
4352 cycles_passed = psxRegs.cycle - cycles_prev;
4353 cycles_prev = psxRegs.cycle;
4355 if (cycles_passed < 10 || cycles_passed > 50 || v0 != v0_expect)
4358 waste_cycles = schedule_timeslice() - psxRegs.cycle;
4359 loops = waste_cycles / cycles_passed;
4363 psxRegs.cycle += loops * cycles_passed;
4364 //printf("c %4u %d\n", loops, cycles_passed);
4368 #define bfreeze(ptr, size) { \
4369 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4370 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4374 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4375 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4377 void psxBiosFreeze(int Mode) {