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