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