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