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