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