log unhandled io more clearly
[pcsx_rearmed.git] / libpcsxcore / psxbios.c
... / ...
CommitLineData
1/***************************************************************************
2 * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, *
3 * dmitrysmagin, senquack *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
20
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.
25 * */
26
27/*
28 * Internal simulated HLE BIOS.
29 */
30
31// TODO: implement all system calls, count the exact CPU cycles of system calls.
32
33#include "psxbios.h"
34#include "psxhw.h"
35#include "gpu.h"
36#include "sio.h"
37#include "psxhle.h"
38#include <zlib.h>
39
40#if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)
41#pragma GCC diagnostic ignored "-Wpointer-sign"
42#endif
43
44#undef SysPrintf
45#define SysPrintf if (Config.PsxOut) printf
46
47char *biosA0n[256] = {
48// 0x00
49 "open", "lseek", "read", "write",
50 "close", "ioctl", "exit", "sys_a0_07",
51 "getc", "putc", "todigit", "atof",
52 "strtoul", "strtol", "abs", "labs",
53// 0x10
54 "atoi", "atol", "atob", "setjmp",
55 "longjmp", "strcat", "strncat", "strcmp",
56 "strncmp", "strcpy", "strncpy", "strlen",
57 "index", "rindex", "strchr", "strrchr",
58// 0x20
59 "strpbrk", "strspn", "strcspn", "strtok",
60 "strstr", "toupper", "tolower", "bcopy",
61 "bzero", "bcmp", "memcpy", "memset",
62 "memmove", "memcmp", "memchr", "rand",
63// 0x30
64 "srand", "qsort", "strtod", "malloc",
65 "free", "lsearch", "bsearch", "calloc",
66 "realloc", "InitHeap", "_exit", "getchar",
67 "putchar", "gets", "puts", "printf",
68// 0x40
69 "sys_a0_40", "LoadTest", "Load", "Exec",
70 "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram",
71 "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets",
72 "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f",
73// 0x50
74 "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53",
75 "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57",
76 "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init",
77 "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open",
78// 0x60
79 "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile",
80 "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write",
81 "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase",
82 "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f",
83// 0x70
84 "_bu_init", "_96_init", "CdRemove", "sys_a0_73",
85 "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77",
86 "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b",
87 "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f",
88// 0x80
89 "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83",
90 "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87",
91 "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b",
92 "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f",
93// 0x90
94 "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93",
95 "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide",
96 "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
97 "SetConf", "GetConf", "sys_a0_9e", "SetMem",
98// 0xa0
99 "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr",
100 "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0",
101 "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info",
102 "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af",
103// 0xb0
104 "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3",
105 "?? sub_function",
106};
107
108char *biosB0n[256] = {
109// 0x00
110 "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03",
111 "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent",
112 "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent",
113 "EnableEvent", "DisableEvent", "OpenTh", "CloseTh",
114// 0x10
115 "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD",
116 "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption",
117 "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b",
118 "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f",
119// 0x20
120 "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23",
121 "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27",
122 "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b",
123 "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f",
124// 0x30
125 "sys_b0_30", "sys_b0_31", "open", "lseek",
126 "read", "write", "close", "ioctl",
127 "exit", "sys_b0_39", "getc", "putc",
128 "getchar", "putchar", "gets", "puts",
129// 0x40
130 "cd", "format", "firstfile", "nextfile",
131 "rename", "delete", "undelete", "AddDevice",
132 "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD",
133 "StopCARD", "sys_b0_4d", "_card_write", "_card_read",
134// 0x50
135 "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53",
136 "_get_errno", "_get_error", "GetC0Table", "GetB0Table",
137 "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD",
138 "_card_status", "_card_wait",
139};
140
141char *biosC0n[256] = {
142// 0x00
143 "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP",
144 "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler",
145 "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError",
146 "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f",
147// 0x10
148 "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut",
149 "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc",
150 "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect",
151 "PatchAOTable",
152};
153
154//#define r0 (psxRegs.GPR.n.r0)
155#define at (psxRegs.GPR.n.at)
156#define v0 (psxRegs.GPR.n.v0)
157#define v1 (psxRegs.GPR.n.v1)
158#define a0 (psxRegs.GPR.n.a0)
159#define a1 (psxRegs.GPR.n.a1)
160#define a2 (psxRegs.GPR.n.a2)
161#define a3 (psxRegs.GPR.n.a3)
162#define t0 (psxRegs.GPR.n.t0)
163#define t1 (psxRegs.GPR.n.t1)
164#define t2 (psxRegs.GPR.n.t2)
165#define t3 (psxRegs.GPR.n.t3)
166#define t4 (psxRegs.GPR.n.t4)
167#define t5 (psxRegs.GPR.n.t5)
168#define t6 (psxRegs.GPR.n.t6)
169#define t7 (psxRegs.GPR.n.t7)
170#define t8 (psxRegs.GPR.n.t8)
171#define t9 (psxRegs.GPR.n.t9)
172#define s0 (psxRegs.GPR.n.s0)
173#define s1 (psxRegs.GPR.n.s1)
174#define s2 (psxRegs.GPR.n.s2)
175#define s3 (psxRegs.GPR.n.s3)
176#define s4 (psxRegs.GPR.n.s4)
177#define s5 (psxRegs.GPR.n.s5)
178#define s6 (psxRegs.GPR.n.s6)
179#define s7 (psxRegs.GPR.n.s7)
180#define k0 (psxRegs.GPR.n.k0)
181#define k1 (psxRegs.GPR.n.k1)
182#define gp (psxRegs.GPR.n.gp)
183#define sp (psxRegs.GPR.n.sp)
184#define fp (psxRegs.GPR.n.s8)
185#define ra (psxRegs.GPR.n.ra)
186#define pc0 (psxRegs.pc)
187
188#define Ra0 ((char *)PSXM(a0))
189#define Ra1 ((char *)PSXM(a1))
190#define Ra2 ((char *)PSXM(a2))
191#define Ra3 ((char *)PSXM(a3))
192#define Rv0 ((char *)PSXM(v0))
193#define Rsp ((char *)PSXM(sp))
194
195typedef struct {
196 u32 desc;
197 s32 status;
198 s32 mode;
199 u32 fhandler;
200} EvCB[32];
201
202#define EvStUNUSED 0x0000
203#define EvStWAIT 0x1000
204#define EvStACTIVE 0x2000
205#define EvStALREADY 0x4000
206
207#define EvMdINTR 0x1000
208#define EvMdNOINTR 0x2000
209
210/*
211typedef struct {
212 s32 next;
213 s32 func1;
214 s32 func2;
215 s32 pad;
216} SysRPst;
217*/
218
219typedef struct {
220 u32 status;
221 u32 mode;
222 u32 reg[32];
223 u32 epc;
224 u32 hi, lo;
225 u32 sr, cause;
226 u32 unused[9];
227} TCB;
228
229typedef struct {
230 u32 _pc0;
231 u32 gp0;
232 u32 t_addr;
233 u32 t_size;
234 u32 d_addr;
235 u32 d_size;
236 u32 b_addr;
237 u32 b_size;
238 u32 S_addr;
239 u32 s_size;
240 u32 _sp, _fp, _gp, ret, base;
241} EXEC;
242
243struct DIRENTRY {
244 char name[20];
245 s32 attr;
246 s32 size;
247 u32 next;
248 s32 head;
249 char system[4];
250};
251
252typedef struct {
253 char name[32];
254 u32 mode;
255 u32 offset;
256 u32 size;
257 u32 mcfile;
258} FileDesc;
259
260static int *pad_buf = NULL;
261static char *pad_buf1 = NULL, *pad_buf2 = NULL;
262static int pad_buf1len, pad_buf2len;
263static int pad_stopped = 0;
264
265static u32 regs[35];
266static EvCB *EventCB;
267static EvCB *HwEV; // 0xf0
268static EvCB *EvEV; // 0xf1
269static EvCB *RcEV; // 0xf2
270static EvCB *UeEV; // 0xf3
271static EvCB *SwEV; // 0xf4
272static EvCB *ThEV; // 0xff
273static u32 heap_size = 0;
274static u32 *heap_addr = NULL;
275static u32 *heap_end = NULL;
276static int CardState = -1;
277static int CurThread = 0;
278static FileDesc FDesc[32];
279static u32 card_active_chan = 0;
280
281// fixed RAM offsets, SCPH1001 compatible
282#define A_TT_ExCB 0x0100
283#define A_TT_PCB 0x0108
284#define A_TT_TCB 0x0110
285#define A_A0_TABLE 0x0200
286#define A_B0_TABLE 0x0874
287#define A_C0_TABLE 0x0674
288#define A_SYSCALL 0x0650
289#define A_EXCEPTION 0x0c80
290#define A_EXC_SP 0x6cf0
291#define A_EEXIT_DEF 0x6cf4
292#define A_KMALLOC_PTR 0x7460
293#define A_KMALLOC_SIZE 0x7464
294#define A_KMALLOC_END 0x7468
295#define A_EEXIT_PTR 0x75d0
296#define A_EXC_STACK 0x85d8 // exception stack top
297#define A_RCNT_VBL_ACK 0x8600
298#define A_EXC_GP 0xf450
299
300#define HLEOP(n) SWAPu32((0x3b << 26) | (n));
301
302static u32 loadRam32(u32 addr)
303{
304 assert(!(addr & 0x5f800000));
305 return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2)));
306}
307
308static void *castRam32ptr(u32 addr)
309{
310 assert(!(addr & 0x5f800003));
311 return psxM + (addr & 0x1ffffc);
312}
313
314static void *loadRam32ptr(u32 addr)
315{
316 return castRam32ptr(loadRam32(addr));
317}
318
319static void storeRam32(u32 addr, u32 d)
320{
321 assert(!(addr & 0x5f800000));
322 *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d);
323}
324
325static void mips_return(u32 val)
326{
327 v0 = val;
328 pc0 = ra;
329}
330
331static void use_cycles(u32 cycle)
332{
333 psxRegs.cycle += cycle * 2;
334}
335
336static void mips_return_c(u32 val, u32 cycle)
337{
338 use_cycles(cycle);
339 mips_return(val);
340}
341
342static void mips_return_void_c(u32 cycle)
343{
344 use_cycles(cycle);
345 pc0 = ra;
346}
347
348static int returned_from_exception(void)
349{
350 // 0x80000080 means it took another exception just after return
351 return pc0 == k0 || pc0 == 0x80000080;
352}
353
354static inline void softCall(u32 pc) {
355 u32 sra = ra;
356 u32 ssr = psxRegs.CP0.n.SR;
357 pc0 = pc;
358 ra = 0x80001000;
359 psxRegs.CP0.n.SR &= ~0x404; // disable interrupts
360
361 while (pc0 != 0x80001000)
362 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
363
364 ra = sra;
365 psxRegs.CP0.n.SR = ssr;
366}
367
368static inline void softCallInException(u32 pc) {
369 u32 sra = ra;
370 pc0 = pc;
371 ra = 0x80001000;
372
373 while (!returned_from_exception() && pc0 != 0x80001000)
374 psxCpu->ExecuteBlock(EXEC_CALLER_HLE);
375
376 if (pc0 == 0x80001000)
377 ra = sra;
378}
379
380static inline void DeliverEvent(u32 ev, u32 spec) {
381 if (EventCB[ev][spec].status != EvStACTIVE) return;
382
383// EventCB[ev][spec].status = EvStALREADY;
384 if (EventCB[ev][spec].mode == EvMdINTR) {
385 softCall(EventCB[ev][spec].fhandler);
386 } else EventCB[ev][spec].status = EvStALREADY;
387}
388
389/* *
390// *
391// *
392// System calls A0 */
393
394
395#define buread(Ra1, mcd, length) { \
396 SysPrintf("read %d: %x,%x (%s)\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2, Mcd##mcd##Data + 128 * FDesc[1 + mcd].mcfile + 0xa); \
397 ptr = Mcd##mcd##Data + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
398 memcpy(Ra1, ptr, length); \
399 if (FDesc[1 + mcd].mode & 0x8000) { \
400 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
401 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
402 v0 = 0; } \
403 else v0 = length; \
404 FDesc[1 + mcd].offset += v0; \
405}
406
407#define buwrite(Ra1, mcd, length) { \
408 u32 offset = + 8192 * FDesc[1 + mcd].mcfile + FDesc[1 + mcd].offset; \
409 SysPrintf("write %d: %x,%x\n", FDesc[1 + mcd].mcfile, FDesc[1 + mcd].offset, a2); \
410 ptr = Mcd##mcd##Data + offset; \
411 memcpy(ptr, Ra1, length); \
412 FDesc[1 + mcd].offset += length; \
413 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, offset, length); \
414 if (FDesc[1 + mcd].mode & 0x8000) { \
415 DeliverEvent(0x11, 0x2); /* 0xf0000011, 0x0004 */ \
416 DeliverEvent(0x81, 0x2); /* 0xf4000001, 0x0004 */ \
417 v0 = 0; } \
418 else v0 = length; \
419}
420
421#ifndef PSXBIOS_LOG
422//#define PSXBIOS_LOG printf
423#define PSXBIOS_LOG(...)
424#endif
425
426/* Internally redirects to "FileRead(fd,tempbuf,1)".*/
427/* For some strange reason, the returned character is sign-expanded; */
428/* So if a return value of FFFFFFFFh could mean either character FFh, or error. */
429/* TODO FIX ME : Properly implement this behaviour */
430void psxBios_getc(void) // 0x03, 0x35
431{
432 char *ptr;
433 void *pa1 = Ra1;
434#ifdef PSXBIOS_LOG
435 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x03]);
436#endif
437 v0 = -1;
438
439 if (pa1 != INVALID_PTR) {
440 switch (a0) {
441 case 2: buread(pa1, 1, 1); break;
442 case 3: buread(pa1, 2, 1); break;
443 }
444 }
445
446 pc0 = ra;
447}
448
449/* Copy of psxBios_write, except size is 1. */
450void psxBios_putc(void) // 0x09, 0x3B
451{
452 char *ptr;
453 void *pa1 = Ra1;
454#ifdef PSXBIOS_LOG
455 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
456#endif
457 v0 = -1;
458 if (pa1 == INVALID_PTR) {
459 pc0 = ra;
460 return;
461 }
462
463 if (a0 == 1) { // stdout
464 char *ptr = (char *)pa1;
465
466 v0 = a2;
467 while (a2 > 0) {
468 printf("%c", *ptr++); a2--;
469 }
470 pc0 = ra; return;
471 }
472
473 switch (a0) {
474 case 2: buwrite(pa1, 1, 1); break;
475 case 3: buwrite(pa1, 2, 1); break;
476 }
477
478 pc0 = ra;
479}
480
481void psxBios_todigit(void) // 0x0a
482{
483 int c = a0;
484#ifdef PSXBIOS_LOG
485 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x0a]);
486#endif
487 c &= 0xFF;
488 if (c >= 0x30 && c < 0x3A) {
489 c -= 0x30;
490 }
491 else if (c > 0x60 && c < 0x7B) {
492 c -= 0x20;
493 }
494 else if (c > 0x40 && c < 0x5B) {
495 c = c - 0x41 + 10;
496 }
497 else if (c >= 0x80) {
498 c = -1;
499 }
500 else
501 {
502 c = 0x0098967F;
503 }
504 v0 = c;
505 pc0 = ra;
506}
507
508void psxBios_abs() { // 0x0e
509 if ((s32)a0 < 0) v0 = -(s32)a0;
510 else v0 = a0;
511 pc0 = ra;
512}
513
514void psxBios_labs() { // 0x0f
515 psxBios_abs();
516}
517
518void psxBios_atoi() { // 0x10
519 s32 n = 0, f = 0;
520 char *p = (char *)Ra0;
521
522 for (;;p++) {
523 switch (*p) {
524 case ' ': case '\t': continue;
525 case '-': f++;
526 case '+': p++;
527 }
528 break;
529 }
530
531 while (*p >= '0' && *p <= '9') {
532 n = n * 10 + *p++ - '0';
533 }
534
535 v0 = (f ? -n : n);
536 pc0 = ra;
537}
538
539void psxBios_atol() { // 0x11
540 psxBios_atoi();
541}
542
543struct jmp_buf_ {
544 u32 ra_, sp_, fp_;
545 u32 s[8];
546 u32 gp_;
547};
548
549static void psxBios_setjmp() { // 0x13
550 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
551 int i;
552
553 PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x13], a0);
554
555 jmp_buf->ra_ = SWAP32(ra);
556 jmp_buf->sp_ = SWAP32(sp);
557 jmp_buf->fp_ = SWAP32(fp);
558 for (i = 0; i < 8; i++) // s0-s7
559 jmp_buf->s[i] = SWAP32(psxRegs.GPR.r[16 + i]);
560 jmp_buf->gp_ = SWAP32(gp);
561
562 mips_return_c(0, 15);
563}
564
565static void longjmp_load(const struct jmp_buf_ *jmp_buf)
566{
567 int i;
568
569 ra = SWAP32(jmp_buf->ra_);
570 sp = SWAP32(jmp_buf->sp_);
571 fp = SWAP32(jmp_buf->fp_);
572 for (i = 0; i < 8; i++) // s0-s7
573 psxRegs.GPR.r[16 + i] = SWAP32(jmp_buf->s[i]);
574 gp = SWAP32(jmp_buf->gp_);;
575}
576
577void psxBios_longjmp() { // 0x14
578 struct jmp_buf_ *jmp_buf = castRam32ptr(a0);
579
580 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x14]);
581 longjmp_load(jmp_buf);
582 mips_return_c(a1, 15);
583}
584
585void psxBios_strcat() { // 0x15
586 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
587
588#ifdef PSXBIOS_LOG
589 PSXBIOS_LOG("psxBios_%s: %s, %s\n", biosA0n[0x15], Ra0, Ra1);
590#endif
591 if (a0 == 0 || a1 == 0)
592 {
593 v0 = 0;
594 pc0 = ra;
595 return;
596 }
597 while (*p1++);
598 --p1;
599 while ((*p1++ = *p2++) != '\0');
600
601 v0 = a0; pc0 = ra;
602}
603
604void psxBios_strncat() { // 0x16
605 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
606 s32 n = a2;
607
608#ifdef PSXBIOS_LOG
609 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x16], Ra0, a0, Ra1, a1, a2);
610#endif
611 if (a0 == 0 || a1 == 0)
612 {
613 v0 = 0;
614 pc0 = ra;
615 return;
616 }
617 while (*p1++);
618 --p1;
619 while ((*p1++ = *p2++) != '\0') {
620 if (--n < 0) {
621 *--p1 = '\0';
622 break;
623 }
624 }
625
626 v0 = a0; pc0 = ra;
627}
628
629void psxBios_strcmp() { // 0x17
630 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
631 s32 n=0;
632 if (a0 == 0 && a1 == 0)
633 {
634 v0 = 0;
635 pc0 = ra;
636 return;
637 }
638 else if (a0 == 0 && a1 != 0)
639 {
640 v0 = -1;
641 pc0 = ra;
642 return;
643 }
644 else if (a0 != 0 && a1 == 0)
645 {
646 v0 = 1;
647 pc0 = ra;
648 return;
649 }
650#ifdef PSXBIOS_LOG
651 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x)\n", biosA0n[0x17], Ra0, a0, Ra1, a1);
652#endif
653
654 while (*p1 == *p2++) {
655 n++;
656 if (*p1++ == '\0') {
657 v1=n-1;
658 a0+=n;
659 a1+=n;
660 v0 = 0;
661 pc0 = ra;
662 return;
663 }
664 }
665
666 v0 = (*p1 - *--p2);
667 v1 = n;
668 a0+=n;
669 a1+=n;
670 pc0 = ra;
671}
672
673void psxBios_strncmp() { // 0x18
674 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
675 s32 n = a2;
676 if (a0 == 0 && a1 == 0)
677 {
678 v0 = 0;
679 pc0 = ra;
680 return;
681 }
682 else if (a0 == 0 && a1 != 0)
683 {
684 v0 = -1;
685 pc0 = ra;
686 return;
687 }
688 else if (a0 != 0 && a1 == 0)
689 {
690 v0 = 1;
691 pc0 = ra;
692 return;
693 }
694#ifdef PSXBIOS_LOG
695 PSXBIOS_LOG("psxBios_%s: %s (%x), %s (%x), %d\n", biosA0n[0x18], Ra0, a0, Ra1, a1, a2);
696#endif
697
698 while (--n >= 0 && *p1 == *p2++) {
699 if (*p1++ == '\0') {
700 v0 = 0;
701 pc0 = ra;
702 v1 = a2 - ((a2-n) - 1);
703 a0 += (a2-n) - 1;
704 a1 += (a2-n) - 1;
705 a2 = n;
706 return;
707 }
708 }
709
710 v0 = (n < 0 ? 0 : *p1 - *--p2);
711 pc0 = ra;
712 v1 = a2 - ((a2-n) - 1);
713 a0 += (a2-n) - 1;
714 a1 += (a2-n) - 1;
715 a2 = n;
716}
717
718void psxBios_strcpy() { // 0x19
719 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
720 if (a0 == 0 || a1 == 0)
721 {
722 v0 = 0;
723 pc0 = ra;
724 return;
725 }
726 while ((*p1++ = *p2++) != '\0');
727
728 v0 = a0; pc0 = ra;
729}
730
731void psxBios_strncpy() { // 0x1a
732 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
733 s32 n = a2, i;
734 if (a0 == 0 || a1 == 0)
735 {
736 v0 = 0;
737 pc0 = ra;
738 return;
739 }
740 for (i = 0; i < n; i++) {
741 if ((*p1++ = *p2++) == '\0') {
742 while (++i < n) {
743 *p1++ = '\0';
744 }
745 v0 = a0; pc0 = ra;
746 return;
747 }
748 }
749
750 v0 = a0; pc0 = ra;
751}
752
753void psxBios_strlen() { // 0x1b
754 char *p = (char *)Ra0;
755 v0 = 0;
756 if (a0 == 0)
757 {
758 pc0 = ra;
759 return;
760 }
761 while (*p++) v0++;
762 pc0 = ra;
763}
764
765void psxBios_index() { // 0x1c
766 char *p = (char *)Ra0;
767 if (a0 == 0)
768 {
769 v0 = 0;
770 pc0 = ra;
771 return;
772 }
773
774 do {
775 if (*p == a1) {
776 v0 = a0 + (p - (char *)Ra0);
777 pc0 = ra;
778 return;
779 }
780 } while (*p++ != '\0');
781
782 v0 = 0; pc0 = ra;
783}
784
785void psxBios_rindex() { // 0x1d
786 char *p = (char *)Ra0;
787
788 v0 = 0;
789 if (a0 == 0)
790 {
791 pc0 = ra;
792 return;
793 }
794 do {
795 if (*p == a1)
796 v0 = a0 + (p - (char *)Ra0);
797 } while (*p++ != '\0');
798
799 pc0 = ra;
800}
801
802void psxBios_strchr() { // 0x1e
803 psxBios_index();
804}
805
806void psxBios_strrchr() { // 0x1f
807 psxBios_rindex();
808}
809
810void psxBios_strpbrk() { // 0x20
811 char *p1 = (char *)Ra0, *p2 = (char *)Ra1, *scanp, c, sc;
812
813 while ((c = *p1++) != '\0') {
814 for (scanp = p2; (sc = *scanp++) != '\0';) {
815 if (sc == c) {
816 v0 = a0 + (p1 - 1 - (char *)Ra0);
817 pc0 = ra;
818 return;
819 }
820 }
821 }
822
823 // BUG: return a0 instead of NULL if not found
824 v0 = a0; pc0 = ra;
825}
826
827void psxBios_strspn() { // 0x21
828 char *p1, *p2;
829
830 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
831 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
832 if (*p2 == '\0') break;
833 }
834
835 v0 = p1 - (char *)Ra0; pc0 = ra;
836}
837
838void psxBios_strcspn() { // 0x22
839 char *p1, *p2;
840
841 for (p1 = (char *)Ra0; *p1 != '\0'; p1++) {
842 for (p2 = (char *)Ra1; *p2 != '\0' && *p2 != *p1; p2++);
843 if (*p2 != '\0') break;
844 }
845
846 v0 = p1 - (char *)Ra0; pc0 = ra;
847}
848
849void psxBios_strtok() { // 0x23
850 char *pcA0 = (char *)Ra0;
851 char *pcRet = strtok(pcA0, (char *)Ra1);
852 if (pcRet)
853 v0 = a0 + pcRet - pcA0;
854 else
855 v0 = 0;
856 pc0 = ra;
857}
858
859void psxBios_strstr() { // 0x24
860 char *p = (char *)Ra0, *p1, *p2;
861
862 while (*p != '\0') {
863 p1 = p;
864 p2 = (char *)Ra1;
865
866 while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2) {
867 p1++; p2++;
868 }
869
870 if (*p2 == '\0') {
871 v0 = a0 + (p - (char *)Ra0);
872 pc0 = ra;
873 return;
874 }
875
876 p++;
877 }
878
879 v0 = 0; pc0 = ra;
880}
881
882void psxBios_toupper() { // 0x25
883 v0 = (s8)(a0 & 0xff);
884 if (v0 >= 'a' && v0 <= 'z') v0 -= 'a' - 'A';
885 pc0 = ra;
886}
887
888void psxBios_tolower() { // 0x26
889 v0 = (s8)(a0 & 0xff);
890 if (v0 >= 'A' && v0 <= 'Z') v0 += 'a' - 'A';
891 pc0 = ra;
892}
893
894void psxBios_bcopy() { // 0x27
895 char *p1 = (char *)Ra1, *p2 = (char *)Ra0;
896 v0 = a0;
897 if (a0 == 0 || a2 > 0x7FFFFFFF)
898 {
899 pc0 = ra;
900 return;
901 }
902 while ((s32)a2-- > 0) *p1++ = *p2++;
903 a2 = 0;
904 pc0 = ra;
905}
906
907void psxBios_bzero() { // 0x28
908 char *p = (char *)Ra0;
909 v0 = a0;
910 /* Same as memset here (See memset below) */
911 if (a1 > 0x7FFFFFFF || a1 == 0)
912 {
913 v0 = 0;
914 pc0 = ra;
915 return;
916 }
917 else if (a0 == 0)
918 {
919 pc0 = ra;
920 return;
921 }
922 while ((s32)a1-- > 0) *p++ = '\0';
923 a1 = 0;
924 pc0 = ra;
925}
926
927void psxBios_bcmp() { // 0x29
928 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
929
930 if (a0 == 0 || a1 == 0) { v0 = 0; pc0 = ra; return; }
931
932 while ((s32)a2-- > 0) {
933 if (*p1++ != *p2++) {
934 v0 = *p1 - *p2; // BUG: compare the NEXT byte
935 pc0 = ra;
936 return;
937 }
938 }
939
940 v0 = 0; pc0 = ra;
941}
942
943void psxBios_memcpy() { // 0x2a
944 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
945 v0 = a0;
946 if (a0 == 0 || a2 > 0x7FFFFFFF)
947 {
948 pc0 = ra;
949 return;
950 }
951 while ((s32)a2-- > 0) {
952 *p1++ = *p2++;
953 }
954 a2 = 0;
955 pc0 = ra;
956}
957
958void psxBios_memset() { // 0x2b
959 char *p = (char *)Ra0;
960 v0 = a0;
961 if (a2 > 0x7FFFFFFF || a2 == 0)
962 {
963 v0 = 0;
964 pc0 = ra;
965 return;
966 }
967 if (a0 == 0)
968 {
969 pc0 = ra;
970 return;
971 }
972 while ((s32)a2-- > 0) *p++ = (char)a1;
973 a2 = 0;
974 v0 = a0; pc0 = ra;
975}
976
977void psxBios_memmove() { // 0x2c
978 char *p1 = (char *)Ra0, *p2 = (char *)Ra1;
979 v0 = a0;
980 if (a0 == 0 || a2 > 0x7FFFFFFF)
981 {
982 pc0 = ra;
983 return;
984 }
985 if (p2 <= p1 && p2 + a2 > p1) {
986 a2++; // BUG: copy one more byte here
987 p1 += a2;
988 p2 += a2;
989 while ((s32)a2-- > 0) *--p1 = *--p2;
990 } else {
991 while ((s32)a2-- > 0) *p1++ = *p2++;
992 }
993 pc0 = ra;
994}
995
996void psxBios_memcmp() { // 0x2d
997 psxBios_bcmp();
998}
999
1000void psxBios_memchr() { // 0x2e
1001 char *p = (char *)Ra0;
1002
1003 if (a0 == 0 || a2 > 0x7FFFFFFF)
1004 {
1005 pc0 = ra;
1006 return;
1007 }
1008
1009 while ((s32)a2-- > 0) {
1010 if (*p++ != (s8)a1) continue;
1011 v0 = a0 + (p - (char *)Ra0 - 1);
1012 pc0 = ra;
1013 return;
1014 }
1015
1016 v0 = 0; pc0 = ra;
1017}
1018
1019void psxBios_rand() { // 0x2f
1020 u32 s = psxMu32(0x9010) * 1103515245 + 12345;
1021 v0 = (s >> 16) & 0x7fff;
1022 psxMu32ref(0x9010) = SWAPu32(s);
1023 pc0 = ra;
1024}
1025
1026void psxBios_srand() { // 0x30
1027 psxMu32ref(0x9010) = SWAPu32(a0);
1028 pc0 = ra;
1029}
1030
1031static u32 qscmpfunc, qswidth;
1032
1033static inline int qscmp(char *a, char *b) {
1034 u32 sa0 = a0;
1035
1036 a0 = sa0 + (a - (char *)PSXM(sa0));
1037 a1 = sa0 + (b - (char *)PSXM(sa0));
1038
1039 softCall(qscmpfunc);
1040
1041 a0 = sa0;
1042 return (s32)v0;
1043}
1044
1045static inline void qexchange(char *i, char *j) {
1046 char t;
1047 int n = qswidth;
1048
1049 do {
1050 t = *i;
1051 *i++ = *j;
1052 *j++ = t;
1053 } while (--n);
1054}
1055
1056static inline void q3exchange(char *i, char *j, char *k) {
1057 char t;
1058 int n = qswidth;
1059
1060 do {
1061 t = *i;
1062 *i++ = *k;
1063 *k++ = *j;
1064 *j++ = t;
1065 } while (--n);
1066}
1067
1068static void qsort_main(char *a, char *l) {
1069 char *i, *j, *lp, *hp;
1070 int c;
1071 unsigned int n;
1072
1073start:
1074 if ((n = l - a) <= qswidth)
1075 return;
1076 n = qswidth * (n / (2 * qswidth));
1077 hp = lp = a + n;
1078 i = a;
1079 j = l - qswidth;
1080 while (TRUE) {
1081 if (i < lp) {
1082 if ((c = qscmp(i, lp)) == 0) {
1083 qexchange(i, lp -= qswidth);
1084 continue;
1085 }
1086 if (c < 0) {
1087 i += qswidth;
1088 continue;
1089 }
1090 }
1091
1092loop:
1093 if (j > hp) {
1094 if ((c = qscmp(hp, j)) == 0) {
1095 qexchange(hp += qswidth, j);
1096 goto loop;
1097 }
1098 if (c > 0) {
1099 if (i == lp) {
1100 q3exchange(i, hp += qswidth, j);
1101 i = lp += qswidth;
1102 goto loop;
1103 }
1104 qexchange(i, j);
1105 j -= qswidth;
1106 i += qswidth;
1107 continue;
1108 }
1109 j -= qswidth;
1110 goto loop;
1111 }
1112
1113 if (i == lp) {
1114 if (lp - a >= l - hp) {
1115 qsort_main(hp + qswidth, l);
1116 l = lp;
1117 } else {
1118 qsort_main(a, lp);
1119 a = hp + qswidth;
1120 }
1121 goto start;
1122 }
1123
1124 q3exchange(j, lp -= qswidth, i);
1125 j = hp -= qswidth;
1126 }
1127}
1128
1129void psxBios_qsort() { // 0x31
1130 qswidth = a2;
1131 qscmpfunc = a3;
1132 qsort_main((char *)Ra0, (char *)Ra0 + a1 * a2);
1133
1134 pc0 = ra;
1135}
1136
1137void psxBios_malloc() { // 0x33
1138 u32 *chunk, *newchunk = NULL;
1139 unsigned int dsize = 0, csize, cstat;
1140 int colflag;
1141#ifdef PSXBIOS_LOG
1142 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x33]);
1143#endif
1144 if (!a0 || (!heap_size || !heap_addr)) {
1145 v0 = 0;
1146 pc0 = ra;
1147 return;
1148 }
1149
1150 // scan through heap and combine free chunks of space
1151 chunk = heap_addr;
1152 colflag = 0;
1153 while(chunk < heap_end) {
1154 // get size and status of actual chunk
1155 csize = ((u32)*chunk) & 0xfffffffc;
1156 cstat = ((u32)*chunk) & 1;
1157
1158 // most probably broken heap descriptor
1159 // this fixes Burning Road
1160 if (*chunk == 0) {
1161 newchunk = chunk;
1162 dsize = ((uptr)heap_end - (uptr)chunk) - 4;
1163 colflag = 1;
1164 break;
1165 }
1166
1167 // it's a free chunk
1168 if(cstat == 1) {
1169 if(colflag == 0) {
1170 newchunk = chunk;
1171 dsize = csize;
1172 colflag = 1; // let's begin a new collection of free memory
1173 }
1174 else dsize += (csize+4); // add the new size including header
1175 }
1176 // not a free chunk: did we start a collection ?
1177 else {
1178 if(colflag == 1) { // collection is over
1179 colflag = 0;
1180 *newchunk = SWAP32(dsize | 1);
1181 }
1182 }
1183
1184 // next chunk
1185 chunk = (u32*)((uptr)chunk + csize + 4);
1186 }
1187 // if neccessary free memory on end of heap
1188 if (colflag == 1)
1189 *newchunk = SWAP32(dsize | 1);
1190
1191 chunk = heap_addr;
1192 csize = ((u32)*chunk) & 0xfffffffc;
1193 cstat = ((u32)*chunk) & 1;
1194 dsize = (a0 + 3) & 0xfffffffc;
1195
1196 // exit on uninitialized heap
1197 if (chunk == NULL) {
1198 printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0);
1199 v0 = 0;
1200 pc0 = ra;
1201 return;
1202 }
1203
1204 // search an unused chunk that is big enough until the end of the heap
1205 while ((dsize > csize || cstat==0) && chunk < heap_end ) {
1206 chunk = (u32*)((uptr)chunk + csize + 4);
1207
1208 // catch out of memory
1209 if(chunk >= heap_end) {
1210 printf("malloc %x,%x: Out of memory error!\n",
1211 v0, a0);
1212 v0 = 0; pc0 = ra;
1213 return;
1214 }
1215
1216 csize = ((u32)*chunk) & 0xfffffffc;
1217 cstat = ((u32)*chunk) & 1;
1218 }
1219
1220 // allocate memory
1221 if(dsize == csize) {
1222 // chunk has same size
1223 *chunk &= 0xfffffffc;
1224 } else if (dsize > csize) {
1225 v0 = 0; pc0 = ra;
1226 return;
1227 } else {
1228 // split free chunk
1229 *chunk = SWAP32(dsize);
1230 newchunk = (u32*)((uptr)chunk + dsize + 4);
1231 *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1);
1232 }
1233
1234 // return pointer to allocated memory
1235 v0 = ((uptr)chunk - (uptr)psxM) + 4;
1236 v0|= 0x80000000;
1237 //printf ("malloc %x,%x\n", v0, a0);
1238 pc0 = ra;
1239}
1240
1241void psxBios_free() { // 0x34
1242
1243#ifdef PSXBIOS_LOG
1244 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x34]);
1245#endif
1246
1247 SysPrintf("free %x: %x bytes\n", a0, *(u32*)(Ra0-4));
1248
1249 if (a0)
1250 *(u32*)(Ra0-4) |= 1; // set chunk to free
1251 pc0 = ra;
1252}
1253
1254void psxBios_calloc() { // 0x37
1255 void *pv0;
1256#ifdef PSXBIOS_LOG
1257 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x37]);
1258#endif
1259
1260 a0 = a0 * a1;
1261 psxBios_malloc();
1262 pv0 = Rv0;
1263 if (pv0)
1264 memset(pv0, 0, a0);
1265}
1266
1267void psxBios_realloc() { // 0x38
1268 u32 block = a0;
1269 u32 size = a1;
1270#ifdef PSXBIOS_LOG
1271 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x38]);
1272#endif
1273
1274 a0 = block;
1275 /* If "old_buf" is zero, executes malloc(new_size), and returns r2=new_buf (or 0=failed). */
1276 if (block == 0)
1277 {
1278 psxBios_malloc();
1279 }
1280 /* Else, if "new_size" is zero, executes free(old_buf), and returns r2=garbage. */
1281 else if (size == 0)
1282 {
1283 psxBios_free();
1284 }
1285 /* Else, executes malloc(new_size), bcopy(old_buf,new_buf,new_size), and free(old_buf), and returns r2=new_buf (or 0=failed). */
1286 /* Note that it is not quite implemented this way here. */
1287 else
1288 {
1289 psxBios_free();
1290 a0 = size;
1291 psxBios_malloc();
1292 }
1293}
1294
1295
1296/* InitHeap(void *block , int n) */
1297void psxBios_InitHeap() { // 0x39
1298 unsigned int size;
1299
1300#ifdef PSXBIOS_LOG
1301 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x39]);
1302#endif
1303
1304 if (((a0 & 0x1fffff) + a1)>= 0x200000) size = 0x1ffffc - (a0 & 0x1fffff);
1305 else size = a1;
1306
1307 size &= 0xfffffffc;
1308
1309 heap_addr = (u32 *)Ra0;
1310 heap_size = size;
1311 heap_end = (u32 *)((u8 *)heap_addr + heap_size);
1312 /* HACKFIX: Commenting out this line fixes GTA2 crash */
1313 //*heap_addr = SWAP32(size | 1);
1314
1315 SysPrintf("InitHeap %x,%x : %x %x\n",a0,a1, (int)((uptr)heap_addr-(uptr)psxM), size);
1316
1317 pc0 = ra;
1318}
1319
1320void psxBios_getchar() { //0x3b
1321 v0 = getchar(); pc0 = ra;
1322}
1323
1324static void psxBios_printf_psxout() { // 0x3f
1325 char tmp[1024];
1326 char tmp2[1024];
1327 u32 save[4];
1328 char *ptmp = tmp;
1329 int n=1, i=0, j;
1330 void *psp;
1331
1332 psp = PSXM(sp);
1333 if (psp != INVALID_PTR) {
1334 memcpy(save, psp, 4 * 4);
1335 psxMu32ref(sp) = SWAP32((u32)a0);
1336 psxMu32ref(sp + 4) = SWAP32((u32)a1);
1337 psxMu32ref(sp + 8) = SWAP32((u32)a2);
1338 psxMu32ref(sp + 12) = SWAP32((u32)a3);
1339 }
1340
1341 while (Ra0[i]) {
1342 switch (Ra0[i]) {
1343 case '%':
1344 j = 0;
1345 tmp2[j++] = '%';
1346_start:
1347 switch (Ra0[++i]) {
1348 case '.':
1349 case 'l':
1350 tmp2[j++] = Ra0[i]; goto _start;
1351 default:
1352 if (Ra0[i] >= '0' && Ra0[i] <= '9') {
1353 tmp2[j++] = Ra0[i];
1354 goto _start;
1355 }
1356 break;
1357 }
1358 tmp2[j++] = Ra0[i];
1359 tmp2[j] = 0;
1360
1361 switch (Ra0[i]) {
1362 case 'f': case 'F':
1363 ptmp += sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break;
1364 case 'a': case 'A':
1365 case 'e': case 'E':
1366 case 'g': case 'G':
1367 ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break;
1368 case 'p':
1369 case 'i': case 'u':
1370 case 'd': case 'D':
1371 case 'o': case 'O':
1372 case 'x': case 'X':
1373 ptmp += sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break;
1374 case 'c':
1375 ptmp += sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break;
1376 case 's':
1377 ptmp += sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break;
1378 case '%':
1379 *ptmp++ = Ra0[i]; break;
1380 }
1381 i++;
1382 break;
1383 default:
1384 *ptmp++ = Ra0[i++];
1385 }
1386 }
1387 *ptmp = 0;
1388
1389 if (psp != INVALID_PTR)
1390 memcpy(psp, save, 4 * 4);
1391
1392 SysPrintf("%s", tmp);
1393}
1394
1395void psxBios_printf() { // 0x3f
1396 psxBios_printf_psxout();
1397 pc0 = ra;
1398}
1399
1400void psxBios_format() { // 0x41
1401 if (strcmp(Ra0, "bu00:") == 0 && Config.Mcd1[0] != '\0')
1402 {
1403 CreateMcd(Config.Mcd1);
1404 LoadMcd(1, Config.Mcd1);
1405 v0 = 1;
1406 }
1407 else if (strcmp(Ra0, "bu10:") == 0 && Config.Mcd2[0] != '\0')
1408 {
1409 CreateMcd(Config.Mcd2);
1410 LoadMcd(2, Config.Mcd2);
1411 v0 = 1;
1412 }
1413 else
1414 {
1415 v0 = 0;
1416 }
1417 pc0 = ra;
1418}
1419
1420static void psxBios_SystemErrorUnresolvedException() {
1421 if (loadRam32(0xfffc) != 0x12345678) { // prevent log flood
1422 SysPrintf("psxBios_%s\n", biosA0n[0x40]);
1423 storeRam32(0xfffc, 0x12345678);
1424 }
1425 mips_return_void_c(1000);
1426}
1427
1428/*
1429 * long Load(char *name, struct EXEC *header);
1430 */
1431
1432void psxBios_Load() { // 0x42
1433 EXE_HEADER eheader;
1434 void *pa1;
1435
1436 pa1 = Ra1;
1437 if (pa1 && LoadCdromFile(Ra0, &eheader) == 0) {
1438 memcpy(pa1, ((char*)&eheader)+16, sizeof(EXEC));
1439 v0 = 1;
1440 } else v0 = 0;
1441 PSXBIOS_LOG("psxBios_%s: %s, %d -> %d\n", biosA0n[0x42], Ra0, a1, v0);
1442
1443 pc0 = ra;
1444}
1445
1446/*
1447 * int Exec(struct EXEC *header , int argc , char **argv);
1448 */
1449
1450void psxBios_Exec() { // 43
1451 EXEC *header = (EXEC*)Ra0;
1452 u32 tmp;
1453
1454#ifdef PSXBIOS_LOG
1455 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosA0n[0x43], a0, a1, a2);
1456#endif
1457
1458 header->_sp = sp;
1459 header->_fp = fp;
1460 header->_sp = sp;
1461 header->_gp = gp;
1462 header->ret = ra;
1463 header->base = s0;
1464
1465 if (header->S_addr != 0) {
1466 tmp = header->S_addr + header->s_size;
1467 sp = tmp;
1468 fp = sp;
1469 }
1470
1471 gp = header->gp0;
1472
1473 s0 = a0;
1474
1475 a0 = a1;
1476 a1 = a2;
1477
1478 ra = 0x8000;
1479 pc0 = header->_pc0;
1480}
1481
1482void psxBios_FlushCache() { // 44
1483#ifdef PSXBIOS_LOG
1484 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x44]);
1485#endif
1486 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
1487 psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL);
1488 pc0 = ra;
1489}
1490
1491void psxBios_GPU_dw() { // 0x46
1492 int size;
1493 u32 *ptr;
1494
1495#ifdef PSXBIOS_LOG
1496 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x46]);
1497#endif
1498
1499 GPU_writeData(0xa0000000);
1500 GPU_writeData((a1<<0x10)|(a0&0xffff));
1501 GPU_writeData((a3<<0x10)|(a2&0xffff));
1502 size = (a2*a3)/2;
1503 ptr = (u32*)PSXM(Rsp[4]); //that is correct?
1504 while(size--)
1505 {
1506 GPU_writeData(SWAPu32(*ptr++));
1507 }
1508
1509 pc0 = ra;
1510}
1511
1512void psxBios_mem2vram() { // 0x47
1513 int size;
1514 gpuSyncPluginSR();
1515 GPU_writeData(0xa0000000);
1516 GPU_writeData((a1<<0x10)|(a0&0xffff));
1517 GPU_writeData((a3<<0x10)|(a2&0xffff));
1518 size = ((((a2 * a3) / 2) >> 4) << 16);
1519 GPU_writeStatus(0x04000002);
1520 psxHwWrite32(0x1f8010f4,0);
1521 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1522 psxHwWrite32(0x1f8010a0,Rsp[4]);//might have a buggy...
1523 psxHwWrite32(0x1f8010a4, size | 0x10);
1524 psxHwWrite32(0x1f8010a8,0x01000201);
1525
1526 pc0 = ra;
1527}
1528
1529void psxBios_SendGPU() { // 0x48
1530 GPU_writeStatus(a0);
1531 gpuSyncPluginSR();
1532 pc0 = ra;
1533}
1534
1535void psxBios_GPU_cw() { // 0x49
1536 gpuSyncPluginSR();
1537 GPU_writeData(a0);
1538 v0 = HW_GPU_STATUS;
1539 pc0 = ra;
1540}
1541
1542void psxBios_GPU_cwb() { // 0x4a
1543 u32 *ptr = (u32*)Ra0;
1544 int size = a1;
1545 gpuSyncPluginSR();
1546 while(size--)
1547 {
1548 GPU_writeData(SWAPu32(*ptr++));
1549 }
1550
1551 pc0 = ra;
1552}
1553
1554void psxBios_GPU_SendPackets() { //4b:
1555 gpuSyncPluginSR();
1556 GPU_writeStatus(0x04000002);
1557 psxHwWrite32(0x1f8010f4,0);
1558 psxHwWrite32(0x1f8010f0,psxHwRead32(0x1f8010f0)|0x800);
1559 psxHwWrite32(0x1f8010a0,a0);
1560 psxHwWrite32(0x1f8010a4,0);
1561 psxHwWrite32(0x1f8010a8,0x010000401);
1562 pc0 = ra;
1563}
1564
1565void psxBios_sys_a0_4c() { // 0x4c GPU relate
1566 psxHwWrite32(0x1f8010a8,0x00000401);
1567 GPU_writeData(0x0400000);
1568 GPU_writeData(0x0200000);
1569 GPU_writeData(0x0100000);
1570 v0 = 0x1f801814;
1571 pc0 = ra;
1572}
1573
1574void psxBios_GPU_GetGPUStatus() { // 0x4d
1575 v0 = GPU_readStatus();
1576 pc0 = ra;
1577}
1578
1579#undef s_addr
1580
1581void psxBios_LoadExec() { // 51
1582 EXEC *header = (EXEC*)PSXM(0xf000);
1583 u32 s_addr, s_size;
1584
1585#ifdef PSXBIOS_LOG
1586 PSXBIOS_LOG("psxBios_%s: %s: %x,%x\n", biosA0n[0x51], Ra0, a1, a2);
1587#endif
1588 s_addr = a1; s_size = a2;
1589
1590 a1 = 0xf000;
1591 psxBios_Load();
1592
1593 header->S_addr = s_addr;
1594 header->s_size = s_size;
1595
1596 a0 = 0xf000; a1 = 0; a2 = 0;
1597 psxBios_Exec();
1598}
1599
1600void psxBios__bu_init() { // 70
1601#ifdef PSXBIOS_LOG
1602 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x70]);
1603#endif
1604
1605 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1606 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1607
1608 pc0 = ra;
1609}
1610
1611void psxBios__96_init() { // 71
1612#ifdef PSXBIOS_LOG
1613 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x71]);
1614#endif
1615
1616 pc0 = ra;
1617}
1618
1619static void psxBios_SysDeqIntRP_();
1620
1621static void psxBios_DequeueCdIntr_() {
1622 a0 = 0; a1 = 0x91d0;
1623 psxBios_SysDeqIntRP_();
1624 a0 = 0; a1 = 0x91e0;
1625 psxBios_SysDeqIntRP_();
1626 use_cycles(16);
1627}
1628
1629static void psxBios_DequeueCdIntr() { // a3
1630 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0xa3]);
1631 psxBios_DequeueCdIntr_();
1632}
1633
1634static void psxBios_CdRemove() { // 56, 72
1635 PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x72]);
1636
1637 // CloseEvent 0xf1000000
1638 // CloseEvent 0xf1000001
1639 // CloseEvent 0xf1000002
1640 // CloseEvent 0xf1000003
1641 // CloseEvent 0xf1000004
1642 psxBios_DequeueCdIntr_();
1643
1644 // EnterCriticalSection - should be done at the beginning,
1645 // but this way is much easier to implement
1646 a0 = 1;
1647 pc0 = A_SYSCALL;
1648 use_cycles(30);
1649}
1650
1651void psxBios_SetMem() { // 9f
1652 u32 new = psxHu32(0x1060);
1653
1654#ifdef PSXBIOS_LOG
1655 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosA0n[0x9f], a0, a1);
1656#endif
1657
1658 switch(a0) {
1659 case 2:
1660 psxHu32ref(0x1060) = SWAP32(new);
1661 psxMu32ref(0x060) = a0;
1662 SysPrintf("Change effective memory : %d MBytes\n",a0);
1663 break;
1664
1665 case 8:
1666 psxHu32ref(0x1060) = SWAP32(new | 0x300);
1667 psxMu32ref(0x060) = a0;
1668 SysPrintf("Change effective memory : %d MBytes\n",a0);
1669
1670 default:
1671 SysPrintf("Effective memory must be 2/8 MBytes\n");
1672 break;
1673 }
1674
1675 pc0 = ra;
1676}
1677
1678/* TODO FIXME : Not compliant. -1 indicates failure but using 1 for now. */
1679void psxBios_get_cd_status(void) //a6
1680{
1681 v0 = 1;
1682 pc0 = ra;
1683}
1684
1685void psxBios__card_info() { // ab
1686#ifdef PSXBIOS_LOG
1687 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xab], a0);
1688#endif
1689 u32 ret, port;
1690 card_active_chan = a0;
1691 port = card_active_chan >> 4;
1692
1693 switch (port) {
1694 case 0x0:
1695 case 0x1:
1696 ret = 0x2;
1697 if (McdDisable[port & 1])
1698 ret = 0x8;
1699 break;
1700 default:
1701#ifdef PSXBIOS_LOG
1702 PSXBIOS_LOG("psxBios_%s: UNKNOWN PORT 0x%x\n", biosA0n[0xab], card_active_chan);
1703#endif
1704 ret = 0x11;
1705 break;
1706 }
1707
1708 if (McdDisable[0] && McdDisable[1])
1709 ret = 0x8;
1710
1711 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1712// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1713 DeliverEvent(0x81, ret); // 0xf4000001, 0x0004
1714 v0 = 1; pc0 = ra;
1715}
1716
1717void psxBios__card_load() { // ac
1718#ifdef PSXBIOS_LOG
1719 PSXBIOS_LOG("psxBios_%s: %x\n", biosA0n[0xac], a0);
1720#endif
1721
1722 card_active_chan = a0;
1723
1724// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
1725 DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
1726
1727 v0 = 1; pc0 = ra;
1728}
1729
1730/* System calls B0 */
1731
1732static u32 psxBios_SysMalloc_(u32 size);
1733
1734static void psxBios_SysMalloc() { // B 00
1735 u32 ret = psxBios_SysMalloc_(a0);
1736
1737 PSXBIOS_LOG("psxBios_%s 0x%x -> %x\n", biosB0n[0x00], a0, ret);
1738 mips_return_c(ret, 33);
1739}
1740
1741void psxBios_SetRCnt() { // 02
1742#ifdef PSXBIOS_LOG
1743 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x02]);
1744#endif
1745
1746 a0&= 0x3;
1747 if (a0 != 3) {
1748 u32 mode=0;
1749
1750 psxRcntWtarget(a0, a1);
1751 if (a2&0x1000) mode|= 0x050; // Interrupt Mode
1752 if (a2&0x0100) mode|= 0x008; // Count to 0xffff
1753 if (a2&0x0010) mode|= 0x001; // Timer stop mode
1754 if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
1755 else { if (a2&0x0001) mode|= 0x100; } // System Clock mode
1756
1757 psxRcntWmode(a0, mode);
1758 }
1759 pc0 = ra;
1760}
1761
1762void psxBios_GetRCnt() { // 03
1763#ifdef PSXBIOS_LOG
1764 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]);
1765#endif
1766
1767 a0&= 0x3;
1768 if (a0 != 3) v0 = psxRcntRcount(a0);
1769 else v0 = 0;
1770 pc0 = ra;
1771}
1772
1773void psxBios_StartRCnt() { // 04
1774#ifdef PSXBIOS_LOG
1775 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x04]);
1776#endif
1777
1778 a0&= 0x3;
1779 if (a0 != 3) psxHu32ref(0x1074)|= SWAP32((u32)((1<<(a0+4))));
1780 else psxHu32ref(0x1074)|= SWAPu32(0x1);
1781 v0 = 1; pc0 = ra;
1782}
1783
1784void psxBios_StopRCnt() { // 05
1785#ifdef PSXBIOS_LOG
1786 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x05]);
1787#endif
1788
1789 a0&= 0x3;
1790 if (a0 != 3) psxHu32ref(0x1074)&= SWAP32((u32)(~(1<<(a0+4))));
1791 else psxHu32ref(0x1074)&= SWAPu32(~0x1);
1792 pc0 = ra;
1793}
1794
1795void psxBios_ResetRCnt() { // 06
1796#ifdef PSXBIOS_LOG
1797 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x06]);
1798#endif
1799
1800 a0&= 0x3;
1801 if (a0 != 3) {
1802 psxRcntWmode(a0, 0);
1803 psxRcntWtarget(a0, 0);
1804 psxRcntWcount(a0, 0);
1805 }
1806 pc0 = ra;
1807}
1808
1809
1810/* gets ev for use with EventCB */
1811#define GetEv() \
1812 ev = (a0 >> 24) & 0xf; \
1813 if (ev == 0xf) ev = 0x5; \
1814 ev*= 32; \
1815 ev+= a0&0x1f;
1816
1817/* gets spec for use with EventCB */
1818#define GetSpec() \
1819 spec = 0; \
1820 switch (a1) { \
1821 case 0x0301: spec = 16; break; \
1822 case 0x0302: spec = 17; break; \
1823 default: \
1824 for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
1825 break; \
1826 }
1827
1828void psxBios_DeliverEvent() { // 07
1829 int ev, spec;
1830 int i;
1831
1832 GetEv();
1833 GetSpec();
1834
1835#ifdef PSXBIOS_LOG
1836 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x07], ev, spec);
1837#endif
1838
1839 DeliverEvent(ev, spec);
1840
1841 pc0 = ra;
1842}
1843
1844void psxBios_OpenEvent() { // 08
1845 int ev, spec;
1846 int i;
1847
1848 GetEv();
1849 GetSpec();
1850
1851#ifdef PSXBIOS_LOG
1852 PSXBIOS_LOG("psxBios_%s %x,%x (class:%x, spec:%x, mode:%x, func:%x)\n", biosB0n[0x08], ev, spec, a0, a1, a2, a3);
1853#endif
1854
1855 EventCB[ev][spec].status = EvStWAIT;
1856 EventCB[ev][spec].mode = a2;
1857 EventCB[ev][spec].fhandler = a3;
1858
1859 v0 = ev | (spec << 8);
1860 pc0 = ra;
1861}
1862
1863void psxBios_CloseEvent() { // 09
1864 int ev, spec;
1865
1866 ev = a0 & 0xff;
1867 spec = (a0 >> 8) & 0xff;
1868
1869#ifdef PSXBIOS_LOG
1870 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x09], ev, spec);
1871#endif
1872
1873 EventCB[ev][spec].status = EvStUNUSED;
1874
1875 v0 = 1; pc0 = ra;
1876}
1877
1878void psxBios_WaitEvent() { // 0a
1879 int ev, spec;
1880
1881 ev = a0 & 0xff;
1882 spec = (a0 >> 8) & 0xff;
1883#ifdef PSXBIOS_LOG
1884 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0a], ev, spec);
1885#endif
1886 if (EventCB[ev][spec].status == EvStUNUSED)
1887 {
1888 v0 = 0;
1889 pc0 = ra;
1890 return;
1891 }
1892
1893 if (EventCB[ev][spec].status == EvStALREADY)
1894 {
1895 /* Callback events (mode=EvMdINTR) do never set the ready flag (and thus WaitEvent would hang forever). */
1896 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1897 v0 = 1;
1898 pc0 = ra;
1899 return;
1900 }
1901
1902 v0 = 0;
1903 pc0 = ra;
1904}
1905
1906void psxBios_TestEvent() { // 0b
1907 int ev, spec;
1908
1909 ev = a0 & 0xff;
1910 spec = (a0 >> 8) & 0xff;
1911
1912 if (EventCB[ev][spec].status == EvStALREADY)
1913 {
1914 if (!(EventCB[ev][spec].mode == EvMdINTR)) EventCB[ev][spec].status = EvStACTIVE;
1915 v0 = 1;
1916 }
1917 else
1918 {
1919 v0 = 0;
1920 }
1921
1922#ifdef PSXBIOS_LOG
1923 PSXBIOS_LOG("psxBios_%s %x,%x: %x\n", biosB0n[0x0b], ev, spec, v0);
1924#endif
1925
1926 pc0 = ra;
1927}
1928
1929void psxBios_EnableEvent() { // 0c
1930 int ev, spec;
1931
1932 ev = a0 & 0xff;
1933 spec = (a0 >> 8) & 0xff;
1934
1935#ifdef PSXBIOS_LOG
1936 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0c], ev, spec);
1937#endif
1938
1939 EventCB[ev][spec].status = EvStACTIVE;
1940
1941 v0 = 1; pc0 = ra;
1942}
1943
1944void psxBios_DisableEvent() { // 0d
1945 int ev, spec;
1946
1947 ev = a0 & 0xff;
1948 spec = (a0 >> 8) & 0xff;
1949
1950#ifdef PSXBIOS_LOG
1951 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x0d], ev, spec);
1952#endif
1953
1954 EventCB[ev][spec].status = EvStWAIT;
1955
1956 v0 = 1; pc0 = ra;
1957}
1958
1959/*
1960 * long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
1961 */
1962
1963void psxBios_OpenTh() { // 0e
1964 TCB *tcb = loadRam32ptr(A_TT_TCB);
1965 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
1966 int th;
1967
1968 for (th = 1; th < limit; th++)
1969 {
1970 if (tcb[th].status != SWAP32(0x4000)) break;
1971
1972 }
1973 if (th == limit) {
1974 // Feb 2019 - Added out-of-bounds fix caught by cppcheck:
1975 // When no free TCB is found, return 0xffffffff according to Nocash doc.
1976#ifdef PSXBIOS_LOG
1977 PSXBIOS_LOG("\t%s() WARNING! No Free TCBs found!\n", __func__);
1978#endif
1979 mips_return_c(0xffffffff, 20);
1980 return;
1981 }
1982 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0e], th);
1983
1984 tcb[th].status = SWAP32(0x4000);
1985 tcb[th].mode = SWAP32(0x1000);
1986 tcb[th].epc = SWAP32(a0);
1987 tcb[th].reg[30] = SWAP32(a1); // fp
1988 tcb[th].reg[29] = SWAP32(a1); // sp
1989 tcb[th].reg[28] = SWAP32(a2); // gp
1990
1991 mips_return_c(0xff000000 + th, 34);
1992}
1993
1994/*
1995 * int CloseTh(long thread);
1996 */
1997
1998void psxBios_CloseTh() { // 0f
1999 TCB *tcb = loadRam32ptr(A_TT_TCB);
2000 u32 limit = loadRam32(A_TT_TCB + 4) / 0xc0u;
2001 u32 th = a0 & 0xff;
2002
2003#ifdef PSXBIOS_LOG
2004 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x0f], th);
2005#endif
2006 /* The return value is always 1 (even if the handle was already closed). */
2007 v0 = 1;
2008 if (th < limit && tcb[th].status == SWAP32(0x4000)) {
2009 tcb[th].status = SWAP32(0x1000);
2010 }
2011
2012 pc0 = ra;
2013}
2014
2015/*
2016 * int ChangeTh(long thread);
2017 */
2018
2019void psxBios_ChangeTh() { // 10
2020 u32 tcbBase = loadRam32(A_TT_TCB);
2021 u32 th = a0 & 0xffff;
2022
2023#ifdef PSXBIOS_LOG
2024// PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x10], th);
2025#endif
2026 // without doing any argument checks, just issue a syscall
2027 // (like the real bios does)
2028 a0 = 3;
2029 a1 = tcbBase + th * sizeof(TCB);
2030 pc0 = A_SYSCALL;
2031 use_cycles(15);
2032}
2033
2034void psxBios_InitPAD() { // 0x12
2035#ifdef PSXBIOS_LOG
2036 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x12]);
2037#endif
2038
2039 pad_buf1 = (char*)Ra0;
2040 pad_buf1len = a1;
2041 pad_buf2 = (char*)Ra2;
2042 pad_buf2len = a3;
2043
2044 v0 = 1; pc0 = ra;
2045}
2046
2047void psxBios_StartPAD() { // 13
2048#ifdef PSXBIOS_LOG
2049 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x13]);
2050#endif
2051 pad_stopped = 0;
2052 psxHwWrite16(0x1f801074, (unsigned short)(psxHwRead16(0x1f801074) | 0x1));
2053 psxRegs.CP0.n.SR |= 0x401;
2054 pc0 = ra;
2055}
2056
2057void psxBios_StopPAD() { // 14
2058#ifdef PSXBIOS_LOG
2059 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x14]);
2060#endif
2061 pad_stopped = 1;
2062 pad_buf1 = NULL;
2063 pad_buf2 = NULL;
2064 pc0 = ra;
2065}
2066
2067void psxBios_PAD_init() { // 15
2068#ifdef PSXBIOS_LOG
2069 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x15]);
2070#endif
2071 if (!(a0 == 0x20000000 || a0 == 0x20000001))
2072 {
2073 v0 = 0;
2074 pc0 = ra;
2075 return;
2076 }
2077 psxHwWrite16(0x1f801074, (u16)(psxHwRead16(0x1f801074) | 0x1));
2078 pad_buf = (int *)Ra1;
2079 *pad_buf = -1;
2080 psxRegs.CP0.n.SR |= 0x401;
2081 v0 = 2;
2082 pc0 = ra;
2083}
2084
2085void psxBios_PAD_dr() { // 16
2086#ifdef PSXBIOS_LOG
2087 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x16]);
2088#endif
2089
2090 v0 = -1; pc0 = ra;
2091}
2092
2093static void psxBios_ReturnFromException() { // 17
2094 u32 tcbPtr = loadRam32(A_TT_PCB);
2095 const TCB *tcb = loadRam32ptr(tcbPtr);
2096 int i;
2097
2098 for (i = 1; i < 32; i++)
2099 psxRegs.GPR.r[i] = SWAP32(tcb->reg[i]);
2100 psxRegs.GPR.n.lo = SWAP32(tcb->lo);
2101 psxRegs.GPR.n.hi = SWAP32(tcb->hi);
2102 psxRegs.CP0.n.SR = SWAP32(tcb->sr);
2103
2104 //printf("%s %08x->%08x %u\n", __func__, pc0, tcb->epc, psxRegs.cycle);
2105 pc0 = k0 = SWAP32(tcb->epc);
2106
2107 psxRegs.CP0.n.SR = (psxRegs.CP0.n.SR & ~0x0f) | ((psxRegs.CP0.n.SR & 0x3c) >> 2);
2108 use_cycles(53);
2109 psxBranchTest();
2110}
2111
2112void psxBios_ResetEntryInt() { // 18
2113 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x18]);
2114
2115 storeRam32(A_EEXIT_PTR, A_EEXIT_DEF);
2116 mips_return_void_c(5);
2117}
2118
2119void psxBios_HookEntryInt() { // 19
2120 PSXBIOS_LOG("psxBios_%s %x\n", biosB0n[0x19], a0);
2121
2122 storeRam32(A_EEXIT_PTR, a0);
2123 mips_return_void_c(3);
2124}
2125
2126void psxBios_UnDeliverEvent() { // 0x20
2127 int ev, spec;
2128 int i;
2129
2130 GetEv();
2131 GetSpec();
2132
2133#ifdef PSXBIOS_LOG
2134 PSXBIOS_LOG("psxBios_%s %x,%x\n", biosB0n[0x20], ev, spec);
2135#endif
2136
2137 if (EventCB[ev][spec].status == EvStALREADY &&
2138 EventCB[ev][spec].mode == EvMdNOINTR)
2139 EventCB[ev][spec].status = EvStACTIVE;
2140
2141 pc0 = ra;
2142}
2143
2144char ffile[64], *pfile;
2145int nfile;
2146
2147static void buopen(int mcd, char *ptr, char *cfg)
2148{
2149 int i;
2150 char *mcd_data = ptr;
2151
2152 strcpy(FDesc[1 + mcd].name, Ra0+5);
2153 FDesc[1 + mcd].offset = 0;
2154 FDesc[1 + mcd].mode = a1;
2155
2156 for (i=1; i<16; i++) {
2157 const char *fptr = mcd_data + 128 * i;
2158 if ((*fptr & 0xF0) != 0x50) continue;
2159 if (strcmp(FDesc[1 + mcd].name, fptr+0xa)) continue;
2160 FDesc[1 + mcd].mcfile = i;
2161 SysPrintf("open %s\n", fptr+0xa);
2162 v0 = 1 + mcd;
2163 break;
2164 }
2165 if (a1 & 0x200 && v0 == -1) { /* FCREAT */
2166 for (i=1; i<16; i++) {
2167 int j, xor, nblk = a1 >> 16;
2168 char *pptr, *fptr2;
2169 char *fptr = mcd_data + 128 * i;
2170
2171 if ((*fptr & 0xF0) != 0xa0) continue;
2172
2173 FDesc[1 + mcd].mcfile = i;
2174 fptr[0] = 0x51;
2175 fptr[4] = 0x00;
2176 fptr[5] = 0x20 * nblk;
2177 fptr[6] = 0x00;
2178 fptr[7] = 0x00;
2179 strcpy(fptr+0xa, FDesc[1 + mcd].name);
2180 pptr = fptr2 = fptr;
2181 for(j=2; j<=nblk; j++) {
2182 int k;
2183 for(i++; i<16; i++) {
2184 fptr2 += 128;
2185
2186 memset(fptr2, 0, 128);
2187 fptr2[0] = j < nblk ? 0x52 : 0x53;
2188 pptr[8] = i - 1;
2189 pptr[9] = 0;
2190 for (k=0, xor=0; k<127; k++) xor^= pptr[k];
2191 pptr[127] = xor;
2192 pptr = fptr2;
2193 break;
2194 }
2195 /* shouldn't this return ENOSPC if i == 16? */
2196 }
2197 pptr[8] = pptr[9] = 0xff;
2198 for (j=0, xor=0; j<127; j++) xor^= pptr[j];
2199 pptr[127] = xor;
2200 SysPrintf("openC %s %d\n", ptr, nblk);
2201 v0 = 1 + mcd;
2202 /* just go ahead and resave them all */
2203 SaveMcd(cfg, ptr, 128, 128 * 15);
2204 break;
2205 }
2206 /* shouldn't this return ENOSPC if i == 16? */
2207 }
2208}
2209
2210/*
2211 * int open(char *name , int mode);
2212 */
2213
2214void psxBios_open() { // 0x32
2215 void *pa0 = Ra0;
2216
2217#ifdef PSXBIOS_LOG
2218 PSXBIOS_LOG("psxBios_%s: %s,%x\n", biosB0n[0x32], Ra0, a1);
2219#endif
2220
2221 v0 = -1;
2222
2223 if (pa0 != INVALID_PTR) {
2224 if (!strncmp(pa0, "bu00", 4)) {
2225 buopen(1, Mcd1Data, Config.Mcd1);
2226 }
2227
2228 if (!strncmp(pa0, "bu10", 4)) {
2229 buopen(2, Mcd2Data, Config.Mcd2);
2230 }
2231 }
2232
2233 pc0 = ra;
2234}
2235
2236/*
2237 * int lseek(int fd , int offset , int whence);
2238 */
2239
2240void psxBios_lseek() { // 0x33
2241#ifdef PSXBIOS_LOG
2242 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x33], a0, a1, a2);
2243#endif
2244
2245 switch (a2) {
2246 case 0: // SEEK_SET
2247 FDesc[a0].offset = a1;
2248 v0 = a1;
2249// DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2250// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2251 break;
2252
2253 case 1: // SEEK_CUR
2254 FDesc[a0].offset+= a1;
2255 v0 = FDesc[a0].offset;
2256 break;
2257 }
2258
2259 pc0 = ra;
2260}
2261
2262
2263/*
2264 * int read(int fd , void *buf , int nbytes);
2265 */
2266
2267void psxBios_read() { // 0x34
2268 char *ptr;
2269 void *pa1 = Ra1;
2270
2271#ifdef PSXBIOS_LOG
2272 PSXBIOS_LOG("psxBios_%s: %x, %x, %x\n", biosB0n[0x34], a0, a1, a2);
2273#endif
2274
2275 v0 = -1;
2276
2277 if (pa1 != INVALID_PTR) {
2278 switch (a0) {
2279 case 2: buread(pa1, 1, a2); break;
2280 case 3: buread(pa1, 2, a2); break;
2281 }
2282 }
2283
2284 pc0 = ra;
2285}
2286
2287/*
2288 * int write(int fd , void *buf , int nbytes);
2289 */
2290
2291void psxBios_write() { // 0x35/0x03
2292 char *ptr;
2293 void *pa1 = Ra1;
2294
2295#ifdef PSXBIOS_LOG
2296 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2);
2297#endif
2298
2299 v0 = -1;
2300 if (pa1 == INVALID_PTR) {
2301 pc0 = ra;
2302 return;
2303 }
2304
2305 if (a0 == 1) { // stdout
2306 char *ptr = pa1;
2307
2308 v0 = a2;
2309 while (a2 > 0) {
2310 SysPrintf("%c", *ptr++); a2--;
2311 }
2312 pc0 = ra; return;
2313 }
2314
2315 switch (a0) {
2316 case 2: buwrite(pa1, 1, a2); break;
2317 case 3: buwrite(pa1, 2, a2); break;
2318 }
2319
2320 pc0 = ra;
2321}
2322
2323static void psxBios_write_psxout() {
2324 if (a0 == 1) { // stdout
2325 const char *ptr = Ra1;
2326 int len = a2;
2327
2328 if (ptr != INVALID_PTR)
2329 while (len-- > 0)
2330 SysPrintf("%c", *ptr++);
2331 }
2332}
2333
2334static void psxBios_putchar_psxout() { // 3d
2335 SysPrintf("%c", (char)a0);
2336}
2337
2338static void psxBios_puts_psxout() { // 3e/3f
2339 SysPrintf("%s", Ra0);
2340}
2341
2342/*
2343 * int close(int fd);
2344 */
2345
2346void psxBios_close() { // 0x36
2347#ifdef PSXBIOS_LOG
2348 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x36], a0);
2349#endif
2350
2351 v0 = a0;
2352 pc0 = ra;
2353}
2354
2355void psxBios_putchar() { // 3d
2356 SysPrintf("%c", (char)a0);
2357 pc0 = ra;
2358}
2359
2360void psxBios_puts() { // 3e/3f
2361 SysPrintf("%s", Ra0);
2362 pc0 = ra;
2363}
2364
2365
2366/* To avoid any issues with different behaviour when using the libc's own strlen instead.
2367 * We want to mimic the PSX's behaviour in this case for bufile. */
2368static size_t strlen_internal(char* p)
2369{
2370 size_t size_of_array = 0;
2371 while (*p++) size_of_array++;
2372 return size_of_array;
2373}
2374
2375#define bufile(mcd) { \
2376 size_t size_of_name = strlen_internal(dir->name); \
2377 while (nfile < 16) { \
2378 int match=1; \
2379 \
2380 ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
2381 nfile++; \
2382 if ((*ptr & 0xF0) != 0x50) continue; \
2383 /* Bug link files show up as free block. */ \
2384 if (!ptr[0xa]) continue; \
2385 ptr+= 0xa; \
2386 if (pfile[0] == 0) { \
2387 strncpy(dir->name, ptr, sizeof(dir->name) - 1); \
2388 if (size_of_name < sizeof(dir->name)) dir->name[size_of_name] = '\0'; \
2389 } else for (i=0; i<20; i++) { \
2390 if (pfile[i] == ptr[i]) { \
2391 dir->name[i] = ptr[i]; continue; } \
2392 if (pfile[i] == '?') { \
2393 dir->name[i] = ptr[i]; continue; } \
2394 if (pfile[i] == '*') { \
2395 strcpy(dir->name+i, ptr+i); break; } \
2396 match = 0; break; \
2397 } \
2398 SysPrintf("%d : %s = %s + %s (match=%d)\n", nfile, dir->name, pfile, ptr, match); \
2399 if (match == 0) { continue; } \
2400 dir->size = 8192; \
2401 v0 = _dir; \
2402 break; \
2403 } \
2404}
2405
2406/*
2407 * struct DIRENTRY* firstfile(char *name,struct DIRENTRY *dir);
2408 */
2409
2410void psxBios_firstfile() { // 42
2411 struct DIRENTRY *dir = (struct DIRENTRY *)Ra1;
2412 void *pa0 = Ra0;
2413 u32 _dir = a1;
2414 char *ptr;
2415 int i;
2416
2417#ifdef PSXBIOS_LOG
2418 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x42], Ra0);
2419#endif
2420
2421 v0 = 0;
2422
2423 if (pa0 != INVALID_PTR) {
2424 strcpy(ffile, pa0);
2425 pfile = ffile+5;
2426 nfile = 0;
2427 if (!strncmp(pa0, "bu00", 4)) {
2428 // firstfile() calls _card_read() internally, so deliver it's event
2429 DeliverEvent(0x11, 0x2);
2430 bufile(1);
2431 } else if (!strncmp(pa0, "bu10", 4)) {
2432 // firstfile() calls _card_read() internally, so deliver it's event
2433 DeliverEvent(0x11, 0x2);
2434 bufile(2);
2435 }
2436 }
2437
2438 pc0 = ra;
2439}
2440
2441/*
2442 * struct DIRENTRY* nextfile(struct DIRENTRY *dir);
2443 */
2444
2445void psxBios_nextfile() { // 43
2446 struct DIRENTRY *dir = (struct DIRENTRY *)Ra0;
2447 u32 _dir = a0;
2448 char *ptr;
2449 int i;
2450
2451#ifdef PSXBIOS_LOG
2452 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x43], dir->name);
2453#endif
2454
2455 v0 = 0;
2456
2457 if (!strncmp(ffile, "bu00", 4)) {
2458 bufile(1);
2459 }
2460
2461 if (!strncmp(ffile, "bu10", 4)) {
2462 bufile(2);
2463 }
2464
2465 pc0 = ra;
2466}
2467
2468#define burename(mcd) { \
2469 for (i=1; i<16; i++) { \
2470 int namelen, j, xor = 0; \
2471 ptr = Mcd##mcd##Data + 128 * i; \
2472 if ((*ptr & 0xF0) != 0x50) continue; \
2473 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2474 namelen = strlen(Ra1+5); \
2475 memcpy(ptr+0xa, Ra1+5, namelen); \
2476 memset(ptr+0xa+namelen, 0, 0x75-namelen); \
2477 for (j=0; j<127; j++) xor^= ptr[j]; \
2478 ptr[127] = xor; \
2479 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i + 0xa, 0x76); \
2480 v0 = 1; \
2481 break; \
2482 } \
2483}
2484
2485/*
2486 * int rename(char *old, char *new);
2487 */
2488
2489void psxBios_rename() { // 44
2490 void *pa0 = Ra0;
2491 void *pa1 = Ra1;
2492 char *ptr;
2493 int i;
2494
2495#ifdef PSXBIOS_LOG
2496 PSXBIOS_LOG("psxBios_%s: %s,%s\n", biosB0n[0x44], Ra0, Ra1);
2497#endif
2498
2499 v0 = 0;
2500
2501 if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
2502 if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
2503 burename(1);
2504 }
2505
2506 if (!strncmp(pa0, "bu10", 4) && !strncmp(pa1, "bu10", 4)) {
2507 burename(2);
2508 }
2509 }
2510
2511 pc0 = ra;
2512}
2513
2514
2515#define budelete(mcd) { \
2516 for (i=1; i<16; i++) { \
2517 ptr = Mcd##mcd##Data + 128 * i; \
2518 if ((*ptr & 0xF0) != 0x50) continue; \
2519 if (strcmp(Ra0+5, ptr+0xa)) continue; \
2520 *ptr = (*ptr & 0xf) | 0xA0; \
2521 SaveMcd(Config.Mcd##mcd, Mcd##mcd##Data, 128 * i, 1); \
2522 SysPrintf("delete %s\n", ptr+0xa); \
2523 v0 = 1; \
2524 break; \
2525 } \
2526}
2527
2528/*
2529 * int delete(char *name);
2530 */
2531
2532void psxBios_delete() { // 45
2533 void *pa0 = Ra0;
2534 char *ptr;
2535 int i;
2536
2537#ifdef PSXBIOS_LOG
2538 PSXBIOS_LOG("psxBios_%s: %s\n", biosB0n[0x45], Ra0);
2539#endif
2540
2541 v0 = 0;
2542
2543 if (pa0 != INVALID_PTR) {
2544 if (!strncmp(pa0, "bu00", 4)) {
2545 budelete(1);
2546 }
2547
2548 if (!strncmp(pa0, "bu10", 4)) {
2549 budelete(2);
2550 }
2551 }
2552
2553 pc0 = ra;
2554}
2555
2556void psxBios_InitCARD() { // 4a
2557#ifdef PSXBIOS_LOG
2558 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0);
2559#endif
2560
2561 CardState = 0;
2562
2563 pc0 = ra;
2564}
2565
2566void psxBios_StartCARD() { // 4b
2567#ifdef PSXBIOS_LOG
2568 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4b]);
2569#endif
2570
2571 if (CardState == 0) CardState = 1;
2572
2573 pc0 = ra;
2574}
2575
2576void psxBios_StopCARD() { // 4c
2577#ifdef PSXBIOS_LOG
2578 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4c]);
2579#endif
2580
2581 if (CardState == 1) CardState = 0;
2582
2583 pc0 = ra;
2584}
2585
2586void psxBios__card_write() { // 0x4e
2587 void *pa2 = Ra2;
2588 int port;
2589
2590#ifdef PSXBIOS_LOG
2591 PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
2592#endif
2593 /*
2594 Function also accepts sector 400h (a bug).
2595 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2596 */
2597 if (!(a1 <= 0x3FF))
2598 {
2599 /* Invalid sectors */
2600 v0 = 0; pc0 = ra;
2601 return;
2602 }
2603 card_active_chan = a0;
2604 port = a0 >> 4;
2605
2606 if (pa2 != INVALID_PTR) {
2607 if (port == 0) {
2608 memcpy(Mcd1Data + a1 * 128, pa2, 128);
2609 SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
2610 } else {
2611 memcpy(Mcd2Data + a1 * 128, pa2, 128);
2612 SaveMcd(Config.Mcd2, Mcd2Data, a1 * 128, 128);
2613 }
2614 }
2615
2616 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2617// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2618
2619 v0 = 1; pc0 = ra;
2620}
2621
2622void psxBios__card_read() { // 0x4f
2623 void *pa2 = Ra2;
2624 int port;
2625
2626#ifdef PSXBIOS_LOG
2627 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x4f]);
2628#endif
2629 /*
2630 Function also accepts sector 400h (a bug).
2631 But notaz said we shouldn't allow sector 400h because it can corrupt the emulator.
2632 */
2633 if (!(a1 <= 0x3FF))
2634 {
2635 /* Invalid sectors */
2636 v0 = 0; pc0 = ra;
2637 return;
2638 }
2639 card_active_chan = a0;
2640 port = a0 >> 4;
2641
2642 if (pa2 != INVALID_PTR) {
2643 if (port == 0) {
2644 memcpy(pa2, Mcd1Data + a1 * 128, 128);
2645 } else {
2646 memcpy(pa2, Mcd2Data + a1 * 128, 128);
2647 }
2648 }
2649
2650 DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
2651// DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004
2652
2653 v0 = 1; pc0 = ra;
2654}
2655
2656void psxBios__new_card() { // 0x50
2657#ifdef PSXBIOS_LOG
2658 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x50]);
2659#endif
2660
2661 pc0 = ra;
2662}
2663
2664/* According to a user, this allows Final Fantasy Tactics to save/load properly */
2665void psxBios__get_error(void) // 55
2666{
2667 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x55]);
2668 v0 = 0;
2669 pc0 = ra;
2670}
2671
2672void psxBios_Krom2RawAdd() { // 0x51
2673 int i = 0;
2674
2675 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x51]);
2676 const u32 table_8140[][2] = {
2677 {0x8140, 0x0000}, {0x8180, 0x0762}, {0x81ad, 0x0cc6}, {0x81b8, 0x0ca8},
2678 {0x81c0, 0x0f00}, {0x81c8, 0x0d98}, {0x81cf, 0x10c2}, {0x81da, 0x0e6a},
2679 {0x81e9, 0x13ce}, {0x81f0, 0x102c}, {0x81f8, 0x1590}, {0x81fc, 0x111c},
2680 {0x81fd, 0x1626}, {0x824f, 0x113a}, {0x8259, 0x20ee}, {0x8260, 0x1266},
2681 {0x827a, 0x24cc}, {0x8281, 0x1572}, {0x829b, 0x28aa}, {0x829f, 0x187e},
2682 {0x82f2, 0x32dc}, {0x8340, 0x2238}, {0x837f, 0x4362}, {0x8380, 0x299a},
2683 {0x8397, 0x4632}, {0x839f, 0x2c4c}, {0x83b7, 0x49f2}, {0x83bf, 0x2f1c},
2684 {0x83d7, 0x4db2}, {0x8440, 0x31ec}, {0x8461, 0x5dde}, {0x8470, 0x35ca},
2685 {0x847f, 0x6162}, {0x8480, 0x378c}, {0x8492, 0x639c}, {0x849f, 0x39a8},
2686 {0xffff, 0}
2687 };
2688
2689 const u32 table_889f[][2] = {
2690 {0x889f, 0x3d68}, {0x8900, 0x40ec}, {0x897f, 0x4fb0}, {0x8a00, 0x56f4},
2691 {0x8a7f, 0x65b8}, {0x8b00, 0x6cfc}, {0x8b7f, 0x7bc0}, {0x8c00, 0x8304},
2692 {0x8c7f, 0x91c8}, {0x8d00, 0x990c}, {0x8d7f, 0xa7d0}, {0x8e00, 0xaf14},
2693 {0x8e7f, 0xbdd8}, {0x8f00, 0xc51c}, {0x8f7f, 0xd3e0}, {0x9000, 0xdb24},
2694 {0x907f, 0xe9e8}, {0x9100, 0xf12c}, {0x917f, 0xfff0}, {0x9200, 0x10734},
2695 {0x927f, 0x115f8}, {0x9300, 0x11d3c}, {0x937f, 0x12c00}, {0x9400, 0x13344},
2696 {0x947f, 0x14208}, {0x9500, 0x1494c}, {0x957f, 0x15810}, {0x9600, 0x15f54},
2697 {0x967f, 0x16e18}, {0x9700, 0x1755c}, {0x977f, 0x18420}, {0x9800, 0x18b64},
2698 {0xffff, 0}
2699 };
2700
2701 if (a0 >= 0x8140 && a0 <= 0x84be) {
2702 while (table_8140[i][0] <= a0) i++;
2703 a0 -= table_8140[i - 1][0];
2704 v0 = 0xbfc66000 + (a0 * 0x1e + table_8140[i - 1][1]);
2705 } else if (a0 >= 0x889f && a0 <= 0x9872) {
2706 while (table_889f[i][0] <= a0) i++;
2707 a0 -= table_889f[i - 1][0];
2708 v0 = 0xbfc66000 + (a0 * 0x1e + table_889f[i - 1][1]);
2709 } else {
2710 v0 = 0xffffffff;
2711 }
2712
2713 pc0 = ra;
2714}
2715
2716void psxBios_GetC0Table() { // 56
2717 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x56]);
2718 log_unhandled("GetC0Table @%08x\n", ra);
2719
2720 mips_return_c(A_C0_TABLE, 3);
2721}
2722
2723void psxBios_GetB0Table() { // 57
2724 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x57]);
2725 log_unhandled("GetB0Table @%08x\n", ra);
2726
2727 mips_return_c(A_B0_TABLE, 3);
2728}
2729
2730void psxBios__card_chan() { // 0x58
2731#ifdef PSXBIOS_LOG
2732 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x58]);
2733#endif
2734
2735 v0 = card_active_chan;
2736 pc0 = ra;
2737}
2738
2739void psxBios_ChangeClearPad() { // 5b
2740#ifdef PSXBIOS_LOG
2741 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5b], a0);
2742#endif
2743
2744 pc0 = ra;
2745}
2746
2747void psxBios__card_status() { // 5c
2748#ifdef PSXBIOS_LOG
2749 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5c], a0);
2750#endif
2751
2752 v0 = card_active_chan;
2753 pc0 = ra;
2754}
2755
2756void psxBios__card_wait() { // 5d
2757#ifdef PSXBIOS_LOG
2758 PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x5d], a0);
2759#endif
2760
2761 v0 = 1;
2762 pc0 = ra;
2763}
2764
2765/* System calls C0 */
2766
2767static void psxBios_SysEnqIntRP();
2768
2769static void psxBios_InitRCnt() { // 00
2770 int i;
2771 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x00], a0);
2772 psxHwWrite16(0x1f801074, psxHu32(0x1074) & ~0x71);
2773 for (i = 0; i < 3; i++) {
2774 psxHwWrite16(0x1f801100 + i*0x10 + 4, 0);
2775 psxHwWrite16(0x1f801100 + i*0x10 + 8, 0);
2776 psxHwWrite16(0x1f801100 + i*0x10 + 0, 0);
2777 }
2778 a1 = 0x6d88;
2779 psxBios_SysEnqIntRP();
2780 mips_return_c(0, 9);
2781}
2782
2783static void psxBios_InitException() { // 01
2784 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x01], a0);
2785 a1 = 0x6da8;
2786 psxBios_SysEnqIntRP();
2787 mips_return_c(0, 9);
2788}
2789
2790/*
2791 * int SysEnqIntRP(int index , long *queue);
2792 */
2793
2794static void psxBios_SysEnqIntRP() { // 02
2795 u32 old, base = loadRam32(A_TT_ExCB);
2796 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x02], a0, a1);
2797
2798 old = loadRam32(base + (a0 << 3));
2799 storeRam32(base + (a0 << 3), a1);
2800 storeRam32(a1, old);
2801 mips_return_c(0, 9);
2802}
2803
2804/*
2805 * int SysDeqIntRP(int index , long *queue);
2806 */
2807
2808static void psxBios_SysDeqIntRP_() { // 03
2809 u32 ptr, next, base = loadRam32(A_TT_ExCB);
2810 u32 lim = 0, ret = 0;
2811
2812 // as in original: no arg checks of any kind, bug if a1 == 0
2813 ptr = loadRam32(base + (a0 << 3));
2814 while (ptr) {
2815 next = loadRam32(ptr);
2816 if (ptr == a1) {
2817 storeRam32(base + (a0 << 3), next);
2818 ret = ptr;
2819 use_cycles(6);
2820 break;
2821 }
2822 while (next && next != a1 && lim++ < 100) {
2823 ptr = next;
2824 next = loadRam32(ptr);
2825 use_cycles(8);
2826 }
2827 if (next == a1) {
2828 next = loadRam32(next);
2829 storeRam32(ptr, next);
2830 ret = ptr;
2831 use_cycles(6);
2832 }
2833 break;
2834 }
2835 if (lim == 100)
2836 PSXBIOS_LOG("bad chain %u %x\n", a0, base);
2837
2838 mips_return_c(ret, 12);
2839}
2840
2841static void psxBios_SysDeqIntRP() { // 03
2842 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x03], a0, a1);
2843 psxBios_SysDeqIntRP_();
2844}
2845
2846static void psxBios_SysInitMemory_(u32 base, u32 size) {
2847 storeRam32(base, 0);
2848 storeRam32(A_KMALLOC_PTR, base);
2849 storeRam32(A_KMALLOC_SIZE, size);
2850 storeRam32(A_KMALLOC_END, base + (size & ~3) + 4);
2851}
2852
2853// this should be much more complicated, but maybe that'll be enough
2854static u32 psxBios_SysMalloc_(u32 size) {
2855 u32 ptr = loadRam32(A_KMALLOC_PTR);
2856
2857 size = (size + 3) & ~3;
2858 storeRam32(A_KMALLOC_PTR, ptr + 4 + size);
2859 storeRam32(ptr, size);
2860 return ptr + 4;
2861}
2862
2863static void psxBios_SysInitMemory() { // 08
2864 PSXBIOS_LOG("psxBios_%s %x %x\n", biosC0n[0x08], a0, a1);
2865
2866 psxBios_SysInitMemory_(a0, a1);
2867 mips_return_void_c(12);
2868}
2869
2870static void psxBios_ChangeClearRCnt() { // 0a
2871 u32 ret;
2872
2873 PSXBIOS_LOG("psxBios_%s: %x, %x\n", biosC0n[0x0a], a0, a1);
2874
2875 ret = loadRam32(A_RCNT_VBL_ACK + (a0 << 2));
2876 storeRam32(A_RCNT_VBL_ACK + (a0 << 2), a1);
2877 mips_return_c(ret, 8);
2878}
2879
2880static void psxBios_InitDefInt() { // 0c
2881 PSXBIOS_LOG("psxBios_%s %x\n", biosC0n[0x0c], a0);
2882 // should also clear the autoack table
2883 a1 = 0x6d98;
2884 psxBios_SysEnqIntRP();
2885 mips_return_c(0, 20 + 6*2);
2886}
2887
2888void psxBios_dummy() {
2889 u32 pc = (pc0 & 0x1fffff) - 4;
2890 char **ntab = pc == 0xa0 ? biosA0n : pc == 0xb0 ? biosB0n
2891 : pc == 0xc0 ? biosC0n : NULL;
2892 PSXBIOS_LOG("unk %x call: %x ra=%x (%s)\n",
2893 pc, t1, ra, ntab ? ntab[t1 & 0xff] : "???");
2894 (void)pc; (void)ntab;
2895 mips_return_c(0, 100);
2896}
2897
2898void (*biosA0[256])();
2899// C0 and B0 overlap (end of C0 is start of B0)
2900void (*biosC0[256+128])();
2901void (**biosB0)() = biosC0 + 128;
2902
2903#include "sjisfont.h"
2904
2905void setup_mips_code()
2906{
2907 u32 *ptr;
2908 ptr = (u32 *)&psxM[A_SYSCALL];
2909 ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0
2910 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra
2911 ptr[0x08/4] = SWAPu32(0x00000000); // nop
2912
2913 ptr = (u32 *)&psxM[A_EXCEPTION];
2914 memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes)
2915 ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB
2916 ptr[0x14/4] = SWAPu32(0x00000000); // nop
2917 ptr[0x18/4] = SWAPu32(0x8f5a0000); // lw $k0, ($k0) // TCB
2918 ptr[0x1c/4] = SWAPu32(0x00000000); // nop
2919 ptr[0x20/4] = SWAPu32(0x275a0008); // addiu $k0, $k0, 8 // regs
2920 ptr[0x24/4] = SWAPu32(0xaf5f007c); // sw $ra, 0x7c($k0)
2921 ptr[0x28/4] = SWAPu32(0xaf410004); // sw $at, 0x04($k0)
2922 ptr[0x2c/4] = SWAPu32(0xaf420008); // sw $v0, 0x08($k0)
2923 ptr[0x30/4] = SWAPu32(0xaf43000c); // sw $v1, 0x0c($k0)
2924
2925 ptr[0x60/4] = SWAPu32(0x40037000); // mfc0 $v1, EPC
2926 ptr[0x64/4] = SWAPu32(0x40026800); // mfc0 $v0, Cause
2927 ptr[0x68/4] = SWAPu32(0x24630004); // addiu $v1, $v1, 4
2928 ptr[0x6c/4] = SWAPu32(0xaf430080); // sw $v1, 0x80($k0)
2929
2930 ptr[0xb0/4] = HLEOP(hleop_exception);
2931}
2932
2933static const struct {
2934 u32 addr;
2935 enum hle_op op;
2936} chainfns[] = {
2937 { 0xbfc050a4, hleop_exc0_0_1 },
2938 { 0xbfc04fbc, hleop_exc0_0_2 },
2939 { 0xbfc0506c, hleop_exc0_1_1 },
2940 { 0xbfc04dec, hleop_exc0_1_2 },
2941 { 0x1a00, hleop_exc0_2_2 },
2942 { 0x19c8, hleop_exc1_0_1 },
2943 { 0x18bc, hleop_exc1_0_2 },
2944 { 0x1990, hleop_exc1_1_1 },
2945 { 0x1858, hleop_exc1_1_2 },
2946 { 0x1958, hleop_exc1_2_1 },
2947 { 0x17f4, hleop_exc1_2_2 },
2948 { 0x1920, hleop_exc1_3_1 },
2949 { 0x1794, hleop_exc1_3_2 },
2950 { 0x2458, hleop_exc3_0_2 },
2951};
2952
2953static int chain_hle_op(u32 handler)
2954{
2955 size_t i;
2956
2957 for (i = 0; i < sizeof(chainfns) / sizeof(chainfns[0]); i++)
2958 if (chainfns[i].addr == handler)
2959 return chainfns[i].op;
2960 return hleop_dummy;
2961}
2962
2963static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2)
2964{
2965 d[0] = SWAPu32(next);
2966 d[1] = SWAPu32(handler1);
2967 d[2] = SWAPu32(handler2);
2968
2969 // install hle traps
2970 PSXMu32ref(handler1) = HLEOP(chain_hle_op(handler1));
2971 PSXMu32ref(handler2) = HLEOP(chain_hle_op(handler2));
2972}
2973
2974static void setup_tt(u32 tcb_cnt, u32 evcb_cnt)
2975{
2976 u32 *ram32 = (u32 *)psxM;
2977 u32 s_excb = 0x20, s_evcb = 0x1c * evcb_cnt;
2978 u32 s_pcb = 4, s_tcb = 0xc0 * tcb_cnt;
2979 u32 p_excb, p_evcb, p_pcb, p_tcb;
2980
2981 memset(ram32 + 0xe000/4, 0, s_excb + s_evcb + s_pcb + s_tcb + 5*4);
2982 psxBios_SysInitMemory_(0xa000e000, 0x2000);
2983 p_excb = psxBios_SysMalloc_(s_excb);
2984 p_evcb = psxBios_SysMalloc_(s_evcb);
2985 p_pcb = psxBios_SysMalloc_(s_pcb);
2986 p_tcb = psxBios_SysMalloc_(s_tcb);
2987
2988 // "table of tables". Some games modify it
2989 assert(A_TT_ExCB == 0x0100);
2990 ram32[0x0100/4] = SWAPu32(p_excb); // ExCB - exception chains
2991 ram32[0x0104/4] = SWAPu32(s_excb); // ExCB size
2992 ram32[0x0108/4] = SWAPu32(p_pcb); // PCB - process control
2993 ram32[0x010c/4] = SWAPu32(s_pcb); // PCB size
2994 ram32[0x0110/4] = SWAPu32(p_tcb); // TCB - thread control
2995 ram32[0x0114/4] = SWAPu32(s_tcb); // TCB size
2996 ram32[0x0120/4] = SWAPu32(p_evcb); // EvCB - event control
2997 ram32[0x0124/4] = SWAPu32(s_evcb); // EvCB size
2998 ram32[0x0140/4] = SWAPu32(0x8648); // FCB - file control
2999 ram32[0x0144/4] = SWAPu32(0x02c0); // FCB size
3000 ram32[0x0150/4] = SWAPu32(0x6ee0); // DCB - device control
3001 ram32[0x0154/4] = SWAPu32(0x0320); // DCB size
3002
3003 storeRam32(p_excb + 0*4, 0x91e0); // chain0
3004 storeRam32(p_excb + 2*4, 0x6d88); // chain1
3005 storeRam32(p_excb + 4*4, 0x0000); // chain2
3006 storeRam32(p_excb + 6*4, 0x6d98); // chain3
3007
3008 storeRam32(p_pcb, p_tcb);
3009 storeRam32(p_tcb, 0x4000); // first TCB
3010}
3011
3012void psxBiosInit() {
3013 u32 base, size;
3014 u32 *ptr, *ram32;
3015 int i;
3016 uLongf len;
3017
3018 memset(psxM, 0, 0x10000);
3019 for(i = 0; i < 256; i++) {
3020 biosA0[i] = NULL;
3021 biosB0[i] = NULL;
3022 biosC0[i] = NULL;
3023 }
3024 biosA0[0x03] = biosB0[0x35] = psxBios_write_psxout;
3025 biosA0[0x3c] = biosB0[0x3d] = psxBios_putchar_psxout;
3026 biosA0[0x3e] = biosB0[0x3f] = psxBios_puts_psxout;
3027 biosA0[0x3f] = psxBios_printf_psxout;
3028
3029 if (!Config.HLE) return;
3030
3031 for(i = 0; i < 256; i++) {
3032 if (biosA0[i] == NULL) biosA0[i] = psxBios_dummy;
3033 if (biosB0[i] == NULL) biosB0[i] = psxBios_dummy;
3034 if (biosC0[i] == NULL) biosC0[i] = psxBios_dummy;
3035 }
3036
3037 biosA0[0x00] = psxBios_open;
3038 biosA0[0x01] = psxBios_lseek;
3039 biosA0[0x02] = psxBios_read;
3040 biosA0[0x03] = psxBios_write;
3041 biosA0[0x04] = psxBios_close;
3042 //biosA0[0x05] = psxBios_ioctl;
3043 //biosA0[0x06] = psxBios_exit;
3044 //biosA0[0x07] = psxBios_sys_a0_07;
3045 biosA0[0x08] = psxBios_getc;
3046 biosA0[0x09] = psxBios_putc;
3047 biosA0[0x0a] = psxBios_todigit;
3048 //biosA0[0x0b] = psxBios_atof;
3049 //biosA0[0x0c] = psxBios_strtoul;
3050 //biosA0[0x0d] = psxBios_strtol;
3051 biosA0[0x0e] = psxBios_abs;
3052 biosA0[0x0f] = psxBios_labs;
3053 biosA0[0x10] = psxBios_atoi;
3054 biosA0[0x11] = psxBios_atol;
3055 //biosA0[0x12] = psxBios_atob;
3056 biosA0[0x13] = psxBios_setjmp;
3057 biosA0[0x14] = psxBios_longjmp;
3058 biosA0[0x15] = psxBios_strcat;
3059 biosA0[0x16] = psxBios_strncat;
3060 biosA0[0x17] = psxBios_strcmp;
3061 biosA0[0x18] = psxBios_strncmp;
3062 biosA0[0x19] = psxBios_strcpy;
3063 biosA0[0x1a] = psxBios_strncpy;
3064 biosA0[0x1b] = psxBios_strlen;
3065 biosA0[0x1c] = psxBios_index;
3066 biosA0[0x1d] = psxBios_rindex;
3067 biosA0[0x1e] = psxBios_strchr;
3068 biosA0[0x1f] = psxBios_strrchr;
3069 biosA0[0x20] = psxBios_strpbrk;
3070 biosA0[0x21] = psxBios_strspn;
3071 biosA0[0x22] = psxBios_strcspn;
3072 biosA0[0x23] = psxBios_strtok;
3073 biosA0[0x24] = psxBios_strstr;
3074 biosA0[0x25] = psxBios_toupper;
3075 biosA0[0x26] = psxBios_tolower;
3076 biosA0[0x27] = psxBios_bcopy;
3077 biosA0[0x28] = psxBios_bzero;
3078 biosA0[0x29] = psxBios_bcmp;
3079 biosA0[0x2a] = psxBios_memcpy;
3080 biosA0[0x2b] = psxBios_memset;
3081 biosA0[0x2c] = psxBios_memmove;
3082 biosA0[0x2d] = psxBios_memcmp;
3083 biosA0[0x2e] = psxBios_memchr;
3084 biosA0[0x2f] = psxBios_rand;
3085 biosA0[0x30] = psxBios_srand;
3086 biosA0[0x31] = psxBios_qsort;
3087 //biosA0[0x32] = psxBios_strtod;
3088 biosA0[0x33] = psxBios_malloc;
3089 biosA0[0x34] = psxBios_free;
3090 //biosA0[0x35] = psxBios_lsearch;
3091 //biosA0[0x36] = psxBios_bsearch;
3092 biosA0[0x37] = psxBios_calloc;
3093 biosA0[0x38] = psxBios_realloc;
3094 biosA0[0x39] = psxBios_InitHeap;
3095 //biosA0[0x3a] = psxBios__exit;
3096 biosA0[0x3b] = psxBios_getchar;
3097 biosA0[0x3c] = psxBios_putchar;
3098 //biosA0[0x3d] = psxBios_gets;
3099 biosA0[0x40] = psxBios_SystemErrorUnresolvedException;
3100 //biosA0[0x41] = psxBios_LoadTest;
3101 biosA0[0x42] = psxBios_Load;
3102 biosA0[0x43] = psxBios_Exec;
3103 biosA0[0x44] = psxBios_FlushCache;
3104 //biosA0[0x45] = psxBios_InstallInterruptHandler;
3105 biosA0[0x46] = psxBios_GPU_dw;
3106 biosA0[0x47] = psxBios_mem2vram;
3107 biosA0[0x48] = psxBios_SendGPU;
3108 biosA0[0x49] = psxBios_GPU_cw;
3109 biosA0[0x4a] = psxBios_GPU_cwb;
3110 biosA0[0x4b] = psxBios_GPU_SendPackets;
3111 biosA0[0x4c] = psxBios_sys_a0_4c;
3112 biosA0[0x4d] = psxBios_GPU_GetGPUStatus;
3113 //biosA0[0x4e] = psxBios_GPU_sync;
3114 //biosA0[0x4f] = psxBios_sys_a0_4f;
3115 //biosA0[0x50] = psxBios_sys_a0_50;
3116 biosA0[0x51] = psxBios_LoadExec;
3117 //biosA0[0x52] = psxBios_GetSysSp;
3118 //biosA0[0x53] = psxBios_sys_a0_53;
3119 //biosA0[0x54] = psxBios__96_init_a54;
3120 //biosA0[0x55] = psxBios__bu_init_a55;
3121 biosA0[0x56] = psxBios_CdRemove;
3122 //biosA0[0x57] = psxBios_sys_a0_57;
3123 //biosA0[0x58] = psxBios_sys_a0_58;
3124 //biosA0[0x59] = psxBios_sys_a0_59;
3125 //biosA0[0x5a] = psxBios_sys_a0_5a;
3126 //biosA0[0x5b] = psxBios_dev_tty_init;
3127 //biosA0[0x5c] = psxBios_dev_tty_open;
3128 //biosA0[0x5d] = psxBios_sys_a0_5d;
3129 //biosA0[0x5e] = psxBios_dev_tty_ioctl;
3130 //biosA0[0x5f] = psxBios_dev_cd_open;
3131 //biosA0[0x60] = psxBios_dev_cd_read;
3132 //biosA0[0x61] = psxBios_dev_cd_close;
3133 //biosA0[0x62] = psxBios_dev_cd_firstfile;
3134 //biosA0[0x63] = psxBios_dev_cd_nextfile;
3135 //biosA0[0x64] = psxBios_dev_cd_chdir;
3136 //biosA0[0x65] = psxBios_dev_card_open;
3137 //biosA0[0x66] = psxBios_dev_card_read;
3138 //biosA0[0x67] = psxBios_dev_card_write;
3139 //biosA0[0x68] = psxBios_dev_card_close;
3140 //biosA0[0x69] = psxBios_dev_card_firstfile;
3141 //biosA0[0x6a] = psxBios_dev_card_nextfile;
3142 //biosA0[0x6b] = psxBios_dev_card_erase;
3143 //biosA0[0x6c] = psxBios_dev_card_undelete;
3144 //biosA0[0x6d] = psxBios_dev_card_format;
3145 //biosA0[0x6e] = psxBios_dev_card_rename;
3146 //biosA0[0x6f] = psxBios_dev_card_6f;
3147 biosA0[0x70] = psxBios__bu_init;
3148 biosA0[0x71] = psxBios__96_init;
3149 biosA0[0x72] = psxBios_CdRemove;
3150 //biosA0[0x73] = psxBios_sys_a0_73;
3151 //biosA0[0x74] = psxBios_sys_a0_74;
3152 //biosA0[0x75] = psxBios_sys_a0_75;
3153 //biosA0[0x76] = psxBios_sys_a0_76;
3154 //biosA0[0x77] = psxBios_sys_a0_77;
3155 //biosA0[0x78] = psxBios__96_CdSeekL;
3156 //biosA0[0x79] = psxBios_sys_a0_79;
3157 //biosA0[0x7a] = psxBios_sys_a0_7a;
3158 //biosA0[0x7b] = psxBios_sys_a0_7b;
3159 //biosA0[0x7c] = psxBios__96_CdGetStatus;
3160 //biosA0[0x7d] = psxBios_sys_a0_7d;
3161 //biosA0[0x7e] = psxBios__96_CdRead;
3162 //biosA0[0x7f] = psxBios_sys_a0_7f;
3163 //biosA0[0x80] = psxBios_sys_a0_80;
3164 //biosA0[0x81] = psxBios_sys_a0_81;
3165 //biosA0[0x82] = psxBios_sys_a0_82;
3166 //biosA0[0x83] = psxBios_sys_a0_83;
3167 //biosA0[0x84] = psxBios_sys_a0_84;
3168 //biosA0[0x85] = psxBios__96_CdStop;
3169 //biosA0[0x86] = psxBios_sys_a0_86;
3170 //biosA0[0x87] = psxBios_sys_a0_87;
3171 //biosA0[0x88] = psxBios_sys_a0_88;
3172 //biosA0[0x89] = psxBios_sys_a0_89;
3173 //biosA0[0x8a] = psxBios_sys_a0_8a;
3174 //biosA0[0x8b] = psxBios_sys_a0_8b;
3175 //biosA0[0x8c] = psxBios_sys_a0_8c;
3176 //biosA0[0x8d] = psxBios_sys_a0_8d;
3177 //biosA0[0x8e] = psxBios_sys_a0_8e;
3178 //biosA0[0x8f] = psxBios_sys_a0_8f;
3179 biosA0[0x90] = hleExc0_1_2;
3180 biosA0[0x91] = hleExc0_0_2;
3181 biosA0[0x92] = hleExc0_1_1;
3182 biosA0[0x93] = hleExc0_0_1;
3183 //biosA0[0x94] = psxBios_sys_a0_94;
3184 //biosA0[0x95] = psxBios_sys_a0_95;
3185 //biosA0[0x96] = psxBios_AddCDROMDevice;
3186 //biosA0[0x97] = psxBios_AddMemCardDevide;
3187 //biosA0[0x98] = psxBios_DisableKernelIORedirection;
3188 //biosA0[0x99] = psxBios_EnableKernelIORedirection;
3189 //biosA0[0x9a] = psxBios_sys_a0_9a;
3190 //biosA0[0x9b] = psxBios_sys_a0_9b;
3191 //biosA0[0x9c] = psxBios_SetConf;
3192 //biosA0[0x9d] = psxBios_GetConf;
3193 //biosA0[0x9e] = psxBios_sys_a0_9e;
3194 biosA0[0x9f] = psxBios_SetMem;
3195 //biosA0[0xa0] = psxBios__boot;
3196 //biosA0[0xa1] = psxBios_SystemError;
3197 //biosA0[0xa2] = psxBios_EnqueueCdIntr;
3198 biosA0[0xa3] = psxBios_DequeueCdIntr;
3199 //biosA0[0xa4] = psxBios_sys_a0_a4;
3200 //biosA0[0xa5] = psxBios_ReadSector;
3201 biosA0[0xa6] = psxBios_get_cd_status;
3202 //biosA0[0xa7] = psxBios_bufs_cb_0;
3203 //biosA0[0xa8] = psxBios_bufs_cb_1;
3204 //biosA0[0xa9] = psxBios_bufs_cb_2;
3205 //biosA0[0xaa] = psxBios_bufs_cb_3;
3206 biosA0[0xab] = psxBios__card_info;
3207 biosA0[0xac] = psxBios__card_load;
3208 //biosA0[0axd] = psxBios__card_auto;
3209 //biosA0[0xae] = psxBios_bufs_cd_4;
3210 //biosA0[0xaf] = psxBios_sys_a0_af;
3211 //biosA0[0xb0] = psxBios_sys_a0_b0;
3212 //biosA0[0xb1] = psxBios_sys_a0_b1;
3213 //biosA0[0xb2] = psxBios_do_a_long_jmp
3214 //biosA0[0xb3] = psxBios_sys_a0_b3;
3215 //biosA0[0xb4] = psxBios_sub_function;
3216//*******************B0 CALLS****************************
3217 biosB0[0x00] = psxBios_SysMalloc;
3218 //biosB0[0x01] = psxBios_sys_b0_01;
3219 biosB0[0x02] = psxBios_SetRCnt;
3220 biosB0[0x03] = psxBios_GetRCnt;
3221 biosB0[0x04] = psxBios_StartRCnt;
3222 biosB0[0x05] = psxBios_StopRCnt;
3223 biosB0[0x06] = psxBios_ResetRCnt;
3224 biosB0[0x07] = psxBios_DeliverEvent;
3225 biosB0[0x08] = psxBios_OpenEvent;
3226 biosB0[0x09] = psxBios_CloseEvent;
3227 biosB0[0x0a] = psxBios_WaitEvent;
3228 biosB0[0x0b] = psxBios_TestEvent;
3229 biosB0[0x0c] = psxBios_EnableEvent;
3230 biosB0[0x0d] = psxBios_DisableEvent;
3231 biosB0[0x0e] = psxBios_OpenTh;
3232 biosB0[0x0f] = psxBios_CloseTh;
3233 biosB0[0x10] = psxBios_ChangeTh;
3234 //biosB0[0x11] = psxBios_psxBios_b0_11;
3235 biosB0[0x12] = psxBios_InitPAD;
3236 biosB0[0x13] = psxBios_StartPAD;
3237 biosB0[0x14] = psxBios_StopPAD;
3238 biosB0[0x15] = psxBios_PAD_init;
3239 biosB0[0x16] = psxBios_PAD_dr;
3240 biosB0[0x17] = psxBios_ReturnFromException;
3241 biosB0[0x18] = psxBios_ResetEntryInt;
3242 biosB0[0x19] = psxBios_HookEntryInt;
3243 //biosB0[0x1a] = psxBios_sys_b0_1a;
3244 //biosB0[0x1b] = psxBios_sys_b0_1b;
3245 //biosB0[0x1c] = psxBios_sys_b0_1c;
3246 //biosB0[0x1d] = psxBios_sys_b0_1d;
3247 //biosB0[0x1e] = psxBios_sys_b0_1e;
3248 //biosB0[0x1f] = psxBios_sys_b0_1f;
3249 biosB0[0x20] = psxBios_UnDeliverEvent;
3250 //biosB0[0x21] = psxBios_sys_b0_21;
3251 //biosB0[0x22] = psxBios_sys_b0_22;
3252 //biosB0[0x23] = psxBios_sys_b0_23;
3253 //biosB0[0x24] = psxBios_sys_b0_24;
3254 //biosB0[0x25] = psxBios_sys_b0_25;
3255 //biosB0[0x26] = psxBios_sys_b0_26;
3256 //biosB0[0x27] = psxBios_sys_b0_27;
3257 //biosB0[0x28] = psxBios_sys_b0_28;
3258 //biosB0[0x29] = psxBios_sys_b0_29;
3259 //biosB0[0x2a] = psxBios_sys_b0_2a;
3260 //biosB0[0x2b] = psxBios_sys_b0_2b;
3261 //biosB0[0x2c] = psxBios_sys_b0_2c;
3262 //biosB0[0x2d] = psxBios_sys_b0_2d;
3263 //biosB0[0x2e] = psxBios_sys_b0_2e;
3264 //biosB0[0x2f] = psxBios_sys_b0_2f;
3265 //biosB0[0x30] = psxBios_sys_b0_30;
3266 //biosB0[0x31] = psxBios_sys_b0_31;
3267 biosB0[0x32] = psxBios_open;
3268 biosB0[0x33] = psxBios_lseek;
3269 biosB0[0x34] = psxBios_read;
3270 biosB0[0x35] = psxBios_write;
3271 biosB0[0x36] = psxBios_close;
3272 //biosB0[0x37] = psxBios_ioctl;
3273 //biosB0[0x38] = psxBios_exit;
3274 //biosB0[0x39] = psxBios_sys_b0_39;
3275 //biosB0[0x3a] = psxBios_getc;
3276 //biosB0[0x3b] = psxBios_putc;
3277 biosB0[0x3c] = psxBios_getchar;
3278 //biosB0[0x3e] = psxBios_gets;
3279 //biosB0[0x40] = psxBios_cd;
3280 biosB0[0x41] = psxBios_format;
3281 biosB0[0x42] = psxBios_firstfile;
3282 biosB0[0x43] = psxBios_nextfile;
3283 biosB0[0x44] = psxBios_rename;
3284 biosB0[0x45] = psxBios_delete;
3285 //biosB0[0x46] = psxBios_undelete;
3286 //biosB0[0x47] = psxBios_AddDevice;
3287 //biosB0[0x48] = psxBios_RemoteDevice;
3288 //biosB0[0x49] = psxBios_PrintInstalledDevices;
3289 biosB0[0x4a] = psxBios_InitCARD;
3290 biosB0[0x4b] = psxBios_StartCARD;
3291 biosB0[0x4c] = psxBios_StopCARD;
3292 //biosB0[0x4d] = psxBios_sys_b0_4d;
3293 biosB0[0x4e] = psxBios__card_write;
3294 biosB0[0x4f] = psxBios__card_read;
3295 biosB0[0x50] = psxBios__new_card;
3296 biosB0[0x51] = psxBios_Krom2RawAdd;
3297 //biosB0[0x52] = psxBios_sys_b0_52;
3298 //biosB0[0x53] = psxBios_sys_b0_53;
3299 //biosB0[0x54] = psxBios__get_errno;
3300 biosB0[0x55] = psxBios__get_error;
3301 biosB0[0x56] = psxBios_GetC0Table;
3302 biosB0[0x57] = psxBios_GetB0Table;
3303 biosB0[0x58] = psxBios__card_chan;
3304 //biosB0[0x59] = psxBios_sys_b0_59;
3305 //biosB0[0x5a] = psxBios_sys_b0_5a;
3306 biosB0[0x5b] = psxBios_ChangeClearPad;
3307 biosB0[0x5c] = psxBios__card_status;
3308 biosB0[0x5d] = psxBios__card_wait;
3309//*******************C0 CALLS****************************
3310 biosC0[0x00] = psxBios_InitRCnt;
3311 biosC0[0x01] = psxBios_InitException;
3312 biosC0[0x02] = psxBios_SysEnqIntRP;
3313 biosC0[0x03] = psxBios_SysDeqIntRP;
3314 //biosC0[0x04] = psxBios_get_free_EvCB_slot;
3315 //biosC0[0x05] = psxBios_get_free_TCB_slot;
3316 //biosC0[0x06] = psxBios_ExceptionHandler;
3317 //biosC0[0x07] = psxBios_InstallExeptionHandler;
3318 biosC0[0x08] = psxBios_SysInitMemory;
3319 //biosC0[0x09] = psxBios_SysInitKMem;
3320 biosC0[0x0a] = psxBios_ChangeClearRCnt;
3321 //biosC0[0x0b] = psxBios_SystemError;
3322 biosC0[0x0c] = psxBios_InitDefInt;
3323 //biosC0[0x0d] = psxBios_sys_c0_0d;
3324 //biosC0[0x0e] = psxBios_sys_c0_0e;
3325 //biosC0[0x0f] = psxBios_sys_c0_0f;
3326 //biosC0[0x10] = psxBios_sys_c0_10;
3327 //biosC0[0x11] = psxBios_sys_c0_11;
3328 //biosC0[0x12] = psxBios_InstallDevices;
3329 //biosC0[0x13] = psxBios_FlushStfInOutPut;
3330 //biosC0[0x14] = psxBios_sys_c0_14;
3331 //biosC0[0x15] = psxBios__cdevinput;
3332 //biosC0[0x16] = psxBios__cdevscan;
3333 //biosC0[0x17] = psxBios__circgetc;
3334 //biosC0[0x18] = psxBios__circputc;
3335 //biosC0[0x19] = psxBios_ioabort;
3336 //biosC0[0x1a] = psxBios_sys_c0_1a
3337 //biosC0[0x1b] = psxBios_KernelRedirect;
3338 //biosC0[0x1c] = psxBios_PatchAOTable;
3339//************** THE END ***************************************
3340/**/
3341 base = 0x1000;
3342 size = sizeof(EvCB) * 32;
3343 EventCB = (void *)&psxR[base]; base += size * 6;
3344 memset(EventCB, 0, size * 6);
3345 HwEV = EventCB;
3346 EvEV = EventCB + 32;
3347 RcEV = EventCB + 32 * 2;
3348 UeEV = EventCB + 32 * 3;
3349 SwEV = EventCB + 32 * 4;
3350 ThEV = EventCB + 32 * 5;
3351
3352 pad_stopped = 1;
3353 pad_buf = NULL;
3354 pad_buf1 = NULL;
3355 pad_buf2 = NULL;
3356 pad_buf1len = pad_buf2len = 0;
3357 heap_addr = NULL;
3358 heap_end = NULL;
3359 heap_size = 0;
3360 CardState = -1;
3361 CurThread = 0;
3362 memset(FDesc, 0, sizeof(FDesc));
3363 card_active_chan = 0;
3364
3365 // initial RNG seed
3366 psxMu32ref(0x9010) = SWAPu32(0xac20cc00);
3367
3368 // fonts
3369 len = 0x80000 - 0x66000;
3370 uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140));
3371 len = 0x80000 - 0x69d68;
3372 uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f));
3373
3374 // memory size 2 MB
3375 psxHu32ref(0x1060) = SWAPu32(0x00000b88);
3376
3377 /* Some games like R-Types, CTR, Fade to Black read from adress 0x00000000 due to uninitialized pointers.
3378 See Garbage Area at Address 00000000h in Nocash PSX Specfications for more information.
3379 Here are some examples of games not working with this fix in place :
3380 R-type won't get past the Irem logo if not implemented.
3381 Crash Team Racing will softlock after the Sony logo.
3382 */
3383
3384 ram32 = (u32 *)psxM;
3385 ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3)
3386 ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3387 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0
3388 ram32[0x000c/4] = SWAPu32(0x00000000); // nop
3389
3390 ram32[0x0060/4] = SWAPu32(0x00000002); // ram size?
3391 ram32[0x0068/4] = SWAPu32(0x000000ff); // unknown
3392
3393 ram32[0x0080/4] = SWAPu32(0x3c1a0000); // lui $k0, 0 // exception vector
3394 ram32[0x0084/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80
3395 ram32[0x0088/4] = SWAPu32(0x03400008); // jr $k0
3396 ram32[0x008c/4] = SWAPu32(0x00000000); // nop
3397
3398 ram32[0x00a0/4] = HLEOP(hleop_a0);
3399 ram32[0x00b0/4] = HLEOP(hleop_b0);
3400 ram32[0x00c0/4] = HLEOP(hleop_c0);
3401
3402 setup_tt(4, 16);
3403
3404 ram32[0x6ee0/4] = SWAPu32(0x0000eff0); // DCB
3405 strcpy((char *)&ram32[0xeff0/4], "bu");
3406
3407 // default exception handler chains
3408 write_chain(&ram32[0x91e0/4], 0x91d0, 0xbfc050a4, 0xbfc04fbc); // chain0.e0
3409 write_chain(&ram32[0x91d0/4], 0x6da8, 0xbfc0506c, 0xbfc04dec); // chain0.e1
3410 write_chain(&ram32[0x6da8/4], 0, 0, 0x1a00); // chain0.e2
3411 write_chain(&ram32[0x6d88/4], 0x6d78, 0x19c8, 0x18bc); // chain1.e0
3412 write_chain(&ram32[0x6d78/4], 0x6d68, 0x1990, 0x1858); // chain1.e1
3413 write_chain(&ram32[0x6d68/4], 0x6d58, 0x1958, 0x17f4); // chain1.e2
3414 write_chain(&ram32[0x6d58/4], 0, 0x1920, 0x1794); // chain1.e3
3415 write_chain(&ram32[0x6d98/4], 0, 0, 0x2458); // chain3.e0
3416
3417 setup_mips_code();
3418
3419 // fill the api jumptables with fake entries as some games patch them
3420 // (or rather the funcs listed there)
3421 ptr = (u32 *)&psxM[A_A0_TABLE];
3422 for (i = 0; i < 256; i++)
3423 ptr[i] = SWAP32(0x1000);
3424
3425 ptr = (u32 *)&psxM[A_B0_TABLE];
3426 for (i = 0; i < 256; i++)
3427 ptr[i] = SWAP32(0x2000);
3428 // B(5b) is special because games patch (sometimes even jump to)
3429 // code at fixed offsets from it, nocash lists offsets:
3430 // patch: +3d8, +4dc, +594, +62c, +9c8, +1988
3431 // call: +7a0=4b70, +884=4c54, +894=4c64
3432 ptr[0x5b] = SWAP32(0x43d0);
3433 ram32[0x4b70/4] = SWAP32(0x03e00008); // jr $ra
3434 ram32[0x4c54/4] = SWAP32(0x03e00008); // jr $ra
3435 ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra
3436
3437 ptr = (u32 *)&psxM[A_C0_TABLE];
3438 for (i = 0; i < 256/2; i++)
3439 ptr[i] = SWAP32(0x3000);
3440 ptr[6] = SWAP32(A_EXCEPTION);
3441
3442 // more HLE traps
3443 ram32[0x1000/4] = HLEOP(hleop_dummy);
3444 ram32[0x2000/4] = HLEOP(hleop_dummy);
3445 ram32[0x3000/4] = HLEOP(hleop_dummy);
3446 ram32[0x4c54/4] = HLEOP(hleop_dummy); // for B12_InitPad?
3447 ram32[0x8000/4] = HLEOP(hleop_execret);
3448
3449 ram32[A_EEXIT_PTR/4] = SWAP32(A_EEXIT_DEF);
3450 ram32[A_EXC_SP/4] = SWAP32(A_EXC_STACK);
3451 ram32[A_RCNT_VBL_ACK/4 + 0] = SWAP32(1);
3452 ram32[A_RCNT_VBL_ACK/4 + 1] = SWAP32(1);
3453 ram32[A_RCNT_VBL_ACK/4 + 2] = SWAP32(1);
3454 ram32[A_RCNT_VBL_ACK/4 + 3] = SWAP32(1);
3455}
3456
3457void psxBiosShutdown() {
3458}
3459
3460void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt) {
3461 if (tcb_cnt != 4 || evcb_cnt != 16)
3462 setup_tt(tcb_cnt, evcb_cnt);
3463}
3464
3465#define psxBios_PADpoll(pad) { \
3466 PAD##pad##_startPoll(pad); \
3467 pad_buf##pad[0] = 0; \
3468 pad_buf##pad[1] = PAD##pad##_poll(0x42); \
3469 if (!(pad_buf##pad[1] & 0x0f)) { \
3470 bufcount = 32; \
3471 } else { \
3472 bufcount = (pad_buf##pad[1] & 0x0f) * 2; \
3473 } \
3474 PAD##pad##_poll(0); \
3475 i = 2; \
3476 while (bufcount--) { \
3477 pad_buf##pad[i++] = PAD##pad##_poll(0); \
3478 } \
3479}
3480
3481static void biosPadHLE() {
3482 int i, bufcount;
3483
3484 if (pad_buf != NULL) {
3485 u32 *buf = (u32*)pad_buf;
3486
3487 PAD1_startPoll(1);
3488 if (PAD1_poll(0x42) == 0x23) {
3489 PAD1_poll(0);
3490 *buf = PAD1_poll(0) << 8;
3491 *buf |= PAD1_poll(0);
3492 PAD1_poll(0);
3493 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 6 : 0);
3494 *buf &= ~((PAD1_poll(0) > 0x20) ? 1 << 7 : 0);
3495 } else {
3496 PAD1_poll(0);
3497 *buf = PAD1_poll(0) << 8;
3498 *buf|= PAD1_poll(0);
3499 }
3500
3501 PAD2_startPoll(2);
3502 if (PAD2_poll(0x42) == 0x23) {
3503 PAD2_poll(0);
3504 *buf |= PAD2_poll(0) << 24;
3505 *buf |= PAD2_poll(0) << 16;
3506 PAD2_poll(0);
3507 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 22 : 0);
3508 *buf &= ~((PAD2_poll(0) > 0x20) ? 1 << 23 : 0);
3509 } else {
3510 PAD2_poll(0);
3511 *buf |= PAD2_poll(0) << 24;
3512 *buf |= PAD2_poll(0) << 16;
3513 }
3514 }
3515 if (!pad_stopped) {
3516 if (pad_buf1) {
3517 psxBios_PADpoll(1);
3518 }
3519
3520 if (pad_buf2) {
3521 psxBios_PADpoll(2);
3522 }
3523 }
3524}
3525
3526static void handle_chain_x_x_1(u32 enable, u32 irqbit)
3527{
3528 use_cycles(10);
3529 if (enable) {
3530 psxHwWrite16(0x1f801070, ~(1u << irqbit));
3531 psxBios_ReturnFromException();
3532 }
3533 else
3534 pc0 = ra;
3535}
3536
3537// hleExc0_{0,1}* are usually removed by A(56)/A(72) on the game's startup,
3538// so this is only partially implemented
3539void hleExc0_0_1() // A(93h) - CdromDmaIrqFunc2
3540{
3541 u32 cdrom_dma_ack_enable = 1; // a000b93c
3542 handle_chain_x_x_1(cdrom_dma_ack_enable, 3); // IRQ3 DMA
3543}
3544
3545void hleExc0_0_2() // A(91h) - CdromDmaIrqFunc1
3546{
3547 u32 ret = 0;
3548 //PSXBIOS_LOG("%s\n", __func__);
3549
3550 if (psxHu32(0x1074) & psxHu32(0x1070) & 8) { // IRQ3 DMA
3551 psxHwWrite32(0x1f8010f4, (psxHu32(0x10f4) & 0xffffff) | 0x88000000);
3552 //if (--cdrom_irq_counter == 0) // 0xa0009180
3553 // DeliverEvent(); // 0xf0000003, 0x10
3554 use_cycles(22);
3555 ret = 1;
3556 }
3557 mips_return_c(ret, 20);
3558}
3559
3560void hleExc0_1_1() // A(92h) - CdromIoIrqFunc2
3561{
3562 u32 cdrom_irq_ack_enable = 1; // a000b938
3563 handle_chain_x_x_1(cdrom_irq_ack_enable, 2); // IRQ2 cdrom
3564}
3565
3566void hleExc0_1_2() // A(90h) - CdromIoIrqFunc1
3567{
3568 u32 ret = 0;
3569 if (psxHu32(0x1074) & psxHu32(0x1070) & 4) { // IRQ2 cdrom
3570 PSXBIOS_LOG("%s TODO\n", __func__);
3571 ret = 1;
3572 }
3573 mips_return_c(ret, 20);
3574}
3575
3576void hleExc0_2_2_syscall() // not in any A/B/C table
3577{
3578 u32 code = (psxRegs.CP0.n.Cause & 0x3c) >> 2;
3579 u32 tcbPtr = loadRam32(A_TT_PCB);
3580 TCB *tcb = loadRam32ptr(tcbPtr);
3581
3582 if (code != R3000E_Syscall) {
3583 if (code != 0) {
3584 // DeliverEvent(); // 0xf0000010, 0x1000
3585 psxBios_SystemErrorUnresolvedException();
3586 }
3587 mips_return_c(0, 17);
3588 return;
3589 }
3590
3591 //printf("%s c=%d a0=%d\n", __func__, code, a0);
3592 tcb->epc += SWAP32(4);
3593 switch (a0) {
3594 case 0: // noop
3595 break;
3596
3597 case 1: { // EnterCritical - disable irqs
3598 u32 was_enabled = ((SWAP32(tcb->sr) & 0x404) == 0x404);
3599 tcb->reg[2] = SWAP32(was_enabled);
3600 tcb->sr &= SWAP32(~0x404);
3601 break;
3602 }
3603 case 2: // ExitCritical - enable irqs
3604 tcb->sr |= SWAP32(0x404);
3605 break;
3606
3607 case 3: { // ChangeThreadSubFunction
3608 u32 tcbPtr = loadRam32(A_TT_PCB);
3609 storeRam32(tcbPtr, a1);
3610 break;
3611 }
3612 default:
3613 // DeliverEvent(); // 0xf0000010, 0x4000
3614 break;
3615 }
3616 use_cycles(30);
3617 psxBios_ReturnFromException();
3618}
3619
3620void hleExc1_0_1(void)
3621{
3622 u32 vbl_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x0c); // 860c
3623 handle_chain_x_x_1(vbl_irq_ack_enable, 0); // IRQ0 vblank
3624}
3625
3626static void handle_chain_1_x_2(u32 ev_index, u32 irqbit)
3627{
3628 u32 ret = 0;
3629 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << irqbit)) {
3630 // DeliverEvent 0xf2000000 + ev_index, 2
3631 if (RcEV[ev_index][1].status == EvStACTIVE) {
3632 softCall(RcEV[ev_index][1].fhandler);
3633 }
3634 ret = 1;
3635 }
3636 mips_return_c(ret, 22);
3637}
3638
3639void hleExc1_0_2(void)
3640{
3641 handle_chain_1_x_2(3, 0); // IRQ0 vblank
3642}
3643
3644void hleExc1_1_1(void)
3645{
3646 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x08); // 8608
3647 handle_chain_x_x_1(rcnt_irq_ack_enable, 6); // IRQ6 rcnt2
3648}
3649
3650void hleExc1_1_2(void)
3651{
3652 handle_chain_1_x_2(2, 6); // IRQ6 rcnt2
3653}
3654
3655void hleExc1_2_1(void)
3656{
3657 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x04); // 8604
3658 handle_chain_x_x_1(rcnt_irq_ack_enable, 5); // IRQ5 rcnt1
3659}
3660
3661void hleExc1_2_2(void)
3662{
3663 handle_chain_1_x_2(1, 5); // IRQ5 rcnt1
3664}
3665
3666void hleExc1_3_1(void)
3667{
3668 u32 rcnt_irq_ack_enable = loadRam32(A_RCNT_VBL_ACK + 0x00); // 8600
3669 handle_chain_x_x_1(rcnt_irq_ack_enable, 4); // IRQ4 rcnt0
3670}
3671
3672void hleExc1_3_2(void)
3673{
3674 handle_chain_1_x_2(0, 4); // IRQ4 rcnt0
3675}
3676
3677void hleExc3_0_2_defint(void)
3678{
3679 static const struct {
3680 u8 ev, irqbit;
3681 } tab[] = {
3682 { 3, 2 }, // cdrom
3683 { 9, 9 }, // spu
3684 { 2, 1 }, // gpu
3685 { 10, 10 }, // io
3686 { 11, 8 }, // sio
3687 { 1, 0 }, // vbl
3688 { 5, 4 }, // rcnt0
3689 { 6, 5 }, // rcnt1
3690 { 6, 6 }, // rcnt2 (bug)
3691 { 8, 7 }, // sio rx
3692 { 4, 3 }, // sio
3693 };
3694 size_t i;
3695 for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
3696 if (psxHu32(0x1074) & psxHu32(0x1070) & (1u << tab[i].irqbit)) {
3697 // DeliverEvent 0xf0000000 + ev, 0x1000
3698 use_cycles(7);
3699 }
3700
3701 }
3702 mips_return_c(0, 11 + 7*11 + 7*11 + 12);
3703}
3704
3705void psxBiosException() {
3706 u32 tcbPtr = loadRam32(A_TT_PCB);
3707 u32 *chains = loadRam32ptr(A_TT_ExCB);
3708 TCB *tcb = loadRam32ptr(tcbPtr);
3709 u32 ptr, *chain;
3710 int c, lim;
3711 int i;
3712
3713 // save the regs
3714 // $at, $v0, $v1 already saved by the mips code at A_EXCEPTION
3715 for (i = 4; i < 32; i++) {
3716 if (i == 26) // $k0
3717 continue;
3718 tcb->reg[i] = SWAP32(psxRegs.GPR.r[i]);
3719 }
3720 tcb->lo = SWAP32(psxRegs.GPR.n.lo);
3721 tcb->hi = SWAP32(psxRegs.GPR.n.hi);
3722 tcb->epc = SWAP32(psxRegs.CP0.n.EPC);
3723 tcb->sr = SWAP32(psxRegs.CP0.n.SR);
3724 tcb->cause = SWAP32(psxRegs.CP0.n.Cause);
3725 sp = fp = loadRam32(A_EXC_SP);
3726 gp = A_EXC_GP;
3727 use_cycles(46);
3728
3729 // do the chains (always 4)
3730 for (c = lim = 0; c < 4; c++) {
3731 if (chains[c * 2] == 0)
3732 continue;
3733 ptr = SWAP32(chains[c * 2]);
3734 for (; ptr && lim < 100; ptr = SWAP32(chain[0])) {
3735 chain = castRam32ptr(ptr);
3736 use_cycles(14);
3737 lim++;
3738 if (chain[2] == 0)
3739 continue;
3740 softCallInException(SWAP32(chain[2]));
3741 if (returned_from_exception())
3742 return;
3743
3744 if (v0 == 0 || chain[1] == 0)
3745 continue;
3746 softCallInException(SWAP32(chain[1]));
3747 if (returned_from_exception())
3748 return;
3749 }
3750 }
3751 assert(lim < 100);
3752
3753 // TODO make this a chain entry
3754 if (psxHu32(0x1070) & 1)
3755 biosPadHLE();
3756
3757 // return from exception (custom or default)
3758 use_cycles(23);
3759 ptr = loadRam32(A_EEXIT_PTR);
3760 if (ptr != A_EEXIT_DEF) {
3761 const struct jmp_buf_ *jmp_buf = castRam32ptr(ptr);
3762 longjmp_load(jmp_buf);
3763 v0 = 1;
3764 pc0 = ra;
3765 return;
3766 }
3767 psxBios_ReturnFromException();
3768}
3769
3770#define bfreeze(ptr, size) { \
3771 if (Mode == 1) memcpy(&psxR[base], ptr, size); \
3772 if (Mode == 0) memcpy(ptr, &psxR[base], size); \
3773 base += size; \
3774}
3775
3776#define bfreezes(ptr) bfreeze(ptr, sizeof(ptr))
3777#define bfreezel(ptr) bfreeze(ptr, sizeof(*ptr))
3778
3779#define bfreezepsxMptr(ptr, type) { \
3780 if (Mode == 1) { \
3781 if (ptr) psxRu32ref(base) = SWAPu32((s8 *)(ptr) - psxM); \
3782 else psxRu32ref(base) = 0; \
3783 } else { \
3784 if (psxRu32(base) != 0) ptr = (type *)(psxM + psxRu32(base)); \
3785 else (ptr) = NULL; \
3786 } \
3787 base += sizeof(u32); \
3788}
3789
3790void psxBiosFreeze(int Mode) {
3791 u32 base = 0x40000;
3792
3793 bfreezepsxMptr(pad_buf, int);
3794 bfreezepsxMptr(pad_buf1, char);
3795 bfreezepsxMptr(pad_buf2, char);
3796 bfreezepsxMptr(heap_addr, u32);
3797 bfreezel(&pad_buf1len);
3798 bfreezel(&pad_buf2len);
3799 bfreezes(regs);
3800 bfreezel(&CardState);
3801 bfreezel(&CurThread);
3802 bfreezes(FDesc);
3803 bfreezel(&card_active_chan);
3804 bfreezel(&pad_stopped);
3805 bfreezel(&heap_size);
3806}