1 /***************************************************************************
2 * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3 * dmitrysmagin, senquack *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
19 ***************************************************************************/
21 /* Gameblabla 2018-2019 :
22 * Numerous changes to bios calls as well as improvements in order to conform to nocash's findings
23 * for the PSX bios calls. Thanks senquack for helping out with some of the changes
24 * and helping to spot issues and refine my patches.
28 * Internal simulated HLE BIOS.
31 // TODO: implement all system calls, count the exact CPU cycles of system calls.
38 #include "psxinterpreter.h"
42 //#define PSXBIOS_LOG printf
43 #define PSXBIOS_LOG(...)
46 #define PTR_1 (void *)(size_t)1
48 char *biosA0n[256] = {
50 "open", "lseek", "read", "write",
51 "close", "ioctl", "exit", "sys_a0_07",
52 "getc", "putc", "todigit", "atof",
53 "strtoul", "strtol", "abs", "labs",
55 "atoi", "atol", "atob", "setjmp",
56 "longjmp", "strcat", "strncat", "strcmp",
57 "strncmp", "strcpy", "strncpy", "strlen",
58 "index", "rindex", "strchr", "strrchr",
60 "strpbrk", "strspn", "strcspn", "strtok",
61 "strstr", "toupper", "tolower", "bcopy",
62 "bzero", "bcmp", "memcpy", "memset",
63 "memmove", "memcmp", "memchr", "rand",
65 "srand", "qsort", "strtod", "malloc",
66 "free", "lsearch", "bsearch", "calloc",
67 "realloc", "InitHeap", "_exit", "getchar",
68 "putchar", "gets", "puts", "printf",
70 "SystemErrorUnresolvedException", "LoadTest", "Load", "Exec",
71 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
72 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
73 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
75 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
76 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
77 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
78 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
80 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
81 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
82 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
83 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
85 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
86 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
87 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
88 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
90 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
91 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
92 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
93 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
95 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
96 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
97 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
98 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
100 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
101 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
102 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
103 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
105 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
109 char *biosB0n[256] = {
111 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
112 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
113 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
114 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
116 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
117 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
118 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
119 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
121 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
122 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
123 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
124 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
126 "sys_b0_30", "sys_b0_31", "open", "lseek",
127 "read", "write", "close", "ioctl",
128 "exit", "sys_b0_39", "getc", "putc",
129 "getchar", "putchar", "gets", "puts",
131 "cd", "format", "firstfile", "nextfile",
132 "rename", "delete", "undelete", "AddDevice",
133 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
134 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
136 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
137 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
138 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
139 "_card_status", "_card_wait",
142 char *biosC0n[256] = {
144 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
145 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
146 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
147 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
149 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
150 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
151 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
155 //#define r0 (psxRegs.GPR.n.r0)
156 #define at (psxRegs.GPR.n.at)
157 #define v0 (psxRegs.GPR.n.v0)
158 #define v1 (psxRegs.GPR.n.v1)
159 #define a0 (psxRegs.GPR.n.a0)
160 #define a1 (psxRegs.GPR.n.a1)
161 #define a2 (psxRegs.GPR.n.a2)
162 #define a3 (psxRegs.GPR.n.a3)
163 #define t0 (psxRegs.GPR.n.t0)
164 #define t1 (psxRegs.GPR.n.t1)
165 #define t2 (psxRegs.GPR.n.t2)
166 #define t3 (psxRegs.GPR.n.t3)
167 #define t4 (psxRegs.GPR.n.t4)
168 #define t5 (psxRegs.GPR.n.t5)
169 #define t6 (psxRegs.GPR.n.t6)
170 #define t7 (psxRegs.GPR.n.t7)
171 #define t8 (psxRegs.GPR.n.t8)
172 #define t9 (psxRegs.GPR.n.t9)
173 #define s0 (psxRegs.GPR.n.s0)
174 #define s1 (psxRegs.GPR.n.s1)
175 #define s2 (psxRegs.GPR.n.s2)
176 #define s3 (psxRegs.GPR.n.s3)
177 #define s4 (psxRegs.GPR.n.s4)
178 #define s5 (psxRegs.GPR.n.s5)
179 #define s6 (psxRegs.GPR.n.s6)
180 #define s7 (psxRegs.GPR.n.s7)
181 #define k0 (psxRegs.GPR.n.k0)
182 #define k1 (psxRegs.GPR.n.k1)
183 #define gp (psxRegs.GPR.n.gp)
184 #define sp (psxRegs.GPR.n.sp)
185 #define fp (psxRegs.GPR.n.fp)
186 #define ra (psxRegs.GPR.n.ra)
187 #define pc0 (psxRegs.pc)
189 #define Ra0 ((char *)PSXM(a0))
190 #define Ra1 ((char *)PSXM(a1))
191 #define Ra2 ((char *)PSXM(a2))
192 #define Ra3 ((char *)PSXM(a3))
193 #define Rv0 ((char *)PSXM(v0))
194 #define Rsp ((char *)PSXM(sp))
205 #define EvStUNUSED 0x0000
206 #define EvStDISABLED 0x1000
207 #define EvStACTIVE 0x2000
208 #define EvStALREADY 0x4000
210 #define EvMdCALL 0x1000
211 #define EvMdMARK 0x2000
234 u32 _sp, _fp, _gp, ret, base;
254 // todo: FileDesc layout is wrong
255 // todo: get rid of these globals
256 static FileDesc FDesc[32];
257 static char ffile[64];
259 static char cdir[8*8+8];
262 // fixed RAM offsets, SCPH1001 compatible
263 #define A_TT_ExCB 0x0100
264 #define A_TT_PCB 0x0108
265 #define A_TT_TCB 0x0110
266 #define A_TT_EvCB 0x0120
267 #define A_A0_TABLE 0x0200
268 #define A_B0_TABLE 0x0874
269 #define A_C0_TABLE 0x0674
270 #define A_SYSCALL 0x0650
271 #define A_EXCEPTION 0x0c80
272 #define A_EXC_SP 0x6cf0
273 #define A_EEXIT_DEF 0x6cf4
274 #define A_KMALLOC_PTR 0x7460
275 #define A_KMALLOC_SIZE 0x7464
276 #define A_KMALLOC_END 0x7468
277 #define A_PADCRD_CHN_E 0x74a8 // pad/card irq chain entry, see hleExcPadCard1()
278 #define A_PAD_IRQR_ENA 0x74b8 // pad read on vint irq (nocash 'pad_enable_flag')
279 #define A_CARD_IRQR_ENA 0x74bc // same for card
280 #define A_PAD_INBUF 0x74c8 // 2x buffers for rx pad data
281 #define A_PAD_OUTBUF 0x74d0 // 2x buffers for tx pad data
282 #define A_PAD_IN_LEN 0x74d8
283 #define A_PAD_OUT_LEN 0x74e0
284 #define A_PAD_DR_DST 0x74c4
285 #define A_CARD_CHAN1 0x7500
286 #define A_PAD_DR_BUF1 0x7570
287 #define A_PAD_DR_BUF2 0x7598
288 #define A_EEXIT_PTR 0x75d0
289 #define A_EXC_STACK 0x85d8 // exception stack top
290 #define A_RCNT_VBL_ACK 0x8600
291 #define A_PAD_ACK_VBL 0x8914 // enable vint ack by pad reading code
292 #define A_HEAP_BASE 0x9000
293 #define A_HEAP_SIZE 0x9004
294 #define A_HEAP_END 0x9008
295 #define A_HEAP_INIT_FLG 0x900c
296 #define A_RND_SEED 0x9010
297 #define A_HEAP_FRSTCHNK 0xb060
298 #define A_HEAP_CURCHNK 0xb064
299 #define A_CONF_TCB 0xb940
300 #define A_CONF_EvCB 0xb944
301 #define A_CONF_SP 0xb948
302 #define A_CD_EVENTS 0xb9b8
303 #define A_EXC_GP 0xf450
305 #define 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 static int malloc_heap_grow(u32 size) {
1220 u32 heap_addr, heap_end, heap_addr_new;
1222 heap_addr = loadRam32(A_HEAP_BASE);
1223 heap_end = loadRam32(A_HEAP_END);
1224 heap_addr_new = heap_addr + 4 + size;
1225 if (heap_addr_new >= heap_end)
1227 storeRam32(A_HEAP_BASE, heap_addr_new);
1228 storeRam32(heap_addr - 4, size | 1);
1229 storeRam32(heap_addr + size, ~1); // terminator
1233 static void psxBios_malloc() { // 0x33
1234 u32 size = (a0 + 3) & ~3;
1235 u32 limit = 32*1024;
1239 PSXBIOS_LOG("psxBios_%s %d\n", biosA0n[0x33], a0);
1241 if (!loadRam32(A_HEAP_INIT_FLG)) {
1242 u32 heap_addr = loadRam32(A_HEAP_BASE);
1243 storeRam32(heap_addr, ~1);
1244 storeRam32(A_HEAP_FRSTCHNK, heap_addr);
1245 storeRam32(A_HEAP_CURCHNK, heap_addr);
1246 storeRam32(A_HEAP_BASE, heap_addr + 4);
1247 if (malloc_heap_grow(size)) {
1248 PSXBIOS_LOG("malloc: init OOM\n");
1249 mips_return_c(0, 20);
1252 storeRam32(A_HEAP_INIT_FLG, 1);
1255 for (i = 0; tries > 0 && i < limit; i++)
1257 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1258 u32 chunk_hdr = loadRam32(chunk);
1259 u32 next_chunk = chunk + 4 + (chunk_hdr & ~3);
1260 u32 next_chunk_hdr = loadRam32(next_chunk);
1262 //printf(" c %08x %08x\n", chunk, chunk_hdr);
1263 if (chunk_hdr & 1) {
1265 if (chunk_hdr > (size | 1)) {
1267 u32 p2size = (chunk_hdr & ~3) - size - 4;
1268 storeRam32(chunk + 4 + size, p2size | 1);
1269 chunk_hdr = size | 1;
1271 if (chunk_hdr == (size | 1)) {
1272 storeRam32(chunk, size);
1276 if (next_chunk_hdr & 1) {
1278 u32 msize = (chunk_hdr & ~3) + 4 + (next_chunk_hdr & ~3);
1279 storeRam32(chunk, msize | 1);
1283 if (chunk_hdr == ~1) {
1286 storeRam32(A_HEAP_CURCHNK, loadRam32(A_HEAP_FRSTCHNK));
1290 // go to the next chunk
1291 storeRam32(A_HEAP_CURCHNK, next_chunk);
1297 else if (tries == 0 && malloc_heap_grow(size))
1300 u32 chunk = loadRam32(A_HEAP_CURCHNK);
1301 storeRam32(chunk, loadRam32(chunk) & ~3);
1305 PSXBIOS_LOG(" -> %08x\n", ret);
1306 mips_return_c(ret, 40);
1309 static void psxBios_free() { // 0x34
1310 PSXBIOS_LOG("psxBios_%s %x (%d bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4));
1311 storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free
1312 mips_return_void_c(5);
1315 static void psxBios_calloc() { // 0x37
1317 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x37], a0, a1);
1319 a0 = size = a0 * a1;
1323 a0 = ret; a1 = size;
1326 mips_return_c(ret, 21);
1329 void psxBios_realloc() { // 0x38
1333 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1337 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1342 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1347 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1348 /* Note that it is not quite implemented this way here. */
1358 /* InitHeap(void *block , int n) */
1359 static void psxBios_InitHeap() { // 0x39
1360 PSXBIOS_LOG("psxBios_%s %x %x\n", biosA0n[0x39], a0, a1);
1362 storeRam32(A_HEAP_BASE, a0);
1363 storeRam32(A_HEAP_SIZE, a1);
1364 storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4);
1365 storeRam32(A_HEAP_INIT_FLG, 0);
1368 mips_return_void_c(14);
1371 void psxBios_getchar() { //0x3b
1372 v0 = getchar(); pc0 = ra;
1375 static void psxBios_printf_psxout() { // 0x3f
1384 if (psp != INVALID_PTR) {
1385 memcpy(save, psp, 4 * 4);
1386 psxMu32ref(sp) = SWAP32((u32)a0);
1387 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1388 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1389 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1401 tmp2[j++] = Ra0[i]; goto _start;
1403 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1414 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1418 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1424 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1426 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1428 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1430 *ptmp++ = Ra0[i]; break;
1440 if (psp != INVALID_PTR)
1441 memcpy(psp, save, 4 * 4);
1444 SysPrintf("%s", tmp);
1447 void psxBios_printf() { // 0x3f
1448 psxBios_printf_psxout();
1452 static void psxBios_cd() { // 0x40
1453 const char *p, *dir = castRam8ptr(a0);
1454 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x40], a0, dir);
1455 if ((p = strchr(dir, ':')))
1459 snprintf(cdir, sizeof(cdir), "%s", dir);
1460 mips_return_c(1, 100);
1463 static void psxBios_format() { // 0x41
1464 PSXBIOS_LOG("psxBios_%s %x(%s)\n", biosB0n[0x41], a0, Ra0);
1465 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1467 CreateMcd(Config.Mcd1);
1468 LoadMcd(1, Config.Mcd1);
1471 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1473 CreateMcd(Config.Mcd2);
1474 LoadMcd(2, Config.Mcd2);
1484 static void psxBios_SystemErrorUnresolvedException() {
1485 if (floodchk != 0x12340a40) { // prevent log flood
1486 SysPrintf("psxBios_%s called from %08x\n", biosA0n[0x40], ra);
1487 floodchk = 0x12340a40;
1489 mips_return_void_c(1000);
1492 static void FlushCache() {
1493 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1494 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1496 // runs from uncached mem so tons of cycles
1501 * long Load(char *name, struct EXEC *header);
1504 void psxBios_Load() { // 0x42
1512 PSXBIOS_LOG("psxBios_%s %x(%s), %x\n", biosA0n[0x42], a0, pa0, a1);
1513 if (pa0 == INVALID_PTR || pa1 == INVALID_PTR) {
1517 if ((p = strchr(pa0, ':')))
1522 snprintf(path, sizeof(path), "%s\\%s", cdir, (char *)pa0);
1524 snprintf(path, sizeof(path), "%s", (char *)pa0);
1526 if (LoadCdromFile(path, &eheader) == 0) {
1527 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1528 psxCpu->Clear(a1, sizeof(EXEC) / 4);
1532 PSXBIOS_LOG(" -> %d\n", v0);
1538 * int Exec(struct EXEC *header , int argc , char **argv);
1541 void psxBios_Exec() { // 43
1542 EXEC *header = (EXEC *)castRam32ptr(a0);
1546 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1548 header->_sp = SWAP32(sp);
1549 header->_fp = SWAP32(fp);
1550 header->_sp = SWAP32(sp);
1551 header->_gp = SWAP32(gp);
1552 header->ret = SWAP32(ra);
1553 header->base = SWAP32(s0);
1555 ptr = SWAP32(header->b_addr);
1556 len = SWAP32(header->b_size);
1562 if (header->S_addr != 0)
1563 sp = fp = SWAP32(header->S_addr) + SWAP32(header->s_size);
1565 gp = SWAP32(header->gp0);
1573 pc0 = SWAP32(header->_pc0);
1576 static void psxBios_FlushCache() { // 44
1577 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1582 void psxBios_GPU_dw() { // 0x46
1587 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1590 GPU_writeData(0xa0000000);
1591 GPU_writeData((a1<<0x10)|(a0&0xffff));
1592 GPU_writeData((a3<<0x10)|(a2&0xffff));
1594 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1597 GPU_writeData(SWAPu32(*ptr++));
1603 void psxBios_mem2vram() { // 0x47
1605 gpuSyncPluginSR(); // flush
1606 GPU_writeData(0xa0000000);
1607 GPU_writeData((a1<<0x10)|(a0&0xffff));
1608 GPU_writeData((a3<<0x10)|(a2&0xffff));
1609 size = ((((a2 * a3) / 2) >> 4) << 16);
1610 GPU_writeStatus(0x04000002);
1611 psxHwWrite32(0x1f8010f4,0);
1612 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1613 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1614 psxHwWrite32(0x1f8010a4, size | 0x10);
1615 psxHwWrite32(0x1f8010a8,0x01000201);
1620 void psxBios_SendGPU() { // 0x48
1621 GPU_writeStatus(a0);
1626 void psxBios_GPU_cw() { // 0x49
1633 void psxBios_GPU_cwb() { // 0x4a
1634 u32 *ptr = (u32*)Ra0;
1639 GPU_writeData(SWAPu32(*ptr++));
1645 void psxBios_GPU_SendPackets() { //4b:
1647 GPU_writeStatus(0x04000002);
1648 psxHwWrite32(0x1f8010f4,0);
1649 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1650 psxHwWrite32(0x1f8010a0,a0);
1651 psxHwWrite32(0x1f8010a4,0);
1652 psxHwWrite32(0x1f8010a8,0x010000401);
1656 void psxBios_sys_a0_4c() { // 0x4c GPU relate
1657 psxHwWrite32(0x1f8010a8,0x00000401);
1658 GPU_writeData(0x0400000);
1659 GPU_writeData(0x0200000);
1660 GPU_writeData(0x0100000);
1665 void psxBios_GPU_GetGPUStatus() { // 0x4d
1666 v0 = GPU_readStatus();
1672 void psxBios_LoadExec() { // 51
1673 EXEC *header = (EXEC*)PSXM(0xf000);
1677 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1679 s_addr = a1; s_size = a2;
1684 header->S_addr = s_addr;
1685 header->s_size = s_size;
1687 a0 = 0xf000; a1 = 0; a2 = 0;
1691 void psxBios__bu_init() { // 70
1693 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1696 DeliverEvent(0xf0000011, 0x0004);
1697 DeliverEvent(0xf4000001, 0x0004);
1702 void psxBios__96_init() { // 71
1704 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1710 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2);
1711 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr);
1712 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr);
1714 static void psxBios_DequeueCdIntr_() {
1715 psxBios_SysDeqIntRP_(0, 0x91d0);
1716 psxBios_SysDeqIntRP_(0, 0x91e0);
1720 static void psxBios_DequeueCdIntr() { // a3
1721 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1722 psxBios_DequeueCdIntr_();
1725 static void psxBios_CdRemove() { // 56, 72
1726 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1728 CloseEvent(loadRam32(A_CD_EVENTS + 0x00));
1729 CloseEvent(loadRam32(A_CD_EVENTS + 0x04));
1730 CloseEvent(loadRam32(A_CD_EVENTS + 0x08));
1731 CloseEvent(loadRam32(A_CD_EVENTS + 0x0c));
1732 CloseEvent(loadRam32(A_CD_EVENTS + 0x10));
1733 psxBios_DequeueCdIntr_();
1735 // EnterCriticalSection - should be done at the beginning,
1736 // but this way is much easier to implement
1742 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack);
1744 static void psxBios_SetConf() { // 9c
1745 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9c], a0, a1, a2);
1746 setup_tt(a1, a0, a2);
1747 psxRegs.CP0.n.SR |= 0x401;
1748 mips_return_void_c(500);
1751 static void psxBios_GetConf() { // 9d
1752 PSXBIOS_LOG("psxBios_%s %x %x %x\n", biosA0n[0x9d], a0, a1, a2);
1753 storeRam32(a0, loadRam32(A_CONF_EvCB));
1754 storeRam32(a1, loadRam32(A_CONF_TCB));
1755 storeRam32(a2, loadRam32(A_CONF_SP));
1756 mips_return_void_c(10);
1759 void psxBios_SetMem() { // 9f
1760 u32 new = psxHu32(0x1060);
1763 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1768 psxHu32ref(0x1060) = SWAP32(new);
1769 psxMu32ref(0x060) = a0;
1770 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1774 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1775 psxMu32ref(0x060) = a0;
1776 PSXBIOS_LOG("Change effective memory : %d MBytes\n",a0);
1779 PSXBIOS_LOG("Effective memory must be 2/8 MBytes\n");
1786 /* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1787 static void psxBios_get_cd_status() // a6
1789 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa6]);
1794 static void psxBios__card_info() { // ab
1795 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1797 storeRam32(A_CARD_CHAN1, a0);
1804 if (McdDisable[port & 1])
1808 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], a0);
1813 if (McdDisable[0] && McdDisable[1])
1816 DeliverEvent(0xf0000011, 0x0004);
1817 // DeliverEvent(0xf4000001, 0x0004);
1818 DeliverEvent(0xf4000001, ret);
1822 void psxBios__card_load() { // ac
1824 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1827 storeRam32(A_CARD_CHAN1, a0);
1829 // DeliverEvent(0xf0000011, 0x0004);
1830 DeliverEvent(0xf4000001, 0x0004);
1835 static void psxBios_GetSystemInfo() { // b4
1837 //PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0xb4], a0);
1838 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0);
1841 case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break;
1842 case 2: ret = 0xbfc0012c; break;
1843 case 5: ret = loadRam32(0x60) << 10; break;
1845 mips_return_c(ret, 20);
1848 /* System calls B0 */
1850 static u32 psxBios_SysMalloc_(u32 size);
1852 static void psxBios_SysMalloc() { // B 00
1853 u32 ret = psxBios_SysMalloc_(a0);
1855 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1856 mips_return_c(ret, 33);
1859 void psxBios_SetRCnt() { // 02
1861 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1868 psxRcntWtarget(a0, a1);
1869 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1870 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1871 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1872 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1873 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1875 psxRcntWmode(a0, mode);
1880 void psxBios_GetRCnt() { // 03
1882 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1887 case 0: v0 = psxRcntRcount0(); break;
1888 case 1: v0 = psxRcntRcount1(); break;
1889 case 2: v0 = psxRcntRcount2(); break;
1890 case 3: v0 = 0; break;
1895 void psxBios_StartRCnt() { // 04
1897 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1901 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1902 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1906 void psxBios_StopRCnt() { // 05
1908 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1912 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1913 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1917 void psxBios_ResetRCnt() { // 06
1919 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1924 psxRcntWmode(a0, 0);
1925 psxRcntWtarget(a0, 0);
1926 psxRcntWcount(a0, 0);
1931 static u32 DeliverEvent(u32 class, u32 spec) {
1932 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1933 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1934 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1935 u32 i, lim = evcb_len / 0x1c;
1937 //printf("%s %08x %x\n", __func__, class, spec);
1938 for (i = 0; i < lim; i++, ev++) {
1940 if (SWAP32(ev->status) != EvStACTIVE)
1943 if (SWAP32(ev->class) != class)
1946 if (SWAP32(ev->spec) != spec)
1949 ret = SWAP32(ev->mode);
1950 if (ret == EvMdMARK) {
1951 ev->status = SWAP32(EvStALREADY);
1955 if (ret == EvMdCALL) {
1956 ret = SWAP32(ev->fhandler);
1969 static u32 UnDeliverEvent(u32 class, u32 spec) {
1970 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
1971 u32 evcb_len = loadRam32(A_TT_EvCB + 4);
1972 u32 ret = loadRam32(A_TT_EvCB) + evcb_len;
1973 u32 i, lim = evcb_len / 0x1c;
1975 for (i = 0; i < lim; i++, ev++) {
1977 if (SWAP32(ev->status) != EvStALREADY)
1980 if (SWAP32(ev->class) != class)
1983 if (SWAP32(ev->spec) != spec)
1986 if (SWAP32(ev->mode) == EvMdMARK)
1987 ev->status = SWAP32(EvStACTIVE);
1993 static void psxBios_DeliverEvent() { // 07
1995 PSXBIOS_LOG("psxBios_%s %x %04x\n", biosB0n[0x07], a0, a1);
1997 ret = DeliverEvent(a0, a1);
2001 static s32 get_free_EvCB_slot() {
2002 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB);
2003 u32 i, lim = loadRam32(A_TT_EvCB + 4) / 0x1c;
2006 for (i = 0; i < lim; i++, ev++) {
2008 if (ev->status == SWAP32(EvStUNUSED))
2014 static u32 OpenEvent(u32 class, u32 spec, u32 mode, u32 func) {
2015 u32 ret = get_free_EvCB_slot();
2016 if ((s32)ret >= 0) {
2017 EvCB *ev = (EvCB *)loadRam32ptr(A_TT_EvCB) + ret;
2018 ev->class = SWAP32(class);
2019 ev->status = SWAP32(EvStDISABLED);
2020 ev->spec = SWAP32(spec);
2021 ev->mode = SWAP32(mode);
2022 ev->fhandler = SWAP32(func);
2028 static void psxBios_OpenEvent() { // 08
2029 u32 ret = OpenEvent(a0, a1, a2, a3);
2030 PSXBIOS_LOG("psxBios_%s (class:%x, spec:%04x, mode:%04x, func:%x) -> %x\n",
2031 biosB0n[0x08], a0, a1, a2, a3, ret);
2032 mips_return_c(ret, 36);
2035 static void CloseEvent(u32 ev)
2037 u32 base = loadRam32(A_TT_EvCB);
2038 storeRam32(base + (ev & 0xffff) * sizeof(EvCB) + 4, EvStUNUSED);
2041 static void psxBios_CloseEvent() { // 09
2042 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x09], a0,
2043 loadRam32(loadRam32(A_TT_EvCB) + (a0 & 0xffff) * sizeof(EvCB) + 4));
2045 mips_return_c(1, 10);
2048 static void psxBios_WaitEvent() { // 0a
2049 u32 base = loadRam32(A_TT_EvCB);
2050 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2051 PSXBIOS_LOG("psxBios_%s %x (status=%x)\n", biosB0n[0x0a], a0, status);
2054 if (status == EvStALREADY) {
2055 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2059 if (status != EvStACTIVE)
2061 mips_return_c(0, 2);
2065 // retrigger this hlecall after the next emulation event
2067 if ((s32)(next_interupt - psxRegs.cycle) > 0)
2068 psxRegs.cycle = next_interupt;
2072 static void psxBios_TestEvent() { // 0b
2073 u32 base = loadRam32(A_TT_EvCB);
2074 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2077 if (psxRegs.cycle - floodchk > 16*1024u) { // prevent log flood
2078 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x0b], a0, status);
2079 floodchk = psxRegs.cycle;
2081 if (status == EvStALREADY) {
2082 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2086 mips_return_c(ret, 15);
2089 static void psxBios_EnableEvent() { // 0c
2090 u32 base = loadRam32(A_TT_EvCB);
2091 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2092 PSXBIOS_LOG("psxBios_%s %x (%x)\n", biosB0n[0x0c], a0, status);
2093 if (status != EvStUNUSED)
2094 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStACTIVE);
2096 mips_return_c(1, 15);
2099 static void psxBios_DisableEvent() { // 0d
2100 u32 base = loadRam32(A_TT_EvCB);
2101 u32 status = loadRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4);
2102 PSXBIOS_LOG("psxBios_%s %x: %x\n", biosB0n[0x0d], a0, status);
2103 if (status != EvStUNUSED)
2104 storeRam32(base + (a0 & 0xffff) * sizeof(EvCB) + 4, EvStDISABLED);
2106 mips_return_c(1, 15);
2110 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
2113 void psxBios_OpenTh() { // 0e
2114 TCB *tcb = loadRam32ptr(A_TT_TCB);
2115 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2118 for (th = 1; th < limit; th++)
2120 if (tcb[th].status != SWAP32(0x4000)) break;
2124 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
2125 // When no free TCB is found, return 0xffffffff according to Nocash doc.
2127 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
2129 mips_return_c(0xffffffff, 20);
2132 PSXBIOS_LOG("psxBios_%s -> %x\n", biosB0n[0x0e], 0xff000000 + th);
2134 tcb[th].status = SWAP32(0x4000);
2135 tcb[th].mode = SWAP32(0x1000);
2136 tcb[th].epc = SWAP32(a0);
2137 tcb[th].reg[30] = SWAP32(a1); // fp
2138 tcb[th].reg[29] = SWAP32(a1); // sp
2139 tcb[th].reg[28] = SWAP32(a2); // gp
2141 mips_return_c(0xff000000 + th, 34);
2145 * int CloseTh(long thread);
2148 static void psxBios_CloseTh() { // 0f
2149 u32 tcb = loadRam32(A_TT_TCB);
2150 u32 th = a0 & 0xffff;
2152 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x0f], a0);
2153 // in the usual bios fashion no checks, just write and return 1
2154 storeRam32(tcb + th * sizeof(TCB), 0x1000);
2156 mips_return_c(1, 11);
2160 * int ChangeTh(long thread);
2163 void psxBios_ChangeTh() { // 10
2164 u32 tcbBase = loadRam32(A_TT_TCB);
2165 u32 th = a0 & 0xffff;
2167 // this is quite spammy
2168 //PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x10], th);
2170 // without doing any argument checks, just issue a syscall
2171 // (like the real bios does)
2173 a1 = tcbBase + th * sizeof(TCB);
2178 void psxBios_InitPAD() { // 0x12
2179 u32 i, *ram32 = (u32 *)psxM;
2180 PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3);
2182 // printf("%s", "PS-X Control PAD Driver Ver 3.0");
2183 ram32[A_PAD_DR_DST/4] = 0;
2184 ram32[A_PAD_OUTBUF/4 + 0] = 0;
2185 ram32[A_PAD_OUTBUF/4 + 1] = 0;
2186 ram32[A_PAD_OUT_LEN/4 + 0] = 0;
2187 ram32[A_PAD_OUT_LEN/4 + 1] = 0;
2188 ram32[A_PAD_INBUF/4 + 0] = SWAP32(a0);
2189 ram32[A_PAD_INBUF/4 + 1] = SWAP32(a2);
2190 ram32[A_PAD_IN_LEN/4 + 0] = SWAP32(a1);
2191 ram32[A_PAD_IN_LEN/4 + 1] = SWAP32(a3);
2193 for (i = 0; i < a1; i++) {
2195 storeRam8(a0 + i, 0);
2197 for (i = 0; i < a3; i++) {
2199 storeRam8(a2 + i, 0);
2201 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2203 ram32[A_PAD_IRQR_ENA/4] = SWAP32(1);
2205 mips_return_c(1, 200);
2208 void psxBios_StartPAD() { // 13
2209 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2211 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2212 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2213 psxHwWrite16(0x1f801070, ~1);
2214 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2215 storeRam32(A_PAD_ACK_VBL, 1);
2216 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2217 psxRegs.CP0.n.SR |= 0x401;
2219 mips_return_c(1, 300);
2222 void psxBios_StopPAD() { // 14
2223 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2224 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2225 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2226 psxRegs.CP0.n.SR |= 0x401;
2227 mips_return_void_c(200);
2230 static void psxBios_PAD_init() { // 15
2232 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2233 if (a0 == 0x20000000 || a0 == 0x20000001)
2236 a0 = A_PAD_DR_BUF1; a1 = 0x22;
2237 a2 = A_PAD_DR_BUF2; a3 = 0x22;
2240 storeRam32(A_PAD_DR_DST, dst);
2243 mips_return_c(ret, 100);
2246 static u32 psxBios_PAD_dr_() {
2247 u8 *dst = loadRam32ptr(A_PAD_DR_DST);
2248 u8 *buf1 = castRam8ptr(A_PAD_DR_BUF1);
2249 u8 *buf2 = castRam8ptr(A_PAD_DR_BUF2);
2250 dst[0] = dst[1] = dst[2] = dst[3] = ~0;
2251 if (buf1[0] == 0 && (buf1[1] == 0x23 || buf1[1] == 0x41))
2253 dst[0] = buf1[3], dst[1] = buf1[2];
2254 if (buf1[1] == 0x23) {
2255 dst[0] |= 0xc7, dst[1] |= 7;
2256 if (buf1[5] >= 0x10) dst[0] &= ~(1u << 6);
2257 if (buf1[6] >= 0x10) dst[0] &= ~(1u << 7);
2260 if (buf2[0] == 0 && (buf2[1] == 0x23 || buf2[1] == 0x41))
2262 dst[2] = buf2[3], dst[3] = buf2[2];
2263 if (buf2[1] == 0x23) {
2264 dst[2] |= 0xc7, dst[3] |= 7;
2265 if (buf2[5] >= 0x10) dst[2] &= ~(1u << 6);
2266 if (buf2[6] >= 0x10) dst[2] &= ~(1u << 7);
2270 return SWAP32(*(u32 *)dst);
2273 static void psxBios_PAD_dr() { // 16
2274 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2275 u32 ret = psxBios_PAD_dr_();
2279 static void psxBios_ReturnFromException() { // 17
2280 u32 tcbPtr = loadRam32(A_TT_PCB);
2281 const TCB *tcb = loadRam32ptr(tcbPtr);
2285 for (i = 1; i < 32; i++)
2286 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2287 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2288 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2289 sr = SWAP32(tcb->sr);
2291 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2292 pc0 = k0 = SWAP32(tcb->epc);
2294 // the interpreter wants to know about sr changes, so do a MTC0
2295 sr = (sr & ~0x0f) | ((sr & 0x3c) >> 2);
2296 MTC0(&psxRegs, 12, sr);
2302 void psxBios_ResetEntryInt() { // 18
2303 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2305 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2306 mips_return_void_c(5);
2309 void psxBios_HookEntryInt() { // 19
2310 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2312 storeRam32(A_EEXIT_PTR, a0);
2313 mips_return_void_c(3);
2316 static void psxBios_UnDeliverEvent() { // 0x20
2318 PSXBIOS_LOG("psxBios_%s %x %x\n", biosB0n[0x20], a0, a1);
2320 ret = UnDeliverEvent(a0, a1);
2324 static void buopen(int mcd, char *ptr, char *cfg)
2327 char *mcd_data = ptr;
2329 strcpy(FDesc[1 + mcd].name, Ra0+5);
2330 FDesc[1 + mcd].offset = 0;
2331 FDesc[1 + mcd].mode = a1;
2333 for (i=1; i<16; i++) {
2334 const char *fptr = mcd_data + 128 * i;
2335 if ((*fptr & 0xF0) != 0x50) continue;
2336 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2337 FDesc[1 + mcd].mcfile = i;
2338 PSXBIOS_LOG("open %s\n", fptr+0xa);
2342 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2343 for (i=1; i<16; i++) {
2344 int j, xor, nblk = a1 >> 16;
2346 char *fptr = mcd_data + 128 * i;
2348 if ((*fptr & 0xF0) != 0xa0) continue;
2350 FDesc[1 + mcd].mcfile = i;
2353 fptr[5] = 0x20 * nblk;
2356 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2357 pptr = fptr2 = fptr;
2358 for(j=2; j<=nblk; j++) {
2360 for(i++; i<16; i++) {
2363 memset(fptr2, 0, 128);
2364 fptr2[0] = j < nblk ? 0x52 : 0x53;
2367 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2372 /* shouldn't this return ENOSPC if i == 16? */
2374 pptr[8] = pptr[9] = 0xff;
2375 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2377 PSXBIOS_LOG("openC %s %d\n", ptr, nblk);
2379 /* just go ahead and resave them all */
2380 SaveMcd(cfg, ptr, 128, 128 * 15);
2383 /* shouldn't this return ENOSPC if i == 16? */
2388 * int open(char *name , int mode);
2391 void psxBios_open() { // 0x32
2394 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x32], Ra0, a1);
2398 if (pa0 != INVALID_PTR) {
2399 if (!strncmp(pa0, "bu00", 4)) {
2400 buopen(1, Mcd1Data, Config.Mcd1);
2403 if (!strncmp(pa0, "bu10", 4)) {
2404 buopen(2, Mcd2Data, Config.Mcd2);
2412 * int lseek(int fd , int offset , int whence);
2415 void psxBios_lseek() { // 0x33
2417 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2422 FDesc[a0].offset = a1;
2424 // DeliverEvent(0xf0000011, 0x0004);
2425 // DeliverEvent(0xf4000001, 0x0004);
2429 FDesc[a0].offset+= a1;
2430 v0 = FDesc[a0].offset;
2439 * int read(int fd , void *buf , int nbytes);
2442 void psxBios_read() { // 0x34
2447 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2452 if (pa1 != INVALID_PTR) {
2454 case 2: buread(pa1, 1, a2); break;
2455 case 3: buread(pa1, 2, a2); break;
2463 * int write(int fd , void *buf , int nbytes);
2466 void psxBios_write() { // 0x35/0x03
2470 if (a0 != 1) // stdout
2471 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2474 if (pa1 == INVALID_PTR) {
2479 if (a0 == 1) { // stdout
2483 if (Config.PsxOut) while (a2 > 0) {
2484 SysPrintf("%c", *ptr++); a2--;
2490 case 2: buwrite(pa1, 1, a2); break;
2491 case 3: buwrite(pa1, 2, a2); break;
2497 static void psxBios_write_psxout() {
2498 if (a0 == 1) { // stdout
2499 const char *ptr = Ra1;
2502 if (ptr != INVALID_PTR)
2504 SysPrintf("%c", *ptr++);
2508 static void psxBios_putchar_psxout() { // 3d
2509 SysPrintf("%c", (char)a0);
2512 static void psxBios_puts_psxout() { // 3e/3f
2513 SysPrintf("%s", Ra0);
2517 * int close(int fd);
2520 void psxBios_close() { // 0x36
2522 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2529 void psxBios_putchar() { // 3d
2530 if (Config.PsxOut) SysPrintf("%c", (char)a0);
2534 void psxBios_puts() { // 3e/3f
2535 if (Config.PsxOut) SysPrintf("%s", Ra0);
2539 static void bufile(const u8 *mcd_data, u32 dir_) {
2540 struct DIRENTRY *dir = (struct DIRENTRY *)castRam8ptr(dir_);
2541 const char *pfile = ffile + 5;
2542 const u8 *data = mcd_data;
2543 int i = 0, match = 0;
2548 for (; nfile <= 15 && !match; nfile++) {
2551 head = nfile * 0x40;
2552 data = mcd_data + 128 * nfile;
2553 name = (const char *)data + 0x0a;
2554 if ((data[0] & 0xF0) != 0x50) continue;
2555 /* Bug link files show up as free block. */
2556 if (!name[0]) continue;
2558 for (i = 0; i < 20; i++) {
2559 if (pfile[i] == name[i] || pfile[i] == '?')
2560 dir->name[i] = name[i];
2561 else if (pfile[i] == '*') {
2562 int len = strlen(name + i);
2565 memcpy(dir->name + i, name + i, len + 1);
2576 PSXBIOS_LOG("%d : %s = %s + %s (match=%d)\n",
2577 nfile, dir->name, pfile, name, match);
2579 for (; nfile <= 15; nfile++, blocks++) {
2580 const u8 *data2 = mcd_data + 128 * nfile;
2581 const char *name = (const char *)data2 + 0x0a;
2582 if ((data2[0] & 0xF0) != 0x50 || name[0])
2586 // nul char of full lenth name seems to overwrite .attr
2587 dir->attr = SWAP32(i < 20 ? data[0] & 0xf0 : 0); // ?
2588 dir->size = 8192 * blocks;
2592 PSXBIOS_LOG(" -> %x '%s' %x %x %x %x\n", v0, v0 ? dir->name : "",
2593 dir->attr, dir->size, dir->next, dir->head);
2597 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2600 static void psxBios_firstfile() { // 42
2601 char *pa0 = castRam8ptr(a0);
2603 PSXBIOS_LOG("psxBios_%s %s %x\n", biosB0n[0x42], pa0, a1);
2607 snprintf(ffile, sizeof(ffile), "%s", pa0);
2609 strcpy(ffile + 5, "*"); // maybe?
2611 if (!strncmp(pa0, "bu00", 4)) {
2612 // firstfile() calls _card_read() internally, so deliver it's event
2613 DeliverEvent(0xf0000011, 0x0004);
2614 bufile((u8 *)Mcd1Data, a1);
2615 } else if (!strncmp(pa0, "bu10", 4)) {
2616 // firstfile() calls _card_read() internally, so deliver it's event
2617 DeliverEvent(0xf0000011, 0x0004);
2618 bufile((u8 *)Mcd2Data, a1);
2626 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2629 void psxBios_nextfile() { // 43
2630 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x43], a0);
2633 if (!strncmp(ffile, "bu00", 4))
2634 bufile((u8 *)Mcd1Data, a0);
2635 else if (!strncmp(ffile, "bu10", 4))
2636 bufile((u8 *)Mcd2Data, a0);
2641 #define burename(mcd) { \
2642 for (i=1; i<16; i++) { \
2643 int namelen, j, xor = 0; \
2644 ptr = Mcd##mcd##Data + 128 * i; \
2645 if ((*ptr & 0xF0) != 0x50) continue; \
2646 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2647 namelen = strlen(Ra1+5); \
2648 memcpy(ptr+0xa, Ra1+5, namelen); \
2649 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2650 for (j=0; j<127; j++) xor^= ptr[j]; \
2652 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2659 * int rename(char *old, char *new);
2662 void psxBios_rename() { // 44
2669 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2674 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2675 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2679 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2688 #define budelete(mcd) { \
2689 for (i=1; i<16; i++) { \
2690 ptr = Mcd##mcd##Data + 128 * i; \
2691 if ((*ptr & 0xF0) != 0x50) continue; \
2692 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2693 *ptr = (*ptr & 0xf) | 0xA0; \
2694 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2695 PSXBIOS_LOG("delete %s\n", ptr+0xa); \
2702 * int delete(char *name);
2705 void psxBios_delete() { // 45
2711 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2716 if (pa0 != INVALID_PTR) {
2717 if (!strncmp(pa0, "bu00", 4)) {
2721 if (!strncmp(pa0, "bu10", 4)) {
2729 void psxBios_InitCARD() { // 4a
2730 u32 *ram32 = (u32 *)psxM;
2731 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2732 write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c);
2733 // (maybe) todo: early_card_irq, etc
2735 ram32[A_PAD_IRQR_ENA/4] = SWAP32(a0);
2737 psxBios_FlushCache();
2738 mips_return_c(0, 34+13+15+6);
2741 void psxBios_StartCARD() { // 4b
2742 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2743 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2744 psxBios_SysEnqIntRP_(2, A_PADCRD_CHN_E);
2746 psxHwWrite16(0x1f801074, psxHu32(0x1074) | 1);
2747 storeRam32(A_PAD_ACK_VBL, 1);
2748 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 0);
2749 storeRam32(A_CARD_IRQR_ENA, 1);
2750 psxRegs.CP0.n.SR |= 0x401;
2752 mips_return_c(1, 200);
2755 void psxBios_StopCARD() { // 4c
2756 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2757 storeRam32(A_RCNT_VBL_ACK + (3 << 2), 1);
2758 psxBios_SysDeqIntRP_(2, A_PADCRD_CHN_E);
2759 storeRam32(A_CARD_IRQR_ENA, 0);
2760 psxRegs.CP0.n.SR |= 0x401;
2761 mips_return_void_c(200);
2764 void psxBios__card_write() { // 0x4e
2769 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2772 Function also accepts sector 400h (a bug).
2773 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2777 /* Invalid sectors */
2781 storeRam32(A_CARD_CHAN1, a0);
2784 if (pa2 != INVALID_PTR) {
2786 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2787 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2789 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2790 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2794 DeliverEvent(0xf0000011, 0x0004);
2795 // DeliverEvent(0xf4000001, 0x0004);
2800 void psxBios__card_read() { // 0x4f
2805 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2808 Function also accepts sector 400h (a bug).
2809 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2813 /* Invalid sectors */
2817 storeRam32(A_CARD_CHAN1, a0);
2820 if (pa2 != INVALID_PTR) {
2822 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2824 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2828 DeliverEvent(0xf0000011, 0x0004);
2829 // DeliverEvent(0xf4000001, 0x0004);
2834 void psxBios__new_card() { // 0x50
2836 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2842 /* According to a user, this allows Final Fantasy Tactics to save/load properly */
2843 void psxBios__get_error(void) // 55
2845 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2850 void psxBios_Krom2RawAdd() { // 0x51
2853 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2854 const u32 table_8140[][2] = {
2855 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2856 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2857 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2858 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2859 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2860 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2861 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2862 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2863 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2867 const u32 table_889f[][2] = {
2868 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2869 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2870 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2871 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2872 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2873 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2874 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2875 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2879 if (a0 >= 0x8140 && a0 <= 0x84be) {
2880 while (table_8140[i][0] <= a0) i++;
2881 a0 -= table_8140[i - 1][0];
2882 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2883 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2884 while (table_889f[i][0] <= a0) i++;
2885 a0 -= table_889f[i - 1][0];
2886 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2894 void psxBios_GetC0Table() { // 56
2895 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2896 log_unhandled("GetC0Table @%08x\n", ra);
2898 mips_return_c(A_C0_TABLE, 3);
2901 void psxBios_GetB0Table() { // 57
2902 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2903 log_unhandled("GetB0Table @%08x\n", ra);
2905 mips_return_c(A_B0_TABLE, 3);
2908 static void psxBios__card_chan() { // 0x58
2910 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2912 // todo: should return active slot chan
2913 // (active - which was last processed by irq code)
2914 ret = loadRam32(A_CARD_CHAN1);
2915 mips_return_c(ret, 8);
2918 static void psxBios_ChangeClearPad() { // 5b
2920 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2921 ret = loadRam32(A_PAD_ACK_VBL);
2922 storeRam32(A_PAD_ACK_VBL, a0);
2924 mips_return_c(ret, 6);
2927 static void psxBios__card_status() { // 5c
2928 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5c], a0);
2934 static void psxBios__card_wait() { // 5d
2935 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x5d], a0);
2941 /* System calls C0 */
2943 static void psxBios_InitRCnt() { // 00
2945 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2946 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2947 for (i = 0; i < 3; i++) {
2948 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2949 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2950 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2952 psxBios_SysEnqIntRP_(a0, 0x6d88);
2953 mips_return_c(0, 9);
2956 static void psxBios_InitException() { // 01
2957 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2958 psxBios_SysEnqIntRP_(a0, 0x6da8);
2959 mips_return_c(0, 9);
2963 * int SysEnqIntRP(int index , long *queue);
2966 static void psxBios_SysEnqIntRP_(u32 priority, u32 chain_eptr) {
2967 u32 old, base = loadRam32(A_TT_ExCB);
2969 old = loadRam32(base + (priority << 3));
2970 storeRam32(base + (priority << 3), chain_eptr);
2971 storeRam32(chain_eptr, old);
2972 mips_return_c(0, 9);
2975 static void psxBios_SysEnqIntRP() { // 02
2976 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2977 psxBios_SysEnqIntRP_(a0, a1);
2981 * int SysDeqIntRP(int index , long *queue);
2984 static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr) {
2985 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2986 u32 lim = 0, ret = 0;
2988 // as in original: no arg checks of any kind, bug if a1 == 0
2989 ptr = loadRam32(base + (priority << 3));
2991 next = loadRam32(ptr);
2992 if (ptr == chain_rm_eptr) {
2993 storeRam32(base + (priority << 3), next);
2998 while (next && next != chain_rm_eptr && lim++ < 100) {
3000 next = loadRam32(ptr);
3003 if (next == chain_rm_eptr) {
3004 next = loadRam32(next);
3005 storeRam32(ptr, next);
3012 PSXBIOS_LOG("bad chain %u %x\n", priority, base);
3014 mips_return_c(ret, 12);
3017 static void psxBios_SysDeqIntRP() { // 03
3018 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
3019 psxBios_SysDeqIntRP_(a0, a1);
3022 static void psxBios_get_free_EvCB_slot() { // 04
3023 PSXBIOS_LOG("psxBios_%s\n", biosC0n[0x04]);
3024 s32 ret = get_free_EvCB_slot();
3025 mips_return_c(ret, 0);
3028 static void psxBios_SysInitMemory_(u32 base, u32 size) {
3029 storeRam32(base, 0);
3030 storeRam32(A_KMALLOC_PTR, base);
3031 storeRam32(A_KMALLOC_SIZE, size);
3032 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
3035 // this should be much more complicated, but maybe that'll be enough
3036 static u32 psxBios_SysMalloc_(u32 size) {
3037 u32 ptr = loadRam32(A_KMALLOC_PTR);
3039 size = (size + 3) & ~3;
3040 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
3041 storeRam32(ptr, size);
3045 static void psxBios_SysInitMemory() { // 08
3046 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
3048 psxBios_SysInitMemory_(a0, a1);
3049 mips_return_void_c(12);
3052 static void psxBios_ChangeClearRCnt() { // 0a
3055 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
3057 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
3058 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
3059 mips_return_c(ret, 8);
3062 static void psxBios_InitDefInt() { // 0c
3063 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
3064 // should also clear the autoack table
3065 psxBios_SysEnqIntRP_(a0, 0x6d98);
3066 mips_return_c(0, 20 + 6*2);
3069 void psxBios_dummy() {
3070 u32 pc = (pc0 & 0x1fffff) - 4;
3071 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
3072 : pc == 0xc0 ? biosC0n : NULL;
3073 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
3074 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
3075 (void)pc; (void)ntab;
3076 mips_return_c(0, 100);
3079 void (*biosA0[256])();
3080 // C0 and B0 overlap (end of C0 is start of B0)
3081 void (*biosC0[256+128])();
3082 void (**biosB0)() = biosC0 + 128;
3084 static void setup_mips_code()
3087 ptr = (u32 *)&psxM[A_SYSCALL];
3088 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
3089 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
3090 ptr[0x08/4] = SWAPu32(0x00000000); // nop
3092 ptr = (u32 *)&psxM[A_EXCEPTION];
3093 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
3094 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
3095 ptr[0x14/4] = SWAPu32(0x00000000); // nop
3096 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
3097 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
3098 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
3099 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
3100 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
3101 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
3102 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
3104 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
3105 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
3106 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
3108 ptr[0xb0/4] = HLEOP(hleop_exception);
3111 static const struct {
3115 { 0xbfc050a4, hleop_exc0_0_1 },
3116 { 0xbfc04fbc, hleop_exc0_0_2 },
3117 { 0xbfc0506c, hleop_exc0_1_1 },
3118 { 0xbfc04dec, hleop_exc0_1_2 },
3119 { 0x1a00, hleop_exc0_2_2 },
3120 { 0x19c8, hleop_exc1_0_1 },
3121 { 0x18bc, hleop_exc1_0_2 },
3122 { 0x1990, hleop_exc1_1_1 },
3123 { 0x1858, hleop_exc1_1_2 },
3124 { 0x1958, hleop_exc1_2_1 },
3125 { 0x17f4, hleop_exc1_2_2 },
3126 { 0x1920, hleop_exc1_3_1 },
3127 { 0x1794, hleop_exc1_3_2 },
3128 { 0x2458, hleop_exc3_0_2 },
3129 { 0x49bc, hleop_exc_padcard1 },
3130 { 0x4a4c, hleop_exc_padcard2 },
3133 static int chain_hle_op(u32 handler)
3137 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
3138 if (chainfns[i].addr == handler)
3139 return chainfns[i].op;
3143 static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
3145 d[0] = SWAPu32(next);
3146 d[1] = SWAPu32(handler1);
3147 d[2] = SWAPu32(handler2);
3149 // install the hle traps
3150 if (handler1) PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
3151 if (handler2) PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
3154 static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack)
3156 u32 *ram32 = (u32 *)psxM;
3157 u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb;
3158 u32 p_excb, p_evcb, p_pcb, p_tcb;
3161 PSXBIOS_LOG("setup: tcb %u, evcb %u\n", tcb_cnt, evcb_cnt);
3163 // the real bios doesn't care, but we just don't
3164 // want to crash in case of garbage parameters
3165 if (tcb_cnt > 1024) tcb_cnt = 1024;
3166 if (evcb_cnt > 1024) evcb_cnt = 1024;
3167 s_evcb = 0x1c * evcb_cnt;
3168 s_tcb = 0xc0 * tcb_cnt;
3170 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
3171 psxBios_SysInitMemory_(0xa000e000, 0x2000);
3172 p_excb = psxBios_SysMalloc_(s_excb);
3173 p_evcb = psxBios_SysMalloc_(s_evcb);
3174 p_pcb = psxBios_SysMalloc_(s_pcb);
3175 p_tcb = psxBios_SysMalloc_(s_tcb);
3177 // "table of tables". Some games modify it
3178 assert(A_TT_ExCB == 0x0100);
3179 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
3180 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
3181 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
3182 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
3183 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
3184 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
3185 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
3186 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
3187 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
3188 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3189 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3190 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3192 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3193 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3194 storeRam32(p_excb + 4*4, 0x0000); // chain2
3195 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3197 storeRam32(p_pcb, p_tcb);
3198 storeRam32(p_tcb, 0x4000); // first TCB
3199 for (i = 1; i < tcb_cnt; i++)
3200 storeRam32(p_tcb + sizeof(TCB) * i, 0x1000);
3203 storeRam32(A_CD_EVENTS + 0x00, OpenEvent(0xf0000003, 0x0010, EvMdMARK, 0));
3204 storeRam32(A_CD_EVENTS + 0x04, OpenEvent(0xf0000003, 0x0020, EvMdMARK, 0));
3205 storeRam32(A_CD_EVENTS + 0x08, OpenEvent(0xf0000003, 0x0040, EvMdMARK, 0));
3206 storeRam32(A_CD_EVENTS + 0x0c, OpenEvent(0xf0000003, 0x0080, EvMdMARK, 0));
3207 storeRam32(A_CD_EVENTS + 0x10, OpenEvent(0xf0000003, 0x8000, EvMdMARK, 0));
3209 storeRam32(A_CONF_EvCB, evcb_cnt);
3210 storeRam32(A_CONF_TCB, tcb_cnt);
3211 storeRam32(A_CONF_SP, stack);
3214 static const u32 gpu_ctl_def[] = {
3215 0x00000000, 0x01000000, 0x03000000, 0x04000000,
3216 0x05000800, 0x06c60260, 0x0703fc10, 0x08000027
3219 static const u32 gpu_data_def[] = {
3220 0xe100360b, 0xe2000000, 0xe3000800, 0xe4077e7f,
3221 0xe5001000, 0xe6000000,
3222 0x02000000, 0x00000000, 0x01ff03ff
3226 static const u16 spu_config[] = {
3227 0x3fff, 0x37ef, 0x5ebc, 0x5ebc, 0x0000, 0x0000, 0x0000, 0x00a0,
3228 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x00ff, 0x0000, 0x0000,
3229 0x0000, 0xe128, 0x0000, 0x0200, 0xf0f0, 0xc085, 0x0004, 0x0000,
3230 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3231 0x033d, 0x0231, 0x7e00, 0x5000, 0xb400, 0xb000, 0x4c00, 0xb000,
3232 0x6000, 0x5400, 0x1ed6, 0x1a31, 0x1d14, 0x183b, 0x1bc2, 0x16b2,
3233 0x1a32, 0x15ef, 0x15ee, 0x1055, 0x1334, 0x0f2d, 0x11f6, 0x0c5d,
3234 0x1056, 0x0ae1, 0x0ae0, 0x07a2, 0x0464, 0x0232, 0x8000, 0x8000
3237 void psxBiosSetupBootState(void)
3239 boolean hle = Config.HLE;
3240 u32 *hw = (u32 *)psxH;
3243 // see also SetBootRegs()
3246 a0 = 1; a2 = a3 = 0; a3 = 0x2a;
3247 t2 = 0x2d; t4 = 0x23; t5 = 0x2b; t6 = 0xa0010000;
3249 k0 = 0xbfc0d968; k1 = 0xf1c;
3250 ra = 0xf0001234; // just to easily detect attempts to return
3251 psxRegs.CP0.n.Cause = 0x20;
3252 psxRegs.CP0.n.EPC = 0xbfc0d964; // EnterCriticalSection syscall
3254 hw[0x1000/4] = SWAP32(0x1f000000);
3255 hw[0x1004/4] = SWAP32(0x1f802000);
3256 hw[0x1008/4] = SWAP32(0x0013243f);
3257 hw[0x100c/4] = SWAP32(0x00003022);
3258 hw[0x1010/4] = SWAP32(0x0013243f);
3259 hw[0x1014/4] = SWAP32(0x200931e1);
3260 hw[0x1018/4] = SWAP32(0x00020943);
3261 hw[0x101c/4] = SWAP32(0x00070777);
3262 hw[0x1020/4] = SWAP32(0x0000132c);
3263 hw[0x1060/4] = SWAP32(0x00000b88);
3264 hw[0x1070/4] = SWAP32(0x00000001);
3265 hw[0x1074/4] = SWAP32(0x0000000c);
3266 hw[0x2040/4] = SWAP32(0x00000900);
3269 hw[0x10a0/4] = SWAP32(0x00ffffff);
3270 hw[0x10a8/4] = SWAP32(0x00000401);
3271 hw[0x10b0/4] = SWAP32(0x0008b000);
3272 hw[0x10b4/4] = SWAP32(0x00010200);
3273 hw[0x10e0/4] = SWAP32(0x000eccf4);
3274 hw[0x10e4/4] = SWAP32(0x00000400);
3275 hw[0x10e8/4] = SWAP32(0x00000002);
3276 hw[0x10f0/4] = SWAP32(0x00009099);
3277 hw[0x10f4/4] = SWAP32(0x8c8c0000);
3286 for (i = 0; i < sizeof(gpu_ctl_def) / sizeof(gpu_ctl_def[0]); i++)
3287 GPU_writeStatus(gpu_ctl_def[i]);
3288 for (i = 0; i < sizeof(gpu_data_def) / sizeof(gpu_data_def[0]); i++)
3289 GPU_writeData(gpu_data_def[i]);
3290 HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
3293 for (i = 0x1f801d80; i < sizeof(spu_config) / sizeof(spu_config[0]); i++)
3294 SPU_writeRegister(0x1f801d80 + i*2, spu_config[i], psxRegs.cycle);
3297 #include "sjisfont.h"
3299 void psxBiosInit() {
3300 u32 *ptr, *ram32, *rom32;
3305 memset(psxM, 0, 0x10000);
3306 for(i = 0; i < 256; i++) {
3311 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3312 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3313 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3314 biosA0[0x3f] = psxBios_printf_psxout;
3316 if (!Config.HLE) return;
3318 for(i = 0; i < 256; i++) {
3319 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3320 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3321 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3324 biosA0[0x00] = psxBios_open;
3325 biosA0[0x01] = psxBios_lseek;
3326 biosA0[0x02] = psxBios_read;
3327 biosA0[0x03] = psxBios_write;
3328 biosA0[0x04] = psxBios_close;
3329 //biosA0[0x05] = psxBios_ioctl;
3330 //biosA0[0x06] = psxBios_exit;
3331 //biosA0[0x07] = psxBios_sys_a0_07;
3332 biosA0[0x08] = psxBios_getc;
3333 biosA0[0x09] = psxBios_putc;
3334 biosA0[0x0a] = psxBios_todigit;
3335 //biosA0[0x0b] = psxBios_atof;
3336 //biosA0[0x0c] = psxBios_strtoul;
3337 //biosA0[0x0d] = psxBios_strtol;
3338 biosA0[0x0e] = psxBios_abs;
3339 biosA0[0x0f] = psxBios_labs;
3340 biosA0[0x10] = psxBios_atoi;
3341 biosA0[0x11] = psxBios_atol;
3342 //biosA0[0x12] = psxBios_atob;
3343 biosA0[0x13] = psxBios_setjmp;
3344 biosA0[0x14] = psxBios_longjmp;
3345 biosA0[0x15] = psxBios_strcat;
3346 biosA0[0x16] = psxBios_strncat;
3347 biosA0[0x17] = psxBios_strcmp;
3348 biosA0[0x18] = psxBios_strncmp;
3349 biosA0[0x19] = psxBios_strcpy;
3350 biosA0[0x1a] = psxBios_strncpy;
3351 biosA0[0x1b] = psxBios_strlen;
3352 biosA0[0x1c] = psxBios_index;
3353 biosA0[0x1d] = psxBios_rindex;
3354 biosA0[0x1e] = psxBios_strchr;
3355 biosA0[0x1f] = psxBios_strrchr;
3356 biosA0[0x20] = psxBios_strpbrk;
3357 biosA0[0x21] = psxBios_strspn;
3358 biosA0[0x22] = psxBios_strcspn;
3359 biosA0[0x23] = psxBios_strtok;
3360 biosA0[0x24] = psxBios_strstr;
3361 biosA0[0x25] = psxBios_toupper;
3362 biosA0[0x26] = psxBios_tolower;
3363 biosA0[0x27] = psxBios_bcopy;
3364 biosA0[0x28] = psxBios_bzero;
3365 biosA0[0x29] = psxBios_bcmp;
3366 biosA0[0x2a] = psxBios_memcpy;
3367 biosA0[0x2b] = psxBios_memset;
3368 biosA0[0x2c] = psxBios_memmove;
3369 biosA0[0x2d] = psxBios_memcmp;
3370 biosA0[0x2e] = psxBios_memchr;
3371 biosA0[0x2f] = psxBios_rand;
3372 biosA0[0x30] = psxBios_srand;
3373 biosA0[0x31] = psxBios_qsort;
3374 //biosA0[0x32] = psxBios_strtod;
3375 biosA0[0x33] = psxBios_malloc;
3376 biosA0[0x34] = psxBios_free;
3377 //biosA0[0x35] = psxBios_lsearch;
3378 //biosA0[0x36] = psxBios_bsearch;
3379 biosA0[0x37] = psxBios_calloc;
3380 biosA0[0x38] = psxBios_realloc;
3381 biosA0[0x39] = psxBios_InitHeap;
3382 //biosA0[0x3a] = psxBios__exit;
3383 biosA0[0x3b] = psxBios_getchar;
3384 biosA0[0x3c] = psxBios_putchar;
3385 //biosA0[0x3d] = psxBios_gets;
3386 biosA0[0x3e] = psxBios_puts;
3387 biosA0[0x3f] = psxBios_printf;
3388 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3389 //biosA0[0x41] = psxBios_LoadTest;
3390 biosA0[0x42] = psxBios_Load;
3391 biosA0[0x43] = psxBios_Exec;
3392 biosA0[0x44] = psxBios_FlushCache;
3393 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3394 biosA0[0x46] = psxBios_GPU_dw;
3395 biosA0[0x47] = psxBios_mem2vram;
3396 biosA0[0x48] = psxBios_SendGPU;
3397 biosA0[0x49] = psxBios_GPU_cw;
3398 biosA0[0x4a] = psxBios_GPU_cwb;
3399 biosA0[0x4b] = psxBios_GPU_SendPackets;
3400 biosA0[0x4c] = psxBios_sys_a0_4c;
3401 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3402 //biosA0[0x4e] = psxBios_GPU_sync;
3403 //biosA0[0x4f] = psxBios_sys_a0_4f;
3404 //biosA0[0x50] = psxBios_sys_a0_50;
3405 biosA0[0x51] = psxBios_LoadExec;
3406 //biosA0[0x52] = psxBios_GetSysSp;
3407 //biosA0[0x53] = psxBios_sys_a0_53;
3408 //biosA0[0x54] = psxBios__96_init_a54;
3409 //biosA0[0x55] = psxBios__bu_init_a55;
3410 biosA0[0x56] = psxBios_CdRemove;
3411 //biosA0[0x57] = psxBios_sys_a0_57;
3412 //biosA0[0x58] = psxBios_sys_a0_58;
3413 //biosA0[0x59] = psxBios_sys_a0_59;
3414 //biosA0[0x5a] = psxBios_sys_a0_5a;
3415 //biosA0[0x5b] = psxBios_dev_tty_init;
3416 //biosA0[0x5c] = psxBios_dev_tty_open;
3417 //biosA0[0x5d] = psxBios_sys_a0_5d;
3418 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3419 //biosA0[0x5f] = psxBios_dev_cd_open;
3420 //biosA0[0x60] = psxBios_dev_cd_read;
3421 //biosA0[0x61] = psxBios_dev_cd_close;
3422 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3423 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3424 //biosA0[0x64] = psxBios_dev_cd_chdir;
3425 //biosA0[0x65] = psxBios_dev_card_open;
3426 //biosA0[0x66] = psxBios_dev_card_read;
3427 //biosA0[0x67] = psxBios_dev_card_write;
3428 //biosA0[0x68] = psxBios_dev_card_close;
3429 //biosA0[0x69] = psxBios_dev_card_firstfile;
3430 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3431 //biosA0[0x6b] = psxBios_dev_card_erase;
3432 //biosA0[0x6c] = psxBios_dev_card_undelete;
3433 //biosA0[0x6d] = psxBios_dev_card_format;
3434 //biosA0[0x6e] = psxBios_dev_card_rename;
3435 //biosA0[0x6f] = psxBios_dev_card_6f;
3436 biosA0[0x70] = psxBios__bu_init;
3437 biosA0[0x71] = psxBios__96_init;
3438 biosA0[0x72] = psxBios_CdRemove;
3439 //biosA0[0x73] = psxBios_sys_a0_73;
3440 //biosA0[0x74] = psxBios_sys_a0_74;
3441 //biosA0[0x75] = psxBios_sys_a0_75;
3442 //biosA0[0x76] = psxBios_sys_a0_76;
3443 //biosA0[0x77] = psxBios_sys_a0_77;
3444 //biosA0[0x78] = psxBios__96_CdSeekL;
3445 //biosA0[0x79] = psxBios_sys_a0_79;
3446 //biosA0[0x7a] = psxBios_sys_a0_7a;
3447 //biosA0[0x7b] = psxBios_sys_a0_7b;
3448 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3449 //biosA0[0x7d] = psxBios_sys_a0_7d;
3450 //biosA0[0x7e] = psxBios__96_CdRead;
3451 //biosA0[0x7f] = psxBios_sys_a0_7f;
3452 //biosA0[0x80] = psxBios_sys_a0_80;
3453 //biosA0[0x81] = psxBios_sys_a0_81;
3454 //biosA0[0x82] = psxBios_sys_a0_82;
3455 //biosA0[0x83] = psxBios_sys_a0_83;
3456 //biosA0[0x84] = psxBios_sys_a0_84;
3457 //biosA0[0x85] = psxBios__96_CdStop;
3458 //biosA0[0x86] = psxBios_sys_a0_86;
3459 //biosA0[0x87] = psxBios_sys_a0_87;
3460 //biosA0[0x88] = psxBios_sys_a0_88;
3461 //biosA0[0x89] = psxBios_sys_a0_89;
3462 //biosA0[0x8a] = psxBios_sys_a0_8a;
3463 //biosA0[0x8b] = psxBios_sys_a0_8b;
3464 //biosA0[0x8c] = psxBios_sys_a0_8c;
3465 //biosA0[0x8d] = psxBios_sys_a0_8d;
3466 //biosA0[0x8e] = psxBios_sys_a0_8e;
3467 //biosA0[0x8f] = psxBios_sys_a0_8f;
3468 biosA0[0x90] = hleExc0_1_2;
3469 biosA0[0x91] = hleExc0_0_2;
3470 biosA0[0x92] = hleExc0_1_1;
3471 biosA0[0x93] = hleExc0_0_1;
3472 //biosA0[0x94] = psxBios_sys_a0_94;
3473 //biosA0[0x95] = psxBios_sys_a0_95;
3474 //biosA0[0x96] = psxBios_AddCDROMDevice;
3475 //biosA0[0x97] = psxBios_AddMemCardDevide;
3476 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3477 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3478 //biosA0[0x9a] = psxBios_sys_a0_9a;
3479 //biosA0[0x9b] = psxBios_sys_a0_9b;
3480 biosA0[0x9c] = psxBios_SetConf;
3481 biosA0[0x9d] = psxBios_GetConf;
3482 //biosA0[0x9e] = psxBios_sys_a0_9e;
3483 biosA0[0x9f] = psxBios_SetMem;
3484 //biosA0[0xa0] = psxBios__boot;
3485 //biosA0[0xa1] = psxBios_SystemError;
3486 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3487 biosA0[0xa3] = psxBios_DequeueCdIntr;
3488 //biosA0[0xa4] = psxBios_sys_a0_a4;
3489 //biosA0[0xa5] = psxBios_ReadSector;
3490 biosA0[0xa6] = psxBios_get_cd_status;
3491 //biosA0[0xa7] = psxBios_bufs_cb_0;
3492 //biosA0[0xa8] = psxBios_bufs_cb_1;
3493 //biosA0[0xa9] = psxBios_bufs_cb_2;
3494 //biosA0[0xaa] = psxBios_bufs_cb_3;
3495 biosA0[0xab] = psxBios__card_info;
3496 biosA0[0xac] = psxBios__card_load;
3497 //biosA0[0axd] = psxBios__card_auto;
3498 //biosA0[0xae] = psxBios_bufs_cd_4;
3499 //biosA0[0xaf] = psxBios_sys_a0_af;
3500 //biosA0[0xb0] = psxBios_sys_a0_b0;
3501 //biosA0[0xb1] = psxBios_sys_a0_b1;
3502 //biosA0[0xb2] = psxBios_do_a_long_jmp
3503 //biosA0[0xb3] = psxBios_sys_a0_b3;
3504 biosA0[0xb4] = psxBios_GetSystemInfo;
3505 //*******************B0 CALLS****************************
3506 biosB0[0x00] = psxBios_SysMalloc;
3507 //biosB0[0x01] = psxBios_sys_b0_01;
3508 biosB0[0x02] = psxBios_SetRCnt;
3509 biosB0[0x03] = psxBios_GetRCnt;
3510 biosB0[0x04] = psxBios_StartRCnt;
3511 biosB0[0x05] = psxBios_StopRCnt;
3512 biosB0[0x06] = psxBios_ResetRCnt;
3513 biosB0[0x07] = psxBios_DeliverEvent;
3514 biosB0[0x08] = psxBios_OpenEvent;
3515 biosB0[0x09] = psxBios_CloseEvent;
3516 biosB0[0x0a] = psxBios_WaitEvent;
3517 biosB0[0x0b] = psxBios_TestEvent;
3518 biosB0[0x0c] = psxBios_EnableEvent;
3519 biosB0[0x0d] = psxBios_DisableEvent;
3520 biosB0[0x0e] = psxBios_OpenTh;
3521 biosB0[0x0f] = psxBios_CloseTh;
3522 biosB0[0x10] = psxBios_ChangeTh;
3523 //biosB0[0x11] = psxBios_psxBios_b0_11;
3524 biosB0[0x12] = psxBios_InitPAD;
3525 biosB0[0x13] = psxBios_StartPAD;
3526 biosB0[0x14] = psxBios_StopPAD;
3527 biosB0[0x15] = psxBios_PAD_init;
3528 biosB0[0x16] = psxBios_PAD_dr;
3529 biosB0[0x17] = psxBios_ReturnFromException;
3530 biosB0[0x18] = psxBios_ResetEntryInt;
3531 biosB0[0x19] = psxBios_HookEntryInt;
3532 //biosB0[0x1a] = psxBios_sys_b0_1a;
3533 //biosB0[0x1b] = psxBios_sys_b0_1b;
3534 //biosB0[0x1c] = psxBios_sys_b0_1c;
3535 //biosB0[0x1d] = psxBios_sys_b0_1d;
3536 //biosB0[0x1e] = psxBios_sys_b0_1e;
3537 //biosB0[0x1f] = psxBios_sys_b0_1f;
3538 biosB0[0x20] = psxBios_UnDeliverEvent;
3539 //biosB0[0x21] = psxBios_sys_b0_21;
3540 //biosB0[0x22] = psxBios_sys_b0_22;
3541 //biosB0[0x23] = psxBios_sys_b0_23;
3542 //biosB0[0x24] = psxBios_sys_b0_24;
3543 //biosB0[0x25] = psxBios_sys_b0_25;
3544 //biosB0[0x26] = psxBios_sys_b0_26;
3545 //biosB0[0x27] = psxBios_sys_b0_27;
3546 //biosB0[0x28] = psxBios_sys_b0_28;
3547 //biosB0[0x29] = psxBios_sys_b0_29;
3548 //biosB0[0x2a] = psxBios_sys_b0_2a;
3549 //biosB0[0x2b] = psxBios_sys_b0_2b;
3550 //biosB0[0x2c] = psxBios_sys_b0_2c;
3551 //biosB0[0x2d] = psxBios_sys_b0_2d;
3552 //biosB0[0x2e] = psxBios_sys_b0_2e;
3553 //biosB0[0x2f] = psxBios_sys_b0_2f;
3554 //biosB0[0x30] = psxBios_sys_b0_30;
3555 //biosB0[0x31] = psxBios_sys_b0_31;
3556 biosB0[0x32] = psxBios_open;
3557 biosB0[0x33] = psxBios_lseek;
3558 biosB0[0x34] = psxBios_read;
3559 biosB0[0x35] = psxBios_write;
3560 biosB0[0x36] = psxBios_close;
3561 //biosB0[0x37] = psxBios_ioctl;
3562 //biosB0[0x38] = psxBios_exit;
3563 //biosB0[0x39] = psxBios_sys_b0_39;
3564 //biosB0[0x3a] = psxBios_getc;
3565 //biosB0[0x3b] = psxBios_putc;
3566 biosB0[0x3c] = psxBios_getchar;
3567 biosB0[0x3d] = psxBios_putchar;
3568 //biosB0[0x3e] = psxBios_gets;
3569 biosB0[0x3f] = psxBios_puts;
3570 biosB0[0x40] = psxBios_cd;
3571 biosB0[0x41] = psxBios_format;
3572 biosB0[0x42] = psxBios_firstfile;
3573 biosB0[0x43] = psxBios_nextfile;
3574 biosB0[0x44] = psxBios_rename;
3575 biosB0[0x45] = psxBios_delete;
3576 //biosB0[0x46] = psxBios_undelete;
3577 //biosB0[0x47] = psxBios_AddDevice;
3578 //biosB0[0x48] = psxBios_RemoteDevice;
3579 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3580 biosB0[0x4a] = psxBios_InitCARD;
3581 biosB0[0x4b] = psxBios_StartCARD;
3582 biosB0[0x4c] = psxBios_StopCARD;
3583 //biosB0[0x4d] = psxBios_sys_b0_4d;
3584 biosB0[0x4e] = psxBios__card_write;
3585 biosB0[0x4f] = psxBios__card_read;
3586 biosB0[0x50] = psxBios__new_card;
3587 biosB0[0x51] = psxBios_Krom2RawAdd;
3588 //biosB0[0x52] = psxBios_sys_b0_52;
3589 //biosB0[0x53] = psxBios_sys_b0_53;
3590 //biosB0[0x54] = psxBios__get_errno;
3591 biosB0[0x55] = psxBios__get_error;
3592 biosB0[0x56] = psxBios_GetC0Table;
3593 biosB0[0x57] = psxBios_GetB0Table;
3594 biosB0[0x58] = psxBios__card_chan;
3595 //biosB0[0x59] = psxBios_sys_b0_59;
3596 //biosB0[0x5a] = psxBios_sys_b0_5a;
3597 biosB0[0x5b] = psxBios_ChangeClearPad;
3598 biosB0[0x5c] = psxBios__card_status;
3599 biosB0[0x5d] = psxBios__card_wait;
3600 //*******************C0 CALLS****************************
3601 biosC0[0x00] = psxBios_InitRCnt;
3602 biosC0[0x01] = psxBios_InitException;
3603 biosC0[0x02] = psxBios_SysEnqIntRP;
3604 biosC0[0x03] = psxBios_SysDeqIntRP;
3605 biosC0[0x04] = psxBios_get_free_EvCB_slot;
3606 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3607 //biosC0[0x06] = psxBios_ExceptionHandler;
3608 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3609 biosC0[0x08] = psxBios_SysInitMemory;
3610 //biosC0[0x09] = psxBios_SysInitKMem;
3611 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3612 //biosC0[0x0b] = psxBios_SystemError;
3613 biosC0[0x0c] = psxBios_InitDefInt;
3614 //biosC0[0x0d] = psxBios_sys_c0_0d;
3615 //biosC0[0x0e] = psxBios_sys_c0_0e;
3616 //biosC0[0x0f] = psxBios_sys_c0_0f;
3617 //biosC0[0x10] = psxBios_sys_c0_10;
3618 //biosC0[0x11] = psxBios_sys_c0_11;
3619 //biosC0[0x12] = psxBios_InstallDevices;
3620 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3621 //biosC0[0x14] = psxBios_sys_c0_14;
3622 //biosC0[0x15] = psxBios__cdevinput;
3623 //biosC0[0x16] = psxBios__cdevscan;
3624 //biosC0[0x17] = psxBios__circgetc;
3625 //biosC0[0x18] = psxBios__circputc;
3626 //biosC0[0x19] = psxBios_ioabort;
3627 //biosC0[0x1a] = psxBios_sys_c0_1a
3628 //biosC0[0x1b] = psxBios_KernelRedirect;
3629 //biosC0[0x1c] = psxBios_PatchAOTable;
3630 //************** THE END ***************************************
3633 memset(FDesc, 0, sizeof(FDesc));
3634 memset(cdir, 0, sizeof(cdir));
3637 // somewhat pretend to be a SCPH1001 BIOS
3638 // some games look for these and take an exception if they're missing
3639 rom32 = (u32 *)psxR;
3640 rom32[0x100/4] = SWAP32(0x19951204);
3641 rom32[0x104/4] = SWAP32(3);
3642 romc = (char *)psxR;
3643 strcpy(romc + 0x108, "PCSX authors");
3644 strcpy(romc + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo
3645 strcpy(romc + 0x7ff32, "System ROM Version 2.2 12/04/95 A");
3646 strcpy(romc + 0x7ff54, "GPL-2.0-or-later");
3649 len = 0x80000 - 0x66000;
3650 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3651 len = 0x80000 - 0x69d68;
3652 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3654 // trap attempts to call bios directly
3655 rom32[0x00000/4] = HLEOP(hleop_dummy);
3656 rom32[0x00180/4] = HLEOP(hleop_dummy);
3657 rom32[0x3fffc/4] = HLEOP(hleop_dummy);
3658 rom32[0x65ffc/4] = HLEOP(hleop_dummy);
3659 rom32[0x7ff2c/4] = HLEOP(hleop_dummy);
3661 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3662 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3663 Here are some examples of games not working with this fix in place :
3664 R-type won't get past the Irem logo if not implemented.
3665 Crash Team Racing will softlock after the Sony logo.
3668 ram32 = (u32 *)psxM;
3669 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3670 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3671 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3672 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3674 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3675 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3677 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3678 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3679 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3680 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3682 ram32[0x00a0/4] = HLEOP(hleop_a0);
3683 ram32[0x00b0/4] = HLEOP(hleop_b0);
3684 ram32[0x00c0/4] = HLEOP(hleop_c0);
3686 setup_tt(4, 16, 0x801fff00);
3687 DeliverEvent(0xf0000003, 0x0010);
3689 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3690 strcpy((char *)&ram32[0xeff0/4], "bu");
3692 // default exception handler chains
3693 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3694 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3695 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3696 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3697 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3698 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3699 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3700 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3704 // fill the api jumptables with fake entries as some games patch them
3705 // (or rather the funcs listed there)
3706 ptr = (u32 *)&psxM[A_A0_TABLE];
3707 for (i = 0; i < 256; i++)
3708 ptr[i] = SWAP32(0x1000);
3710 ptr = (u32 *)&psxM[A_B0_TABLE];
3711 for (i = 0; i < 256; i++)
3712 ptr[i] = SWAP32(0x2000);
3713 // B(5b) is special because games patch (sometimes even jump to)
3714 // code at fixed offsets from it, nocash lists offsets:
3715 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3716 // call: +7a0=4b70, +884=4c54, +894=4c64
3717 ptr[0x5b] = SWAP32(0x43d0);
3718 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra // setPadOutputBuf
3720 ram32[0x4c54/4] = SWAP32(0x240e0001); // mov $t6, 1
3721 ram32[0x4c58/4] = SWAP32(0x03e00008); // jr $ra
3722 ram32[0x4c5c/4] = SWAP32(0xac0e0000 + A_PAD_IRQR_ENA); // sw $t6, ...
3724 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3725 ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ...
3727 ptr = (u32 *)&psxM[A_C0_TABLE];
3728 for (i = 0; i < 256/2; i++)
3729 ptr[i] = SWAP32(0x3000);
3730 ptr[6] = SWAP32(A_EXCEPTION);
3733 ram32[0x1000/4] = HLEOP(hleop_dummy);
3734 ram32[0x2000/4] = HLEOP(hleop_dummy);
3735 ram32[0x3000/4] = HLEOP(hleop_dummy);
3736 ram32[0x8000/4] = HLEOP(hleop_execret);
3738 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3739 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3740 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3741 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3742 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3743 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3744 ram32[A_RND_SEED/4] = SWAPu32(0x24040001); // was 0xac20cc00
3747 void psxBiosShutdown() {
3750 void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) {
3753 if (tcb_cnt != 4 || evcb_cnt != 16) {
3754 setup_tt(tcb_cnt, evcb_cnt, stack);
3755 DeliverEvent(0xf0000003, 0x0010);
3757 storeRam32(A_CONF_SP, stack);
3760 #define psxBios_PADpoll(pad) { \
3761 int i, more_data = 0; \
3762 PAD##pad##_startPoll(pad); \
3763 pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \
3764 pad_buf##pad[0] = more_data ? 0 : 0xff; \
3765 PAD##pad##_poll(0, &more_data); \
3767 while (more_data) { \
3768 pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \
3772 static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3776 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3777 psxBios_ReturnFromException();
3783 // hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3784 // so this is only partially implemented
3785 void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3787 u32 cdrom_dma_ack_enable = 1; // a000b93c
3788 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3791 void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3794 //PSXBIOS_LOG("%s\n", __func__);
3796 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3797 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3798 //if (--cdrom_irq_counter == 0) // 0xa0009180
3799 // DeliverEvent(0xf0000003, 0x10);
3803 mips_return_c(ret, 20);
3806 void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3808 u32 cdrom_irq_ack_enable = 1; // a000b938
3809 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3812 void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3815 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3816 PSXBIOS_LOG("%s TODO\n", __func__);
3819 mips_return_c(ret, 20);
3822 void hleExc0_2_2_syscall() // not in any A/B/C table
3824 u32 tcbPtr = loadRam32(A_TT_PCB);
3825 TCB *tcb = loadRam32ptr(tcbPtr);
3826 u32 code = (SWAP32(tcb->cause) & 0x3c) >> 2;
3828 if (code != R3000E_Syscall) {
3830 DeliverEvent(0xf0000010, 0x1000);
3831 //psxBios_SystemErrorUnresolvedException();
3833 mips_return_c(0, 17);
3837 //printf("%s c=%d a0=%d\n", __func__, code, SWAP32(tcb->reg[4]));
3838 tcb->epc += SWAP32(4);
3839 switch (SWAP32(tcb->reg[4])) { // a0
3843 case 1: { // EnterCritical - disable irqs
3844 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3845 tcb->reg[2] = SWAP32(was_enabled);
3846 tcb->sr &= SWAP32(~0x404);
3849 case 2: // ExitCritical - enable irqs
3850 tcb->sr |= SWAP32(0x404);
3853 case 3: { // ChangeThreadSubFunction
3854 u32 tcbPtr = loadRam32(A_TT_PCB);
3855 storeRam32(tcbPtr, SWAP32(tcb->reg[5])); // a1
3859 DeliverEvent(0xf0000010, 0x4000);
3863 psxBios_ReturnFromException();
3866 void hleExc1_0_1(void)
3868 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3869 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3872 static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3875 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3876 DeliverEvent(0xf2000000 + ev_index, 0x0002);
3879 mips_return_c(ret, 22);
3882 void hleExc1_0_2(void)
3884 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3887 void hleExc1_1_1(void)
3889 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3890 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3893 void hleExc1_1_2(void)
3895 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3898 void hleExc1_2_1(void)
3900 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3901 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3904 void hleExc1_2_2(void)
3906 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3909 void hleExc1_3_1(void)
3911 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3912 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3915 void hleExc1_3_2(void)
3917 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3920 void hleExc3_0_2_defint(void)
3922 static const struct {
3933 { 6, 6 }, // rcnt2 (bug)
3938 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3939 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3940 DeliverEvent(0xf0000000 + tab[i].ev, 0x1000);
3945 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3948 void hleExcPadCard1(void)
3950 if (loadRam32(A_PAD_IRQR_ENA)) {
3951 u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0);
3952 u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4);
3957 if (loadRam32(A_PAD_DR_DST))
3960 if (loadRam32(A_PAD_ACK_VBL))
3961 psxHwWrite16(0x1f801070, ~1);
3962 if (loadRam32(A_CARD_IRQR_ENA)) {
3966 mips_return_c(0, 18);
3969 void hleExcPadCard2(void)
3971 u32 ret = psxHu32(0x1074) & psxHu32(0x1070) & 1;
3972 mips_return_c(ret, 15);
3975 void psxBiosException() {
3976 u32 tcbPtr = loadRam32(A_TT_PCB);
3977 u32 *chains = loadRam32ptr(A_TT_ExCB);
3978 TCB *tcb = loadRam32ptr(tcbPtr);
3984 // $at, $v0, $v1, $ra already saved by the mips code at A_EXCEPTION
3985 for (i = 4; i < 31; i++) {
3988 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3990 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3991 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3992 //tcb->epc = SWAP32(psxRegs.CP0.n.EPC); // done by asm
3993 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3994 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3995 sp = fp = loadRam32(A_EXC_SP);
3999 // do the chains (always 4)
4000 for (c = lim = 0; c < 4; c++) {
4001 if (chains[c * 2] == 0)
4003 ptr = SWAP32(chains[c * 2]);
4004 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
4005 chain = castRam32ptr(ptr);
4010 softCallInException(SWAP32(chain[2]));
4011 if (returned_from_exception())
4014 if (v0 == 0 || chain[1] == 0)
4016 softCallInException(SWAP32(chain[1]));
4017 if (returned_from_exception())
4023 // return from exception (custom or default)
4025 ptr = loadRam32(A_EEXIT_PTR);
4026 if (ptr != A_EEXIT_DEF) {
4027 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
4028 longjmp_load(jmp_buf);
4033 psxBios_ReturnFromException();
4036 #define bfreeze(ptr, size) { \
4037 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
4038 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
4042 #define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
4043 #define bfreezel(ptr) bfreeze(ptr, sizeof(*(ptr)))
4045 void psxBiosFreeze(int Mode) {