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