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