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