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