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]);
1873 if (a0 != 3) v0 = psxRcntRcount(a0);
1878 void psxBios_StartRCnt() { // 04
1880 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1884 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1885 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1889 void psxBios_StopRCnt() { // 05
1891 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1895 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1896 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1900 void psxBios_ResetRCnt() { // 06
1902 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1907 psxRcntWmode(a0, 0);
1908 psxRcntWtarget(a0, 0);
1909 psxRcntWcount(a0, 0);
1914 static u32 DeliverEvent(u32 class, u32 spec) {
1915 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1916 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1917 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1918 u32 i, lim = evcb_len / 0x1c;
1920 //printf("%s %08x %x\n", __func__, class, spec);
1921 for (i = 0; i < lim; i++, ev++) {
1923 if (SWAP32(ev->status) != EvStACTIVE)
1926 if (SWAP32(ev->class) != class)
1929 if (SWAP32(ev->spec) != spec)
1932 ret = SWAP32(ev->mode);
1933 if (ret == EvMdMARK) {
1934 ev->status = SWAP32(EvStALREADY);
1938 if (ret == EvMdCALL) {
1939 ret = SWAP32(ev->fhandler);
1951 static u32 UnDeliverEvent(u32 class, u32 spec) {
1952 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1953 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1954 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1955 u32 i, lim = evcb_len / 0x1c;
1957 for (i = 0; i < lim; i++, ev++) {
1959 if (SWAP32(ev->status) != EvStALREADY)
1962 if (SWAP32(ev->class) != class)
1965 if (SWAP32(ev->spec) != spec)
1968 if (SWAP32(ev->mode) == EvMdMARK)
1969 ev->status = SWAP32(EvStACTIVE);
1975 static void psxBios_DeliverEvent() { // 07
1977 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1979 ret = DeliverEvent(a0, a1);
1983 static s32 get_free_EvCB_slot() {
1984 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1985 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
1988 for (i = 0; i < lim; i++, ev++) {
1990 if (ev->status == SWAP32(EvStUNUSED))
1996 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
1997 u32 ret = get_free_EvCB_slot();
1998 if ((s32)ret >= 0) {
1999 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2000 ev->class = SWAP32(class);
2001 ev->status = SWAP32(EvStDISABLED);
2002 ev->spec = SWAP32(spec);
2003 ev->mode = SWAP32(mode);
2004 ev->fhandler = SWAP32(func);
2010 static void psxBios_OpenEvent() { // 08
2011 u32 ret = OpenEvent(a0, a1, a2, a3);
2012 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2013 biosB0n[0x08], a0, a1, a2, a3, ret);
2014 mips_return_c(ret, 36);
2017 static void CloseEvent(u32 ev)
2019 u32 base = loadRam32(A_TT_EvCB);
2020 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2023 static void psxBios_CloseEvent() { // 09
2024 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2025 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2027 mips_return_c(1, 10);
2030 static void psxBios_WaitEvent() { // 0a
2031 u32 base = loadRam32(A_TT_EvCB);
2032 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2033 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2036 if (status == EvStALREADY) {
2037 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2041 if (status != EvStACTIVE)
2043 mips_return_c(0, 2);
2047 // retrigger this hlecall after the next emulation event
2049 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2050 psxRegs.cycle = next_interupt;
2054 static void psxBios_TestEvent() { // 0b
2055 u32 base = loadRam32(A_TT_EvCB);
2056 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2058 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2059 if (status == EvStALREADY) {
2060 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2064 mips_return_c(ret, 15);
2067 static void psxBios_EnableEvent() { // 0c
2068 u32 base = loadRam32(A_TT_EvCB);
2069 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2070 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2071 if (status != EvStUNUSED)
2072 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2074 mips_return_c(1, 15);
2077 static void psxBios_DisableEvent() { // 0d
2078 u32 base = loadRam32(A_TT_EvCB);
2079 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2080 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2081 if (status != EvStUNUSED)
2082 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2084 mips_return_c(1, 15);
2088 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2091 void psxBios_OpenTh() { // 0e
2092 TCB *tcb = loadRam32ptr(A_TT_TCB);
2093 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2096 for (th = 1; th < limit; th++)
2098 if (tcb[th].status != SWAP32(0x4000)) break;
2102 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2103 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2105 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2107 mips_return_c(0xffffffff, 20);
2110 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2112 tcb[th].status = SWAP32(0x4000);
2113 tcb[th].mode = SWAP32(0x1000);
2114 tcb[th].epc = SWAP32(a0);
2115 tcb[th].reg[30] = SWAP32(a1); // fp
2116 tcb[th].reg[29] = SWAP32(a1); // sp
2117 tcb[th].reg[28] = SWAP32(a2); // gp
2119 mips_return_c(0xff000000 + th, 34);
2123 * int CloseTh(long thread);
2126 static void psxBios_CloseTh() { // 0f
2127 u32 tcb = loadRam32(A_TT_TCB);
2128 u32 th = a0 & 0xffff;
2130 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2131 // in the usual bios fashion no checks, just write and return 1
2132 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2134 mips_return_c(1, 11);
2138 * int ChangeTh(long thread);
2141 void psxBios_ChangeTh() { // 10
2142 u32 tcbBase = loadRam32(A_TT_TCB);
2143 u32 th = a0 & 0xffff;
2145 // this is quite spammy
2146 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2148 // without doing any argument checks, just issue a syscall
2149 // (like the real bios does)
2151 a1 = tcbBase + th * sizeof(TCB);
2156 void psxBios_InitPAD() { // 0x12
2157 u32 i, *ram32 = (u32 *)psxM;
2158 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2160 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2161 ram32[A_PAD_DR_DST/4] = 0;
2162 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2163 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2164 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2165 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2166 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2167 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2168 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2169 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2171 for (i = 0; i < a1; i++) {
2173 storeRam8(a0 + i, 0);
2175 for (i = 0; i < a3; i++) {
2177 storeRam8(a2 + i, 0);
2179 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2181 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2183 mips_return_c(1, 200);
2186 void psxBios_StartPAD() { // 13
2187 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2189 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2190 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2191 psxHwWrite16(0x1f801070, ~1);
2192 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2193 storeRam32(A_PAD_ACK_VBL, 1);
2194 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2195 psxRegs.CP0.n.SR |= 0x401;
2197 mips_return_c(1, 300);
2200 void psxBios_StopPAD() { // 14
2201 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2202 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2203 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2204 psxRegs.CP0.n.SR |= 0x401;
2205 mips_return_void_c(200);
2208 static void psxBios_PAD_init() { // 15
2210 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2211 if (a0 == 0x20000000 || a0 == 0x20000001)
2214 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2215 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2218 storeRam32(A_PAD_DR_DST, dst);
2221 mips_return_c(ret, 100);
2224 static u32 psxBios_PAD_dr_() {
2225 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2226 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2227 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2228 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2229 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2231 dst[0] = buf1[3], dst[1] = buf1[2];
2232 if (buf1[1] == 0x23) {
2233 dst[0] |= 0xc7, dst[1] |= 7;
2234 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2235 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2238 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2240 dst[2] = buf2[3], dst[3] = buf2[2];
2241 if (buf2[1] == 0x23) {
2242 dst[2] |= 0xc7, dst[3] |= 7;
2243 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2244 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2248 return SWAP32(*(u32 *)dst);
2251 static void psxBios_PAD_dr() { // 16
2252 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2253 u32 ret = psxBios_PAD_dr_();
2257 static void psxBios_ReturnFromException() { // 17
2258 u32 tcbPtr = loadRam32(A_TT_PCB);
2259 const TCB *tcb = loadRam32ptr(tcbPtr);
2263 for (i = 1; i < 32; i++)
2264 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2265 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2266 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2267 sr = SWAP32(tcb->sr);
2269 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2270 pc0 = k0 = SWAP32(tcb->epc);
2272 // the interpreter wants to know about sr changes, so do a MTC0
2273 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2274 MTC0(&psxRegs, 12, sr);
2280 void psxBios_ResetEntryInt() { // 18
2281 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2283 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2284 mips_return_void_c(5);
2287 void psxBios_HookEntryInt() { // 19
2288 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2290 storeRam32(A_EEXIT_PTR, a0);
2291 mips_return_void_c(3);
2294 static void psxBios_UnDeliverEvent() { // 0x20
2296 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2298 ret = UnDeliverEvent(a0, a1);
2302 static void buopen(int mcd, char *ptr, char *cfg)
2305 char *mcd_data = ptr;
2307 strcpy(FDesc[1 + mcd].name, Ra0+5);
2308 FDesc[1 + mcd].offset = 0;
2309 FDesc[1 + mcd].mode = a1;
2311 for (i=1; i<16; i++) {
2312 const char *fptr = mcd_data + 128 * i;
2313 if ((*fptr & 0xF0) != 0x50) continue;
2314 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2315 FDesc[1 + mcd].mcfile = i;
2316 PSXBIOS_LOG("open %s\n", fptr+0xa);
2320 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2321 for (i=1; i<16; i++) {
2322 int j, xor, nblk = a1 >> 16;
2324 char *fptr = mcd_data + 128 * i;
2326 if ((*fptr & 0xF0) != 0xa0) continue;
2328 FDesc[1 + mcd].mcfile = i;
2331 fptr[5] = 0x20 * nblk;
2334 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2335 pptr = fptr2 = fptr;
2336 for(j=2; j<=nblk; j++) {
2338 for(i++; i<16; i++) {
2341 memset(fptr2, 0, 128);
2342 fptr2[0] = j < nblk ? 0x52 : 0x53;
2345 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2350 /* shouldn't this return ENOSPC if i == 16? */
2352 pptr[8] = pptr[9] = 0xff;
2353 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2355 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2357 /* just go ahead and resave them all */
2358 SaveMcd(cfg, ptr, 128, 128 * 15);
2361 /* shouldn't this return ENOSPC if i == 16? */
2366 * int open(char *name , int mode);
2369 void psxBios_open() { // 0x32
2372 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2376 if (pa0 != INVALID_PTR) {
2377 if (!strncmp(pa0, "bu00", 4)) {
2378 buopen(1, Mcd1Data, Config.Mcd1);
2381 if (!strncmp(pa0, "bu10", 4)) {
2382 buopen(2, Mcd2Data, Config.Mcd2);
2390 * int lseek(int fd , int offset , int whence);
2393 void psxBios_lseek() { // 0x33
2395 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2400 FDesc[a0].offset = a1;
2402 // DeliverEvent(0xf0000011, 0x0004);
2403 // DeliverEvent(0xf4000001, 0x0004);
2407 FDesc[a0].offset+= a1;
2408 v0 = FDesc[a0].offset;
2417 * int read(int fd , void *buf , int nbytes);
2420 void psxBios_read() { // 0x34
2425 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2430 if (pa1 != INVALID_PTR) {
2432 case 2: buread(pa1, 1, a2); break;
2433 case 3: buread(pa1, 2, a2); break;
2441 * int write(int fd , void *buf , int nbytes);
2444 void psxBios_write() { // 0x35/0x03
2448 if (a0 != 1) // stdout
2449 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2452 if (pa1 == INVALID_PTR) {
2457 if (a0 == 1) { // stdout
2461 if (Config.PsxOut) while (a2 > 0) {
2462 SysPrintf("%c", *ptr++); a2--;
2468 case 2: buwrite(pa1, 1, a2); break;
2469 case 3: buwrite(pa1, 2, a2); break;
2475 static void psxBios_write_psxout() {
2476 if (a0 == 1) { // stdout
2477 const char *ptr = Ra1;
2480 if (ptr != INVALID_PTR)
2482 SysPrintf("%c", *ptr++);
2486 static void psxBios_putchar_psxout() { // 3d
2487 SysPrintf("%c", (char)a0);
2490 static void psxBios_puts_psxout() { // 3e/3f
2491 SysPrintf("%s", Ra0);
2495 * int close(int fd);
2498 void psxBios_close() { // 0x36
2500 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2507 void psxBios_putchar() { // 3d
2508 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2512 void psxBios_puts() { // 3e/3f
2513 if (Config.PsxOut) SysPrintf("%s", Ra0);
2517 static void bufile(const u8 *mcd_data, u32 dir_) {
2518 struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(dir_);
2519 const char *pfile = ffile + 5;
2520 const u8 *data = mcd_data;
2521 int i = 0, match = 0;
2526 for (; nfile <= 15 && !match; nfile++) {
2529 head = nfile * 0x40;
2530 data = mcd_data + 128 * nfile;
2531 name = (const char *)data + 0x0a;
2532 if ((data[0] & 0xF0) != 0x50) continue;
2533 /* Bug link files show up as free block. */
2534 if (!name[0]) continue;
2536 for (i = 0; i < 20; i++) {
2537 if (pfile[i] == name[i] || pfile[i] == '?')
2538 dir->name[i] = name[i];
2539 else if (pfile[i] == '*') {
2540 int len = strlen(name + i);
2543 memcpy(dir->name + i, name + i, len + 1);
2554 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2555 nfile, dir->name, pfile, name, match);
2557 for (; nfile <= 15; nfile++, blocks++) {
2558 const u8 *data2 = mcd_data + 128 * nfile;
2559 const char *name = data2 + 0x0a;
2560 if ((data2[0] & 0xF0) != 0x50 || name[0])
2564 // nul char of full lenth name seems to overwrite .attr
2565 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2566 dir->size = 8192 * blocks;
2570 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2571 dir->attr, dir->size, dir->next, dir->head);
2575 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2578 static void psxBios_firstfile() { // 42
2579 char *pa0 = castRam8ptr(a0);
2581 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2585 snprintf(ffile, sizeof(ffile), "%s", pa0);
2587 strcpy(ffile + 5, "*"); // maybe?
2589 if (!strncmp(pa0, "bu00", 4)) {
2590 // firstfile() calls _card_read() internally, so deliver it's event
2591 DeliverEvent(0xf0000011, 0x0004);
2592 bufile(Mcd1Data, a1);
2593 } else if (!strncmp(pa0, "bu10", 4)) {
2594 // firstfile() calls _card_read() internally, so deliver it's event
2595 DeliverEvent(0xf0000011, 0x0004);
2596 bufile(Mcd2Data, a1);
2604 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2607 void psxBios_nextfile() { // 43
2608 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2611 if (!strncmp(ffile, "bu00", 4))
2612 bufile(Mcd1Data, a0);
2613 else if (!strncmp(ffile, "bu10", 4))
2614 bufile(Mcd2Data, a0);
2619 #define burename(mcd) { \
2620 for (i=1; i<16; i++) { \
2621 int namelen, j, xor = 0; \
2622 ptr = Mcd##mcd##Data + 128 * i; \
2623 if ((*ptr & 0xF0) != 0x50) continue; \
2624 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2625 namelen = strlen(Ra1+5); \
2626 memcpy(ptr+0xa, Ra1+5, namelen); \
2627 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2628 for (j=0; j<127; j++) xor^= ptr[j]; \
2630 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2637 * int rename(char *old, char *new);
2640 void psxBios_rename() { // 44
2647 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2652 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2653 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2657 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2666 #define budelete(mcd) { \
2667 for (i=1; i<16; i++) { \
2668 ptr = Mcd##mcd##Data + 128 * i; \
2669 if ((*ptr & 0xF0) != 0x50) continue; \
2670 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2671 *ptr = (*ptr & 0xf) | 0xA0; \
2672 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2673 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2680 * int delete(char *name);
2683 void psxBios_delete() { // 45
2689 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2694 if (pa0 != INVALID_PTR) {
2695 if (!strncmp(pa0, "bu00", 4)) {
2699 if (!strncmp(pa0, "bu10", 4)) {
2707 void psxBios_InitCARD() { // 4a
2708 u32 *ram32 = (u32 *)psxM;
2709 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2710 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2711 // (maybe) todo: early_card_irq, etc
2713 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2715 psxBios_FlushCache();
2716 mips_return_c(0, 34+13+15+6);
2719 void psxBios_StartCARD() { // 4b
2720 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2721 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2722 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2724 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2725 storeRam32(A_PAD_ACK_VBL, 1);
2726 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2727 storeRam32(A_CARD_IRQR_ENA, 1);
2728 psxRegs.CP0.n.SR |= 0x401;
2730 mips_return_c(1, 200);
2733 void psxBios_StopCARD() { // 4c
2734 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2735 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2736 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2737 storeRam32(A_CARD_IRQR_ENA, 0);
2738 psxRegs.CP0.n.SR |= 0x401;
2739 mips_return_void_c(200);
2742 void psxBios__card_write() { // 0x4e
2747 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2750 Function also accepts sector 400h (a bug).
2751 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2755 /* Invalid sectors */
2759 storeRam32(A_CARD_CHAN1, a0);
2762 if (pa2 != INVALID_PTR) {
2764 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2765 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2767 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2768 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2772 DeliverEvent(0xf0000011, 0x0004);
2773 // DeliverEvent(0xf4000001, 0x0004);
2778 void psxBios__card_read() { // 0x4f
2783 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2786 Function also accepts sector 400h (a bug).
2787 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2791 /* Invalid sectors */
2795 storeRam32(A_CARD_CHAN1, a0);
2798 if (pa2 != INVALID_PTR) {
2800 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2802 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2806 DeliverEvent(0xf0000011, 0x0004);
2807 // DeliverEvent(0xf4000001, 0x0004);
2812 void psxBios__new_card() { // 0x50
2814 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2820 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2821 void psxBios__get_error(void) // 55
2823 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2828 void psxBios_Krom2RawAdd() { // 0x51
2831 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2832 const u32 table_8140[][2] = {
2833 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2834 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2835 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2836 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2837 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2838 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2839 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2840 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2841 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2845 const u32 table_889f[][2] = {
2846 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2847 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2848 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2849 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2850 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2851 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2852 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2853 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2857 if (a0 >= 0x8140 && a0 <= 0x84be) {
2858 while (table_8140[i][0] <= a0) i++;
2859 a0 -= table_8140[i - 1][0];
2860 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2861 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2862 while (table_889f[i][0] <= a0) i++;
2863 a0 -= table_889f[i - 1][0];
2864 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2872 void psxBios_GetC0Table() { // 56
2873 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2874 log_unhandled("GetC0Table @%08x\n", ra);
2876 mips_return_c(A_C0_TABLE, 3);
2879 void psxBios_GetB0Table() { // 57
2880 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2881 log_unhandled("GetB0Table @%08x\n", ra);
2883 mips_return_c(A_B0_TABLE, 3);
2886 static void psxBios__card_chan() { // 0x58
2888 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2890 // todo: should return active slot chan
2891 // (active - which was last processed by irq code)
2892 ret = loadRam32(A_CARD_CHAN1);
2893 mips_return_c(ret, 8);
2896 static void psxBios_ChangeClearPad() { // 5b
2898 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2899 ret = loadRam32(A_PAD_ACK_VBL);
2900 storeRam32(A_PAD_ACK_VBL, a0);
2902 mips_return_c(ret, 6);
2905 static void psxBios__card_status() { // 5c
2906 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2912 static void psxBios__card_wait() { // 5d
2913 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2919 /* System calls C0 */
2921 static void psxBios_InitRCnt() { // 00
2923 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2924 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2925 for (i = 0; i < 3; i++) {
2926 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2927 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2928 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2930 psxBios_SysEnqIntRP_(a0, 0x6d88);
2931 mips_return_c(0, 9);
2934 static void psxBios_InitException() { // 01
2935 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2936 psxBios_SysEnqIntRP_(a0, 0x6da8);
2937 mips_return_c(0, 9);
2941 * int SysEnqIntRP(int index , long *queue);
2944 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2945 u32 old, base = loadRam32(A_TT_ExCB);
2947 old = loadRam32(base + (priority << 3));
2948 storeRam32(base + (priority << 3), chain_eptr);
2949 storeRam32(chain_eptr, old);
2950 mips_return_c(0, 9);
2953 static void psxBios_SysEnqIntRP() { // 02
2954 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2955 psxBios_SysEnqIntRP_(a0, a1);
2959 * int SysDeqIntRP(int index , long *queue);
2962 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2963 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2964 u32 lim = 0, ret = 0;
2966 // as in original: no arg checks of any kind, bug if a1 == 0
2967 ptr = loadRam32(base + (priority << 3));
2969 next = loadRam32(ptr);
2970 if (ptr == chain_rm_eptr) {
2971 storeRam32(base + (priority << 3), next);
2976 while (next && next != chain_rm_eptr && lim++ < 100) {
2978 next = loadRam32(ptr);
2981 if (next == chain_rm_eptr) {
2982 next = loadRam32(next);
2983 storeRam32(ptr, next);
2990 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
2992 mips_return_c(ret, 12);
2995 static void psxBios_SysDeqIntRP() { // 03
2996 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2997 psxBios_SysDeqIntRP_(a0, a1);
3000 static void psxBios_get_free_EvCB_slot() { // 04
3001 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3002 s32 ret = get_free_EvCB_slot();
3003 mips_return_c(ret, 0);
3006 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3007 storeRam32(base, 0);
3008 storeRam32(A_KMALLOC_PTR, base);
3009 storeRam32(A_KMALLOC_SIZE, size);
3010 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3013 // this should be much more complicated, but maybe that'll be enough
3014 static u32 psxBios_SysMalloc_(u32 size) {
3015 u32 ptr = loadRam32(A_KMALLOC_PTR);
3017 size = (size + 3) & ~3;
3018 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3019 storeRam32(ptr, size);
3023 static void psxBios_SysInitMemory() { // 08
3024 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3026 psxBios_SysInitMemory_(a0, a1);
3027 mips_return_void_c(12);
3030 static void psxBios_ChangeClearRCnt() { // 0a
3033 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3035 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3036 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3037 mips_return_c(ret, 8);
3040 static void psxBios_InitDefInt() { // 0c
3041 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3042 // should also clear the autoack table
3043 psxBios_SysEnqIntRP_(a0, 0x6d98);
3044 mips_return_c(0, 20 + 6*2);
3047 void psxBios_dummy() {
3048 u32 pc = (pc0 & 0x1fffff) - 4;
3049 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3050 : pc == 0xc0 ? biosC0n : NULL;
3051 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3052 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3053 (void)pc; (void)ntab;
3054 mips_return_c(0, 100);
3057 void (*biosA0[256])();
3058 // C0 and B0 overlap (end of C0 is start of B0)
3059 void (*biosC0[256+128])();
3060 void (**biosB0)() = biosC0 + 128;
3062 static void setup_mips_code()
3065 ptr = (u32 *)&psxM[A_SYSCALL];
3066 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3067 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3068 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3070 ptr = (u32 *)&psxM[A_EXCEPTION];
3071 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3072 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3073 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3074 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3075 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3076 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3077 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3078 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3079 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3080 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3082 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3083 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3084 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3086 ptr[0xb0/4] = HLEOP(hleop_exception);
3089 static const struct {
3093 { 0xbfc050a4, hleop_exc0_0_1 },
3094 { 0xbfc04fbc, hleop_exc0_0_2 },
3095 { 0xbfc0506c, hleop_exc0_1_1 },
3096 { 0xbfc04dec, hleop_exc0_1_2 },
3097 { 0x1a00, hleop_exc0_2_2 },
3098 { 0x19c8, hleop_exc1_0_1 },
3099 { 0x18bc, hleop_exc1_0_2 },
3100 { 0x1990, hleop_exc1_1_1 },
3101 { 0x1858, hleop_exc1_1_2 },
3102 { 0x1958, hleop_exc1_2_1 },
3103 { 0x17f4, hleop_exc1_2_2 },
3104 { 0x1920, hleop_exc1_3_1 },
3105 { 0x1794, hleop_exc1_3_2 },
3106 { 0x2458, hleop_exc3_0_2 },
3107 { 0x49bc, hleop_exc_padcard1 },
3108 { 0x4a4c, hleop_exc_padcard2 },
3111 static int chain_hle_op(u32 handler)
3115 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3116 if (chainfns[i].addr == handler)
3117 return chainfns[i].op;
3121 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3123 d[0] = SWAPu32(next);
3124 d[1] = SWAPu32(handler1);
3125 d[2] = SWAPu32(handler2);
3127 // install the hle traps
3128 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3129 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3132 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3134 u32 *ram32 = (u32 *)psxM;
3135 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3136 u32 p_excb, p_evcb, p_pcb, p_tcb;
3139 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3141 // the real bios doesn't care, but we just don't
3142 // want to crash in case of garbage parameters
3143 if (tcb_cnt > 1024) tcb_cnt = 1024;
3144 if (evcb_cnt > 1024) evcb_cnt = 1024;
3145 s_evcb = 0x1c * evcb_cnt;
3146 s_tcb = 0xc0 * tcb_cnt;
3148 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3149 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3150 p_excb = psxBios_SysMalloc_(s_excb);
3151 p_evcb = psxBios_SysMalloc_(s_evcb);
3152 p_pcb = psxBios_SysMalloc_(s_pcb);
3153 p_tcb = psxBios_SysMalloc_(s_tcb);
3155 // "table of tables". Some games modify it
3156 assert(A_TT_ExCB == 0x0100);
3157 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3158 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3159 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3160 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3161 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3162 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3163 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3164 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3165 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3166 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3167 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3168 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3170 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3171 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3172 storeRam32(p_excb + 4*4, 0x0000); // chain2
3173 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3175 storeRam32(p_pcb, p_tcb);
3176 storeRam32(p_tcb, 0x4000); // first TCB
3177 for (i = 1; i < tcb_cnt; i++)
3178 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3181 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3182 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3183 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3184 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3185 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3187 storeRam32(A_CONF_EvCB, evcb_cnt);
3188 storeRam32(A_CONF_TCB, tcb_cnt);
3189 storeRam32(A_CONF_SP, stack);
3192 static const u32 gpu_ctl_def[] = {
3193 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3194 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3197 static const u32 gpu_data_def[] = {
3198 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3199 0xe5001000, 0xe6000000,
3200 0x02000000, 0x00000000, 0x01ff03ff
3204 static const u16 spu_config[] = {
3205 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3206 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3207 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3208 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3209 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3210 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3211 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3212 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3215 void psxBiosSetupBootState(void)
3217 boolean hle = Config.HLE;
3218 u32 *hw = (u32 *)psxH;
3221 // see also SetBootRegs()
3224 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3225 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3227 k0 = 0xbfc0d968; k1 = 0xf1c;
3228 ra = 0xf0001234; // just to easily detect attempts to return
3229 psxRegs.CP0.n.Cause = 0x20;
3230 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3232 hw[0x1000/4] = SWAP32(0x1f000000);
3233 hw[0x1004/4] = SWAP32(0x1f802000);
3234 hw[0x1008/4] = SWAP32(0x0013243f);
3235 hw[0x100c/4] = SWAP32(0x00003022);
3236 hw[0x1010/4] = SWAP32(0x0013243f);
3237 hw[0x1014/4] = SWAP32(0x200931e1);
3238 hw[0x1018/4] = SWAP32(0x00020943);
3239 hw[0x101c/4] = SWAP32(0x00070777);
3240 hw[0x1020/4] = SWAP32(0x0000132c);
3241 hw[0x1060/4] = SWAP32(0x00000b88);
3242 hw[0x1070/4] = SWAP32(0x00000001);
3243 hw[0x1074/4] = SWAP32(0x0000000c);
3244 hw[0x2040/4] = SWAP32(0x00000900);
3247 hw[0x10a0/4] = SWAP32(0x00ffffff);
3248 hw[0x10a8/4] = SWAP32(0x00000401);
3249 hw[0x10b0/4] = SWAP32(0x0008b000);
3250 hw[0x10b4/4] = SWAP32(0x00010200);
3251 hw[0x10e0/4] = SWAP32(0x000eccf4);
3252 hw[0x10e4/4] = SWAP32(0x00000400);
3253 hw[0x10e8/4] = SWAP32(0x00000002);
3254 hw[0x10f0/4] = SWAP32(0x00009099);
3255 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3264 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3265 GPU_writeStatus(gpu_ctl_def[i]);
3266 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3267 GPU_writeData(gpu_data_def[i]);
3268 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3271 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3272 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3275 #include "sjisfont.h"
3277 void psxBiosInit() {
3278 u32 *ptr, *ram32, *rom32;
3282 memset(psxM, 0, 0x10000);
3283 for(i = 0; i < 256; i++) {
3288 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3289 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3290 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3291 biosA0[0x3f] = psxBios_printf_psxout;
3293 if (!Config.HLE) return;
3295 for(i = 0; i < 256; i++) {
3296 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3297 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3298 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3301 biosA0[0x00] = psxBios_open;
3302 biosA0[0x01] = psxBios_lseek;
3303 biosA0[0x02] = psxBios_read;
3304 biosA0[0x03] = psxBios_write;
3305 biosA0[0x04] = psxBios_close;
3306 //biosA0[0x05] = psxBios_ioctl;
3307 //biosA0[0x06] = psxBios_exit;
3308 //biosA0[0x07] = psxBios_sys_a0_07;
3309 biosA0[0x08] = psxBios_getc;
3310 biosA0[0x09] = psxBios_putc;
3311 biosA0[0x0a] = psxBios_todigit;
3312 //biosA0[0x0b] = psxBios_atof;
3313 //biosA0[0x0c] = psxBios_strtoul;
3314 //biosA0[0x0d] = psxBios_strtol;
3315 biosA0[0x0e] = psxBios_abs;
3316 biosA0[0x0f] = psxBios_labs;
3317 biosA0[0x10] = psxBios_atoi;
3318 biosA0[0x11] = psxBios_atol;
3319 //biosA0[0x12] = psxBios_atob;
3320 biosA0[0x13] = psxBios_setjmp;
3321 biosA0[0x14] = psxBios_longjmp;
3322 biosA0[0x15] = psxBios_strcat;
3323 biosA0[0x16] = psxBios_strncat;
3324 biosA0[0x17] = psxBios_strcmp;
3325 biosA0[0x18] = psxBios_strncmp;
3326 biosA0[0x19] = psxBios_strcpy;
3327 biosA0[0x1a] = psxBios_strncpy;
3328 biosA0[0x1b] = psxBios_strlen;
3329 biosA0[0x1c] = psxBios_index;
3330 biosA0[0x1d] = psxBios_rindex;
3331 biosA0[0x1e] = psxBios_strchr;
3332 biosA0[0x1f] = psxBios_strrchr;
3333 biosA0[0x20] = psxBios_strpbrk;
3334 biosA0[0x21] = psxBios_strspn;
3335 biosA0[0x22] = psxBios_strcspn;
3336 biosA0[0x23] = psxBios_strtok;
3337 biosA0[0x24] = psxBios_strstr;
3338 biosA0[0x25] = psxBios_toupper;
3339 biosA0[0x26] = psxBios_tolower;
3340 biosA0[0x27] = psxBios_bcopy;
3341 biosA0[0x28] = psxBios_bzero;
3342 biosA0[0x29] = psxBios_bcmp;
3343 biosA0[0x2a] = psxBios_memcpy;
3344 biosA0[0x2b] = psxBios_memset;
3345 biosA0[0x2c] = psxBios_memmove;
3346 biosA0[0x2d] = psxBios_memcmp;
3347 biosA0[0x2e] = psxBios_memchr;
3348 biosA0[0x2f] = psxBios_rand;
3349 biosA0[0x30] = psxBios_srand;
3350 biosA0[0x31] = psxBios_qsort;
3351 //biosA0[0x32] = psxBios_strtod;
3352 biosA0[0x33] = psxBios_malloc;
3353 biosA0[0x34] = psxBios_free;
3354 //biosA0[0x35] = psxBios_lsearch;
3355 //biosA0[0x36] = psxBios_bsearch;
3356 biosA0[0x37] = psxBios_calloc;
3357 biosA0[0x38] = psxBios_realloc;
3358 biosA0[0x39] = psxBios_InitHeap;
3359 //biosA0[0x3a] = psxBios__exit;
3360 biosA0[0x3b] = psxBios_getchar;
3361 biosA0[0x3c] = psxBios_putchar;
3362 //biosA0[0x3d] = psxBios_gets;
3363 biosA0[0x3e] = psxBios_puts;
3364 biosA0[0x3f] = psxBios_printf;
3365 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3366 //biosA0[0x41] = psxBios_LoadTest;
3367 biosA0[0x42] = psxBios_Load;
3368 biosA0[0x43] = psxBios_Exec;
3369 biosA0[0x44] = psxBios_FlushCache;
3370 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3371 biosA0[0x46] = psxBios_GPU_dw;
3372 biosA0[0x47] = psxBios_mem2vram;
3373 biosA0[0x48] = psxBios_SendGPU;
3374 biosA0[0x49] = psxBios_GPU_cw;
3375 biosA0[0x4a] = psxBios_GPU_cwb;
3376 biosA0[0x4b] = psxBios_GPU_SendPackets;
3377 biosA0[0x4c] = psxBios_sys_a0_4c;
3378 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3379 //biosA0[0x4e] = psxBios_GPU_sync;
3380 //biosA0[0x4f] = psxBios_sys_a0_4f;
3381 //biosA0[0x50] = psxBios_sys_a0_50;
3382 biosA0[0x51] = psxBios_LoadExec;
3383 //biosA0[0x52] = psxBios_GetSysSp;
3384 //biosA0[0x53] = psxBios_sys_a0_53;
3385 //biosA0[0x54] = psxBios__96_init_a54;
3386 //biosA0[0x55] = psxBios__bu_init_a55;
3387 biosA0[0x56] = psxBios_CdRemove;
3388 //biosA0[0x57] = psxBios_sys_a0_57;
3389 //biosA0[0x58] = psxBios_sys_a0_58;
3390 //biosA0[0x59] = psxBios_sys_a0_59;
3391 //biosA0[0x5a] = psxBios_sys_a0_5a;
3392 //biosA0[0x5b] = psxBios_dev_tty_init;
3393 //biosA0[0x5c] = psxBios_dev_tty_open;
3394 //biosA0[0x5d] = psxBios_sys_a0_5d;
3395 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3396 //biosA0[0x5f] = psxBios_dev_cd_open;
3397 //biosA0[0x60] = psxBios_dev_cd_read;
3398 //biosA0[0x61] = psxBios_dev_cd_close;
3399 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3400 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3401 //biosA0[0x64] = psxBios_dev_cd_chdir;
3402 //biosA0[0x65] = psxBios_dev_card_open;
3403 //biosA0[0x66] = psxBios_dev_card_read;
3404 //biosA0[0x67] = psxBios_dev_card_write;
3405 //biosA0[0x68] = psxBios_dev_card_close;
3406 //biosA0[0x69] = psxBios_dev_card_firstfile;
3407 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3408 //biosA0[0x6b] = psxBios_dev_card_erase;
3409 //biosA0[0x6c] = psxBios_dev_card_undelete;
3410 //biosA0[0x6d] = psxBios_dev_card_format;
3411 //biosA0[0x6e] = psxBios_dev_card_rename;
3412 //biosA0[0x6f] = psxBios_dev_card_6f;
3413 biosA0[0x70] = psxBios__bu_init;
3414 biosA0[0x71] = psxBios__96_init;
3415 biosA0[0x72] = psxBios_CdRemove;
3416 //biosA0[0x73] = psxBios_sys_a0_73;
3417 //biosA0[0x74] = psxBios_sys_a0_74;
3418 //biosA0[0x75] = psxBios_sys_a0_75;
3419 //biosA0[0x76] = psxBios_sys_a0_76;
3420 //biosA0[0x77] = psxBios_sys_a0_77;
3421 //biosA0[0x78] = psxBios__96_CdSeekL;
3422 //biosA0[0x79] = psxBios_sys_a0_79;
3423 //biosA0[0x7a] = psxBios_sys_a0_7a;
3424 //biosA0[0x7b] = psxBios_sys_a0_7b;
3425 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3426 //biosA0[0x7d] = psxBios_sys_a0_7d;
3427 //biosA0[0x7e] = psxBios__96_CdRead;
3428 //biosA0[0x7f] = psxBios_sys_a0_7f;
3429 //biosA0[0x80] = psxBios_sys_a0_80;
3430 //biosA0[0x81] = psxBios_sys_a0_81;
3431 //biosA0[0x82] = psxBios_sys_a0_82;
3432 //biosA0[0x83] = psxBios_sys_a0_83;
3433 //biosA0[0x84] = psxBios_sys_a0_84;
3434 //biosA0[0x85] = psxBios__96_CdStop;
3435 //biosA0[0x86] = psxBios_sys_a0_86;
3436 //biosA0[0x87] = psxBios_sys_a0_87;
3437 //biosA0[0x88] = psxBios_sys_a0_88;
3438 //biosA0[0x89] = psxBios_sys_a0_89;
3439 //biosA0[0x8a] = psxBios_sys_a0_8a;
3440 //biosA0[0x8b] = psxBios_sys_a0_8b;
3441 //biosA0[0x8c] = psxBios_sys_a0_8c;
3442 //biosA0[0x8d] = psxBios_sys_a0_8d;
3443 //biosA0[0x8e] = psxBios_sys_a0_8e;
3444 //biosA0[0x8f] = psxBios_sys_a0_8f;
3445 biosA0[0x90] = hleExc0_1_2;
3446 biosA0[0x91] = hleExc0_0_2;
3447 biosA0[0x92] = hleExc0_1_1;
3448 biosA0[0x93] = hleExc0_0_1;
3449 //biosA0[0x94] = psxBios_sys_a0_94;
3450 //biosA0[0x95] = psxBios_sys_a0_95;
3451 //biosA0[0x96] = psxBios_AddCDROMDevice;
3452 //biosA0[0x97] = psxBios_AddMemCardDevide;
3453 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3454 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3455 //biosA0[0x9a] = psxBios_sys_a0_9a;
3456 //biosA0[0x9b] = psxBios_sys_a0_9b;
3457 biosA0[0x9c] = psxBios_SetConf;
3458 biosA0[0x9d] = psxBios_GetConf;
3459 //biosA0[0x9e] = psxBios_sys_a0_9e;
3460 biosA0[0x9f] = psxBios_SetMem;
3461 //biosA0[0xa0] = psxBios__boot;
3462 //biosA0[0xa1] = psxBios_SystemError;
3463 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3464 biosA0[0xa3] = psxBios_DequeueCdIntr;
3465 //biosA0[0xa4] = psxBios_sys_a0_a4;
3466 //biosA0[0xa5] = psxBios_ReadSector;
3467 biosA0[0xa6] = psxBios_get_cd_status;
3468 //biosA0[0xa7] = psxBios_bufs_cb_0;
3469 //biosA0[0xa8] = psxBios_bufs_cb_1;
3470 //biosA0[0xa9] = psxBios_bufs_cb_2;
3471 //biosA0[0xaa] = psxBios_bufs_cb_3;
3472 biosA0[0xab] = psxBios__card_info;
3473 biosA0[0xac] = psxBios__card_load;
3474 //biosA0[0axd] = psxBios__card_auto;
3475 //biosA0[0xae] = psxBios_bufs_cd_4;
3476 //biosA0[0xaf] = psxBios_sys_a0_af;
3477 //biosA0[0xb0] = psxBios_sys_a0_b0;
3478 //biosA0[0xb1] = psxBios_sys_a0_b1;
3479 //biosA0[0xb2] = psxBios_do_a_long_jmp
3480 //biosA0[0xb3] = psxBios_sys_a0_b3;
3481 biosA0[0xb4] = psxBios_GetSystemInfo;
3482 //*******************B0 CALLS****************************
3483 biosB0[0x00] = psxBios_SysMalloc;
3484 //biosB0[0x01] = psxBios_sys_b0_01;
3485 biosB0[0x02] = psxBios_SetRCnt;
3486 biosB0[0x03] = psxBios_GetRCnt;
3487 biosB0[0x04] = psxBios_StartRCnt;
3488 biosB0[0x05] = psxBios_StopRCnt;
3489 biosB0[0x06] = psxBios_ResetRCnt;
3490 biosB0[0x07] = psxBios_DeliverEvent;
3491 biosB0[0x08] = psxBios_OpenEvent;
3492 biosB0[0x09] = psxBios_CloseEvent;
3493 biosB0[0x0a] = psxBios_WaitEvent;
3494 biosB0[0x0b] = psxBios_TestEvent;
3495 biosB0[0x0c] = psxBios_EnableEvent;
3496 biosB0[0x0d] = psxBios_DisableEvent;
3497 biosB0[0x0e] = psxBios_OpenTh;
3498 biosB0[0x0f] = psxBios_CloseTh;
3499 biosB0[0x10] = psxBios_ChangeTh;
3500 //biosB0[0x11] = psxBios_psxBios_b0_11;
3501 biosB0[0x12] = psxBios_InitPAD;
3502 biosB0[0x13] = psxBios_StartPAD;
3503 biosB0[0x14] = psxBios_StopPAD;
3504 biosB0[0x15] = psxBios_PAD_init;
3505 biosB0[0x16] = psxBios_PAD_dr;
3506 biosB0[0x17] = psxBios_ReturnFromException;
3507 biosB0[0x18] = psxBios_ResetEntryInt;
3508 biosB0[0x19] = psxBios_HookEntryInt;
3509 //biosB0[0x1a] = psxBios_sys_b0_1a;
3510 //biosB0[0x1b] = psxBios_sys_b0_1b;
3511 //biosB0[0x1c] = psxBios_sys_b0_1c;
3512 //biosB0[0x1d] = psxBios_sys_b0_1d;
3513 //biosB0[0x1e] = psxBios_sys_b0_1e;
3514 //biosB0[0x1f] = psxBios_sys_b0_1f;
3515 biosB0[0x20] = psxBios_UnDeliverEvent;
3516 //biosB0[0x21] = psxBios_sys_b0_21;
3517 //biosB0[0x22] = psxBios_sys_b0_22;
3518 //biosB0[0x23] = psxBios_sys_b0_23;
3519 //biosB0[0x24] = psxBios_sys_b0_24;
3520 //biosB0[0x25] = psxBios_sys_b0_25;
3521 //biosB0[0x26] = psxBios_sys_b0_26;
3522 //biosB0[0x27] = psxBios_sys_b0_27;
3523 //biosB0[0x28] = psxBios_sys_b0_28;
3524 //biosB0[0x29] = psxBios_sys_b0_29;
3525 //biosB0[0x2a] = psxBios_sys_b0_2a;
3526 //biosB0[0x2b] = psxBios_sys_b0_2b;
3527 //biosB0[0x2c] = psxBios_sys_b0_2c;
3528 //biosB0[0x2d] = psxBios_sys_b0_2d;
3529 //biosB0[0x2e] = psxBios_sys_b0_2e;
3530 //biosB0[0x2f] = psxBios_sys_b0_2f;
3531 //biosB0[0x30] = psxBios_sys_b0_30;
3532 //biosB0[0x31] = psxBios_sys_b0_31;
3533 biosB0[0x32] = psxBios_open;
3534 biosB0[0x33] = psxBios_lseek;
3535 biosB0[0x34] = psxBios_read;
3536 biosB0[0x35] = psxBios_write;
3537 biosB0[0x36] = psxBios_close;
3538 //biosB0[0x37] = psxBios_ioctl;
3539 //biosB0[0x38] = psxBios_exit;
3540 //biosB0[0x39] = psxBios_sys_b0_39;
3541 //biosB0[0x3a] = psxBios_getc;
3542 //biosB0[0x3b] = psxBios_putc;
3543 biosB0[0x3c] = psxBios_getchar;
3544 biosB0[0x3d] = psxBios_putchar;
3545 //biosB0[0x3e] = psxBios_gets;
3546 biosB0[0x3f] = psxBios_puts;
3547 //biosB0[0x40] = psxBios_cd;
3548 biosB0[0x41] = psxBios_format;
3549 biosB0[0x42] = psxBios_firstfile;
3550 biosB0[0x43] = psxBios_nextfile;
3551 biosB0[0x44] = psxBios_rename;
3552 biosB0[0x45] = psxBios_delete;
3553 //biosB0[0x46] = psxBios_undelete;
3554 //biosB0[0x47] = psxBios_AddDevice;
3555 //biosB0[0x48] = psxBios_RemoteDevice;
3556 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3557 biosB0[0x4a] = psxBios_InitCARD;
3558 biosB0[0x4b] = psxBios_StartCARD;
3559 biosB0[0x4c] = psxBios_StopCARD;
3560 //biosB0[0x4d] = psxBios_sys_b0_4d;
3561 biosB0[0x4e] = psxBios__card_write;
3562 biosB0[0x4f] = psxBios__card_read;
3563 biosB0[0x50] = psxBios__new_card;
3564 biosB0[0x51] = psxBios_Krom2RawAdd;
3565 //biosB0[0x52] = psxBios_sys_b0_52;
3566 //biosB0[0x53] = psxBios_sys_b0_53;
3567 //biosB0[0x54] = psxBios__get_errno;
3568 biosB0[0x55] = psxBios__get_error;
3569 biosB0[0x56] = psxBios_GetC0Table;
3570 biosB0[0x57] = psxBios_GetB0Table;
3571 biosB0[0x58] = psxBios__card_chan;
3572 //biosB0[0x59] = psxBios_sys_b0_59;
3573 //biosB0[0x5a] = psxBios_sys_b0_5a;
3574 biosB0[0x5b] = psxBios_ChangeClearPad;
3575 biosB0[0x5c] = psxBios__card_status;
3576 biosB0[0x5d] = psxBios__card_wait;
3577 //*******************C0 CALLS****************************
3578 biosC0[0x00] = psxBios_InitRCnt;
3579 biosC0[0x01] = psxBios_InitException;
3580 biosC0[0x02] = psxBios_SysEnqIntRP;
3581 biosC0[0x03] = psxBios_SysDeqIntRP;
3582 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3583 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3584 //biosC0[0x06] = psxBios_ExceptionHandler;
3585 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3586 biosC0[0x08] = psxBios_SysInitMemory;
3587 //biosC0[0x09] = psxBios_SysInitKMem;
3588 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3589 //biosC0[0x0b] = psxBios_SystemError;
3590 biosC0[0x0c] = psxBios_InitDefInt;
3591 //biosC0[0x0d] = psxBios_sys_c0_0d;
3592 //biosC0[0x0e] = psxBios_sys_c0_0e;
3593 //biosC0[0x0f] = psxBios_sys_c0_0f;
3594 //biosC0[0x10] = psxBios_sys_c0_10;
3595 //biosC0[0x11] = psxBios_sys_c0_11;
3596 //biosC0[0x12] = psxBios_InstallDevices;
3597 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3598 //biosC0[0x14] = psxBios_sys_c0_14;
3599 //biosC0[0x15] = psxBios__cdevinput;
3600 //biosC0[0x16] = psxBios__cdevscan;
3601 //biosC0[0x17] = psxBios__circgetc;
3602 //biosC0[0x18] = psxBios__circputc;
3603 //biosC0[0x19] = psxBios_ioabort;
3604 //biosC0[0x1a] = psxBios_sys_c0_1a
3605 //biosC0[0x1b] = psxBios_KernelRedirect;
3606 //biosC0[0x1c] = psxBios_PatchAOTable;
3607 //************** THE END ***************************************
3610 memset(FDesc, 0, sizeof(FDesc));
3612 // somewhat pretend to be a SCPH1001 BIOS
3613 // some games look for these and take an exception if they're missing
3614 rom32 = (u32 *)psxR;
3615 rom32[0x100/4] = SWAP32(0x19951204);
3616 rom32[0x104/4] = SWAP32(3);
3617 strcpy(psxR + 0x108, "PCSX authors");
3618 strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3619 strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3620 strcpy(psxR + 0x7ff54, "GPL-2.0-or-later");
3623 len = 0x80000 - 0x66000;
3624 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3625 len = 0x80000 - 0x69d68;
3626 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3628 // trap attempts to call bios directly
3629 rom32[0x00000/4] = HLEOP(hleop_dummy);
3630 rom32[0x00180/4] = HLEOP(hleop_dummy);
3631 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3632 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3633 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3635 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3636 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3637 Here are some examples of games not working with this fix in place :
3638 R-type won't get past the Irem logo if not implemented.
3639 Crash Team Racing will softlock after the Sony logo.
3642 ram32 = (u32 *)psxM;
3643 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3644 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3645 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3646 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3648 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3649 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3651 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3652 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3653 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3654 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3656 ram32[0x00a0/4] = HLEOP(hleop_a0);
3657 ram32[0x00b0/4] = HLEOP(hleop_b0);
3658 ram32[0x00c0/4] = HLEOP(hleop_c0);
3660 setup_tt(4, 16, 0x801fff00);
3661 DeliverEvent(0xf0000003, 0x0010);
3663 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3664 strcpy((char *)&ram32[0xeff0/4], "bu");
3666 // default exception handler chains
3667 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3668 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3669 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3670 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3671 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3672 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3673 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3674 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3678 // fill the api jumptables with fake entries as some games patch them
3679 // (or rather the funcs listed there)
3680 ptr = (u32 *)&psxM[A_A0_TABLE];
3681 for (i = 0; i < 256; i++)
3682 ptr[i] = SWAP32(0x1000);
3684 ptr = (u32 *)&psxM[A_B0_TABLE];
3685 for (i = 0; i < 256; i++)
3686 ptr[i] = SWAP32(0x2000);
3687 // B(5b) is special because games patch (sometimes even jump to)
3688 // code at fixed offsets from it, nocash lists offsets:
3689 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3690 // call: +7a0=4b70, +884=4c54, +894=4c64
3691 ptr[0x5b] = SWAP32(0x43d0);
3692 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3694 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3695 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3696 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3698 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3699 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3701 ptr = (u32 *)&psxM[A_C0_TABLE];
3702 for (i = 0; i < 256/2; i++)
3703 ptr[i] = SWAP32(0x3000);
3704 ptr[6] = SWAP32(A_EXCEPTION);
3707 ram32[0x1000/4] = HLEOP(hleop_dummy);
3708 ram32[0x2000/4] = HLEOP(hleop_dummy);
3709 ram32[0x3000/4] = HLEOP(hleop_dummy);
3710 ram32[0x8000/4] = HLEOP(hleop_execret);
3712 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3713 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3714 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3715 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3716 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3717 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3718 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3721 void psxBiosShutdown() {
3724 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3727 if (tcb_cnt != 4 || evcb_cnt != 16) {
3728 setup_tt(tcb_cnt, evcb_cnt, stack);
3729 DeliverEvent(0xf0000003, 0x0010);
3731 storeRam32(A_CONF_SP, stack);
3734 #define psxBios_PADpoll(pad) { \
3735 PAD##pad##_startPoll(pad); \
3736 pad_buf##pad[0] = 0; \
3737 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3738 if (!(pad_buf##pad[1] & 0x0f)) { \
3741 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3743 PAD##pad##_poll(0); \
3745 while (bufcount--) { \
3746 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3750 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3754 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3755 psxBios_ReturnFromException();
3761 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3762 // so this is only partially implemented
3763 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3765 u32 cdrom_dma_ack_enable = 1; // a000b93c
3766 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3769 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3772 //PSXBIOS_LOG("%s\n", __func__);
3774 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3775 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3776 //if (--cdrom_irq_counter == 0) // 0xa0009180
3777 // DeliverEvent(0xf0000003, 0x10);
3781 mips_return_c(ret, 20);
3784 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3786 u32 cdrom_irq_ack_enable = 1; // a000b938
3787 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3790 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3793 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3794 PSXBIOS_LOG("%s TODO\n", __func__);
3797 mips_return_c(ret, 20);
3800 void hleExc0_2_2_syscall() // not in any A/B/C table
3802 u32 tcbPtr = loadRam32(A_TT_PCB);
3803 TCB *tcb = loadRam32ptr(tcbPtr);
3804 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3806 if (code != R3000E_Syscall) {
3808 DeliverEvent(0xf0000010, 0x1000);
3809 //psxBios_SystemErrorUnresolvedException();
3811 mips_return_c(0, 17);
3815 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3816 tcb->epc += SWAP32(4);
3817 switch (SWAP32(tcb->reg[4])) { // a0
3821 case 1: { // EnterCritical - disable irqs
3822 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3823 tcb->reg[2] = SWAP32(was_enabled);
3824 tcb->sr &= SWAP32(~0x404);
3827 case 2: // ExitCritical - enable irqs
3828 tcb->sr |= SWAP32(0x404);
3831 case 3: { // ChangeThreadSubFunction
3832 u32 tcbPtr = loadRam32(A_TT_PCB);
3833 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3837 DeliverEvent(0xf0000010, 0x4000);
3841 psxBios_ReturnFromException();
3844 void hleExc1_0_1(void)
3846 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3847 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3850 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3853 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3854 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3857 mips_return_c(ret, 22);
3860 void hleExc1_0_2(void)
3862 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3865 void hleExc1_1_1(void)
3867 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3868 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3871 void hleExc1_1_2(void)
3873 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3876 void hleExc1_2_1(void)
3878 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3879 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3882 void hleExc1_2_2(void)
3884 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3887 void hleExc1_3_1(void)
3889 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3890 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3893 void hleExc1_3_2(void)
3895 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3898 void hleExc3_0_2_defint(void)
3900 static const struct {
3911 { 6, 6 }, // rcnt2 (bug)
3916 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3917 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3918 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3923 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3926 void hleExcPadCard1(void)
3928 if (loadRam32(A_PAD_IRQR_ENA)) {
3929 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3930 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3936 if (loadRam32(A_PAD_DR_DST))
3939 if (loadRam32(A_PAD_ACK_VBL))
3940 psxHwWrite16(0x1f801070, ~1);
3941 if (loadRam32(A_CARD_IRQR_ENA)) {
3945 mips_return_c(0, 18);
3948 void hleExcPadCard2(void)
3950 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3951 mips_return_c(ret, 15);
3954 void psxBiosException() {
3955 u32 tcbPtr = loadRam32(A_TT_PCB);
3956 u32 *chains = loadRam32ptr(A_TT_ExCB);
3957 TCB *tcb = loadRam32ptr(tcbPtr);
3963 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3964 for (i = 4; i < 32; i++) {
3967 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3969 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3970 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3971 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3972 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3973 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3974 sp = fp = loadRam32(A_EXC_SP);
3978 // do the chains (always 4)
3979 for (c = lim = 0; c < 4; c++) {
3980 if (chains[c * 2] == 0)
3982 ptr = SWAP32(chains[c * 2]);
3983 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3984 chain = castRam32ptr(ptr);
3989 softCallInException(SWAP32(chain[2]));
3990 if (returned_from_exception())
3993 if (v0 == 0 || chain[1] == 0)
3995 softCallInException(SWAP32(chain[1]));
3996 if (returned_from_exception())
4002 // return from exception (custom or default)
4004 ptr = loadRam32(A_EEXIT_PTR);
4005 if (ptr != A_EEXIT_DEF) {
4006 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4007 longjmp_load(jmp_buf);
4012 psxBios_ReturnFromException();
4015 #define bfreeze(ptr, size) { \
4016 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4017 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4021 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4022 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4024 void psxBiosFreeze(int Mode) {