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