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