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"
41 #if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
42 #pragma GCC diagnostic ignored "-Wpointer-sign"
46 //#define PSXBIOS_LOG printf
47 #define PSXBIOS_LOG(...)
50 #define PTR_1 (void *)(size_t)1
52 char *biosA0n[256] = {
54 "open", "lseek", "read", "write",
55 "close", "ioctl", "exit", "sys_a0_07",
56 "getc", "putc", "todigit", "atof",
57 "strtoul", "strtol", "abs", "labs",
59 "atoi", "atol", "atob", "setjmp",
60 "longjmp", "strcat", "strncat", "strcmp",
61 "strncmp", "strcpy", "strncpy", "strlen",
62 "index", "rindex", "strchr", "strrchr",
64 "strpbrk", "strspn", "strcspn", "strtok",
65 "strstr", "toupper", "tolower", "bcopy",
66 "bzero", "bcmp", "memcpy", "memset",
67 "memmove", "memcmp", "memchr", "rand",
69 "srand", "qsort", "strtod", "malloc",
70 "free", "lsearch", "bsearch", "calloc",
71 "realloc", "InitHeap", "_exit", "getchar",
72 "putchar", "gets", "puts", "printf",
74 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
75 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
76 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
77 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
79 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
80 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
81 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
82 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
84 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
85 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
86 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
87 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
89 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
90 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
91 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
92 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
94 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
95 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
96 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
97 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
99 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
100 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
101 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
102 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
104 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
105 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
106 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
107 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
109 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
113 char *biosB0n[256] = {
115 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
116 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
117 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
118 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
120 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
121 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
122 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
123 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
125 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
126 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
127 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
128 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
130 "sys_b0_30", "sys_b0_31", "open", "lseek",
131 "read", "write", "close", "ioctl",
132 "exit", "sys_b0_39", "getc", "putc",
133 "getchar", "putchar", "gets", "puts",
135 "cd", "format", "firstfile", "nextfile",
136 "rename", "delete", "undelete", "AddDevice",
137 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
138 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
140 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
141 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
142 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
143 "_card_status", "_card_wait",
146 char *biosC0n[256] = {
148 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
149 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
150 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
151 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
153 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
154 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
155 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
159 //#define r0 (psxRegs.GPR.n.r0)
160 #define at (psxRegs.GPR.n.at)
161 #define v0 (psxRegs.GPR.n.v0)
162 #define v1 (psxRegs.GPR.n.v1)
163 #define a0 (psxRegs.GPR.n.a0)
164 #define a1 (psxRegs.GPR.n.a1)
165 #define a2 (psxRegs.GPR.n.a2)
166 #define a3 (psxRegs.GPR.n.a3)
167 #define t0 (psxRegs.GPR.n.t0)
168 #define t1 (psxRegs.GPR.n.t1)
169 #define t2 (psxRegs.GPR.n.t2)
170 #define t3 (psxRegs.GPR.n.t3)
171 #define t4 (psxRegs.GPR.n.t4)
172 #define t5 (psxRegs.GPR.n.t5)
173 #define t6 (psxRegs.GPR.n.t6)
174 #define t7 (psxRegs.GPR.n.t7)
175 #define t8 (psxRegs.GPR.n.t8)
176 #define t9 (psxRegs.GPR.n.t9)
177 #define s0 (psxRegs.GPR.n.s0)
178 #define s1 (psxRegs.GPR.n.s1)
179 #define s2 (psxRegs.GPR.n.s2)
180 #define s3 (psxRegs.GPR.n.s3)
181 #define s4 (psxRegs.GPR.n.s4)
182 #define s5 (psxRegs.GPR.n.s5)
183 #define s6 (psxRegs.GPR.n.s6)
184 #define s7 (psxRegs.GPR.n.s7)
185 #define k0 (psxRegs.GPR.n.k0)
186 #define k1 (psxRegs.GPR.n.k1)
187 #define gp (psxRegs.GPR.n.gp)
188 #define sp (psxRegs.GPR.n.sp)
189 #define fp (psxRegs.GPR.n.fp)
190 #define ra (psxRegs.GPR.n.ra)
191 #define pc0 (psxRegs.pc)
193 #define Ra0 ((char *)PSXM(a0))
194 #define Ra1 ((char *)PSXM(a1))
195 #define Ra2 ((char *)PSXM(a2))
196 #define Ra3 ((char *)PSXM(a3))
197 #define Rv0 ((char *)PSXM(v0))
198 #define Rsp ((char *)PSXM(sp))
209 #define EvStUNUSED 0x0000
210 #define EvStDISABLED 0x1000
211 #define EvStACTIVE 0x2000
212 #define EvStALREADY 0x4000
214 #define EvMdCALL 0x1000
215 #define EvMdMARK 0x2000
238 u32 _sp, _fp, _gp, ret, base;
258 // todo: FileDesc layout is wrong
259 // todo: get rid of these globals
260 static FileDesc FDesc[32];
261 static char ffile[64];
264 // fixed RAM offsets, SCPH1001 compatible
265 #define A_TT_ExCB 0x0100
266 #define A_TT_PCB 0x0108
267 #define A_TT_TCB 0x0110
268 #define A_TT_EvCB 0x0120
269 #define A_A0_TABLE 0x0200
270 #define A_B0_TABLE 0x0874
271 #define A_C0_TABLE 0x0674
272 #define A_SYSCALL 0x0650
273 #define A_EXCEPTION 0x0c80
274 #define A_EXC_SP 0x6cf0
275 #define A_EEXIT_DEF 0x6cf4
276 #define A_KMALLOC_PTR 0x7460
277 #define A_KMALLOC_SIZE 0x7464
278 #define A_KMALLOC_END 0x7468
279 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
280 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
281 #define A_CARD_IRQR_ENA 0x74bc // same for card
282 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
283 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
284 #define A_PAD_IN_LEN 0x74d8
285 #define A_PAD_OUT_LEN 0x74e0
286 #define A_PAD_DR_DST 0x74c4
287 #define A_CARD_CHAN1 0x7500
288 #define A_PAD_DR_BUF1 0x7570
289 #define A_PAD_DR_BUF2 0x7598
290 #define A_EEXIT_PTR 0x75d0
291 #define A_EXC_STACK 0x85d8 // exception stack top
292 #define A_RCNT_VBL_ACK 0x8600
293 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
294 #define A_HEAP_BASE 0x9000
295 #define A_HEAP_SIZE 0x9004
296 #define A_HEAP_END 0x9008
297 #define A_HEAP_FLAG 0x900c
298 #define A_RND_SEED 0x9010
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 HLEOP(n) SWAPu32((0x3b << 26) | (n));
307 static u32 loadRam32(u32 addr)
309 assert(!(addr & 0x5f800000));
310 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
313 static void *castRam8ptr(u32 addr)
315 assert(!(addr & 0x5f800000));
316 return psxM + (addr & 0x1fffff);
319 static void *castRam32ptr(u32 addr)
321 assert(!(addr & 0x5f800003));
322 return psxM + (addr & 0x1ffffc);
325 static void *loadRam8ptr(u32 addr)
327 return castRam8ptr(loadRam32(addr));
330 static void *loadRam32ptr(u32 addr)
332 return castRam32ptr(loadRam32(addr));
335 static void storeRam8(u32 addr, u8 d)
337 assert(!(addr & 0x5f800000));
338 *((u8 *)psxM + (addr & 0x1fffff)) = d;
341 static void storeRam32(u32 addr, u32 d)
343 assert(!(addr & 0x5f800000));
344 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
347 static void mips_return(u32 val)
353 static void mips_return_void(void)
358 static void use_cycles(u32 cycle)
360 psxRegs.cycle += cycle * 2;
363 static void mips_return_c(u32 val, u32 cycle)
369 static void mips_return_void_c(u32 cycle)
375 static int returned_from_exception(void)
377 // 0x80000080 means it took another exception just after return
378 return pc0 == k0 || pc0 == 0x80000080;
381 static inline void softCall(u32 pc) {
383 u32 ssr = psxRegs.CP0.n.SR;
387 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
389 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
391 while (pc0 != 0x80001000 && ++lim < 1000000)
392 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
394 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
397 PSXBIOS_LOG("softCall @%x hit lim\n", pc);
399 psxRegs.CP0.n.SR |= ssr & 0x404;
402 static inline void softCallInException(u32 pc) {
407 assert(ra != 0x80001000);
408 if (ra == 0x80001000)
412 psxCpu->Notify(R3000ACPU_NOTIFY_AFTER_LOAD, PTR_1);
414 while (!returned_from_exception() && pc0 != 0x80001000 && ++lim < 1000000)
415 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
417 psxCpu->Notify(R3000ACPU_NOTIFY_BEFORE_SAVE, PTR_1);
420 PSXBIOS_LOG("softCallInException @%x hit lim\n", pc);
421 if (pc0 == 0x80001000)
425 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func);
426 static u32 DeliverEvent(u32 class, u32 spec);
427 static u32 UnDeliverEvent(u32 class, u32 spec);
428 static void CloseEvent(u32 ev);
433 // System calls A0 */
436 #define buread(Ra1, mcd, length) { \
437 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); \
438 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
439 memcpy(Ra1, ptr, length); \
440 psxCpu->Clear(a1, (length + 3) / 4); \
441 if (FDesc[1 + mcd].mode & 0x8000) { \
442 DeliverEvent(0xf0000011, 0x0004); \
443 DeliverEvent(0xf4000001, 0x0004); \
446 FDesc[1 + mcd].offset += v0; \
449 #define buwrite(Ra1, mcd, length) { \
450 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
451 PSXBIOS_LOG("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
452 ptr = Mcd##mcd##Data + offset; \
453 memcpy(ptr, Ra1, length); \
454 FDesc[1 + mcd].offset += length; \
455 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
456 if (FDesc[1 + mcd].mode & 0x8000) { \
457 DeliverEvent(0xf0000011, 0x0004); \
458 DeliverEvent(0xf4000001, 0x0004); \
463 /* Internally redirects to "FileRead(fd,tempbuf,1)".*/
464 /* For some strange reason, the returned character is sign-expanded; */
465 /* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
466 /* TODO FIX ME : Properly implement this behaviour */
467 void psxBios_getc(void) // 0x03, 0x35
472 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
476 if (pa1 != INVALID_PTR) {
478 case 2: buread(pa1, 1, 1); break;
479 case 3: buread(pa1, 2, 1); break;
486 /* Copy of psxBios_write, except size is 1. */
487 void psxBios_putc(void) // 0x09, 0x3B
492 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
495 if (pa1 == INVALID_PTR) {
500 if (a0 == 1) { // stdout
501 char *ptr = (char *)pa1;
505 printf("%c", *ptr++); a2--;
511 case 2: buwrite(pa1, 1, 1); break;
512 case 3: buwrite(pa1, 2, 1); break;
518 void psxBios_todigit(void) // 0x0a
522 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
525 if (c >= 0x30 && c < 0x3A) {
528 else if (c > 0x60 && c < 0x7B) {
531 else if (c > 0x40 && c < 0x5B) {
534 else if (c >= 0x80) {
545 void psxBios_abs() { // 0x0e
546 if ((s32)a0 < 0) v0 = -(s32)a0;
551 void psxBios_labs() { // 0x0f
555 void psxBios_atoi() { // 0x10
557 char *p = (char *)Ra0;
561 case ' ': case '\t': continue;
568 while (*p >= '0' && *p <= '9') {
569 n = n * 10 + *p++ - '0';
576 void psxBios_atol() { // 0x11
586 static void psxBios_setjmp() { // 0x13
587 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
590 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
592 jmp_buf->ra_ = SWAP32(ra);
593 jmp_buf->sp_ = SWAP32(sp);
594 jmp_buf->fp_ = SWAP32(fp);
595 for (i = 0; i < 8; i++) // s0-s7
596 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
597 jmp_buf->gp_ = SWAP32(gp);
599 mips_return_c(0, 15);
602 static void longjmp_load(const struct jmp_buf_ *jmp_buf)
606 ra = SWAP32(jmp_buf->ra_);
607 sp = SWAP32(jmp_buf->sp_);
608 fp = SWAP32(jmp_buf->fp_);
609 for (i = 0; i < 8; i++) // s0-s7
610 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
611 gp = SWAP32(jmp_buf->gp_);;
614 void psxBios_longjmp() { // 0x14
615 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
617 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
618 longjmp_load(jmp_buf);
619 mips_return_c(a1, 15);
622 void psxBios_strcat() { // 0x15
623 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
626 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
628 if (a0 == 0 || a1 == 0)
636 while ((*p1++ = *p2++) != '\0');
641 void psxBios_strncat() { // 0x16
642 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
646 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
648 if (a0 == 0 || a1 == 0)
656 while ((*p1++ = *p2++) != '\0') {
666 void psxBios_strcmp() { // 0x17
667 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
669 if (a0 == 0 && a1 == 0)
675 else if (a0 == 0 && a1 != 0)
681 else if (a0 != 0 && a1 == 0)
688 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
691 while (*p1 == *p2++) {
710 void psxBios_strncmp() { // 0x18
711 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
713 if (a0 == 0 && a1 == 0)
719 else if (a0 == 0 && a1 != 0)
725 else if (a0 != 0 && a1 == 0)
732 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
735 while (--n >= 0 && *p1 == *p2++) {
739 v1 = a2 - ((a2-n) - 1);
747 v0 = (n < 0 ? 0 : *p1 - *--p2);
749 v1 = a2 - ((a2-n) - 1);
755 void psxBios_strcpy() { // 0x19
756 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
757 if (a0 == 0 || a1 == 0)
763 while ((*p1++ = *p2++) != '\0');
768 void psxBios_strncpy() { // 0x1a
769 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
771 if (a0 == 0 || a1 == 0)
777 for (i = 0; i < n; i++) {
778 if ((*p1++ = *p2++) == '\0') {
790 void psxBios_strlen() { // 0x1b
791 char *p = (char *)Ra0;
802 void psxBios_index() { // 0x1c
803 char *p = (char *)Ra0;
813 v0 = a0 + (p - (char *)Ra0);
817 } while (*p++ != '\0');
822 void psxBios_rindex() { // 0x1d
823 char *p = (char *)Ra0;
833 v0 = a0 + (p - (char *)Ra0);
834 } while (*p++ != '\0');
839 void psxBios_strchr() { // 0x1e
843 void psxBios_strrchr() { // 0x1f
847 void psxBios_strpbrk() { // 0x20
848 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
850 while ((c = *p1++) != '\0') {
851 for (scanp = p2; (sc = *scanp++) != '\0';) {
853 v0 = a0 + (p1 - 1 - (char *)Ra0);
860 // BUG: return a0 instead of NULL if not found
864 void psxBios_strspn() { // 0x21
867 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
868 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
869 if (*p2 == '\0') break;
872 v0 = p1 - (char *)Ra0; pc0 = ra;
875 void psxBios_strcspn() { // 0x22
878 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
879 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
880 if (*p2 != '\0') break;
883 v0 = p1 - (char *)Ra0; pc0 = ra;
886 void psxBios_strtok() { // 0x23
887 char *pcA0 = (char *)Ra0;
888 char *pcRet = strtok(pcA0, (char *)Ra1);
890 v0 = a0 + pcRet - pcA0;
896 void psxBios_strstr() { // 0x24
897 char *p = (char *)Ra0, *p1, *p2;
903 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
908 v0 = a0 + (p - (char *)Ra0);
919 void psxBios_toupper() { // 0x25
920 v0 = (s8)(a0 & 0xff);
921 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
925 void psxBios_tolower() { // 0x26
926 v0 = (s8)(a0 & 0xff);
927 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
931 static void do_memset(u32 dst, u32 v, s32 len)
937 if (db != INVALID_PTR)
941 psxCpu->Clear(dst, (len + 3) / 4);
944 static void do_memcpy(u32 dst, u32 src, s32 len)
946 u32 d = dst, s = src;
949 const u8 *sb = PSXM(s);
951 if (db != INVALID_PTR && sb != INVALID_PTR)
956 psxCpu->Clear(dst, (len + 3) / 4);
959 static void psxBios_memcpy();
961 static void psxBios_bcopy() { // 0x27 - memcpy with args swapped
962 //PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x27], a0, a1, a2);
963 u32 ret = a0, cycles = 0;
964 if (a0 == 0) // ...but it checks src this time
971 do_memcpy(a1, a0, a2);
977 mips_return_c(ret, cycles + 5);
980 static void psxBios_bzero() { // 0x28
981 /* Same as memset here (See memset below) */
982 u32 ret = a0, cycles;
983 if (a0 == 0 || (s32)a1 <= 0)
988 do_memset(a0, 0, a1);
992 // todo: many more cycles due to uncached bios mem
993 mips_return_c(ret, cycles + 5);
996 void psxBios_bcmp() { // 0x29
997 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
999 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
1001 while ((s32)a2-- > 0) {
1002 if (*p1++ != *p2++) {
1003 v0 = *p1 - *p2; // BUG: compare the NEXT byte
1012 static void psxBios_memcpy() { // 0x2a
1013 u32 ret = a0, cycles = 0;
1016 mips_return_c(0, 4);
1021 do_memcpy(a0, a1, a2);
1027 mips_return_c(ret, cycles + 5);
1030 static void psxBios_memset() { // 0x2b
1031 u32 ret = a0, cycles;
1032 if (a0 == 0 || (s32)a2 <= 0)
1034 mips_return_c(0, 6);
1037 do_memset(a0, a1, a2);
1041 // todo: many more cycles due to uncached bios mem
1042 mips_return_c(ret, cycles + 5);
1045 void psxBios_memmove() { // 0x2c
1046 u32 ret = a0, cycles = 0;
1049 mips_return_c(0, 4);
1053 if ((s32)a2 > 0 && a0 > a1 && a0 < a1 + a2) {
1054 u32 dst = a0, len = a2 + 1;
1057 while ((s32)a2 >= 0) { // BUG: copies one more byte here
1058 const u8 *sb = PSXM(a1);
1060 if (db != INVALID_PTR && sb != INVALID_PTR)
1066 psxCpu->Clear(dst, (len + 3) / 4);
1067 cycles = 10 + len * 8;
1068 } else if ((s32)a2 > 0) {
1069 do_memcpy(a0, a1, a2);
1075 mips_return_c(ret, cycles + 5);
1078 void psxBios_memcmp() { // 0x2d
1082 void psxBios_memchr() { // 0x2e
1083 char *p = (char *)Ra0;
1085 if (a0 == 0 || a2 > 0x7FFFFFFF)
1091 while ((s32)a2-- > 0) {
1092 if (*p++ != (s8)a1) continue;
1093 v0 = a0 + (p - (char *)Ra0 - 1);
1101 static void psxBios_rand() { // 0x2f
1102 u32 s = loadRam32(A_RND_SEED) * 1103515245 + 12345;
1103 storeRam32(A_RND_SEED, s);
1105 mips_return_c((s >> 16) & 0x7fff, 12+37);
1108 static void psxBios_srand() { // 0x30
1109 storeRam32(A_RND_SEED, a0);
1110 mips_return_void_c(3);
1113 static u32 qscmpfunc, qswidth;
1115 static inline int qscmp(char *a, char *b) {
1118 a0 = sa0 + (a - (char *)PSXM(sa0));
1119 a1 = sa0 + (b - (char *)PSXM(sa0));
1121 softCall(qscmpfunc);
1127 static inline void qexchange(char *i, char *j) {
1138 static inline void q3exchange(char *i, char *j, char *k) {
1150 static void qsort_main(char *a, char *l) {
1151 char *i, *j, *lp, *hp;
1156 if ((n = l - a) <= qswidth)
1158 n = qswidth * (n / (2 * qswidth));
1164 if ((c = qscmp(i, lp)) == 0) {
1165 qexchange(i, lp -= qswidth);
1176 if ((c = qscmp(hp, j)) == 0) {
1177 qexchange(hp += qswidth, j);
1182 q3exchange(i, hp += qswidth, j);
1196 if (lp - a >= l - hp) {
1197 qsort_main(hp + qswidth, l);
1206 q3exchange(j, lp -= qswidth, i);
1211 void psxBios_qsort() { // 0x31
1214 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1219 // this isn't how the real bios works, but maybe good enough
1220 static void psxBios_malloc() { // 0x33
1221 u32 *heap_addr, *heap_end;
1222 u32 *chunk, *newchunk = NULL;
1223 unsigned int dsize = 0, csize, cstat;
1225 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0);
1226 heap_addr = loadRam32ptr(A_HEAP_BASE);
1227 heap_end = loadRam32ptr(A_HEAP_END);
1228 if (heap_addr >= heap_end) {
1234 // scan through heap and combine free chunks of space
1237 while(chunk < heap_end) {
1238 // get size and status of actual chunk
1239 csize = ((u32)*chunk) & 0xfffffffc;
1240 cstat = ((u32)*chunk) & 1;
1242 // most probably broken heap descriptor
1243 // this fixes Burning Road
1246 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1251 // it's a free chunk
1256 colflag = 1; // let's begin a new collection of free memory
1258 else dsize += (csize+4); // add the new size including header
1260 // not a free chunk: did we start a collection ?
1262 if(colflag == 1) { // collection is over
1264 *newchunk = SWAP32(dsize | 1);
1269 chunk = (u32*)((uptr)chunk + csize + 4);
1271 // if neccessary free memory on end of heap
1273 *newchunk = SWAP32(dsize | 1);
1276 csize = ((u32)*chunk) & 0xfffffffc;
1277 cstat = ((u32)*chunk) & 1;
1278 dsize = (a0 + 3) & 0xfffffffc;
1280 // exit on uninitialized heap
1281 if (chunk == NULL) {
1282 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1288 // search an unused chunk that is big enough until the end of the heap
1289 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1290 chunk = (u32*)((uptr)chunk + csize + 4);
1292 // catch out of memory
1293 if(chunk >= heap_end) {
1294 printf("malloc %x,%x: Out of memory error!\n",
1300 csize = ((u32)*chunk) & 0xfffffffc;
1301 cstat = ((u32)*chunk) & 1;
1305 if(dsize == csize) {
1306 // chunk has same size
1307 *chunk &= 0xfffffffc;
1308 } else if (dsize > csize) {
1313 *chunk = SWAP32(dsize);
1314 newchunk = (u32*)((uptr)chunk + dsize + 4);
1315 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1318 // return pointer to allocated memory
1319 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1321 //printf ("malloc %x,%x\n", v0, a0);
1325 static void psxBios_free() { // 0x34
1326 PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1327 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1328 mips_return_void_c(5);
1331 static void psxBios_calloc() { // 0x37
1333 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1335 a0 = size = a0 * a1;
1339 a0 = ret; a1 = size;
1342 mips_return_c(ret, 21);
1345 void psxBios_realloc() { // 0x38
1349 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1353 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1358 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1363 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1364 /* Note that it is not quite implemented this way here. */
1374 /* InitHeap(void *block , int n) */
1375 static void psxBios_InitHeap() { // 0x39
1376 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1378 storeRam32(A_HEAP_BASE, a0);
1379 storeRam32(A_HEAP_SIZE, a1);
1380 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1381 storeRam32(A_HEAP_FLAG, 0);
1384 mips_return_void_c(14);
1387 void psxBios_getchar() { //0x3b
1388 v0 = getchar(); pc0 = ra;
1391 static void psxBios_printf_psxout() { // 0x3f
1400 if (psp != INVALID_PTR) {
1401 memcpy(save, psp, 4 * 4);
1402 psxMu32ref(sp) = SWAP32((u32)a0);
1403 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1404 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1405 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1417 tmp2[j++] = Ra0[i]; goto _start;
1419 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1430 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1434 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1440 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1442 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1444 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1446 *ptmp++ = Ra0[i]; break;
1456 if (psp != INVALID_PTR)
1457 memcpy(psp, save, 4 * 4);
1460 SysPrintf("%s", tmp);
1463 void psxBios_printf() { // 0x3f
1464 psxBios_printf_psxout();
1468 void psxBios_format() { // 0x41
1469 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1471 CreateMcd(Config.Mcd1);
1472 LoadMcd(1, Config.Mcd1);
1475 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1477 CreateMcd(Config.Mcd2);
1478 LoadMcd(2, Config.Mcd2);
1488 static void psxBios_SystemErrorUnresolvedException() {
1489 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1490 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1491 storeRam32(0xfffc, 0x12345678);
1493 mips_return_void_c(1000);
1496 static void FlushCache() {
1497 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1498 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1500 // runs from uncached mem so tons of cycles
1505 * long Load(char *name, struct EXEC *header);
1508 void psxBios_Load() { // 0x42
1513 if (pa1 != INVALID_PTR && LoadCdromFile(Ra0, &eheader) == 0) {
1514 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1515 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1519 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1525 * int Exec(struct EXEC *header , int argc , char **argv);
1528 void psxBios_Exec() { // 43
1529 EXEC *header = (EXEC *)castRam32ptr(a0);
1533 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1535 header->_sp = SWAP32(sp);
1536 header->_fp = SWAP32(fp);
1537 header->_sp = SWAP32(sp);
1538 header->_gp = SWAP32(gp);
1539 header->ret = SWAP32(ra);
1540 header->base = SWAP32(s0);
1542 ptr = SWAP32(header->b_addr);
1543 len = SWAP32(header->b_size);
1549 if (header->S_addr != 0)
1550 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1552 gp = SWAP32(header->gp0);
1560 pc0 = SWAP32(header->_pc0);
1563 static void psxBios_FlushCache() { // 44
1564 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1569 void psxBios_GPU_dw() { // 0x46
1574 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1577 GPU_writeData(0xa0000000);
1578 GPU_writeData((a1<<0x10)|(a0&0xffff));
1579 GPU_writeData((a3<<0x10)|(a2&0xffff));
1581 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1584 GPU_writeData(SWAPu32(*ptr++));
1590 void psxBios_mem2vram() { // 0x47
1592 gpuSyncPluginSR(); // flush
1593 GPU_writeData(0xa0000000);
1594 GPU_writeData((a1<<0x10)|(a0&0xffff));
1595 GPU_writeData((a3<<0x10)|(a2&0xffff));
1596 size = ((((a2 * a3) / 2) >> 4) << 16);
1597 GPU_writeStatus(0x04000002);
1598 psxHwWrite32(0x1f8010f4,0);
1599 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1600 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1601 psxHwWrite32(0x1f8010a4, size | 0x10);
1602 psxHwWrite32(0x1f8010a8,0x01000201);
1607 void psxBios_SendGPU() { // 0x48
1608 GPU_writeStatus(a0);
1613 void psxBios_GPU_cw() { // 0x49
1620 void psxBios_GPU_cwb() { // 0x4a
1621 u32 *ptr = (u32*)Ra0;
1626 GPU_writeData(SWAPu32(*ptr++));
1632 void psxBios_GPU_SendPackets() { //4b:
1634 GPU_writeStatus(0x04000002);
1635 psxHwWrite32(0x1f8010f4,0);
1636 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1637 psxHwWrite32(0x1f8010a0,a0);
1638 psxHwWrite32(0x1f8010a4,0);
1639 psxHwWrite32(0x1f8010a8,0x010000401);
1643 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1644 psxHwWrite32(0x1f8010a8,0x00000401);
1645 GPU_writeData(0x0400000);
1646 GPU_writeData(0x0200000);
1647 GPU_writeData(0x0100000);
1652 void psxBios_GPU_GetGPUStatus() { // 0x4d
1653 v0 = GPU_readStatus();
1659 void psxBios_LoadExec() { // 51
1660 EXEC *header = (EXEC*)PSXM(0xf000);
1664 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1666 s_addr = a1; s_size = a2;
1671 header->S_addr = s_addr;
1672 header->s_size = s_size;
1674 a0 = 0xf000; a1 = 0; a2 = 0;
1678 void psxBios__bu_init() { // 70
1680 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1683 DeliverEvent(0xf0000011, 0x0004);
1684 DeliverEvent(0xf4000001, 0x0004);
1689 void psxBios__96_init() { // 71
1691 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1697 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1698 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1699 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1701 static void psxBios_DequeueCdIntr_() {
1702 psxBios_SysDeqIntRP_(0, 0x91d0);
1703 psxBios_SysDeqIntRP_(0, 0x91e0);
1707 static void psxBios_DequeueCdIntr() { // a3
1708 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1709 psxBios_DequeueCdIntr_();
1712 static void psxBios_CdRemove() { // 56, 72
1713 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1715 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1716 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1717 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1718 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1719 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1720 psxBios_DequeueCdIntr_();
1722 // EnterCriticalSection - should be done at the beginning,
1723 // but this way is much easier to implement
1729 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1731 static void psxBios_SetConf() { // 9c
1732 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1733 setup_tt(a1, a0, a2);
1734 psxRegs.CP0.n.SR |= 0x401;
1735 mips_return_void_c(500);
1738 static void psxBios_GetConf() { // 9d
1739 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1740 storeRam32(a0, loadRam32(A_CONF_EvCB));
1741 storeRam32(a1, loadRam32(A_CONF_TCB));
1742 storeRam32(a2, loadRam32(A_CONF_SP));
1743 mips_return_void_c(10);
1746 void psxBios_SetMem() { // 9f
1747 u32 new = psxHu32(0x1060);
1750 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1755 psxHu32ref(0x1060) = SWAP32(new);
1756 psxMu32ref(0x060) = a0;
1757 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1761 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1762 psxMu32ref(0x060) = a0;
1763 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1766 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1773 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1774 static void psxBios_get_cd_status() // a6
1776 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1781 static void psxBios__card_info() { // ab
1782 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1784 storeRam32(A_CARD_CHAN1, a0);
1791 if (McdDisable[port & 1])
1795 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1800 if (McdDisable[0] && McdDisable[1])
1803 DeliverEvent(0xf0000011, 0x0004);
1804 // DeliverEvent(0xf4000001, 0x0004);
1805 DeliverEvent(0xf4000001, ret);
1809 void psxBios__card_load() { // ac
1811 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1814 storeRam32(A_CARD_CHAN1, a0);
1816 // DeliverEvent(0xf0000011, 0x0004);
1817 DeliverEvent(0xf4000001, 0x0004);
1822 static void psxBios_GetSystemInfo() { // b4
1824 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1825 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1828 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1829 case 2: ret = 0xbfc0012c; break;
1830 case 5: ret = loadRam32(0x60) << 10; break;
1832 mips_return_c(ret, 20);
1835 /* System calls B0 */
1837 static u32 psxBios_SysMalloc_(u32 size);
1839 static void psxBios_SysMalloc() { // B 00
1840 u32 ret = psxBios_SysMalloc_(a0);
1842 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1843 mips_return_c(ret, 33);
1846 void psxBios_SetRCnt() { // 02
1848 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1855 psxRcntWtarget(a0, a1);
1856 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1857 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1858 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1859 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1860 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1862 psxRcntWmode(a0, mode);
1867 void psxBios_GetRCnt() { // 03
1869 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1874 case 0: v0 = psxRcntRcount0(); break;
1875 case 1: v0 = psxRcntRcount1(); break;
1876 case 2: v0 = psxRcntRcount2(); break;
1877 case 3: v0 = 0; break;
1882 void psxBios_StartRCnt() { // 04
1884 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1888 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1889 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1893 void psxBios_StopRCnt() { // 05
1895 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1899 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1900 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1904 void psxBios_ResetRCnt() { // 06
1906 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1911 psxRcntWmode(a0, 0);
1912 psxRcntWtarget(a0, 0);
1913 psxRcntWcount(a0, 0);
1918 static u32 DeliverEvent(u32 class, u32 spec) {
1919 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1920 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1921 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1922 u32 i, lim = evcb_len / 0x1c;
1924 //printf("%s %08x %x\n", __func__, class, spec);
1925 for (i = 0; i < lim; i++, ev++) {
1927 if (SWAP32(ev->status) != EvStACTIVE)
1930 if (SWAP32(ev->class) != class)
1933 if (SWAP32(ev->spec) != spec)
1936 ret = SWAP32(ev->mode);
1937 if (ret == EvMdMARK) {
1938 ev->status = SWAP32(EvStALREADY);
1942 if (ret == EvMdCALL) {
1943 ret = SWAP32(ev->fhandler);
1955 static u32 UnDeliverEvent(u32 class, u32 spec) {
1956 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1957 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1958 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1959 u32 i, lim = evcb_len / 0x1c;
1961 for (i = 0; i < lim; i++, ev++) {
1963 if (SWAP32(ev->status) != EvStALREADY)
1966 if (SWAP32(ev->class) != class)
1969 if (SWAP32(ev->spec) != spec)
1972 if (SWAP32(ev->mode) == EvMdMARK)
1973 ev->status = SWAP32(EvStACTIVE);
1979 static void psxBios_DeliverEvent() { // 07
1981 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1983 ret = DeliverEvent(a0, a1);
1987 static s32 get_free_EvCB_slot() {
1988 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1989 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1992 for (i = 0; i < lim; i++, ev++) {
1994 if (ev->status == SWAP32(EvStUNUSED))
2000 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2001 u32 ret = get_free_EvCB_slot();
2002 if ((s32)ret >= 0) {
2003 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2004 ev->class = SWAP32(class);
2005 ev->status = SWAP32(EvStDISABLED);
2006 ev->spec = SWAP32(spec);
2007 ev->mode = SWAP32(mode);
2008 ev->fhandler = SWAP32(func);
2014 static void psxBios_OpenEvent() { // 08
2015 u32 ret = OpenEvent(a0, a1, a2, a3);
2016 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2017 biosB0n[0x08], a0, a1, a2, a3, ret);
2018 mips_return_c(ret, 36);
2021 static void CloseEvent(u32 ev)
2023 u32 base = loadRam32(A_TT_EvCB);
2024 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2027 static void psxBios_CloseEvent() { // 09
2028 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2029 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2031 mips_return_c(1, 10);
2034 static void psxBios_WaitEvent() { // 0a
2035 u32 base = loadRam32(A_TT_EvCB);
2036 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2037 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2040 if (status == EvStALREADY) {
2041 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2045 if (status != EvStACTIVE)
2047 mips_return_c(0, 2);
2051 // retrigger this hlecall after the next emulation event
2053 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2054 psxRegs.cycle = next_interupt;
2058 static void psxBios_TestEvent() { // 0b
2059 u32 base = loadRam32(A_TT_EvCB);
2060 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2062 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2063 if (status == EvStALREADY) {
2064 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2068 mips_return_c(ret, 15);
2071 static void psxBios_EnableEvent() { // 0c
2072 u32 base = loadRam32(A_TT_EvCB);
2073 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2074 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2075 if (status != EvStUNUSED)
2076 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2078 mips_return_c(1, 15);
2081 static void psxBios_DisableEvent() { // 0d
2082 u32 base = loadRam32(A_TT_EvCB);
2083 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2084 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2085 if (status != EvStUNUSED)
2086 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2088 mips_return_c(1, 15);
2092 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2095 void psxBios_OpenTh() { // 0e
2096 TCB *tcb = loadRam32ptr(A_TT_TCB);
2097 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2100 for (th = 1; th < limit; th++)
2102 if (tcb[th].status != SWAP32(0x4000)) break;
2106 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2107 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2109 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2111 mips_return_c(0xffffffff, 20);
2114 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2116 tcb[th].status = SWAP32(0x4000);
2117 tcb[th].mode = SWAP32(0x1000);
2118 tcb[th].epc = SWAP32(a0);
2119 tcb[th].reg[30] = SWAP32(a1); // fp
2120 tcb[th].reg[29] = SWAP32(a1); // sp
2121 tcb[th].reg[28] = SWAP32(a2); // gp
2123 mips_return_c(0xff000000 + th, 34);
2127 * int CloseTh(long thread);
2130 static void psxBios_CloseTh() { // 0f
2131 u32 tcb = loadRam32(A_TT_TCB);
2132 u32 th = a0 & 0xffff;
2134 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2135 // in the usual bios fashion no checks, just write and return 1
2136 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2138 mips_return_c(1, 11);
2142 * int ChangeTh(long thread);
2145 void psxBios_ChangeTh() { // 10
2146 u32 tcbBase = loadRam32(A_TT_TCB);
2147 u32 th = a0 & 0xffff;
2149 // this is quite spammy
2150 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2152 // without doing any argument checks, just issue a syscall
2153 // (like the real bios does)
2155 a1 = tcbBase + th * sizeof(TCB);
2160 void psxBios_InitPAD() { // 0x12
2161 u32 i, *ram32 = (u32 *)psxM;
2162 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2164 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2165 ram32[A_PAD_DR_DST/4] = 0;
2166 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2167 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2168 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2169 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2170 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2171 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2172 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2173 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2175 for (i = 0; i < a1; i++) {
2177 storeRam8(a0 + i, 0);
2179 for (i = 0; i < a3; i++) {
2181 storeRam8(a2 + i, 0);
2183 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2185 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2187 mips_return_c(1, 200);
2190 void psxBios_StartPAD() { // 13
2191 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2193 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2194 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2195 psxHwWrite16(0x1f801070, ~1);
2196 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2197 storeRam32(A_PAD_ACK_VBL, 1);
2198 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2199 psxRegs.CP0.n.SR |= 0x401;
2201 mips_return_c(1, 300);
2204 void psxBios_StopPAD() { // 14
2205 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2206 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2207 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2208 psxRegs.CP0.n.SR |= 0x401;
2209 mips_return_void_c(200);
2212 static void psxBios_PAD_init() { // 15
2214 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2215 if (a0 == 0x20000000 || a0 == 0x20000001)
2218 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2219 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2222 storeRam32(A_PAD_DR_DST, dst);
2225 mips_return_c(ret, 100);
2228 static u32 psxBios_PAD_dr_() {
2229 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2230 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2231 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2232 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2233 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2235 dst[0] = buf1[3], dst[1] = buf1[2];
2236 if (buf1[1] == 0x23) {
2237 dst[0] |= 0xc7, dst[1] |= 7;
2238 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2239 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2242 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2244 dst[2] = buf2[3], dst[3] = buf2[2];
2245 if (buf2[1] == 0x23) {
2246 dst[2] |= 0xc7, dst[3] |= 7;
2247 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2248 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2252 return SWAP32(*(u32 *)dst);
2255 static void psxBios_PAD_dr() { // 16
2256 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2257 u32 ret = psxBios_PAD_dr_();
2261 static void psxBios_ReturnFromException() { // 17
2262 u32 tcbPtr = loadRam32(A_TT_PCB);
2263 const TCB *tcb = loadRam32ptr(tcbPtr);
2267 for (i = 1; i < 32; i++)
2268 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2269 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2270 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2271 sr = SWAP32(tcb->sr);
2273 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2274 pc0 = k0 = SWAP32(tcb->epc);
2276 // the interpreter wants to know about sr changes, so do a MTC0
2277 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2278 MTC0(&psxRegs, 12, sr);
2284 void psxBios_ResetEntryInt() { // 18
2285 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2287 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2288 mips_return_void_c(5);
2291 void psxBios_HookEntryInt() { // 19
2292 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2294 storeRam32(A_EEXIT_PTR, a0);
2295 mips_return_void_c(3);
2298 static void psxBios_UnDeliverEvent() { // 0x20
2300 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2302 ret = UnDeliverEvent(a0, a1);
2306 static void buopen(int mcd, char *ptr, char *cfg)
2309 char *mcd_data = ptr;
2311 strcpy(FDesc[1 + mcd].name, Ra0+5);
2312 FDesc[1 + mcd].offset = 0;
2313 FDesc[1 + mcd].mode = a1;
2315 for (i=1; i<16; i++) {
2316 const char *fptr = mcd_data + 128 * i;
2317 if ((*fptr & 0xF0) != 0x50) continue;
2318 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2319 FDesc[1 + mcd].mcfile = i;
2320 PSXBIOS_LOG("open %s\n", fptr+0xa);
2324 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2325 for (i=1; i<16; i++) {
2326 int j, xor, nblk = a1 >> 16;
2328 char *fptr = mcd_data + 128 * i;
2330 if ((*fptr & 0xF0) != 0xa0) continue;
2332 FDesc[1 + mcd].mcfile = i;
2335 fptr[5] = 0x20 * nblk;
2338 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2339 pptr = fptr2 = fptr;
2340 for(j=2; j<=nblk; j++) {
2342 for(i++; i<16; i++) {
2345 memset(fptr2, 0, 128);
2346 fptr2[0] = j < nblk ? 0x52 : 0x53;
2349 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2354 /* shouldn't this return ENOSPC if i == 16? */
2356 pptr[8] = pptr[9] = 0xff;
2357 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2359 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2361 /* just go ahead and resave them all */
2362 SaveMcd(cfg, ptr, 128, 128 * 15);
2365 /* shouldn't this return ENOSPC if i == 16? */
2370 * int open(char *name , int mode);
2373 void psxBios_open() { // 0x32
2376 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2380 if (pa0 != INVALID_PTR) {
2381 if (!strncmp(pa0, "bu00", 4)) {
2382 buopen(1, Mcd1Data, Config.Mcd1);
2385 if (!strncmp(pa0, "bu10", 4)) {
2386 buopen(2, Mcd2Data, Config.Mcd2);
2394 * int lseek(int fd , int offset , int whence);
2397 void psxBios_lseek() { // 0x33
2399 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2404 FDesc[a0].offset = a1;
2406 // DeliverEvent(0xf0000011, 0x0004);
2407 // DeliverEvent(0xf4000001, 0x0004);
2411 FDesc[a0].offset+= a1;
2412 v0 = FDesc[a0].offset;
2421 * int read(int fd , void *buf , int nbytes);
2424 void psxBios_read() { // 0x34
2429 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2434 if (pa1 != INVALID_PTR) {
2436 case 2: buread(pa1, 1, a2); break;
2437 case 3: buread(pa1, 2, a2); break;
2445 * int write(int fd , void *buf , int nbytes);
2448 void psxBios_write() { // 0x35/0x03
2452 if (a0 != 1) // stdout
2453 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2456 if (pa1 == INVALID_PTR) {
2461 if (a0 == 1) { // stdout
2465 if (Config.PsxOut) while (a2 > 0) {
2466 SysPrintf("%c", *ptr++); a2--;
2472 case 2: buwrite(pa1, 1, a2); break;
2473 case 3: buwrite(pa1, 2, a2); break;
2479 static void psxBios_write_psxout() {
2480 if (a0 == 1) { // stdout
2481 const char *ptr = Ra1;
2484 if (ptr != INVALID_PTR)
2486 SysPrintf("%c", *ptr++);
2490 static void psxBios_putchar_psxout() { // 3d
2491 SysPrintf("%c", (char)a0);
2494 static void psxBios_puts_psxout() { // 3e/3f
2495 SysPrintf("%s", Ra0);
2499 * int close(int fd);
2502 void psxBios_close() { // 0x36
2504 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2511 void psxBios_putchar() { // 3d
2512 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2516 void psxBios_puts() { // 3e/3f
2517 if (Config.PsxOut) SysPrintf("%s", Ra0);
2521 static void bufile(const u8 *mcd_data, u32 dir_) {
2522 struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(dir_);
2523 const char *pfile = ffile + 5;
2524 const u8 *data = mcd_data;
2525 int i = 0, match = 0;
2530 for (; nfile <= 15 && !match; nfile++) {
2533 head = nfile * 0x40;
2534 data = mcd_data + 128 * nfile;
2535 name = (const char *)data + 0x0a;
2536 if ((data[0] & 0xF0) != 0x50) continue;
2537 /* Bug link files show up as free block. */
2538 if (!name[0]) continue;
2540 for (i = 0; i < 20; i++) {
2541 if (pfile[i] == name[i] || pfile[i] == '?')
2542 dir->name[i] = name[i];
2543 else if (pfile[i] == '*') {
2544 int len = strlen(name + i);
2547 memcpy(dir->name + i, name + i, len + 1);
2558 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2559 nfile, dir->name, pfile, name, match);
2561 for (; nfile <= 15; nfile++, blocks++) {
2562 const u8 *data2 = mcd_data + 128 * nfile;
2563 const char *name = data2 + 0x0a;
2564 if ((data2[0] & 0xF0) != 0x50 || name[0])
2568 // nul char of full lenth name seems to overwrite .attr
2569 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2570 dir->size = 8192 * blocks;
2574 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2575 dir->attr, dir->size, dir->next, dir->head);
2579 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2582 static void psxBios_firstfile() { // 42
2583 char *pa0 = castRam8ptr(a0);
2585 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2589 snprintf(ffile, sizeof(ffile), "%s", pa0);
2591 strcpy(ffile + 5, "*"); // maybe?
2593 if (!strncmp(pa0, "bu00", 4)) {
2594 // firstfile() calls _card_read() internally, so deliver it's event
2595 DeliverEvent(0xf0000011, 0x0004);
2596 bufile(Mcd1Data, a1);
2597 } else if (!strncmp(pa0, "bu10", 4)) {
2598 // firstfile() calls _card_read() internally, so deliver it's event
2599 DeliverEvent(0xf0000011, 0x0004);
2600 bufile(Mcd2Data, a1);
2608 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2611 void psxBios_nextfile() { // 43
2612 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2615 if (!strncmp(ffile, "bu00", 4))
2616 bufile(Mcd1Data, a0);
2617 else if (!strncmp(ffile, "bu10", 4))
2618 bufile(Mcd2Data, a0);
2623 #define burename(mcd) { \
2624 for (i=1; i<16; i++) { \
2625 int namelen, j, xor = 0; \
2626 ptr = Mcd##mcd##Data + 128 * i; \
2627 if ((*ptr & 0xF0) != 0x50) continue; \
2628 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2629 namelen = strlen(Ra1+5); \
2630 memcpy(ptr+0xa, Ra1+5, namelen); \
2631 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2632 for (j=0; j<127; j++) xor^= ptr[j]; \
2634 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2641 * int rename(char *old, char *new);
2644 void psxBios_rename() { // 44
2651 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2656 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2657 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2661 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2670 #define budelete(mcd) { \
2671 for (i=1; i<16; i++) { \
2672 ptr = Mcd##mcd##Data + 128 * i; \
2673 if ((*ptr & 0xF0) != 0x50) continue; \
2674 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2675 *ptr = (*ptr & 0xf) | 0xA0; \
2676 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2677 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2684 * int delete(char *name);
2687 void psxBios_delete() { // 45
2693 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2698 if (pa0 != INVALID_PTR) {
2699 if (!strncmp(pa0, "bu00", 4)) {
2703 if (!strncmp(pa0, "bu10", 4)) {
2711 void psxBios_InitCARD() { // 4a
2712 u32 *ram32 = (u32 *)psxM;
2713 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2714 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2715 // (maybe) todo: early_card_irq, etc
2717 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2719 psxBios_FlushCache();
2720 mips_return_c(0, 34+13+15+6);
2723 void psxBios_StartCARD() { // 4b
2724 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2725 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2726 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2728 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2729 storeRam32(A_PAD_ACK_VBL, 1);
2730 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2731 storeRam32(A_CARD_IRQR_ENA, 1);
2732 psxRegs.CP0.n.SR |= 0x401;
2734 mips_return_c(1, 200);
2737 void psxBios_StopCARD() { // 4c
2738 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2739 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2740 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2741 storeRam32(A_CARD_IRQR_ENA, 0);
2742 psxRegs.CP0.n.SR |= 0x401;
2743 mips_return_void_c(200);
2746 void psxBios__card_write() { // 0x4e
2751 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2754 Function also accepts sector 400h (a bug).
2755 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2759 /* Invalid sectors */
2763 storeRam32(A_CARD_CHAN1, a0);
2766 if (pa2 != INVALID_PTR) {
2768 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2769 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2771 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2772 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2776 DeliverEvent(0xf0000011, 0x0004);
2777 // DeliverEvent(0xf4000001, 0x0004);
2782 void psxBios__card_read() { // 0x4f
2787 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2790 Function also accepts sector 400h (a bug).
2791 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2795 /* Invalid sectors */
2799 storeRam32(A_CARD_CHAN1, a0);
2802 if (pa2 != INVALID_PTR) {
2804 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2806 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2810 DeliverEvent(0xf0000011, 0x0004);
2811 // DeliverEvent(0xf4000001, 0x0004);
2816 void psxBios__new_card() { // 0x50
2818 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2824 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2825 void psxBios__get_error(void) // 55
2827 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2832 void psxBios_Krom2RawAdd() { // 0x51
2835 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2836 const u32 table_8140[][2] = {
2837 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2838 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2839 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2840 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2841 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2842 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2843 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2844 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2845 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2849 const u32 table_889f[][2] = {
2850 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2851 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2852 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2853 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2854 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2855 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2856 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2857 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2861 if (a0 >= 0x8140 && a0 <= 0x84be) {
2862 while (table_8140[i][0] <= a0) i++;
2863 a0 -= table_8140[i - 1][0];
2864 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2865 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2866 while (table_889f[i][0] <= a0) i++;
2867 a0 -= table_889f[i - 1][0];
2868 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2876 void psxBios_GetC0Table() { // 56
2877 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2878 log_unhandled("GetC0Table @%08x\n", ra);
2880 mips_return_c(A_C0_TABLE, 3);
2883 void psxBios_GetB0Table() { // 57
2884 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2885 log_unhandled("GetB0Table @%08x\n", ra);
2887 mips_return_c(A_B0_TABLE, 3);
2890 static void psxBios__card_chan() { // 0x58
2892 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2894 // todo: should return active slot chan
2895 // (active - which was last processed by irq code)
2896 ret = loadRam32(A_CARD_CHAN1);
2897 mips_return_c(ret, 8);
2900 static void psxBios_ChangeClearPad() { // 5b
2902 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2903 ret = loadRam32(A_PAD_ACK_VBL);
2904 storeRam32(A_PAD_ACK_VBL, a0);
2906 mips_return_c(ret, 6);
2909 static void psxBios__card_status() { // 5c
2910 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2916 static void psxBios__card_wait() { // 5d
2917 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2923 /* System calls C0 */
2925 static void psxBios_InitRCnt() { // 00
2927 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2928 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2929 for (i = 0; i < 3; i++) {
2930 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2931 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2932 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2934 psxBios_SysEnqIntRP_(a0, 0x6d88);
2935 mips_return_c(0, 9);
2938 static void psxBios_InitException() { // 01
2939 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2940 psxBios_SysEnqIntRP_(a0, 0x6da8);
2941 mips_return_c(0, 9);
2945 * int SysEnqIntRP(int index , long *queue);
2948 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2949 u32 old, base = loadRam32(A_TT_ExCB);
2951 old = loadRam32(base + (priority << 3));
2952 storeRam32(base + (priority << 3), chain_eptr);
2953 storeRam32(chain_eptr, old);
2954 mips_return_c(0, 9);
2957 static void psxBios_SysEnqIntRP() { // 02
2958 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2959 psxBios_SysEnqIntRP_(a0, a1);
2963 * int SysDeqIntRP(int index , long *queue);
2966 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2967 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2968 u32 lim = 0, ret = 0;
2970 // as in original: no arg checks of any kind, bug if a1 == 0
2971 ptr = loadRam32(base + (priority << 3));
2973 next = loadRam32(ptr);
2974 if (ptr == chain_rm_eptr) {
2975 storeRam32(base + (priority << 3), next);
2980 while (next && next != chain_rm_eptr && lim++ < 100) {
2982 next = loadRam32(ptr);
2985 if (next == chain_rm_eptr) {
2986 next = loadRam32(next);
2987 storeRam32(ptr, next);
2994 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2996 mips_return_c(ret, 12);
2999 static void psxBios_SysDeqIntRP() { // 03
3000 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3001 psxBios_SysDeqIntRP_(a0, a1);
3004 static void psxBios_get_free_EvCB_slot() { // 04
3005 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3006 s32 ret = get_free_EvCB_slot();
3007 mips_return_c(ret, 0);
3010 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3011 storeRam32(base, 0);
3012 storeRam32(A_KMALLOC_PTR, base);
3013 storeRam32(A_KMALLOC_SIZE, size);
3014 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3017 // this should be much more complicated, but maybe that'll be enough
3018 static u32 psxBios_SysMalloc_(u32 size) {
3019 u32 ptr = loadRam32(A_KMALLOC_PTR);
3021 size = (size + 3) & ~3;
3022 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3023 storeRam32(ptr, size);
3027 static void psxBios_SysInitMemory() { // 08
3028 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3030 psxBios_SysInitMemory_(a0, a1);
3031 mips_return_void_c(12);
3034 static void psxBios_ChangeClearRCnt() { // 0a
3037 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3039 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3040 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3041 mips_return_c(ret, 8);
3044 static void psxBios_InitDefInt() { // 0c
3045 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3046 // should also clear the autoack table
3047 psxBios_SysEnqIntRP_(a0, 0x6d98);
3048 mips_return_c(0, 20 + 6*2);
3051 void psxBios_dummy() {
3052 u32 pc = (pc0 & 0x1fffff) - 4;
3053 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3054 : pc == 0xc0 ? biosC0n : NULL;
3055 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3056 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3057 (void)pc; (void)ntab;
3058 mips_return_c(0, 100);
3061 void (*biosA0[256])();
3062 // C0 and B0 overlap (end of C0 is start of B0)
3063 void (*biosC0[256+128])();
3064 void (**biosB0)() = biosC0 + 128;
3066 static void setup_mips_code()
3069 ptr = (u32 *)&psxM[A_SYSCALL];
3070 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3071 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3072 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3074 ptr = (u32 *)&psxM[A_EXCEPTION];
3075 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3076 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3077 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3078 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3079 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3080 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3081 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3082 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3083 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3084 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3086 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3087 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3088 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3090 ptr[0xb0/4] = HLEOP(hleop_exception);
3093 static const struct {
3097 { 0xbfc050a4, hleop_exc0_0_1 },
3098 { 0xbfc04fbc, hleop_exc0_0_2 },
3099 { 0xbfc0506c, hleop_exc0_1_1 },
3100 { 0xbfc04dec, hleop_exc0_1_2 },
3101 { 0x1a00, hleop_exc0_2_2 },
3102 { 0x19c8, hleop_exc1_0_1 },
3103 { 0x18bc, hleop_exc1_0_2 },
3104 { 0x1990, hleop_exc1_1_1 },
3105 { 0x1858, hleop_exc1_1_2 },
3106 { 0x1958, hleop_exc1_2_1 },
3107 { 0x17f4, hleop_exc1_2_2 },
3108 { 0x1920, hleop_exc1_3_1 },
3109 { 0x1794, hleop_exc1_3_2 },
3110 { 0x2458, hleop_exc3_0_2 },
3111 { 0x49bc, hleop_exc_padcard1 },
3112 { 0x4a4c, hleop_exc_padcard2 },
3115 static int chain_hle_op(u32 handler)
3119 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3120 if (chainfns[i].addr == handler)
3121 return chainfns[i].op;
3125 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3127 d[0] = SWAPu32(next);
3128 d[1] = SWAPu32(handler1);
3129 d[2] = SWAPu32(handler2);
3131 // install the hle traps
3132 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3133 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3136 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3138 u32 *ram32 = (u32 *)psxM;
3139 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3140 u32 p_excb, p_evcb, p_pcb, p_tcb;
3143 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3145 // the real bios doesn't care, but we just don't
3146 // want to crash in case of garbage parameters
3147 if (tcb_cnt > 1024) tcb_cnt = 1024;
3148 if (evcb_cnt > 1024) evcb_cnt = 1024;
3149 s_evcb = 0x1c * evcb_cnt;
3150 s_tcb = 0xc0 * tcb_cnt;
3152 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3153 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3154 p_excb = psxBios_SysMalloc_(s_excb);
3155 p_evcb = psxBios_SysMalloc_(s_evcb);
3156 p_pcb = psxBios_SysMalloc_(s_pcb);
3157 p_tcb = psxBios_SysMalloc_(s_tcb);
3159 // "table of tables". Some games modify it
3160 assert(A_TT_ExCB == 0x0100);
3161 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3162 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3163 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3164 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3165 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3166 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3167 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3168 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3169 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3170 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3171 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3172 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3174 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3175 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3176 storeRam32(p_excb + 4*4, 0x0000); // chain2
3177 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3179 storeRam32(p_pcb, p_tcb);
3180 storeRam32(p_tcb, 0x4000); // first TCB
3181 for (i = 1; i < tcb_cnt; i++)
3182 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3185 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3186 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3187 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3188 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3189 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3191 storeRam32(A_CONF_EvCB, evcb_cnt);
3192 storeRam32(A_CONF_TCB, tcb_cnt);
3193 storeRam32(A_CONF_SP, stack);
3196 static const u32 gpu_ctl_def[] = {
3197 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3198 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3201 static const u32 gpu_data_def[] = {
3202 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3203 0xe5001000, 0xe6000000,
3204 0x02000000, 0x00000000, 0x01ff03ff
3208 static const u16 spu_config[] = {
3209 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3210 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3211 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3212 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3213 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3214 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3215 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3216 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3219 void psxBiosSetupBootState(void)
3221 boolean hle = Config.HLE;
3222 u32 *hw = (u32 *)psxH;
3225 // see also SetBootRegs()
3228 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3229 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3231 k0 = 0xbfc0d968; k1 = 0xf1c;
3232 ra = 0xf0001234; // just to easily detect attempts to return
3233 psxRegs.CP0.n.Cause = 0x20;
3234 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3236 hw[0x1000/4] = SWAP32(0x1f000000);
3237 hw[0x1004/4] = SWAP32(0x1f802000);
3238 hw[0x1008/4] = SWAP32(0x0013243f);
3239 hw[0x100c/4] = SWAP32(0x00003022);
3240 hw[0x1010/4] = SWAP32(0x0013243f);
3241 hw[0x1014/4] = SWAP32(0x200931e1);
3242 hw[0x1018/4] = SWAP32(0x00020943);
3243 hw[0x101c/4] = SWAP32(0x00070777);
3244 hw[0x1020/4] = SWAP32(0x0000132c);
3245 hw[0x1060/4] = SWAP32(0x00000b88);
3246 hw[0x1070/4] = SWAP32(0x00000001);
3247 hw[0x1074/4] = SWAP32(0x0000000c);
3248 hw[0x2040/4] = SWAP32(0x00000900);
3251 hw[0x10a0/4] = SWAP32(0x00ffffff);
3252 hw[0x10a8/4] = SWAP32(0x00000401);
3253 hw[0x10b0/4] = SWAP32(0x0008b000);
3254 hw[0x10b4/4] = SWAP32(0x00010200);
3255 hw[0x10e0/4] = SWAP32(0x000eccf4);
3256 hw[0x10e4/4] = SWAP32(0x00000400);
3257 hw[0x10e8/4] = SWAP32(0x00000002);
3258 hw[0x10f0/4] = SWAP32(0x00009099);
3259 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3268 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3269 GPU_writeStatus(gpu_ctl_def[i]);
3270 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3271 GPU_writeData(gpu_data_def[i]);
3272 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3275 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3276 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3279 #include "sjisfont.h"
3281 void psxBiosInit() {
3282 u32 *ptr, *ram32, *rom32;
3286 memset(psxM, 0, 0x10000);
3287 for(i = 0; i < 256; i++) {
3292 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3293 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3294 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3295 biosA0[0x3f] = psxBios_printf_psxout;
3297 if (!Config.HLE) return;
3299 for(i = 0; i < 256; i++) {
3300 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3301 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3302 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3305 biosA0[0x00] = psxBios_open;
3306 biosA0[0x01] = psxBios_lseek;
3307 biosA0[0x02] = psxBios_read;
3308 biosA0[0x03] = psxBios_write;
3309 biosA0[0x04] = psxBios_close;
3310 //biosA0[0x05] = psxBios_ioctl;
3311 //biosA0[0x06] = psxBios_exit;
3312 //biosA0[0x07] = psxBios_sys_a0_07;
3313 biosA0[0x08] = psxBios_getc;
3314 biosA0[0x09] = psxBios_putc;
3315 biosA0[0x0a] = psxBios_todigit;
3316 //biosA0[0x0b] = psxBios_atof;
3317 //biosA0[0x0c] = psxBios_strtoul;
3318 //biosA0[0x0d] = psxBios_strtol;
3319 biosA0[0x0e] = psxBios_abs;
3320 biosA0[0x0f] = psxBios_labs;
3321 biosA0[0x10] = psxBios_atoi;
3322 biosA0[0x11] = psxBios_atol;
3323 //biosA0[0x12] = psxBios_atob;
3324 biosA0[0x13] = psxBios_setjmp;
3325 biosA0[0x14] = psxBios_longjmp;
3326 biosA0[0x15] = psxBios_strcat;
3327 biosA0[0x16] = psxBios_strncat;
3328 biosA0[0x17] = psxBios_strcmp;
3329 biosA0[0x18] = psxBios_strncmp;
3330 biosA0[0x19] = psxBios_strcpy;
3331 biosA0[0x1a] = psxBios_strncpy;
3332 biosA0[0x1b] = psxBios_strlen;
3333 biosA0[0x1c] = psxBios_index;
3334 biosA0[0x1d] = psxBios_rindex;
3335 biosA0[0x1e] = psxBios_strchr;
3336 biosA0[0x1f] = psxBios_strrchr;
3337 biosA0[0x20] = psxBios_strpbrk;
3338 biosA0[0x21] = psxBios_strspn;
3339 biosA0[0x22] = psxBios_strcspn;
3340 biosA0[0x23] = psxBios_strtok;
3341 biosA0[0x24] = psxBios_strstr;
3342 biosA0[0x25] = psxBios_toupper;
3343 biosA0[0x26] = psxBios_tolower;
3344 biosA0[0x27] = psxBios_bcopy;
3345 biosA0[0x28] = psxBios_bzero;
3346 biosA0[0x29] = psxBios_bcmp;
3347 biosA0[0x2a] = psxBios_memcpy;
3348 biosA0[0x2b] = psxBios_memset;
3349 biosA0[0x2c] = psxBios_memmove;
3350 biosA0[0x2d] = psxBios_memcmp;
3351 biosA0[0x2e] = psxBios_memchr;
3352 biosA0[0x2f] = psxBios_rand;
3353 biosA0[0x30] = psxBios_srand;
3354 biosA0[0x31] = psxBios_qsort;
3355 //biosA0[0x32] = psxBios_strtod;
3356 biosA0[0x33] = psxBios_malloc;
3357 biosA0[0x34] = psxBios_free;
3358 //biosA0[0x35] = psxBios_lsearch;
3359 //biosA0[0x36] = psxBios_bsearch;
3360 biosA0[0x37] = psxBios_calloc;
3361 biosA0[0x38] = psxBios_realloc;
3362 biosA0[0x39] = psxBios_InitHeap;
3363 //biosA0[0x3a] = psxBios__exit;
3364 biosA0[0x3b] = psxBios_getchar;
3365 biosA0[0x3c] = psxBios_putchar;
3366 //biosA0[0x3d] = psxBios_gets;
3367 biosA0[0x3e] = psxBios_puts;
3368 biosA0[0x3f] = psxBios_printf;
3369 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3370 //biosA0[0x41] = psxBios_LoadTest;
3371 biosA0[0x42] = psxBios_Load;
3372 biosA0[0x43] = psxBios_Exec;
3373 biosA0[0x44] = psxBios_FlushCache;
3374 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3375 biosA0[0x46] = psxBios_GPU_dw;
3376 biosA0[0x47] = psxBios_mem2vram;
3377 biosA0[0x48] = psxBios_SendGPU;
3378 biosA0[0x49] = psxBios_GPU_cw;
3379 biosA0[0x4a] = psxBios_GPU_cwb;
3380 biosA0[0x4b] = psxBios_GPU_SendPackets;
3381 biosA0[0x4c] = psxBios_sys_a0_4c;
3382 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3383 //biosA0[0x4e] = psxBios_GPU_sync;
3384 //biosA0[0x4f] = psxBios_sys_a0_4f;
3385 //biosA0[0x50] = psxBios_sys_a0_50;
3386 biosA0[0x51] = psxBios_LoadExec;
3387 //biosA0[0x52] = psxBios_GetSysSp;
3388 //biosA0[0x53] = psxBios_sys_a0_53;
3389 //biosA0[0x54] = psxBios__96_init_a54;
3390 //biosA0[0x55] = psxBios__bu_init_a55;
3391 biosA0[0x56] = psxBios_CdRemove;
3392 //biosA0[0x57] = psxBios_sys_a0_57;
3393 //biosA0[0x58] = psxBios_sys_a0_58;
3394 //biosA0[0x59] = psxBios_sys_a0_59;
3395 //biosA0[0x5a] = psxBios_sys_a0_5a;
3396 //biosA0[0x5b] = psxBios_dev_tty_init;
3397 //biosA0[0x5c] = psxBios_dev_tty_open;
3398 //biosA0[0x5d] = psxBios_sys_a0_5d;
3399 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3400 //biosA0[0x5f] = psxBios_dev_cd_open;
3401 //biosA0[0x60] = psxBios_dev_cd_read;
3402 //biosA0[0x61] = psxBios_dev_cd_close;
3403 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3404 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3405 //biosA0[0x64] = psxBios_dev_cd_chdir;
3406 //biosA0[0x65] = psxBios_dev_card_open;
3407 //biosA0[0x66] = psxBios_dev_card_read;
3408 //biosA0[0x67] = psxBios_dev_card_write;
3409 //biosA0[0x68] = psxBios_dev_card_close;
3410 //biosA0[0x69] = psxBios_dev_card_firstfile;
3411 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3412 //biosA0[0x6b] = psxBios_dev_card_erase;
3413 //biosA0[0x6c] = psxBios_dev_card_undelete;
3414 //biosA0[0x6d] = psxBios_dev_card_format;
3415 //biosA0[0x6e] = psxBios_dev_card_rename;
3416 //biosA0[0x6f] = psxBios_dev_card_6f;
3417 biosA0[0x70] = psxBios__bu_init;
3418 biosA0[0x71] = psxBios__96_init;
3419 biosA0[0x72] = psxBios_CdRemove;
3420 //biosA0[0x73] = psxBios_sys_a0_73;
3421 //biosA0[0x74] = psxBios_sys_a0_74;
3422 //biosA0[0x75] = psxBios_sys_a0_75;
3423 //biosA0[0x76] = psxBios_sys_a0_76;
3424 //biosA0[0x77] = psxBios_sys_a0_77;
3425 //biosA0[0x78] = psxBios__96_CdSeekL;
3426 //biosA0[0x79] = psxBios_sys_a0_79;
3427 //biosA0[0x7a] = psxBios_sys_a0_7a;
3428 //biosA0[0x7b] = psxBios_sys_a0_7b;
3429 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3430 //biosA0[0x7d] = psxBios_sys_a0_7d;
3431 //biosA0[0x7e] = psxBios__96_CdRead;
3432 //biosA0[0x7f] = psxBios_sys_a0_7f;
3433 //biosA0[0x80] = psxBios_sys_a0_80;
3434 //biosA0[0x81] = psxBios_sys_a0_81;
3435 //biosA0[0x82] = psxBios_sys_a0_82;
3436 //biosA0[0x83] = psxBios_sys_a0_83;
3437 //biosA0[0x84] = psxBios_sys_a0_84;
3438 //biosA0[0x85] = psxBios__96_CdStop;
3439 //biosA0[0x86] = psxBios_sys_a0_86;
3440 //biosA0[0x87] = psxBios_sys_a0_87;
3441 //biosA0[0x88] = psxBios_sys_a0_88;
3442 //biosA0[0x89] = psxBios_sys_a0_89;
3443 //biosA0[0x8a] = psxBios_sys_a0_8a;
3444 //biosA0[0x8b] = psxBios_sys_a0_8b;
3445 //biosA0[0x8c] = psxBios_sys_a0_8c;
3446 //biosA0[0x8d] = psxBios_sys_a0_8d;
3447 //biosA0[0x8e] = psxBios_sys_a0_8e;
3448 //biosA0[0x8f] = psxBios_sys_a0_8f;
3449 biosA0[0x90] = hleExc0_1_2;
3450 biosA0[0x91] = hleExc0_0_2;
3451 biosA0[0x92] = hleExc0_1_1;
3452 biosA0[0x93] = hleExc0_0_1;
3453 //biosA0[0x94] = psxBios_sys_a0_94;
3454 //biosA0[0x95] = psxBios_sys_a0_95;
3455 //biosA0[0x96] = psxBios_AddCDROMDevice;
3456 //biosA0[0x97] = psxBios_AddMemCardDevide;
3457 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3458 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3459 //biosA0[0x9a] = psxBios_sys_a0_9a;
3460 //biosA0[0x9b] = psxBios_sys_a0_9b;
3461 biosA0[0x9c] = psxBios_SetConf;
3462 biosA0[0x9d] = psxBios_GetConf;
3463 //biosA0[0x9e] = psxBios_sys_a0_9e;
3464 biosA0[0x9f] = psxBios_SetMem;
3465 //biosA0[0xa0] = psxBios__boot;
3466 //biosA0[0xa1] = psxBios_SystemError;
3467 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3468 biosA0[0xa3] = psxBios_DequeueCdIntr;
3469 //biosA0[0xa4] = psxBios_sys_a0_a4;
3470 //biosA0[0xa5] = psxBios_ReadSector;
3471 biosA0[0xa6] = psxBios_get_cd_status;
3472 //biosA0[0xa7] = psxBios_bufs_cb_0;
3473 //biosA0[0xa8] = psxBios_bufs_cb_1;
3474 //biosA0[0xa9] = psxBios_bufs_cb_2;
3475 //biosA0[0xaa] = psxBios_bufs_cb_3;
3476 biosA0[0xab] = psxBios__card_info;
3477 biosA0[0xac] = psxBios__card_load;
3478 //biosA0[0axd] = psxBios__card_auto;
3479 //biosA0[0xae] = psxBios_bufs_cd_4;
3480 //biosA0[0xaf] = psxBios_sys_a0_af;
3481 //biosA0[0xb0] = psxBios_sys_a0_b0;
3482 //biosA0[0xb1] = psxBios_sys_a0_b1;
3483 //biosA0[0xb2] = psxBios_do_a_long_jmp
3484 //biosA0[0xb3] = psxBios_sys_a0_b3;
3485 biosA0[0xb4] = psxBios_GetSystemInfo;
3486 //*******************B0 CALLS****************************
3487 biosB0[0x00] = psxBios_SysMalloc;
3488 //biosB0[0x01] = psxBios_sys_b0_01;
3489 biosB0[0x02] = psxBios_SetRCnt;
3490 biosB0[0x03] = psxBios_GetRCnt;
3491 biosB0[0x04] = psxBios_StartRCnt;
3492 biosB0[0x05] = psxBios_StopRCnt;
3493 biosB0[0x06] = psxBios_ResetRCnt;
3494 biosB0[0x07] = psxBios_DeliverEvent;
3495 biosB0[0x08] = psxBios_OpenEvent;
3496 biosB0[0x09] = psxBios_CloseEvent;
3497 biosB0[0x0a] = psxBios_WaitEvent;
3498 biosB0[0x0b] = psxBios_TestEvent;
3499 biosB0[0x0c] = psxBios_EnableEvent;
3500 biosB0[0x0d] = psxBios_DisableEvent;
3501 biosB0[0x0e] = psxBios_OpenTh;
3502 biosB0[0x0f] = psxBios_CloseTh;
3503 biosB0[0x10] = psxBios_ChangeTh;
3504 //biosB0[0x11] = psxBios_psxBios_b0_11;
3505 biosB0[0x12] = psxBios_InitPAD;
3506 biosB0[0x13] = psxBios_StartPAD;
3507 biosB0[0x14] = psxBios_StopPAD;
3508 biosB0[0x15] = psxBios_PAD_init;
3509 biosB0[0x16] = psxBios_PAD_dr;
3510 biosB0[0x17] = psxBios_ReturnFromException;
3511 biosB0[0x18] = psxBios_ResetEntryInt;
3512 biosB0[0x19] = psxBios_HookEntryInt;
3513 //biosB0[0x1a] = psxBios_sys_b0_1a;
3514 //biosB0[0x1b] = psxBios_sys_b0_1b;
3515 //biosB0[0x1c] = psxBios_sys_b0_1c;
3516 //biosB0[0x1d] = psxBios_sys_b0_1d;
3517 //biosB0[0x1e] = psxBios_sys_b0_1e;
3518 //biosB0[0x1f] = psxBios_sys_b0_1f;
3519 biosB0[0x20] = psxBios_UnDeliverEvent;
3520 //biosB0[0x21] = psxBios_sys_b0_21;
3521 //biosB0[0x22] = psxBios_sys_b0_22;
3522 //biosB0[0x23] = psxBios_sys_b0_23;
3523 //biosB0[0x24] = psxBios_sys_b0_24;
3524 //biosB0[0x25] = psxBios_sys_b0_25;
3525 //biosB0[0x26] = psxBios_sys_b0_26;
3526 //biosB0[0x27] = psxBios_sys_b0_27;
3527 //biosB0[0x28] = psxBios_sys_b0_28;
3528 //biosB0[0x29] = psxBios_sys_b0_29;
3529 //biosB0[0x2a] = psxBios_sys_b0_2a;
3530 //biosB0[0x2b] = psxBios_sys_b0_2b;
3531 //biosB0[0x2c] = psxBios_sys_b0_2c;
3532 //biosB0[0x2d] = psxBios_sys_b0_2d;
3533 //biosB0[0x2e] = psxBios_sys_b0_2e;
3534 //biosB0[0x2f] = psxBios_sys_b0_2f;
3535 //biosB0[0x30] = psxBios_sys_b0_30;
3536 //biosB0[0x31] = psxBios_sys_b0_31;
3537 biosB0[0x32] = psxBios_open;
3538 biosB0[0x33] = psxBios_lseek;
3539 biosB0[0x34] = psxBios_read;
3540 biosB0[0x35] = psxBios_write;
3541 biosB0[0x36] = psxBios_close;
3542 //biosB0[0x37] = psxBios_ioctl;
3543 //biosB0[0x38] = psxBios_exit;
3544 //biosB0[0x39] = psxBios_sys_b0_39;
3545 //biosB0[0x3a] = psxBios_getc;
3546 //biosB0[0x3b] = psxBios_putc;
3547 biosB0[0x3c] = psxBios_getchar;
3548 biosB0[0x3d] = psxBios_putchar;
3549 //biosB0[0x3e] = psxBios_gets;
3550 biosB0[0x3f] = psxBios_puts;
3551 //biosB0[0x40] = psxBios_cd;
3552 biosB0[0x41] = psxBios_format;
3553 biosB0[0x42] = psxBios_firstfile;
3554 biosB0[0x43] = psxBios_nextfile;
3555 biosB0[0x44] = psxBios_rename;
3556 biosB0[0x45] = psxBios_delete;
3557 //biosB0[0x46] = psxBios_undelete;
3558 //biosB0[0x47] = psxBios_AddDevice;
3559 //biosB0[0x48] = psxBios_RemoteDevice;
3560 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3561 biosB0[0x4a] = psxBios_InitCARD;
3562 biosB0[0x4b] = psxBios_StartCARD;
3563 biosB0[0x4c] = psxBios_StopCARD;
3564 //biosB0[0x4d] = psxBios_sys_b0_4d;
3565 biosB0[0x4e] = psxBios__card_write;
3566 biosB0[0x4f] = psxBios__card_read;
3567 biosB0[0x50] = psxBios__new_card;
3568 biosB0[0x51] = psxBios_Krom2RawAdd;
3569 //biosB0[0x52] = psxBios_sys_b0_52;
3570 //biosB0[0x53] = psxBios_sys_b0_53;
3571 //biosB0[0x54] = psxBios__get_errno;
3572 biosB0[0x55] = psxBios__get_error;
3573 biosB0[0x56] = psxBios_GetC0Table;
3574 biosB0[0x57] = psxBios_GetB0Table;
3575 biosB0[0x58] = psxBios__card_chan;
3576 //biosB0[0x59] = psxBios_sys_b0_59;
3577 //biosB0[0x5a] = psxBios_sys_b0_5a;
3578 biosB0[0x5b] = psxBios_ChangeClearPad;
3579 biosB0[0x5c] = psxBios__card_status;
3580 biosB0[0x5d] = psxBios__card_wait;
3581 //*******************C0 CALLS****************************
3582 biosC0[0x00] = psxBios_InitRCnt;
3583 biosC0[0x01] = psxBios_InitException;
3584 biosC0[0x02] = psxBios_SysEnqIntRP;
3585 biosC0[0x03] = psxBios_SysDeqIntRP;
3586 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3587 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3588 //biosC0[0x06] = psxBios_ExceptionHandler;
3589 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3590 biosC0[0x08] = psxBios_SysInitMemory;
3591 //biosC0[0x09] = psxBios_SysInitKMem;
3592 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3593 //biosC0[0x0b] = psxBios_SystemError;
3594 biosC0[0x0c] = psxBios_InitDefInt;
3595 //biosC0[0x0d] = psxBios_sys_c0_0d;
3596 //biosC0[0x0e] = psxBios_sys_c0_0e;
3597 //biosC0[0x0f] = psxBios_sys_c0_0f;
3598 //biosC0[0x10] = psxBios_sys_c0_10;
3599 //biosC0[0x11] = psxBios_sys_c0_11;
3600 //biosC0[0x12] = psxBios_InstallDevices;
3601 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3602 //biosC0[0x14] = psxBios_sys_c0_14;
3603 //biosC0[0x15] = psxBios__cdevinput;
3604 //biosC0[0x16] = psxBios__cdevscan;
3605 //biosC0[0x17] = psxBios__circgetc;
3606 //biosC0[0x18] = psxBios__circputc;
3607 //biosC0[0x19] = psxBios_ioabort;
3608 //biosC0[0x1a] = psxBios_sys_c0_1a
3609 //biosC0[0x1b] = psxBios_KernelRedirect;
3610 //biosC0[0x1c] = psxBios_PatchAOTable;
3611 //************** THE END ***************************************
3614 memset(FDesc, 0, sizeof(FDesc));
3616 // somewhat pretend to be a SCPH1001 BIOS
3617 // some games look for these and take an exception if they're missing
3618 rom32 = (u32 *)psxR;
3619 rom32[0x100/4] = SWAP32(0x19951204);
3620 rom32[0x104/4] = SWAP32(3);
3621 strcpy(psxR + 0x108, "PCSX authors");
3622 strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3623 strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3624 strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
3627 len = 0x80000 - 0x66000;
3628 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3629 len = 0x80000 - 0x69d68;
3630 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3632 // trap attempts to call bios directly
3633 rom32[0x00000/4] = HLEOP(hleop_dummy);
3634 rom32[0x00180/4] = HLEOP(hleop_dummy);
3635 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3636 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3637 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3639 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3640 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3641 Here are some examples of games not working with this fix in place :
3642 R-type won't get past the Irem logo if not implemented.
3643 Crash Team Racing will softlock after the Sony logo.
3646 ram32 = (u32 *)psxM;
3647 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3648 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3649 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3650 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3652 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3653 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3655 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3656 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3657 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3658 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3660 ram32[0x00a0/4] = HLEOP(hleop_a0);
3661 ram32[0x00b0/4] = HLEOP(hleop_b0);
3662 ram32[0x00c0/4] = HLEOP(hleop_c0);
3664 setup_tt(4, 16, 0x801fff00);
3665 DeliverEvent(0xf0000003, 0x0010);
3667 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3668 strcpy((char *)&ram32[0xeff0/4], "bu");
3670 // default exception handler chains
3671 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3672 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3673 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3674 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3675 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3676 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3677 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3678 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3682 // fill the api jumptables with fake entries as some games patch them
3683 // (or rather the funcs listed there)
3684 ptr = (u32 *)&psxM[A_A0_TABLE];
3685 for (i = 0; i < 256; i++)
3686 ptr[i] = SWAP32(0x1000);
3688 ptr = (u32 *)&psxM[A_B0_TABLE];
3689 for (i = 0; i < 256; i++)
3690 ptr[i] = SWAP32(0x2000);
3691 // B(5b) is special because games patch (sometimes even jump to)
3692 // code at fixed offsets from it, nocash lists offsets:
3693 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3694 // call: +7a0=4b70, +884=4c54, +894=4c64
3695 ptr[0x5b] = SWAP32(0x43d0);
3696 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3698 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3699 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3700 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3702 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3703 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3705 ptr = (u32 *)&psxM[A_C0_TABLE];
3706 for (i = 0; i < 256/2; i++)
3707 ptr[i] = SWAP32(0x3000);
3708 ptr[6] = SWAP32(A_EXCEPTION);
3711 ram32[0x1000/4] = HLEOP(hleop_dummy);
3712 ram32[0x2000/4] = HLEOP(hleop_dummy);
3713 ram32[0x3000/4] = HLEOP(hleop_dummy);
3714 ram32[0x8000/4] = HLEOP(hleop_execret);
3716 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3717 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3718 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3719 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3720 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3721 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3722 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3725 void psxBiosShutdown() {
3728 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3731 if (tcb_cnt != 4 || evcb_cnt != 16) {
3732 setup_tt(tcb_cnt, evcb_cnt, stack);
3733 DeliverEvent(0xf0000003, 0x0010);
3735 storeRam32(A_CONF_SP, stack);
3738 #define psxBios_PADpoll(pad) { \
3739 PAD##pad##_startPoll(pad); \
3740 pad_buf##pad[0] = 0; \
3741 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3742 if (!(pad_buf##pad[1] & 0x0f)) { \
3745 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3747 PAD##pad##_poll(0); \
3749 while (bufcount--) { \
3750 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3754 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3758 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3759 psxBios_ReturnFromException();
3765 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3766 // so this is only partially implemented
3767 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3769 u32 cdrom_dma_ack_enable = 1; // a000b93c
3770 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3773 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3776 //PSXBIOS_LOG("%s\n", __func__);
3778 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3779 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3780 //if (--cdrom_irq_counter == 0) // 0xa0009180
3781 // DeliverEvent(0xf0000003, 0x10);
3785 mips_return_c(ret, 20);
3788 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3790 u32 cdrom_irq_ack_enable = 1; // a000b938
3791 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3794 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3797 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3798 PSXBIOS_LOG("%s TODO\n", __func__);
3801 mips_return_c(ret, 20);
3804 void hleExc0_2_2_syscall() // not in any A/B/C table
3806 u32 tcbPtr = loadRam32(A_TT_PCB);
3807 TCB *tcb = loadRam32ptr(tcbPtr);
3808 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3810 if (code != R3000E_Syscall) {
3812 DeliverEvent(0xf0000010, 0x1000);
3813 //psxBios_SystemErrorUnresolvedException();
3815 mips_return_c(0, 17);
3819 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3820 tcb->epc += SWAP32(4);
3821 switch (SWAP32(tcb->reg[4])) { // a0
3825 case 1: { // EnterCritical - disable irqs
3826 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3827 tcb->reg[2] = SWAP32(was_enabled);
3828 tcb->sr &= SWAP32(~0x404);
3831 case 2: // ExitCritical - enable irqs
3832 tcb->sr |= SWAP32(0x404);
3835 case 3: { // ChangeThreadSubFunction
3836 u32 tcbPtr = loadRam32(A_TT_PCB);
3837 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3841 DeliverEvent(0xf0000010, 0x4000);
3845 psxBios_ReturnFromException();
3848 void hleExc1_0_1(void)
3850 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3851 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3854 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3857 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3858 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3861 mips_return_c(ret, 22);
3864 void hleExc1_0_2(void)
3866 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3869 void hleExc1_1_1(void)
3871 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3872 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3875 void hleExc1_1_2(void)
3877 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3880 void hleExc1_2_1(void)
3882 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3883 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3886 void hleExc1_2_2(void)
3888 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3891 void hleExc1_3_1(void)
3893 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3894 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3897 void hleExc1_3_2(void)
3899 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3902 void hleExc3_0_2_defint(void)
3904 static const struct {
3915 { 6, 6 }, // rcnt2 (bug)
3920 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3921 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3922 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3927 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3930 void hleExcPadCard1(void)
3932 if (loadRam32(A_PAD_IRQR_ENA)) {
3933 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3934 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3940 if (loadRam32(A_PAD_DR_DST))
3943 if (loadRam32(A_PAD_ACK_VBL))
3944 psxHwWrite16(0x1f801070, ~1);
3945 if (loadRam32(A_CARD_IRQR_ENA)) {
3949 mips_return_c(0, 18);
3952 void hleExcPadCard2(void)
3954 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3955 mips_return_c(ret, 15);
3958 void psxBiosException() {
3959 u32 tcbPtr = loadRam32(A_TT_PCB);
3960 u32 *chains = loadRam32ptr(A_TT_ExCB);
3961 TCB *tcb = loadRam32ptr(tcbPtr);
3967 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3968 for (i = 4; i < 32; i++) {
3971 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3973 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3974 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3975 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3976 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3977 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3978 sp = fp = loadRam32(A_EXC_SP);
3982 // do the chains (always 4)
3983 for (c = lim = 0; c < 4; c++) {
3984 if (chains[c * 2] == 0)
3986 ptr = SWAP32(chains[c * 2]);
3987 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3988 chain = castRam32ptr(ptr);
3993 softCallInException(SWAP32(chain[2]));
3994 if (returned_from_exception())
3997 if (v0 == 0 || chain[1] == 0)
3999 softCallInException(SWAP32(chain[1]));
4000 if (returned_from_exception())
4006 // return from exception (custom or default)
4008 ptr = loadRam32(A_EEXIT_PTR);
4009 if (ptr != A_EEXIT_DEF) {
4010 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4011 longjmp_load(jmp_buf);
4016 psxBios_ReturnFromException();
4019 #define bfreeze(ptr, size) { \
4020 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4021 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4025 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4026 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4028 void psxBiosFreeze(int Mode) {