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