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"
42 //#define PSXBIOS_LOG printf
43 #define PSXBIOS_LOG(...)
46 #define PTR_1 (void *)(size_t)1
48 char *biosA0n[256] = {
50 "open", "lseek", "read", "write",
51 "close", "ioctl", "exit", "sys_a0_07",
52 "getc", "putc", "todigit", "atof",
53 "strtoul", "strtol", "abs", "labs",
55 "atoi", "atol", "atob", "setjmp",
56 "longjmp", "strcat", "strncat", "strcmp",
57 "strncmp", "strcpy", "strncpy", "strlen",
58 "index", "rindex", "strchr", "strrchr",
60 "strpbrk", "strspn", "strcspn", "strtok",
61 "strstr", "toupper", "tolower", "bcopy",
62 "bzero", "bcmp", "memcpy", "memset",
63 "memmove", "memcmp", "memchr", "rand",
65 "srand", "qsort", "strtod", "malloc",
66 "free", "lsearch", "bsearch", "calloc",
67 "realloc", "InitHeap", "_exit", "getchar",
68 "putchar", "gets", "puts", "printf",
70 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
71 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
72 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
73 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
75 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
76 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
77 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
78 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
80 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
81 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
82 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
83 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
85 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
86 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
87 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
88 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
90 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
91 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
92 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
93 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
95 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
96 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
97 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
98 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
100 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
101 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
102 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
103 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
105 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
109 char *biosB0n[256] = {
111 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
112 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
113 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
114 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
116 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
117 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
118 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
119 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
121 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
122 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
123 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
124 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
126 "sys_b0_30", "sys_b0_31", "open", "lseek",
127 "read", "write", "close", "ioctl",
128 "exit", "sys_b0_39", "getc", "putc",
129 "getchar", "putchar", "gets", "puts",
131 "cd", "format", "firstfile", "nextfile",
132 "rename", "delete", "undelete", "AddDevice",
133 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
134 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
136 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
137 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
138 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
139 "_card_status", "_card_wait",
142 char *biosC0n[256] = {
144 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
145 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
146 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
147 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
149 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
150 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
151 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
155 //#define r0 (psxRegs.GPR.n.r0)
156 #define at (psxRegs.GPR.n.at)
157 #define v0 (psxRegs.GPR.n.v0)
158 #define v1 (psxRegs.GPR.n.v1)
159 #define a0 (psxRegs.GPR.n.a0)
160 #define a1 (psxRegs.GPR.n.a1)
161 #define a2 (psxRegs.GPR.n.a2)
162 #define a3 (psxRegs.GPR.n.a3)
163 #define t0 (psxRegs.GPR.n.t0)
164 #define t1 (psxRegs.GPR.n.t1)
165 #define t2 (psxRegs.GPR.n.t2)
166 #define t3 (psxRegs.GPR.n.t3)
167 #define t4 (psxRegs.GPR.n.t4)
168 #define t5 (psxRegs.GPR.n.t5)
169 #define t6 (psxRegs.GPR.n.t6)
170 #define t7 (psxRegs.GPR.n.t7)
171 #define t8 (psxRegs.GPR.n.t8)
172 #define t9 (psxRegs.GPR.n.t9)
173 #define s0 (psxRegs.GPR.n.s0)
174 #define s1 (psxRegs.GPR.n.s1)
175 #define s2 (psxRegs.GPR.n.s2)
176 #define s3 (psxRegs.GPR.n.s3)
177 #define s4 (psxRegs.GPR.n.s4)
178 #define s5 (psxRegs.GPR.n.s5)
179 #define s6 (psxRegs.GPR.n.s6)
180 #define s7 (psxRegs.GPR.n.s7)
181 #define k0 (psxRegs.GPR.n.k0)
182 #define k1 (psxRegs.GPR.n.k1)
183 #define gp (psxRegs.GPR.n.gp)
184 #define sp (psxRegs.GPR.n.sp)
185 #define fp (psxRegs.GPR.n.fp)
186 #define ra (psxRegs.GPR.n.ra)
187 #define pc0 (psxRegs.pc)
189 #define Ra0 ((char *)PSXM(a0))
190 #define Ra1 ((char *)PSXM(a1))
191 #define Ra2 ((char *)PSXM(a2))
192 #define Ra3 ((char *)PSXM(a3))
193 #define Rv0 ((char *)PSXM(v0))
194 #define Rsp ((char *)PSXM(sp))
205 #define EvStUNUSED 0x0000
206 #define EvStDISABLED 0x1000
207 #define EvStACTIVE 0x2000
208 #define EvStALREADY 0x4000
210 #define EvMdCALL 0x1000
211 #define EvMdMARK 0x2000
234 u32 _sp, _fp, _gp, ret, base;
254 // todo: FileDesc layout is wrong
255 // todo: get rid of these globals
256 static FileDesc FDesc[32];
257 static char ffile[64];
259 static char cdir[8*8+8];
262 // fixed RAM offsets, SCPH1001 compatible
263 #define A_TT_ExCB 0x0100
264 #define A_TT_PCB 0x0108
265 #define A_TT_TCB 0x0110
266 #define A_TT_EvCB 0x0120
267 #define A_A0_TABLE 0x0200
268 #define A_B0_TABLE 0x0874
269 #define A_C0_TABLE 0x0674
270 #define A_SYSCALL 0x0650
271 #define A_EXCEPTION 0x0c80
272 #define A_EXC_SP 0x6cf0
273 #define A_EEXIT_DEF 0x6cf4
274 #define A_KMALLOC_PTR 0x7460
275 #define A_KMALLOC_SIZE 0x7464
276 #define A_KMALLOC_END 0x7468
277 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
278 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
279 #define A_CARD_IRQR_ENA 0x74bc // same for card
280 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
281 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
282 #define A_PAD_IN_LEN 0x74d8
283 #define A_PAD_OUT_LEN 0x74e0
284 #define A_PAD_DR_DST 0x74c4
285 #define A_CARD_CHAN1 0x7500
286 #define A_PAD_DR_BUF1 0x7570
287 #define A_PAD_DR_BUF2 0x7598
288 #define A_EEXIT_PTR 0x75d0
289 #define A_EXC_STACK 0x85d8 // exception stack top
290 #define A_RCNT_VBL_ACK 0x8600
291 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
292 #define A_HEAP_BASE 0x9000
293 #define A_HEAP_SIZE 0x9004
294 #define A_HEAP_END 0x9008
295 #define A_HEAP_INIT_FLG 0x900c
296 #define A_RND_SEED 0x9010
297 #define A_HEAP_FRSTCHNK 0xb060
298 #define A_HEAP_CURCHNK 0xb064
299 #define A_CONF_TCB 0xb940
300 #define A_CONF_EvCB 0xb944
301 #define A_CONF_SP 0xb948
302 #define A_CD_EVENTS 0xb9b8
303 #define A_EXC_GP 0xf450
305 #define A_A0_DUMMY 0x1010
306 #define A_B0_DUMMY 0x2010
307 #define A_C0_DUMMY 0x3010
308 #define A_B0_5B_DUMMY 0x43d0
310 #define HLEOP(n) SWAPu32((0x3b << 26) | (n));
312 static u32 loadRam32(u32 addr)
314 assert(!(addr & 0x5f800000));
315 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
318 static void *castRam8ptr(u32 addr)
320 assert(!(addr & 0x5f800000));
321 return psxM + (addr & 0x1fffff);
324 static void *castRam32ptr(u32 addr)
326 assert(!(addr & 0x5f800003));
327 return psxM + (addr & 0x1ffffc);
330 static void *loadRam8ptr(u32 addr)
332 return castRam8ptr(loadRam32(addr));
335 static void *loadRam32ptr(u32 addr)
337 return castRam32ptr(loadRam32(addr));
340 static void storeRam8(u32 addr, u8 d)
342 assert(!(addr & 0x5f800000));
343 *((u8 *)psxM + (addr & 0x1fffff)) = d;
346 static void storeRam32(u32 addr, u32 d)
348 assert(!(addr & 0x5f800000));
349 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
352 static void mips_return(u32 val)
358 static void mips_return_void(void)
363 static void use_cycles(u32 cycle)
365 psxRegs.cycle += cycle * 2;
368 static void mips_return_c(u32 val, u32 cycle)
374 static void mips_return_void_c(u32 cycle)
380 static int returned_from_exception(void)
382 // 0x80000080 means it took another exception just after return
383 return pc0 == k0 || pc0 == 0x80000080;
386 static inline void softCall(u32 pc) {
388 u32 ssr = psxRegs.CP0.n.SR;
392 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
394 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
396 while (pc0 != 0x80001000 && ++lim < 1000000)
397 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
399 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
402 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
404 psxRegs.CP0.n.SR |= ssr & 0x404;
407 static inline void softCallInException(u32 pc) {
412 assert(ra != 0x80001000);
413 if (ra == 0x80001000)
417 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
419 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
420 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
422 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
425 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
426 if (pc0 == 0x80001000)
430 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
431 static u32 DeliverEvent(u32 class, u32 spec);
432 static u32 UnDeliverEvent(u32 class, u32 spec);
433 static void CloseEvent(u32 ev);
438 // System calls A0 */
441 #define buread(Ra1, mcd, length) { \
442 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); \
443 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
444 memcpy(Ra1, ptr, length); \
445 psxCpu->Clear(a1, (length + 3) / 4); \
446 if (FDesc[1 + mcd].mode & 0x8000) { \
447 DeliverEvent(0xf0000011, 0x0004); \
448 DeliverEvent(0xf4000001, 0x0004); \
451 FDesc[1 + mcd].offset += v0; \
454 #define buwrite(Ra1, mcd, length) { \
455 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
456 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
457 ptr = Mcd##mcd##Data + offset; \
458 memcpy(ptr, Ra1, length); \
459 FDesc[1 + mcd].offset += length; \
460 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
461 if (FDesc[1 + mcd].mode & 0x8000) { \
462 DeliverEvent(0xf0000011, 0x0004); \
463 DeliverEvent(0xf4000001, 0x0004); \
468 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
469 /* For some strange reason, the returned character is sign-expanded; */
470 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
471 /* TODO FIX ME : Properly implement this behaviour */
472 void psxBios_getc(void) // 0x03, 0x35
477 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
481 if (pa1 != INVALID_PTR) {
483 case 2: buread(pa1, 1, 1); break;
484 case 3: buread(pa1, 2, 1); break;
491 /* Copy of psxBios_write, except size is 1. */
492 void psxBios_putc(void) // 0x09, 0x3B
497 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
500 if (pa1 == INVALID_PTR) {
505 if (a0 == 1) { // stdout
506 char *ptr = (char *)pa1;
510 printf("%c", *ptr++); a2--;
516 case 2: buwrite(pa1, 1, 1); break;
517 case 3: buwrite(pa1, 2, 1); break;
523 void psxBios_todigit(void) // 0x0a
527 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
530 if (c >= 0x30 && c < 0x3A) {
533 else if (c > 0x60 && c < 0x7B) {
536 else if (c > 0x40 && c < 0x5B) {
539 else if (c >= 0x80) {
550 void psxBios_abs() { // 0x0e
551 if ((s32)a0 < 0) v0 = -(s32)a0;
556 void psxBios_labs() { // 0x0f
560 void psxBios_atoi() { // 0x10
562 char *p = (char *)Ra0;
566 case ' ': case '\t': continue;
573 while (*p >= '0' && *p <= '9') {
574 n = n * 10 + *p++ - '0';
581 void psxBios_atol() { // 0x11
591 static void psxBios_setjmp() { // 0x13
592 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
595 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
597 jmp_buf->ra_ = SWAP32(ra);
598 jmp_buf->sp_ = SWAP32(sp);
599 jmp_buf->fp_ = SWAP32(fp);
600 for (i = 0; i < 8; i++) // s0-s7
601 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
602 jmp_buf->gp_ = SWAP32(gp);
604 mips_return_c(0, 15);
607 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
611 ra = SWAP32(jmp_buf->ra_);
612 sp = SWAP32(jmp_buf->sp_);
613 fp = SWAP32(jmp_buf->fp_);
614 for (i = 0; i < 8; i++) // s0-s7
615 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
616 gp = SWAP32(jmp_buf->gp_);;
619 void psxBios_longjmp() { // 0x14
620 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
622 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
623 longjmp_load(jmp_buf);
624 mips_return_c(a1, 15);
627 void psxBios_strcat() { // 0x15
628 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
631 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
633 if (a0 == 0 || a1 == 0)
641 while ((*p1++ = *p2++) != '\0');
646 void psxBios_strncat() { // 0x16
647 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
651 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
653 if (a0 == 0 || a1 == 0)
661 while ((*p1++ = *p2++) != '\0') {
671 void psxBios_strcmp() { // 0x17
672 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
674 if (a0 == 0 && a1 == 0)
680 else if (a0 == 0 && a1 != 0)
686 else if (a0 != 0 && a1 == 0)
693 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
696 while (*p1 == *p2++) {
715 void psxBios_strncmp() { // 0x18
716 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
718 if (a0 == 0 && a1 == 0)
724 else if (a0 == 0 && a1 != 0)
730 else if (a0 != 0 && a1 == 0)
737 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
740 while (--n >= 0 && *p1 == *p2++) {
744 v1 = a2 - ((a2-n) - 1);
752 v0 = (n < 0 ? 0 : *p1 - *--p2);
754 v1 = a2 - ((a2-n) - 1);
760 void psxBios_strcpy() { // 0x19
761 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
762 if (a0 == 0 || a1 == 0)
768 while ((*p1++ = *p2++) != '\0');
773 void psxBios_strncpy() { // 0x1a
774 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
776 if (a0 == 0 || a1 == 0)
782 for (i = 0; i < n; i++) {
783 if ((*p1++ = *p2++) == '\0') {
795 void psxBios_strlen() { // 0x1b
796 char *p = (char *)Ra0;
807 void psxBios_index() { // 0x1c
808 char *p = (char *)Ra0;
818 v0 = a0 + (p - (char *)Ra0);
822 } while (*p++ != '\0');
827 void psxBios_rindex() { // 0x1d
828 char *p = (char *)Ra0;
838 v0 = a0 + (p - (char *)Ra0);
839 } while (*p++ != '\0');
844 void psxBios_strchr() { // 0x1e
848 void psxBios_strrchr() { // 0x1f
852 void psxBios_strpbrk() { // 0x20
853 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
855 while ((c = *p1++) != '\0') {
856 for (scanp = p2; (sc = *scanp++) != '\0';) {
858 v0 = a0 + (p1 - 1 - (char *)Ra0);
865 // BUG: return a0 instead of NULL if not found
869 void psxBios_strspn() { // 0x21
872 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
873 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
874 if (*p2 == '\0') break;
877 v0 = p1 - (char *)Ra0; pc0 = ra;
880 void psxBios_strcspn() { // 0x22
883 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
884 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
885 if (*p2 != '\0') break;
888 v0 = p1 - (char *)Ra0; pc0 = ra;
891 void psxBios_strtok() { // 0x23
892 char *pcA0 = (char *)Ra0;
893 char *pcRet = strtok(pcA0, (char *)Ra1);
895 v0 = a0 + pcRet - pcA0;
901 void psxBios_strstr() { // 0x24
902 char *p = (char *)Ra0, *p1, *p2;
908 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
913 v0 = a0 + (p - (char *)Ra0);
924 void psxBios_toupper() { // 0x25
925 v0 = (s8)(a0 & 0xff);
926 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
930 void psxBios_tolower() { // 0x26
931 v0 = (s8)(a0 & 0xff);
932 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
936 static void do_memset(u32 dst, u32 v, s32 len)
942 if (db != INVALID_PTR)
946 psxCpu->Clear(dst, (len + 3) / 4);
949 static void do_memcpy(u32 dst, u32 src, s32 len)
951 u32 d = dst, s = src;
954 const u8 *sb = PSXM(s);
956 if (db != INVALID_PTR && sb != INVALID_PTR)
961 psxCpu->Clear(dst, (len + 3) / 4);
964 static void psxBios_memcpy();
966 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
967 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
968 u32 ret = a0, cycles = 0;
969 if (a0 == 0) // ...but it checks src this time
976 do_memcpy(a1, a0, a2);
982 mips_return_c(ret, cycles + 5);
985 static void psxBios_bzero() { // 0x28
986 /* Same as memset here (See memset below) */
987 u32 ret = a0, cycles;
988 if (a0 == 0 || (s32)a1 <= 0)
993 do_memset(a0, 0, a1);
997 // todo: many more cycles due to uncached bios mem
998 mips_return_c(ret, cycles + 5);
1001 void psxBios_bcmp() { // 0x29
1002 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
1004 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
1006 while ((s32)a2-- > 0) {
1007 if (*p1++ != *p2++) {
1008 v0 = *p1 - *p2; // BUG: compare the NEXT byte
1017 static void psxBios_memcpy() { // 0x2a
1018 u32 ret = a0, cycles = 0;
1021 mips_return_c(0, 4);
1026 do_memcpy(a0, a1, a2);
1032 mips_return_c(ret, cycles + 5);
1035 static void psxBios_memset() { // 0x2b
1036 u32 ret = a0, cycles;
1037 if (a0 == 0 || (s32)a2 <= 0)
1039 mips_return_c(0, 6);
1042 do_memset(a0, a1, a2);
1046 // todo: many more cycles due to uncached bios mem
1047 mips_return_c(ret, cycles + 5);
1050 void psxBios_memmove() { // 0x2c
1051 u32 ret = a0, cycles = 0;
1054 mips_return_c(0, 4);
1058 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1059 u32 dst = a0, len = a2 + 1;
1062 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1063 const u8 *sb = PSXM(a1);
1065 if (db != INVALID_PTR && sb != INVALID_PTR)
1071 psxCpu->Clear(dst, (len + 3) / 4);
1072 cycles = 10 + len * 8;
1073 } else if ((s32)a2 > 0) {
1074 do_memcpy(a0, a1, a2);
1080 mips_return_c(ret, cycles + 5);
1083 void psxBios_memcmp() { // 0x2d
1087 void psxBios_memchr() { // 0x2e
1088 char *p = (char *)Ra0;
1090 if (a0 == 0 || a2 > 0x7FFFFFFF)
1096 while ((s32)a2-- > 0) {
1097 if (*p++ != (s8)a1) continue;
1098 v0 = a0 + (p - (char *)Ra0 - 1);
1106 static void psxBios_rand() { // 0x2f
1107 u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1108 storeRam32(A_RND_SEED, s);
1110 mips_return_c((s >> 16) & 0x7fff, 12+37);
1113 static void psxBios_srand() { // 0x30
1114 storeRam32(A_RND_SEED, a0);
1115 mips_return_void_c(3);
1118 static u32 qscmpfunc, qswidth;
1120 static inline int qscmp(char *a, char *b) {
1123 a0 = sa0 + (a - (char *)PSXM(sa0));
1124 a1 = sa0 + (b - (char *)PSXM(sa0));
1126 softCall(qscmpfunc);
1132 static inline void qexchange(char *i, char *j) {
1143 static inline void q3exchange(char *i, char *j, char *k) {
1155 static void qsort_main(char *a, char *l) {
1156 char *i, *j, *lp, *hp;
1161 if ((n = l - a) <= qswidth)
1163 n = qswidth * (n / (2 * qswidth));
1169 if ((c = qscmp(i, lp)) == 0) {
1170 qexchange(i, lp -= qswidth);
1181 if ((c = qscmp(hp, j)) == 0) {
1182 qexchange(hp += qswidth, j);
1187 q3exchange(i, hp += qswidth, j);
1201 if (lp - a >= l - hp) {
1202 qsort_main(hp + qswidth, l);
1211 q3exchange(j, lp -= qswidth, i);
1216 void psxBios_qsort() { // 0x31
1219 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1224 static int malloc_heap_grow(u32 size) {
1225 u32 heap_addr, heap_end, heap_addr_new;
1227 heap_addr = loadRam32(A_HEAP_BASE);
1228 heap_end = loadRam32(A_HEAP_END);
1229 heap_addr_new = heap_addr + 4 + size;
1230 if (heap_addr_new >= heap_end)
1232 storeRam32(A_HEAP_BASE, heap_addr_new);
1233 storeRam32(heap_addr - 4, size | 1);
1234 storeRam32(heap_addr + size, ~1); // terminator
1238 static void psxBios_malloc() { // 0x33
1239 u32 size = (a0 + 3) & ~3;
1240 u32 limit = 32*1024;
1244 PSXBIOS_LOG("psxBios_%s %d\n", biosA0n[0x33], a0);
1246 if (!loadRam32(A_HEAP_INIT_FLG)) {
1247 u32 heap_addr = loadRam32(A_HEAP_BASE);
1248 storeRam32(heap_addr, ~1);
1249 storeRam32(A_HEAP_FRSTCHNK, heap_addr);
1250 storeRam32(A_HEAP_CURCHNK, heap_addr);
1251 storeRam32(A_HEAP_BASE, heap_addr + 4);
1252 if (malloc_heap_grow(size)) {
1253 PSXBIOS_LOG("malloc: init OOM\n");
1254 mips_return_c(0, 20);
1257 storeRam32(A_HEAP_INIT_FLG, 1);
1260 for (i = 0; tries > 0 && i < limit; i++)
1262 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1263 u32 chunk_hdr = loadRam32(chunk);
1264 u32 next_chunk = chunk + 4 + (chunk_hdr & ~3);
1265 u32 next_chunk_hdr = loadRam32(next_chunk);
1267 //printf(" c %08x %08x\n", chunk, chunk_hdr);
1268 if (chunk_hdr & 1) {
1270 if (chunk_hdr > (size | 1)) {
1272 u32 p2size = (chunk_hdr & ~3) - size - 4;
1273 storeRam32(chunk + 4 + size, p2size | 1);
1274 chunk_hdr = size | 1;
1276 if (chunk_hdr == (size | 1)) {
1277 storeRam32(chunk, size);
1281 if (next_chunk_hdr & 1) {
1283 u32 msize = (chunk_hdr & ~3) + 4 + (next_chunk_hdr & ~3);
1284 storeRam32(chunk, msize | 1);
1288 if (chunk_hdr == ~1) {
1291 storeRam32(A_HEAP_CURCHNK, loadRam32(A_HEAP_FRSTCHNK));
1295 // go to the next chunk
1296 storeRam32(A_HEAP_CURCHNK, next_chunk);
1302 else if (tries == 0 && malloc_heap_grow(size))
1305 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1306 storeRam32(chunk, loadRam32(chunk) & ~3);
1310 PSXBIOS_LOG(" -> %08x\n", ret);
1311 mips_return_c(ret, 40);
1314 static void psxBios_free() { // 0x34
1315 PSXBIOS_LOG("psxBios_%s %x (%d bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1316 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1317 mips_return_void_c(5);
1320 static void psxBios_calloc() { // 0x37
1322 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1324 a0 = size = a0 * a1;
1328 a0 = ret; a1 = size;
1331 mips_return_c(ret, 21);
1334 void psxBios_realloc() { // 0x38
1338 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1342 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1347 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1352 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1353 /* Note that it is not quite implemented this way here. */
1363 /* InitHeap(void *block , int n) */
1364 static void psxBios_InitHeap() { // 0x39
1365 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1367 storeRam32(A_HEAP_BASE, a0);
1368 storeRam32(A_HEAP_SIZE, a1);
1369 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1370 storeRam32(A_HEAP_INIT_FLG, 0);
1373 mips_return_void_c(14);
1376 void psxBios_getchar() { //0x3b
1377 v0 = getchar(); pc0 = ra;
1380 static void psxBios_printf_psxout() { // 0x3f
1383 u32 save[4] = { 0, };
1389 if (psp != INVALID_PTR) {
1390 memcpy(save, psp, 4 * 4);
1391 psxMu32ref(sp) = SWAP32((u32)a0);
1392 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1393 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1394 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1406 tmp2[j++] = Ra0[i]; goto _start;
1408 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1419 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1423 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1429 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1431 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1433 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1435 *ptmp++ = Ra0[i]; break;
1445 if (psp != INVALID_PTR)
1446 memcpy(psp, save, 4 * 4);
1449 SysPrintf("%s", tmp);
1452 void psxBios_printf() { // 0x3f
1453 psxBios_printf_psxout();
1457 static void psxBios_cd() { // 0x40
1458 const char *p, *dir = castRam8ptr(a0);
1459 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x40], a0, dir);
1460 if ((p = strchr(dir, ':')))
1464 snprintf(cdir, sizeof(cdir), "%s", dir);
1465 mips_return_c(1, 100);
1468 static void psxBios_format() { // 0x41
1469 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x41], a0, Ra0);
1470 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1472 CreateMcd(Config.Mcd1);
1473 LoadMcd(1, Config.Mcd1);
1476 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1478 CreateMcd(Config.Mcd2);
1479 LoadMcd(2, Config.Mcd2);
1489 static void psxBios_SystemErrorUnresolvedException() {
1490 if (floodchk != 0x12340a40) { // prevent log flood
1491 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1492 floodchk = 0x12340a40;
1494 mips_return_void_c(1000);
1497 static void FlushCache() {
1498 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1499 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1501 // runs from uncached mem so tons of cycles
1506 * long Load(char *name, struct EXEC *header);
1509 void psxBios_Load() { // 0x42
1517 PSXBIOS_LOG("psxBios_%s %x(%s), %x\n", biosA0n[0x42], a0, pa0, a1);
1518 if (pa0 == INVALID_PTR || pa1 == INVALID_PTR) {
1522 if ((p = strchr(pa0, ':')))
1527 snprintf(path, sizeof(path), "%s\\%s", cdir, (char *)pa0);
1529 snprintf(path, sizeof(path), "%s", (char *)pa0);
1531 if (LoadCdromFile(path, &eheader) == 0) {
1532 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1533 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1537 PSXBIOS_LOG(" -> %d\n", v0);
1543 * int Exec(struct EXEC *header , int argc , char **argv);
1546 void psxBios_Exec() { // 43
1547 EXEC *header = (EXEC *)castRam32ptr(a0);
1551 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1553 header->_sp = SWAP32(sp);
1554 header->_fp = SWAP32(fp);
1555 header->_sp = SWAP32(sp);
1556 header->_gp = SWAP32(gp);
1557 header->ret = SWAP32(ra);
1558 header->base = SWAP32(s0);
1560 ptr = SWAP32(header->b_addr);
1561 len = SWAP32(header->b_size);
1567 if (header->S_addr != 0)
1568 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1570 gp = SWAP32(header->gp0);
1578 pc0 = SWAP32(header->_pc0);
1581 static void psxBios_FlushCache() { // 44
1582 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1587 void psxBios_GPU_dw() { // 0x46
1592 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1595 GPU_writeData(0xa0000000);
1596 GPU_writeData((a1<<0x10)|(a0&0xffff));
1597 GPU_writeData((a3<<0x10)|(a2&0xffff));
1599 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1602 GPU_writeData(SWAPu32(*ptr++));
1608 void psxBios_mem2vram() { // 0x47
1610 gpuSyncPluginSR(); // flush
1611 GPU_writeData(0xa0000000);
1612 GPU_writeData((a1<<0x10)|(a0&0xffff));
1613 GPU_writeData((a3<<0x10)|(a2&0xffff));
1614 size = ((((a2 * a3) / 2) >> 4) << 16);
1615 GPU_writeStatus(0x04000002);
1616 psxHwWrite32(0x1f8010f4,0);
1617 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1618 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1619 psxHwWrite32(0x1f8010a4, size | 0x10);
1620 psxHwWrite32(0x1f8010a8,0x01000201);
1625 void psxBios_SendGPU() { // 0x48
1626 GPU_writeStatus(a0);
1631 void psxBios_GPU_cw() { // 0x49
1638 void psxBios_GPU_cwb() { // 0x4a
1639 u32 *ptr = (u32*)Ra0;
1644 GPU_writeData(SWAPu32(*ptr++));
1650 void psxBios_GPU_SendPackets() { //4b:
1652 GPU_writeStatus(0x04000002);
1653 psxHwWrite32(0x1f8010f4,0);
1654 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1655 psxHwWrite32(0x1f8010a0,a0);
1656 psxHwWrite32(0x1f8010a4,0);
1657 psxHwWrite32(0x1f8010a8,0x010000401);
1661 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1662 psxHwWrite32(0x1f8010a8,0x00000401);
1663 GPU_writeData(0x0400000);
1664 GPU_writeData(0x0200000);
1665 GPU_writeData(0x0100000);
1670 void psxBios_GPU_GetGPUStatus() { // 0x4d
1671 v0 = GPU_readStatus();
1677 void psxBios_LoadExec() { // 51
1678 EXEC *header = (EXEC*)PSXM(0xf000);
1682 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1684 s_addr = a1; s_size = a2;
1689 header->S_addr = s_addr;
1690 header->s_size = s_size;
1692 a0 = 0xf000; a1 = 0; a2 = 0;
1696 void psxBios__bu_init() { // 70
1698 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1701 DeliverEvent(0xf0000011, 0x0004);
1702 DeliverEvent(0xf4000001, 0x0004);
1707 void psxBios__96_init() { // 71
1709 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1715 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1716 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1717 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1719 static void psxBios_DequeueCdIntr_() {
1720 psxBios_SysDeqIntRP_(0, 0x91d0);
1721 psxBios_SysDeqIntRP_(0, 0x91e0);
1725 static void psxBios_DequeueCdIntr() { // a3
1726 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1727 psxBios_DequeueCdIntr_();
1730 static void psxBios_CdRemove() { // 56, 72
1731 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1733 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1734 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1735 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1736 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1737 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1738 psxBios_DequeueCdIntr_();
1740 // EnterCriticalSection - should be done at the beginning,
1741 // but this way is much easier to implement
1747 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1749 static void psxBios_SetConf() { // 9c
1750 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1751 setup_tt(a1, a0, a2);
1752 psxRegs.CP0.n.SR |= 0x401;
1753 mips_return_void_c(500);
1756 static void psxBios_GetConf() { // 9d
1757 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1758 storeRam32(a0, loadRam32(A_CONF_EvCB));
1759 storeRam32(a1, loadRam32(A_CONF_TCB));
1760 storeRam32(a2, loadRam32(A_CONF_SP));
1761 mips_return_void_c(10);
1764 void psxBios_SetMem() { // 9f
1765 u32 new = psxHu32(0x1060);
1768 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1773 psxHu32ref(0x1060) = SWAP32(new);
1774 psxMu32ref(0x060) = a0;
1775 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1779 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1780 psxMu32ref(0x060) = a0;
1781 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1784 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1791 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1792 static void psxBios_get_cd_status() // a6
1794 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1799 static void psxBios__card_info() { // ab
1800 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1802 storeRam32(A_CARD_CHAN1, a0);
1809 if (McdDisable[port & 1])
1813 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1818 if (McdDisable[0] && McdDisable[1])
1821 DeliverEvent(0xf0000011, 0x0004);
1822 // DeliverEvent(0xf4000001, 0x0004);
1823 DeliverEvent(0xf4000001, ret);
1827 void psxBios__card_load() { // ac
1829 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1832 storeRam32(A_CARD_CHAN1, a0);
1834 // DeliverEvent(0xf0000011, 0x0004);
1835 DeliverEvent(0xf4000001, 0x0004);
1840 static void psxBios_GetSystemInfo() { // b4
1842 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1843 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1846 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1847 case 2: ret = 0xbfc0012c; break;
1848 case 5: ret = loadRam32(0x60) << 10; break;
1850 mips_return_c(ret, 20);
1853 /* System calls B0 */
1855 static u32 psxBios_SysMalloc_(u32 size);
1857 static void psxBios_SysMalloc() { // B 00
1858 u32 ret = psxBios_SysMalloc_(a0);
1860 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1861 mips_return_c(ret, 33);
1864 void psxBios_SetRCnt() { // 02
1866 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1873 psxRcntWtarget(a0, a1);
1874 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1875 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1876 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1877 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1878 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1880 psxRcntWmode(a0, mode);
1885 void psxBios_GetRCnt() { // 03
1887 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1892 case 0: v0 = psxRcntRcount0(); break;
1893 case 1: v0 = psxRcntRcount1(); break;
1894 case 2: v0 = psxRcntRcount2(); break;
1895 case 3: v0 = 0; break;
1900 void psxBios_StartRCnt() { // 04
1902 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1906 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1907 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1911 void psxBios_StopRCnt() { // 05
1913 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1917 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1918 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1922 void psxBios_ResetRCnt() { // 06
1924 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1929 psxRcntWmode(a0, 0);
1930 psxRcntWtarget(a0, 0);
1931 psxRcntWcount(a0, 0);
1936 static u32 DeliverEvent(u32 class, u32 spec) {
1937 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1938 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1939 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1940 u32 i, lim = evcb_len / 0x1c;
1942 //printf("%s %08x %x\n", __func__, class, spec);
1943 for (i = 0; i < lim; i++, ev++) {
1945 if (SWAP32(ev->status) != EvStACTIVE)
1948 if (SWAP32(ev->class) != class)
1951 if (SWAP32(ev->spec) != spec)
1954 ret = SWAP32(ev->mode);
1955 if (ret == EvMdMARK) {
1956 ev->status = SWAP32(EvStALREADY);
1960 if (ret == EvMdCALL) {
1961 ret = SWAP32(ev->fhandler);
1974 static u32 UnDeliverEvent(u32 class, u32 spec) {
1975 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1976 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1977 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1978 u32 i, lim = evcb_len / 0x1c;
1980 for (i = 0; i < lim; i++, ev++) {
1982 if (SWAP32(ev->status) != EvStALREADY)
1985 if (SWAP32(ev->class) != class)
1988 if (SWAP32(ev->spec) != spec)
1991 if (SWAP32(ev->mode) == EvMdMARK)
1992 ev->status = SWAP32(EvStACTIVE);
1998 static void psxBios_DeliverEvent() { // 07
2000 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
2002 ret = DeliverEvent(a0, a1);
2006 static s32 get_free_EvCB_slot() {
2007 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2008 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
2011 for (i = 0; i < lim; i++, ev++) {
2013 if (ev->status == SWAP32(EvStUNUSED))
2019 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2020 u32 ret = get_free_EvCB_slot();
2021 if ((s32)ret >= 0) {
2022 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2023 ev->class = SWAP32(class);
2024 ev->status = SWAP32(EvStDISABLED);
2025 ev->spec = SWAP32(spec);
2026 ev->mode = SWAP32(mode);
2027 ev->fhandler = SWAP32(func);
2033 static void psxBios_OpenEvent() { // 08
2034 u32 ret = OpenEvent(a0, a1, a2, a3);
2035 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2036 biosB0n[0x08], a0, a1, a2, a3, ret);
2037 mips_return_c(ret, 36);
2040 static void CloseEvent(u32 ev)
2042 u32 base = loadRam32(A_TT_EvCB);
2043 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2046 static void psxBios_CloseEvent() { // 09
2047 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2048 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2050 mips_return_c(1, 10);
2053 static void psxBios_WaitEvent() { // 0a
2054 u32 base = loadRam32(A_TT_EvCB);
2055 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2056 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2059 if (status == EvStALREADY) {
2060 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2064 if (status != EvStACTIVE)
2066 mips_return_c(0, 2);
2070 // retrigger this hlecall after the next emulation event
2072 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2073 psxRegs.cycle = next_interupt;
2077 static void psxBios_TestEvent() { // 0b
2078 u32 base = loadRam32(A_TT_EvCB);
2079 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2082 if (psxRegs.cycle - floodchk > 16*1024u) { // prevent log flood
2083 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2084 floodchk = psxRegs.cycle;
2086 if (status == EvStALREADY) {
2087 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2091 mips_return_c(ret, 15);
2094 static void psxBios_EnableEvent() { // 0c
2095 u32 base = loadRam32(A_TT_EvCB);
2096 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2097 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2098 if (status != EvStUNUSED)
2099 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2101 mips_return_c(1, 15);
2104 static void psxBios_DisableEvent() { // 0d
2105 u32 base = loadRam32(A_TT_EvCB);
2106 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2107 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2108 if (status != EvStUNUSED)
2109 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2111 mips_return_c(1, 15);
2115 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2118 void psxBios_OpenTh() { // 0e
2119 TCB *tcb = loadRam32ptr(A_TT_TCB);
2120 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2123 for (th = 1; th < limit; th++)
2125 if (tcb[th].status != SWAP32(0x4000)) break;
2129 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2130 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2132 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2134 mips_return_c(0xffffffff, 20);
2137 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2139 tcb[th].status = SWAP32(0x4000);
2140 tcb[th].mode = SWAP32(0x1000);
2141 tcb[th].epc = SWAP32(a0);
2142 tcb[th].reg[30] = SWAP32(a1); // fp
2143 tcb[th].reg[29] = SWAP32(a1); // sp
2144 tcb[th].reg[28] = SWAP32(a2); // gp
2146 mips_return_c(0xff000000 + th, 34);
2150 * int CloseTh(long thread);
2153 static void psxBios_CloseTh() { // 0f
2154 u32 tcb = loadRam32(A_TT_TCB);
2155 u32 th = a0 & 0xffff;
2157 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2158 // in the usual bios fashion no checks, just write and return 1
2159 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2161 mips_return_c(1, 11);
2165 * int ChangeTh(long thread);
2168 void psxBios_ChangeTh() { // 10
2169 u32 tcbBase = loadRam32(A_TT_TCB);
2170 u32 th = a0 & 0xffff;
2172 // this is quite spammy
2173 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2175 // without doing any argument checks, just issue a syscall
2176 // (like the real bios does)
2178 a1 = tcbBase + th * sizeof(TCB);
2183 void psxBios_InitPAD() { // 0x12
2184 u32 i, *ram32 = (u32 *)psxM;
2185 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2187 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2188 ram32[A_PAD_DR_DST/4] = 0;
2189 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2190 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2191 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2192 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2193 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2194 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2195 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2196 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2198 for (i = 0; i < a1; i++) {
2200 storeRam8(a0 + i, 0);
2202 for (i = 0; i < a3; i++) {
2204 storeRam8(a2 + i, 0);
2206 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2208 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2210 mips_return_c(1, 200);
2213 void psxBios_StartPAD() { // 13
2214 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2216 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2217 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2218 psxHwWrite16(0x1f801070, ~1);
2219 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2220 storeRam32(A_PAD_ACK_VBL, 1);
2221 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2222 psxRegs.CP0.n.SR |= 0x401;
2224 mips_return_c(1, 300);
2227 void psxBios_StopPAD() { // 14
2228 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2229 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2230 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2231 psxRegs.CP0.n.SR |= 0x401;
2232 mips_return_void_c(200);
2235 static void psxBios_PAD_init() { // 15
2237 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2238 if (a0 == 0x20000000 || a0 == 0x20000001)
2241 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2242 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2245 storeRam32(A_PAD_DR_DST, dst);
2248 mips_return_c(ret, 100);
2251 static u32 psxBios_PAD_dr_() {
2252 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2253 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2254 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2255 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2256 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2258 dst[0] = buf1[3], dst[1] = buf1[2];
2259 if (buf1[1] == 0x23) {
2260 dst[0] |= 0xc7, dst[1] |= 7;
2261 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2262 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2265 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2267 dst[2] = buf2[3], dst[3] = buf2[2];
2268 if (buf2[1] == 0x23) {
2269 dst[2] |= 0xc7, dst[3] |= 7;
2270 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2271 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2275 return SWAP32(*(u32 *)dst);
2278 static void psxBios_PAD_dr() { // 16
2279 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2280 u32 ret = psxBios_PAD_dr_();
2284 static void psxBios_ReturnFromException() { // 17
2285 u32 tcbPtr = loadRam32(A_TT_PCB);
2286 const TCB *tcb = loadRam32ptr(tcbPtr);
2290 for (i = 1; i < 32; i++)
2291 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2292 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2293 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2294 sr = SWAP32(tcb->sr);
2296 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2297 pc0 = k0 = SWAP32(tcb->epc);
2299 // the interpreter wants to know about sr changes, so do a MTC0
2300 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2301 MTC0(&psxRegs, 12, sr);
2307 void psxBios_ResetEntryInt() { // 18
2308 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2310 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2311 mips_return_void_c(5);
2314 void psxBios_HookEntryInt() { // 19
2315 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2317 storeRam32(A_EEXIT_PTR, a0);
2318 mips_return_void_c(3);
2321 static void psxBios_UnDeliverEvent() { // 0x20
2323 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2325 ret = UnDeliverEvent(a0, a1);
2329 static void buopen(int mcd, char *ptr, char *cfg)
2332 char *mcd_data = ptr;
2334 strcpy(FDesc[1 + mcd].name, Ra0+5);
2335 FDesc[1 + mcd].offset = 0;
2336 FDesc[1 + mcd].mode = a1;
2338 for (i=1; i<16; i++) {
2339 const char *fptr = mcd_data + 128 * i;
2340 if ((*fptr & 0xF0) != 0x50) continue;
2341 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2342 FDesc[1 + mcd].mcfile = i;
2343 PSXBIOS_LOG("open %s\n", fptr+0xa);
2347 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2348 for (i=1; i<16; i++) {
2349 int j, xor, nblk = a1 >> 16;
2351 char *fptr = mcd_data + 128 * i;
2353 if ((*fptr & 0xF0) != 0xa0) continue;
2355 FDesc[1 + mcd].mcfile = i;
2358 fptr[5] = 0x20 * nblk;
2361 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2362 pptr = fptr2 = fptr;
2363 for(j=2; j<=nblk; j++) {
2365 for(i++; i<16; i++) {
2368 memset(fptr2, 0, 128);
2369 fptr2[0] = j < nblk ? 0x52 : 0x53;
2372 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2377 /* shouldn't this return ENOSPC if i == 16? */
2379 pptr[8] = pptr[9] = 0xff;
2380 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2382 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2384 /* just go ahead and resave them all */
2385 SaveMcd(cfg, ptr, 128, 128 * 15);
2388 /* shouldn't this return ENOSPC if i == 16? */
2393 * int open(char *name , int mode);
2396 void psxBios_open() { // 0x32
2399 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2403 if (pa0 != INVALID_PTR) {
2404 if (!strncmp(pa0, "bu00", 4)) {
2405 buopen(1, Mcd1Data, Config.Mcd1);
2408 if (!strncmp(pa0, "bu10", 4)) {
2409 buopen(2, Mcd2Data, Config.Mcd2);
2417 * int lseek(int fd , int offset , int whence);
2420 void psxBios_lseek() { // 0x33
2422 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2427 FDesc[a0].offset = a1;
2429 // DeliverEvent(0xf0000011, 0x0004);
2430 // DeliverEvent(0xf4000001, 0x0004);
2434 FDesc[a0].offset+= a1;
2435 v0 = FDesc[a0].offset;
2444 * int read(int fd , void *buf , int nbytes);
2447 void psxBios_read() { // 0x34
2452 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2457 if (pa1 != INVALID_PTR) {
2459 case 2: buread(pa1, 1, a2); break;
2460 case 3: buread(pa1, 2, a2); break;
2468 * int write(int fd , void *buf , int nbytes);
2471 void psxBios_write() { // 0x35/0x03
2475 if (a0 != 1) // stdout
2476 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2479 if (pa1 == INVALID_PTR) {
2484 if (a0 == 1) { // stdout
2488 if (Config.PsxOut) while (a2 > 0) {
2489 SysPrintf("%c", *ptr++); a2--;
2495 case 2: buwrite(pa1, 1, a2); break;
2496 case 3: buwrite(pa1, 2, a2); break;
2502 static void psxBios_write_psxout() {
2503 if (a0 == 1) { // stdout
2504 const char *ptr = Ra1;
2507 if (ptr != INVALID_PTR)
2509 SysPrintf("%c", *ptr++);
2513 static void psxBios_putchar_psxout() { // 3d
2514 SysPrintf("%c", (char)a0);
2517 static void psxBios_puts_psxout() { // 3e/3f
2518 SysPrintf("%s", Ra0);
2522 * int close(int fd);
2525 void psxBios_close() { // 0x36
2527 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2534 void psxBios_putchar() { // 3d
2535 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2539 void psxBios_puts() { // 3e/3f
2540 if (Config.PsxOut) SysPrintf("%s", Ra0);
2544 static void bufile(const u8 *mcd_data, u32 dir_) {
2545 struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(dir_);
2546 const char *pfile = ffile + 5;
2547 const u8 *data = mcd_data;
2548 int i = 0, match = 0;
2553 for (; nfile <= 15 && !match; nfile++) {
2556 head = nfile * 0x40;
2557 data = mcd_data + 128 * nfile;
2558 name = (const char *)data + 0x0a;
2559 if ((data[0] & 0xF0) != 0x50) continue;
2560 /* Bug link files show up as free block. */
2561 if (!name[0]) continue;
2563 for (i = 0; i < 20; i++) {
2564 if (pfile[i] == name[i] || pfile[i] == '?')
2565 dir->name[i] = name[i];
2566 else if (pfile[i] == '*') {
2567 int len = strlen(name + i);
2570 memcpy(dir->name + i, name + i, len + 1);
2581 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2582 nfile, dir->name, pfile, name, match);
2584 for (; nfile <= 15; nfile++, blocks++) {
2585 const u8 *data2 = mcd_data + 128 * nfile;
2586 const char *name = (const char *)data2 + 0x0a;
2587 if ((data2[0] & 0xF0) != 0x50 || name[0])
2591 // nul char of full lenth name seems to overwrite .attr
2592 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2593 dir->size = 8192 * blocks;
2597 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2598 dir->attr, dir->size, dir->next, dir->head);
2602 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2605 static void psxBios_firstfile() { // 42
2606 char *pa0 = castRam8ptr(a0);
2608 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2612 snprintf(ffile, sizeof(ffile), "%s", pa0);
2614 strcpy(ffile + 5, "*"); // maybe?
2616 if (!strncmp(pa0, "bu00", 4)) {
2617 // firstfile() calls _card_read() internally, so deliver it's event
2618 DeliverEvent(0xf0000011, 0x0004);
2619 bufile((u8 *)Mcd1Data, a1);
2620 } else if (!strncmp(pa0, "bu10", 4)) {
2621 // firstfile() calls _card_read() internally, so deliver it's event
2622 DeliverEvent(0xf0000011, 0x0004);
2623 bufile((u8 *)Mcd2Data, a1);
2631 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2634 void psxBios_nextfile() { // 43
2635 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2638 if (!strncmp(ffile, "bu00", 4))
2639 bufile((u8 *)Mcd1Data, a0);
2640 else if (!strncmp(ffile, "bu10", 4))
2641 bufile((u8 *)Mcd2Data, a0);
2646 #define burename(mcd) { \
2647 for (i=1; i<16; i++) { \
2648 int namelen, j, xor = 0; \
2649 ptr = Mcd##mcd##Data + 128 * i; \
2650 if ((*ptr & 0xF0) != 0x50) continue; \
2651 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2652 namelen = strlen(Ra1+5); \
2653 memcpy(ptr+0xa, Ra1+5, namelen); \
2654 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2655 for (j=0; j<127; j++) xor^= ptr[j]; \
2657 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2664 * int rename(char *old, char *new);
2667 void psxBios_rename() { // 44
2674 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2679 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2680 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2684 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2693 #define budelete(mcd) { \
2694 for (i=1; i<16; i++) { \
2695 ptr = Mcd##mcd##Data + 128 * i; \
2696 if ((*ptr & 0xF0) != 0x50) continue; \
2697 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2698 *ptr = (*ptr & 0xf) | 0xA0; \
2699 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2700 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2707 * int delete(char *name);
2710 void psxBios_delete() { // 45
2716 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2721 if (pa0 != INVALID_PTR) {
2722 if (!strncmp(pa0, "bu00", 4)) {
2726 if (!strncmp(pa0, "bu10", 4)) {
2734 void psxBios_InitCARD() { // 4a
2735 u32 *ram32 = (u32 *)psxM;
2736 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2737 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2738 // (maybe) todo: early_card_irq, etc
2740 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2742 psxBios_FlushCache();
2743 mips_return_c(0, 34+13+15+6);
2746 void psxBios_StartCARD() { // 4b
2747 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2748 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2749 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2751 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2752 storeRam32(A_PAD_ACK_VBL, 1);
2753 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2754 storeRam32(A_CARD_IRQR_ENA, 1);
2755 psxRegs.CP0.n.SR |= 0x401;
2757 mips_return_c(1, 200);
2760 void psxBios_StopCARD() { // 4c
2761 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2762 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2763 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2764 storeRam32(A_CARD_IRQR_ENA, 0);
2765 psxRegs.CP0.n.SR |= 0x401;
2766 mips_return_void_c(200);
2769 void psxBios__card_write() { // 0x4e
2774 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2777 Function also accepts sector 400h (a bug).
2778 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2782 /* Invalid sectors */
2786 storeRam32(A_CARD_CHAN1, a0);
2789 if (pa2 != INVALID_PTR) {
2791 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2792 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2794 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2795 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2799 DeliverEvent(0xf0000011, 0x0004);
2800 // DeliverEvent(0xf4000001, 0x0004);
2805 void psxBios__card_read() { // 0x4f
2810 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2813 Function also accepts sector 400h (a bug).
2814 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2818 /* Invalid sectors */
2822 storeRam32(A_CARD_CHAN1, a0);
2825 if (pa2 != INVALID_PTR) {
2827 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2829 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2833 DeliverEvent(0xf0000011, 0x0004);
2834 // DeliverEvent(0xf4000001, 0x0004);
2839 void psxBios__new_card() { // 0x50
2841 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2847 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2848 void psxBios__get_error(void) // 55
2850 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2855 void psxBios_Krom2RawAdd() { // 0x51
2858 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2859 const u32 table_8140[][2] = {
2860 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2861 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2862 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2863 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2864 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2865 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2866 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2867 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2868 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2872 const u32 table_889f[][2] = {
2873 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2874 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2875 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2876 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2877 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2878 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2879 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2880 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2884 if (a0 >= 0x8140 && a0 <= 0x84be) {
2885 while (table_8140[i][0] <= a0) i++;
2886 a0 -= table_8140[i - 1][0];
2887 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2888 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2889 while (table_889f[i][0] <= a0) i++;
2890 a0 -= table_889f[i - 1][0];
2891 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2899 void psxBios_GetC0Table() { // 56
2900 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2901 log_unhandled("GetC0Table @%08x\n", ra);
2903 mips_return_c(A_C0_TABLE, 3);
2906 void psxBios_GetB0Table() { // 57
2907 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2908 log_unhandled("GetB0Table @%08x\n", ra);
2910 mips_return_c(A_B0_TABLE, 3);
2913 static void psxBios__card_chan() { // 0x58
2915 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2917 // todo: should return active slot chan
2918 // (active - which was last processed by irq code)
2919 ret = loadRam32(A_CARD_CHAN1);
2920 mips_return_c(ret, 8);
2923 static void psxBios_ChangeClearPad() { // 5b
2925 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2926 ret = loadRam32(A_PAD_ACK_VBL);
2927 storeRam32(A_PAD_ACK_VBL, a0);
2929 mips_return_c(ret, 6);
2932 static void psxBios__card_status() { // 5c
2933 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2939 static void psxBios__card_wait() { // 5d
2940 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2946 /* System calls C0 */
2948 static void psxBios_InitRCnt() { // 00
2950 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2951 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2952 for (i = 0; i < 3; i++) {
2953 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2954 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2955 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2957 psxBios_SysEnqIntRP_(a0, 0x6d88);
2958 mips_return_c(0, 9);
2961 static void psxBios_InitException() { // 01
2962 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2963 psxBios_SysEnqIntRP_(a0, 0x6da8);
2964 mips_return_c(0, 9);
2968 * int SysEnqIntRP(int index , long *queue);
2971 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2972 u32 old, base = loadRam32(A_TT_ExCB);
2974 old = loadRam32(base + (priority << 3));
2975 storeRam32(base + (priority << 3), chain_eptr);
2976 storeRam32(chain_eptr, old);
2977 mips_return_c(0, 9);
2980 static void psxBios_SysEnqIntRP() { // 02
2981 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2982 psxBios_SysEnqIntRP_(a0, a1);
2986 * int SysDeqIntRP(int index , long *queue);
2989 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2990 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2991 u32 lim = 0, ret = 0;
2993 // as in original: no arg checks of any kind, bug if a1 == 0
2994 ptr = loadRam32(base + (priority << 3));
2996 next = loadRam32(ptr);
2997 if (ptr == chain_rm_eptr) {
2998 storeRam32(base + (priority << 3), next);
3003 while (next && next != chain_rm_eptr && lim++ < 100) {
3005 next = loadRam32(ptr);
3008 if (next == chain_rm_eptr) {
3009 next = loadRam32(next);
3010 storeRam32(ptr, next);
3017 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
3019 mips_return_c(ret, 12);
3022 static void psxBios_SysDeqIntRP() { // 03
3023 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3024 psxBios_SysDeqIntRP_(a0, a1);
3027 static void psxBios_get_free_EvCB_slot() { // 04
3028 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3029 s32 ret = get_free_EvCB_slot();
3030 mips_return_c(ret, 0);
3033 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3034 storeRam32(base, 0);
3035 storeRam32(A_KMALLOC_PTR, base);
3036 storeRam32(A_KMALLOC_SIZE, size);
3037 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3040 // this should be much more complicated, but maybe that'll be enough
3041 static u32 psxBios_SysMalloc_(u32 size) {
3042 u32 ptr = loadRam32(A_KMALLOC_PTR);
3044 size = (size + 3) & ~3;
3045 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3046 storeRam32(ptr, size);
3050 static void psxBios_SysInitMemory() { // 08
3051 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3053 psxBios_SysInitMemory_(a0, a1);
3054 mips_return_void_c(12);
3057 static void psxBios_ChangeClearRCnt() { // 0a
3060 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3062 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3063 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3064 mips_return_c(ret, 8);
3067 static void psxBios_InitDefInt() { // 0c
3068 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3069 // should also clear the autoack table
3070 psxBios_SysEnqIntRP_(a0, 0x6d98);
3071 mips_return_c(0, 20 + 6*2);
3074 void psxBios_dummy() {
3075 u32 pc = (pc0 & 0x1fffff) - 4;
3076 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3077 : pc == 0xc0 ? biosC0n : NULL;
3078 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3079 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3080 (void)pc; (void)ntab;
3081 mips_return_c(0, 100);
3084 void (*biosA0[256])();
3085 // C0 and B0 overlap (end of C0 is start of B0)
3086 void (*biosC0[256+128])();
3087 void (**biosB0)() = biosC0 + 128;
3089 static void setup_mips_code()
3092 ptr = (u32 *)&psxM[A_SYSCALL];
3093 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3094 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3095 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3097 ptr = (u32 *)&psxM[A_EXCEPTION];
3098 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3099 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3100 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3101 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3102 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3103 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3104 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3105 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3106 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3107 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3109 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3110 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3111 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3113 ptr[0xb0/4] = HLEOP(hleop_exception);
3116 static const struct {
3120 { 0xbfc050a4, hleop_exc0_0_1 },
3121 { 0xbfc04fbc, hleop_exc0_0_2 },
3122 { 0xbfc0506c, hleop_exc0_1_1 },
3123 { 0xbfc04dec, hleop_exc0_1_2 },
3124 { 0x1a00, hleop_exc0_2_2 },
3125 { 0x19c8, hleop_exc1_0_1 },
3126 { 0x18bc, hleop_exc1_0_2 },
3127 { 0x1990, hleop_exc1_1_1 },
3128 { 0x1858, hleop_exc1_1_2 },
3129 { 0x1958, hleop_exc1_2_1 },
3130 { 0x17f4, hleop_exc1_2_2 },
3131 { 0x1920, hleop_exc1_3_1 },
3132 { 0x1794, hleop_exc1_3_2 },
3133 { 0x2458, hleop_exc3_0_2 },
3134 { 0x49bc, hleop_exc_padcard1 },
3135 { 0x4a4c, hleop_exc_padcard2 },
3138 static int chain_hle_op(u32 handler)
3142 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3143 if (chainfns[i].addr == handler)
3144 return chainfns[i].op;
3148 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3150 d[0] = SWAPu32(next);
3151 d[1] = SWAPu32(handler1);
3152 d[2] = SWAPu32(handler2);
3154 // install the hle traps
3155 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3156 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3159 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3161 u32 *ram32 = (u32 *)psxM;
3162 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3163 u32 p_excb, p_evcb, p_pcb, p_tcb;
3166 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3168 // the real bios doesn't care, but we just don't
3169 // want to crash in case of garbage parameters
3170 if (tcb_cnt > 1024) tcb_cnt = 1024;
3171 if (evcb_cnt > 1024) evcb_cnt = 1024;
3172 s_evcb = 0x1c * evcb_cnt;
3173 s_tcb = 0xc0 * tcb_cnt;
3175 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3176 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3177 p_excb = psxBios_SysMalloc_(s_excb);
3178 p_evcb = psxBios_SysMalloc_(s_evcb);
3179 p_pcb = psxBios_SysMalloc_(s_pcb);
3180 p_tcb = psxBios_SysMalloc_(s_tcb);
3182 // "table of tables". Some games modify it
3183 assert(A_TT_ExCB == 0x0100);
3184 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3185 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3186 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3187 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3188 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3189 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3190 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3191 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3192 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3193 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3194 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3195 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3197 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3198 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3199 storeRam32(p_excb + 4*4, 0x0000); // chain2
3200 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3202 storeRam32(p_pcb, p_tcb);
3203 storeRam32(p_tcb, 0x4000); // first TCB
3204 for (i = 1; i < tcb_cnt; i++)
3205 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3208 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3209 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3210 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3211 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3212 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3214 storeRam32(A_CONF_EvCB, evcb_cnt);
3215 storeRam32(A_CONF_TCB, tcb_cnt);
3216 storeRam32(A_CONF_SP, stack);
3219 static const u32 gpu_ctl_def[] = {
3220 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3221 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3224 static const u32 gpu_data_def[] = {
3225 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3226 0xe5001000, 0xe6000000,
3227 0x02000000, 0x00000000, 0x01ff03ff
3231 static const u16 spu_config[] = {
3232 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3233 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3234 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3235 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3236 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3237 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3238 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3239 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3242 void psxBiosSetupBootState(void)
3244 boolean hle = Config.HLE;
3245 u32 *hw = (u32 *)psxH;
3248 // see also SetBootRegs()
3251 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3252 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3254 k0 = 0xbfc0d968; k1 = 0xf1c;
3255 ra = 0xf0001234; // just to easily detect attempts to return
3256 psxRegs.CP0.n.Cause = 0x20;
3257 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3259 hw[0x1000/4] = SWAP32(0x1f000000);
3260 hw[0x1004/4] = SWAP32(0x1f802000);
3261 hw[0x1008/4] = SWAP32(0x0013243f);
3262 hw[0x100c/4] = SWAP32(0x00003022);
3263 hw[0x1010/4] = SWAP32(0x0013243f);
3264 hw[0x1014/4] = SWAP32(0x200931e1);
3265 hw[0x1018/4] = SWAP32(0x00020943);
3266 hw[0x101c/4] = SWAP32(0x00070777);
3267 hw[0x1020/4] = SWAP32(0x0000132c);
3268 hw[0x1060/4] = SWAP32(0x00000b88);
3269 hw[0x1070/4] = SWAP32(0x00000001);
3270 hw[0x1074/4] = SWAP32(0x0000000c);
3271 hw[0x2040/4] = SWAP32(0x00000900);
3274 hw[0x10a0/4] = SWAP32(0x00ffffff);
3275 hw[0x10a8/4] = SWAP32(0x00000401);
3276 hw[0x10b0/4] = SWAP32(0x0008b000);
3277 hw[0x10b4/4] = SWAP32(0x00010200);
3278 hw[0x10e0/4] = SWAP32(0x000eccf4);
3279 hw[0x10e4/4] = SWAP32(0x00000400);
3280 hw[0x10e8/4] = SWAP32(0x00000002);
3281 hw[0x10f0/4] = SWAP32(0x00009099);
3282 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3291 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3292 GPU_writeStatus(gpu_ctl_def[i]);
3293 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3294 GPU_writeData(gpu_data_def[i]);
3295 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3298 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3299 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3302 static void hleExc0_0_1();
3303 static void hleExc0_0_2();
3304 static void hleExc0_1_1();
3305 static void hleExc0_1_2();
3307 #include "sjisfont.h"
3309 void psxBiosInit() {
3310 u32 *ptr, *ram32, *rom32;
3315 memset(psxM, 0, 0x10000);
3316 for(i = 0; i < 256; i++) {
3321 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3322 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3323 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3324 biosA0[0x3f] = psxBios_printf_psxout;
3326 if (!Config.HLE) return;
3328 for(i = 0; i < 256; i++) {
3329 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3330 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3331 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3334 biosA0[0x00] = psxBios_open;
3335 biosA0[0x01] = psxBios_lseek;
3336 biosA0[0x02] = psxBios_read;
3337 biosA0[0x03] = psxBios_write;
3338 biosA0[0x04] = psxBios_close;
3339 //biosA0[0x05] = psxBios_ioctl;
3340 //biosA0[0x06] = psxBios_exit;
3341 //biosA0[0x07] = psxBios_sys_a0_07;
3342 biosA0[0x08] = psxBios_getc;
3343 biosA0[0x09] = psxBios_putc;
3344 biosA0[0x0a] = psxBios_todigit;
3345 //biosA0[0x0b] = psxBios_atof;
3346 //biosA0[0x0c] = psxBios_strtoul;
3347 //biosA0[0x0d] = psxBios_strtol;
3348 biosA0[0x0e] = psxBios_abs;
3349 biosA0[0x0f] = psxBios_labs;
3350 biosA0[0x10] = psxBios_atoi;
3351 biosA0[0x11] = psxBios_atol;
3352 //biosA0[0x12] = psxBios_atob;
3353 biosA0[0x13] = psxBios_setjmp;
3354 biosA0[0x14] = psxBios_longjmp;
3355 biosA0[0x15] = psxBios_strcat;
3356 biosA0[0x16] = psxBios_strncat;
3357 biosA0[0x17] = psxBios_strcmp;
3358 biosA0[0x18] = psxBios_strncmp;
3359 biosA0[0x19] = psxBios_strcpy;
3360 biosA0[0x1a] = psxBios_strncpy;
3361 biosA0[0x1b] = psxBios_strlen;
3362 biosA0[0x1c] = psxBios_index;
3363 biosA0[0x1d] = psxBios_rindex;
3364 biosA0[0x1e] = psxBios_strchr;
3365 biosA0[0x1f] = psxBios_strrchr;
3366 biosA0[0x20] = psxBios_strpbrk;
3367 biosA0[0x21] = psxBios_strspn;
3368 biosA0[0x22] = psxBios_strcspn;
3369 biosA0[0x23] = psxBios_strtok;
3370 biosA0[0x24] = psxBios_strstr;
3371 biosA0[0x25] = psxBios_toupper;
3372 biosA0[0x26] = psxBios_tolower;
3373 biosA0[0x27] = psxBios_bcopy;
3374 biosA0[0x28] = psxBios_bzero;
3375 biosA0[0x29] = psxBios_bcmp;
3376 biosA0[0x2a] = psxBios_memcpy;
3377 biosA0[0x2b] = psxBios_memset;
3378 biosA0[0x2c] = psxBios_memmove;
3379 biosA0[0x2d] = psxBios_memcmp;
3380 biosA0[0x2e] = psxBios_memchr;
3381 biosA0[0x2f] = psxBios_rand;
3382 biosA0[0x30] = psxBios_srand;
3383 biosA0[0x31] = psxBios_qsort;
3384 //biosA0[0x32] = psxBios_strtod;
3385 biosA0[0x33] = psxBios_malloc;
3386 biosA0[0x34] = psxBios_free;
3387 //biosA0[0x35] = psxBios_lsearch;
3388 //biosA0[0x36] = psxBios_bsearch;
3389 biosA0[0x37] = psxBios_calloc;
3390 biosA0[0x38] = psxBios_realloc;
3391 biosA0[0x39] = psxBios_InitHeap;
3392 //biosA0[0x3a] = psxBios__exit;
3393 biosA0[0x3b] = psxBios_getchar;
3394 biosA0[0x3c] = psxBios_putchar;
3395 //biosA0[0x3d] = psxBios_gets;
3396 biosA0[0x3e] = psxBios_puts;
3397 biosA0[0x3f] = psxBios_printf;
3398 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3399 //biosA0[0x41] = psxBios_LoadTest;
3400 biosA0[0x42] = psxBios_Load;
3401 biosA0[0x43] = psxBios_Exec;
3402 biosA0[0x44] = psxBios_FlushCache;
3403 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3404 biosA0[0x46] = psxBios_GPU_dw;
3405 biosA0[0x47] = psxBios_mem2vram;
3406 biosA0[0x48] = psxBios_SendGPU;
3407 biosA0[0x49] = psxBios_GPU_cw;
3408 biosA0[0x4a] = psxBios_GPU_cwb;
3409 biosA0[0x4b] = psxBios_GPU_SendPackets;
3410 biosA0[0x4c] = psxBios_sys_a0_4c;
3411 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3412 //biosA0[0x4e] = psxBios_GPU_sync;
3413 //biosA0[0x4f] = psxBios_sys_a0_4f;
3414 //biosA0[0x50] = psxBios_sys_a0_50;
3415 biosA0[0x51] = psxBios_LoadExec;
3416 //biosA0[0x52] = psxBios_GetSysSp;
3417 //biosA0[0x53] = psxBios_sys_a0_53;
3418 //biosA0[0x54] = psxBios__96_init_a54;
3419 //biosA0[0x55] = psxBios__bu_init_a55;
3420 biosA0[0x56] = psxBios_CdRemove;
3421 //biosA0[0x57] = psxBios_sys_a0_57;
3422 //biosA0[0x58] = psxBios_sys_a0_58;
3423 //biosA0[0x59] = psxBios_sys_a0_59;
3424 //biosA0[0x5a] = psxBios_sys_a0_5a;
3425 //biosA0[0x5b] = psxBios_dev_tty_init;
3426 //biosA0[0x5c] = psxBios_dev_tty_open;
3427 //biosA0[0x5d] = psxBios_sys_a0_5d;
3428 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3429 //biosA0[0x5f] = psxBios_dev_cd_open;
3430 //biosA0[0x60] = psxBios_dev_cd_read;
3431 //biosA0[0x61] = psxBios_dev_cd_close;
3432 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3433 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3434 //biosA0[0x64] = psxBios_dev_cd_chdir;
3435 //biosA0[0x65] = psxBios_dev_card_open;
3436 //biosA0[0x66] = psxBios_dev_card_read;
3437 //biosA0[0x67] = psxBios_dev_card_write;
3438 //biosA0[0x68] = psxBios_dev_card_close;
3439 //biosA0[0x69] = psxBios_dev_card_firstfile;
3440 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3441 //biosA0[0x6b] = psxBios_dev_card_erase;
3442 //biosA0[0x6c] = psxBios_dev_card_undelete;
3443 //biosA0[0x6d] = psxBios_dev_card_format;
3444 //biosA0[0x6e] = psxBios_dev_card_rename;
3445 //biosA0[0x6f] = psxBios_dev_card_6f;
3446 biosA0[0x70] = psxBios__bu_init;
3447 biosA0[0x71] = psxBios__96_init;
3448 biosA0[0x72] = psxBios_CdRemove;
3449 //biosA0[0x73] = psxBios_sys_a0_73;
3450 //biosA0[0x74] = psxBios_sys_a0_74;
3451 //biosA0[0x75] = psxBios_sys_a0_75;
3452 //biosA0[0x76] = psxBios_sys_a0_76;
3453 //biosA0[0x77] = psxBios_sys_a0_77;
3454 //biosA0[0x78] = psxBios__96_CdSeekL;
3455 //biosA0[0x79] = psxBios_sys_a0_79;
3456 //biosA0[0x7a] = psxBios_sys_a0_7a;
3457 //biosA0[0x7b] = psxBios_sys_a0_7b;
3458 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3459 //biosA0[0x7d] = psxBios_sys_a0_7d;
3460 //biosA0[0x7e] = psxBios__96_CdRead;
3461 //biosA0[0x7f] = psxBios_sys_a0_7f;
3462 //biosA0[0x80] = psxBios_sys_a0_80;
3463 //biosA0[0x81] = psxBios_sys_a0_81;
3464 //biosA0[0x82] = psxBios_sys_a0_82;
3465 //biosA0[0x83] = psxBios_sys_a0_83;
3466 //biosA0[0x84] = psxBios_sys_a0_84;
3467 //biosA0[0x85] = psxBios__96_CdStop;
3468 //biosA0[0x86] = psxBios_sys_a0_86;
3469 //biosA0[0x87] = psxBios_sys_a0_87;
3470 //biosA0[0x88] = psxBios_sys_a0_88;
3471 //biosA0[0x89] = psxBios_sys_a0_89;
3472 //biosA0[0x8a] = psxBios_sys_a0_8a;
3473 //biosA0[0x8b] = psxBios_sys_a0_8b;
3474 //biosA0[0x8c] = psxBios_sys_a0_8c;
3475 //biosA0[0x8d] = psxBios_sys_a0_8d;
3476 //biosA0[0x8e] = psxBios_sys_a0_8e;
3477 //biosA0[0x8f] = psxBios_sys_a0_8f;
3478 biosA0[0x90] = hleExc0_1_2;
3479 biosA0[0x91] = hleExc0_0_2;
3480 biosA0[0x92] = hleExc0_1_1;
3481 biosA0[0x93] = hleExc0_0_1;
3482 //biosA0[0x94] = psxBios_sys_a0_94;
3483 //biosA0[0x95] = psxBios_sys_a0_95;
3484 //biosA0[0x96] = psxBios_AddCDROMDevice;
3485 //biosA0[0x97] = psxBios_AddMemCardDevide;
3486 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3487 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3488 //biosA0[0x9a] = psxBios_sys_a0_9a;
3489 //biosA0[0x9b] = psxBios_sys_a0_9b;
3490 biosA0[0x9c] = psxBios_SetConf;
3491 biosA0[0x9d] = psxBios_GetConf;
3492 //biosA0[0x9e] = psxBios_sys_a0_9e;
3493 biosA0[0x9f] = psxBios_SetMem;
3494 //biosA0[0xa0] = psxBios__boot;
3495 //biosA0[0xa1] = psxBios_SystemError;
3496 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3497 biosA0[0xa3] = psxBios_DequeueCdIntr;
3498 //biosA0[0xa4] = psxBios_sys_a0_a4;
3499 //biosA0[0xa5] = psxBios_ReadSector;
3500 biosA0[0xa6] = psxBios_get_cd_status;
3501 //biosA0[0xa7] = psxBios_bufs_cb_0;
3502 //biosA0[0xa8] = psxBios_bufs_cb_1;
3503 //biosA0[0xa9] = psxBios_bufs_cb_2;
3504 //biosA0[0xaa] = psxBios_bufs_cb_3;
3505 biosA0[0xab] = psxBios__card_info;
3506 biosA0[0xac] = psxBios__card_load;
3507 //biosA0[0axd] = psxBios__card_auto;
3508 //biosA0[0xae] = psxBios_bufs_cd_4;
3509 //biosA0[0xaf] = psxBios_sys_a0_af;
3510 //biosA0[0xb0] = psxBios_sys_a0_b0;
3511 //biosA0[0xb1] = psxBios_sys_a0_b1;
3512 //biosA0[0xb2] = psxBios_do_a_long_jmp
3513 //biosA0[0xb3] = psxBios_sys_a0_b3;
3514 biosA0[0xb4] = psxBios_GetSystemInfo;
3515 //*******************B0 CALLS****************************
3516 biosB0[0x00] = psxBios_SysMalloc;
3517 //biosB0[0x01] = psxBios_sys_b0_01;
3518 biosB0[0x02] = psxBios_SetRCnt;
3519 biosB0[0x03] = psxBios_GetRCnt;
3520 biosB0[0x04] = psxBios_StartRCnt;
3521 biosB0[0x05] = psxBios_StopRCnt;
3522 biosB0[0x06] = psxBios_ResetRCnt;
3523 biosB0[0x07] = psxBios_DeliverEvent;
3524 biosB0[0x08] = psxBios_OpenEvent;
3525 biosB0[0x09] = psxBios_CloseEvent;
3526 biosB0[0x0a] = psxBios_WaitEvent;
3527 biosB0[0x0b] = psxBios_TestEvent;
3528 biosB0[0x0c] = psxBios_EnableEvent;
3529 biosB0[0x0d] = psxBios_DisableEvent;
3530 biosB0[0x0e] = psxBios_OpenTh;
3531 biosB0[0x0f] = psxBios_CloseTh;
3532 biosB0[0x10] = psxBios_ChangeTh;
3533 //biosB0[0x11] = psxBios_psxBios_b0_11;
3534 biosB0[0x12] = psxBios_InitPAD;
3535 biosB0[0x13] = psxBios_StartPAD;
3536 biosB0[0x14] = psxBios_StopPAD;
3537 biosB0[0x15] = psxBios_PAD_init;
3538 biosB0[0x16] = psxBios_PAD_dr;
3539 biosB0[0x17] = psxBios_ReturnFromException;
3540 biosB0[0x18] = psxBios_ResetEntryInt;
3541 biosB0[0x19] = psxBios_HookEntryInt;
3542 //biosB0[0x1a] = psxBios_sys_b0_1a;
3543 //biosB0[0x1b] = psxBios_sys_b0_1b;
3544 //biosB0[0x1c] = psxBios_sys_b0_1c;
3545 //biosB0[0x1d] = psxBios_sys_b0_1d;
3546 //biosB0[0x1e] = psxBios_sys_b0_1e;
3547 //biosB0[0x1f] = psxBios_sys_b0_1f;
3548 biosB0[0x20] = psxBios_UnDeliverEvent;
3549 //biosB0[0x21] = psxBios_sys_b0_21;
3550 //biosB0[0x22] = psxBios_sys_b0_22;
3551 //biosB0[0x23] = psxBios_sys_b0_23;
3552 //biosB0[0x24] = psxBios_sys_b0_24;
3553 //biosB0[0x25] = psxBios_sys_b0_25;
3554 //biosB0[0x26] = psxBios_sys_b0_26;
3555 //biosB0[0x27] = psxBios_sys_b0_27;
3556 //biosB0[0x28] = psxBios_sys_b0_28;
3557 //biosB0[0x29] = psxBios_sys_b0_29;
3558 //biosB0[0x2a] = psxBios_sys_b0_2a;
3559 //biosB0[0x2b] = psxBios_sys_b0_2b;
3560 //biosB0[0x2c] = psxBios_sys_b0_2c;
3561 //biosB0[0x2d] = psxBios_sys_b0_2d;
3562 //biosB0[0x2e] = psxBios_sys_b0_2e;
3563 //biosB0[0x2f] = psxBios_sys_b0_2f;
3564 //biosB0[0x30] = psxBios_sys_b0_30;
3565 //biosB0[0x31] = psxBios_sys_b0_31;
3566 biosB0[0x32] = psxBios_open;
3567 biosB0[0x33] = psxBios_lseek;
3568 biosB0[0x34] = psxBios_read;
3569 biosB0[0x35] = psxBios_write;
3570 biosB0[0x36] = psxBios_close;
3571 //biosB0[0x37] = psxBios_ioctl;
3572 //biosB0[0x38] = psxBios_exit;
3573 //biosB0[0x39] = psxBios_sys_b0_39;
3574 //biosB0[0x3a] = psxBios_getc;
3575 //biosB0[0x3b] = psxBios_putc;
3576 biosB0[0x3c] = psxBios_getchar;
3577 biosB0[0x3d] = psxBios_putchar;
3578 //biosB0[0x3e] = psxBios_gets;
3579 biosB0[0x3f] = psxBios_puts;
3580 biosB0[0x40] = psxBios_cd;
3581 biosB0[0x41] = psxBios_format;
3582 biosB0[0x42] = psxBios_firstfile;
3583 biosB0[0x43] = psxBios_nextfile;
3584 biosB0[0x44] = psxBios_rename;
3585 biosB0[0x45] = psxBios_delete;
3586 //biosB0[0x46] = psxBios_undelete;
3587 //biosB0[0x47] = psxBios_AddDevice;
3588 //biosB0[0x48] = psxBios_RemoteDevice;
3589 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3590 biosB0[0x4a] = psxBios_InitCARD;
3591 biosB0[0x4b] = psxBios_StartCARD;
3592 biosB0[0x4c] = psxBios_StopCARD;
3593 //biosB0[0x4d] = psxBios_sys_b0_4d;
3594 biosB0[0x4e] = psxBios__card_write;
3595 biosB0[0x4f] = psxBios__card_read;
3596 biosB0[0x50] = psxBios__new_card;
3597 biosB0[0x51] = psxBios_Krom2RawAdd;
3598 //biosB0[0x52] = psxBios_sys_b0_52;
3599 //biosB0[0x53] = psxBios_sys_b0_53;
3600 //biosB0[0x54] = psxBios__get_errno;
3601 biosB0[0x55] = psxBios__get_error;
3602 biosB0[0x56] = psxBios_GetC0Table;
3603 biosB0[0x57] = psxBios_GetB0Table;
3604 biosB0[0x58] = psxBios__card_chan;
3605 //biosB0[0x59] = psxBios_sys_b0_59;
3606 //biosB0[0x5a] = psxBios_sys_b0_5a;
3607 biosB0[0x5b] = psxBios_ChangeClearPad;
3608 biosB0[0x5c] = psxBios__card_status;
3609 biosB0[0x5d] = psxBios__card_wait;
3610 //*******************C0 CALLS****************************
3611 biosC0[0x00] = psxBios_InitRCnt;
3612 biosC0[0x01] = psxBios_InitException;
3613 biosC0[0x02] = psxBios_SysEnqIntRP;
3614 biosC0[0x03] = psxBios_SysDeqIntRP;
3615 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3616 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3617 //biosC0[0x06] = psxBios_ExceptionHandler;
3618 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3619 biosC0[0x08] = psxBios_SysInitMemory;
3620 //biosC0[0x09] = psxBios_SysInitKMem;
3621 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3622 //biosC0[0x0b] = psxBios_SystemError;
3623 biosC0[0x0c] = psxBios_InitDefInt;
3624 //biosC0[0x0d] = psxBios_sys_c0_0d;
3625 //biosC0[0x0e] = psxBios_sys_c0_0e;
3626 //biosC0[0x0f] = psxBios_sys_c0_0f;
3627 //biosC0[0x10] = psxBios_sys_c0_10;
3628 //biosC0[0x11] = psxBios_sys_c0_11;
3629 //biosC0[0x12] = psxBios_InstallDevices;
3630 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3631 //biosC0[0x14] = psxBios_sys_c0_14;
3632 //biosC0[0x15] = psxBios__cdevinput;
3633 //biosC0[0x16] = psxBios__cdevscan;
3634 //biosC0[0x17] = psxBios__circgetc;
3635 //biosC0[0x18] = psxBios__circputc;
3636 //biosC0[0x19] = psxBios_ioabort;
3637 //biosC0[0x1a] = psxBios_sys_c0_1a
3638 //biosC0[0x1b] = psxBios_KernelRedirect;
3639 //biosC0[0x1c] = psxBios_PatchAOTable;
3640 //************** THE END ***************************************
3643 memset(FDesc, 0, sizeof(FDesc));
3644 memset(cdir, 0, sizeof(cdir));
3647 // somewhat pretend to be a SCPH1001 BIOS
3648 // some games look for these and take an exception if they're missing
3649 rom32 = (u32 *)psxR;
3650 rom32[0x100/4] = SWAP32(0x19951204);
3651 rom32[0x104/4] = SWAP32(3);
3652 romc = (char *)psxR;
3653 strcpy(romc + 0x108, "PCSX authors");
3654 strcpy(romc + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3655 strcpy(romc + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3656 strcpy(romc + 0x7ff54, "GPL-2.0-or-later");
3659 len = 0x80000 - 0x66000;
3660 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3661 len = 0x80000 - 0x69d68;
3662 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3664 // trap attempts to call bios directly
3665 rom32[0x00000/4] = HLEOP(hleop_dummy);
3666 rom32[0x00180/4] = HLEOP(hleop_dummy);
3667 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3668 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3669 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3671 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3672 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3673 Here are some examples of games not working with this fix in place :
3674 R-type won't get past the Irem logo if not implemented.
3675 Crash Team Racing will softlock after the Sony logo.
3678 ram32 = (u32 *)psxM;
3679 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3680 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3681 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3682 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3684 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3685 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3687 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3688 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3689 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3690 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3692 ram32[0x00a0/4] = HLEOP(hleop_a0);
3693 ram32[0x00b0/4] = HLEOP(hleop_b0);
3694 ram32[0x00c0/4] = HLEOP(hleop_c0);
3696 setup_tt(4, 16, 0x801fff00);
3697 DeliverEvent(0xf0000003, 0x0010);
3699 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3700 strcpy((char *)&ram32[0xeff0/4], "bu");
3702 // default exception handler chains
3703 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3704 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3705 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3706 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3707 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3708 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3709 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3710 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3714 // fill the api jumptables with fake entries as some games patch them
3715 // (or rather the funcs listed there)
3716 ptr = (u32 *)&psxM[A_A0_TABLE];
3717 for (i = 0; i < 256; i++)
3718 ptr[i] = SWAP32(A_A0_DUMMY);
3720 ptr = (u32 *)&psxM[A_B0_TABLE];
3721 for (i = 0; i < 256; i++)
3722 ptr[i] = SWAP32(A_B0_DUMMY);
3723 // B(5b) is special because games patch (sometimes even jump to)
3724 // code at fixed offsets from it, nocash lists offsets:
3725 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3726 // call: +7a0=4b70, +884=4c54, +894=4c64
3727 ptr[0x5b] = SWAP32(A_B0_5B_DUMMY); // 0x43d0
3728 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3730 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3731 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3732 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3734 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3735 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3737 ptr = (u32 *)&psxM[A_C0_TABLE];
3738 for (i = 0; i < 256/2; i++)
3739 ptr[i] = SWAP32(A_C0_DUMMY);
3740 ptr[6] = SWAP32(A_EXCEPTION);
3743 ram32[A_A0_DUMMY/4] = HLEOP(hleop_dummy);
3744 ram32[A_B0_DUMMY/4] = HLEOP(hleop_dummy);
3745 ram32[A_C0_DUMMY/4] = HLEOP(hleop_dummy);
3746 ram32[A_B0_5B_DUMMY/4] = HLEOP(hleop_dummy);
3747 ram32[0x8000/4] = HLEOP(hleop_execret);
3749 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3750 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3751 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3752 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3753 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3754 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3755 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3758 void psxBiosShutdown() {
3761 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3764 if (tcb_cnt != 4 || evcb_cnt != 16) {
3765 setup_tt(tcb_cnt, evcb_cnt, stack);
3766 DeliverEvent(0xf0000003, 0x0010);
3768 storeRam32(A_CONF_SP, stack);
3771 #define psxBios_PADpoll(pad) { \
3772 int i, more_data = 0; \
3773 PAD##pad##_startPoll(pad); \
3774 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
3775 pad_buf##pad[0] = more_data ? 0 : 0xff; \
3776 PAD##pad##_poll(0, &more_data); \
3778 while (more_data) { \
3779 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
3783 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3787 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3788 psxBios_ReturnFromException();
3794 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3795 // so this is only partially implemented
3796 static void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3798 u32 cdrom_dma_ack_enable = 1; // a000b93c
3799 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3802 static void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3805 //PSXBIOS_LOG("%s\n", __func__);
3807 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3808 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3809 //if (--cdrom_irq_counter == 0) // 0xa0009180
3810 // DeliverEvent(0xf0000003, 0x10);
3814 mips_return_c(ret, 20);
3817 static void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3819 u32 cdrom_irq_ack_enable = 1; // a000b938
3820 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3823 static void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3826 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3827 PSXBIOS_LOG("%s TODO\n", __func__);
3830 mips_return_c(ret, 20);
3833 static void hleExc0_2_2_syscall() // not in any A/B/C table
3835 u32 tcbPtr = loadRam32(A_TT_PCB);
3836 TCB *tcb = loadRam32ptr(tcbPtr);
3837 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3839 if (code != R3000E_Syscall) {
3841 DeliverEvent(0xf0000010, 0x1000);
3842 //psxBios_SystemErrorUnresolvedException();
3844 mips_return_c(0, 17);
3848 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3849 tcb->epc += SWAP32(4);
3850 switch (SWAP32(tcb->reg[4])) { // a0
3854 case 1: { // EnterCritical - disable irqs
3855 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3856 tcb->reg[2] = SWAP32(was_enabled);
3857 tcb->sr &= SWAP32(~0x404);
3860 case 2: // ExitCritical - enable irqs
3861 tcb->sr |= SWAP32(0x404);
3864 case 3: { // ChangeThreadSubFunction
3865 u32 tcbPtr = loadRam32(A_TT_PCB);
3866 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3870 DeliverEvent(0xf0000010, 0x4000);
3874 psxBios_ReturnFromException();
3877 static void hleExc1_0_1(void)
3879 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3880 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3883 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3886 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3887 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3890 mips_return_c(ret, 22);
3893 static void hleExc1_0_2(void)
3895 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3898 static void hleExc1_1_1(void)
3900 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3901 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3904 static void hleExc1_1_2(void)
3906 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3909 static void hleExc1_2_1(void)
3911 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3912 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3915 static void hleExc1_2_2(void)
3917 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3920 static void hleExc1_3_1(void)
3922 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3923 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3926 static void hleExc1_3_2(void)
3928 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3931 static void hleExc3_0_2_defint(void)
3933 static const struct {
3944 { 6, 6 }, // rcnt2 (bug)
3949 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3950 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3951 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3956 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3959 static void hleExcPadCard1(void)
3961 if (loadRam32(A_PAD_IRQR_ENA)) {
3962 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3963 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3968 if (loadRam32(A_PAD_DR_DST))
3971 if (loadRam32(A_PAD_ACK_VBL))
3972 psxHwWrite16(0x1f801070, ~1);
3973 if (loadRam32(A_CARD_IRQR_ENA)) {
3977 mips_return_c(0, 18);
3980 static void hleExcPadCard2(void)
3982 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3983 mips_return_c(ret, 15);
3986 void psxBiosException() {
3987 u32 tcbPtr = loadRam32(A_TT_PCB);
3988 u32 *chains = loadRam32ptr(A_TT_ExCB);
3989 TCB *tcb = loadRam32ptr(tcbPtr);
3995 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
3996 for (i = 4; i < 31; i++) {
3999 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
4001 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
4002 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
4003 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
4004 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
4005 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
4006 sp = fp = loadRam32(A_EXC_SP);
4010 // do the chains (always 4)
4011 for (c = lim = 0; c < 4; c++) {
4012 if (chains[c * 2] == 0)
4014 ptr = SWAP32(chains[c * 2]);
4015 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
4016 chain = castRam32ptr(ptr);
4021 softCallInException(SWAP32(chain[2]));
4022 if (returned_from_exception())
4025 if (v0 == 0 || chain[1] == 0)
4027 softCallInException(SWAP32(chain[1]));
4028 if (returned_from_exception())
4034 // return from exception (custom or default)
4036 ptr = loadRam32(A_EEXIT_PTR);
4037 if (ptr != A_EEXIT_DEF) {
4038 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4039 longjmp_load(jmp_buf);
4044 psxBios_ReturnFromException();
4048 static void hleDummy() {
4049 log_unhandled("hleDummy called @%08x ra=%08x\n", psxRegs.pc - 4, ra);
4051 psxRegs.cycle += 1000;
4056 static void hleA0() {
4057 u32 call = t1 & 0xff;
4058 u32 entry = loadRam32(A_A0_TABLE + call * 4);
4060 if (call < 192 && entry != A_A0_DUMMY) {
4061 PSXBIOS_LOG("custom A%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4062 call, biosA0n[call], a0, entry, ra);
4065 PSXBIOS_LOG(" -> %08x\n", v0);
4067 else if (biosA0[call])
4073 static void hleB0() {
4074 u32 call = t1 & 0xff;
4075 u32 entry = loadRam32(A_B0_TABLE + call * 4);
4079 is_custom = entry != A_B0_5B_DUMMY;
4081 is_custom = entry != A_B0_DUMMY;
4083 PSXBIOS_LOG("custom B%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4084 call, biosB0n[call], a0, entry, ra);
4087 PSXBIOS_LOG(" -> %08x\n", v0);
4089 else if (biosB0[call])
4095 static void hleC0() {
4096 u32 call = t1 & 0xff;
4097 u32 entry = loadRam32(A_C0_TABLE + call * 4);
4099 if (call < 128 && entry != A_C0_DUMMY) {
4100 PSXBIOS_LOG("custom C%02x %s(0x%x, ) addr=%08x ra=%08x\n",
4101 call, biosC0n[call], a0, entry, ra);
4104 PSXBIOS_LOG(" -> %08x\n", v0);
4106 else if (biosC0[call])
4112 // currently not used
4113 static void hleBootstrap() {
4118 static void hleExecRet() {
4119 const EXEC *header = (EXEC *)PSXM(s0);
4121 PSXBIOS_LOG("ExecRet %x: %x\n", s0, header->ret);
4123 ra = SWAP32(header->ret);
4124 sp = SWAP32(header->_sp);
4125 fp = SWAP32(header->_fp);
4126 gp = SWAP32(header->_gp);
4127 s0 = SWAP32(header->base);
4133 void (* const psxHLEt[24])() = {
4134 hleDummy, hleA0, hleB0, hleC0,
4135 hleBootstrap, hleExecRet, psxBiosException, hleDummy,
4136 hleExc0_0_1, hleExc0_0_2,
4137 hleExc0_1_1, hleExc0_1_2, hleExc0_2_2_syscall,
4138 hleExc1_0_1, hleExc1_0_2,
4139 hleExc1_1_1, hleExc1_1_2,
4140 hleExc1_2_1, hleExc1_2_2,
4141 hleExc1_3_1, hleExc1_3_2,
4143 hleExcPadCard1, hleExcPadCard2,
4147 #define bfreeze(ptr, size) { \
4148 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4149 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4153 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4154 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4156 void psxBiosFreeze(int Mode) {