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