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