1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
|
/*
* PSn00bSDK kernel API library
* (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed
*/
/**
* @file psxapi.h
* @brief Kernel API library header
*
* @details This header provides access to most of the APIs made available by
* the system's BIOS, including basic file I/O, TTY output, controller and
* memory card drivers, threads, events as well as kernel memory allocation.
*
* For more information and up-to-date documentation on kernel APIs, see:
* https://psx-spx.consoledev.net/kernelbios/
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <hwregs_c.h>
/* Definitions */
// TODO: these desperately need to be cleaned up
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#define DescMask 0xff000000 // Event descriptor mask
#define DescTH DescMask
#define DescHW 0xf0000000 // Hardware event (IRQ)
#define DescEV 0xf1000000 // Event event
#define DescRC 0xf2000000 // Root counter event
#define DescUEV 0xf3000000 // User event
#define DescSW 0xf4000000 // BIOS event
#define HwVBLANK (DescHW|0x01) // VBlank
#define HwGPU (DescHW|0x02) // GPU
#define HwCdRom (DescHW|0x03) // CDROM
#define HwDMAC (DescHW|0x04) // DMA
#define HwRTC0 (DescHW|0x05) // Timer 0
#define HwRTC1 (DescHW|0x06) // Timer 1
#define HwRTC2 (DescHW|0x07) // Timer 2
#define HwCNTL (DescHW|0x08) // Controller
#define HwSPU (DescHW|0x09) // SPU
#define HwPIO (DescHW|0x0a) // PIO & lightgun
#define HwSIO (DescHW|0x0b) // Serial
#define HwCPU (DescHW|0x10) // Processor exception
#define HwCARD (DescHW|0x11) // Memory card (lower level BIOS functions)
#define HwCard_0 (DescHW|0x12)
#define HwCard_1 (DescHW|0x13)
#define SwCARD (DescSW|0x01) // Memory card (higher level BIOS functions)
#define SwMATH (DescSW|0x02)
#define EvSpIOE 0x0004
#define EvSpERROR 0x8000
#define EvSpTIMOUT 0x0100
#define EvSpNEW 0x0200
#define EvMdINTR 0x1000
#define EvMdNOINTR 0x2000
// Root counter (timer) definitions
#define DescRC 0xf2000000
#define RCntCNT0 (DescRC|0x00)
#define RCntCNT1 (DescRC|0x01)
#define RCntCNT2 (DescRC|0x02)
#define RCntCNT3 (DescRC|0x03)
#define RCntMdINTR 0x1000 // Turns on IRQ
#define RCntMdNOINTR 0x2000 // Polling mode
#define RCntMdSC 0x0001 // IRQ when counter target
#define RCntMdSP 0x0000
#define RCntMdFR 0x0000
#define RCntMdGATE 0x0010
/* Structure definitions */
typedef struct { // Thread control block
int status;
int mode;
union {
uint32_t reg[37];
struct {
uint32_t zero, at;
uint32_t v0, v1;
uint32_t a0, a1, a2, a3;
uint32_t t0, t1, t2, t3, t4, t5, t6, t7;
uint32_t s0, s1, s2, s3, s4, s5, s6, s7;
uint32_t t8, t9;
uint32_t k0, k1;
uint32_t gp, sp, fp, ra;
uint32_t cop0r14;
uint32_t hi;
uint32_t lo;
uint32_t cop0r12;
uint32_t cop0r13;
};
};
int _reserved[9];
} TCB;
typedef struct { // Process control block
TCB *thread;
} PCB;
typedef struct { // Device control block
char *name;
int flags;
int ssize;
char *desc;
void *f_init;
void *f_open;
void *f_inout;
void *f_close;
void *f_ioctl;
void *f_read;
void *f_write;
void *f_erase;
void *f_undelete;
void *f_firstfile;
void *f_nextfile;
void *f_format;
void *f_chdir;
void *f_rename;
void *f_remove;
void *f_testdevice;
} DCB;
typedef struct { // File control block
int status;
uint32_t diskid;
void *trns_addr;
uint32_t trns_len;
uint32_t filepos;
uint32_t flags;
uint32_t lasterr;
DCB *dcb;
uint32_t filesize;
uint32_t lba;
uint32_t fcbnum;
} FCB;
struct DIRENTRY { // Directory entry
char name[20];
int attr;
int size;
struct DIRENTRY *next;
int head;
char system[4];
};
struct EXEC {
uint32_t pc0, gp0;
uint32_t t_addr, t_size;
uint32_t d_addr, d_size;
uint32_t b_addr, b_size;
uint32_t s_addr, s_size;
uint32_t sp, fp, rp, ret, base;
};
struct JMP_BUF {
uint32_t ra, sp, fp;
uint32_t s0, s1, s2, s3, s4, s5, s6, s7;
uint32_t gp;
};
typedef struct {
uint32_t *next;
uint32_t *func2;
uint32_t *func1;
int _reserved;
} INT_RP;
/* Fast interrupt disabling macros */
// Clearing the IRQ_MASK register is faster than manipulating cop0r12, even
// though it requires declaring a "hidden" local variable to save its state to;
// it's also resilient to race conditions as there's no read-modify-write
// operation during which an interrupt can occur. Note that interrupt flags in
// the IRQ_STAT register will get set even if the respective enable bits in
// IRQ_MASK are cleared, so doing this will properly defer IRQs rather than
// dropping them.
#define FastEnterCriticalSection() \
uint16_t __saved_irq_mask = IRQ_MASK; (IRQ_MASK = 0)
#define FastExitCriticalSection() \
(IRQ_MASK = __saved_irq_mask)
#if 0
#define FastEnterCriticalSection() { \
uint32_t r0, r1; \
__asm__ volatile( \
"mfc0 %0, $12;" \
"li %1, -1026;" \
"and %1, %0;" \
"mtc0 %1, $12;" \
"nop;" \
: "=r"(r0), "=r"(r1) :: \
); \
}
#define FastExitCriticalSection() { \
uint32_t r0; \
__asm__ volatile( \
"mfc0 %0, $12;" \
"nop;" \
"ori %0, 0x0401;" \
"mtc0 %0, $12;" \
"nop;" \
: "=r"(r0) :: \
); \
}
#endif
/* BIOS API */
#ifdef __cplusplus
extern "C" {
#endif
void SysEnqIntRP(int pri, INT_RP *rp);
void SysDeqIntRP(int pri, INT_RP *rp);
int OpenEvent(uint32_t cl, uint32_t spec, int mode, void (*func)());
int CloseEvent(int event);
int WaitEvent(int event);
int TestEvent(int event);
int EnableEvent(int event);
int DisableEvent(int event);
void DeliverEvent(uint32_t cl, uint32_t spec);
void UnDeliverEvent(uint32_t cl, uint32_t spec);
int open(const char *path, int mode);
int close(int fd);
int lseek(int fd, uint32_t offset, int mode);
int read(int fd, void *buff, size_t len);
int write(int fd, const void *buff, size_t len);
int getc(int fd);
int putc(int ch, int fd);
int ioctl(int fd, int cmd, int arg);
int isatty(int fd);
struct DIRENTRY *firstfile(const char *wildcard, struct DIRENTRY *entry);
struct DIRENTRY *nextfile(struct DIRENTRY *entry);
int erase(const char *path);
int undelete(const char *path);
int cd(const char *path);
int _get_errno(void);
int _get_error(int fd);
int AddDrv(DCB *dcb);
int DelDrv(const char *name);
void ListDrv(void);
void add_nullcon_driver(void);
int EnterCriticalSection(void);
void ExitCriticalSection(void);
int SwEnterCriticalSection(void);
void SwExitCriticalSection(void);
void _InitCd(void);
void _96_init(void);
void _96_remove(void);
void InitPAD(uint8_t *buff1, int len1, uint8_t *buff2, int len2);
void StartPAD(void);
void StopPAD(void);
void InitCARD(int pad_enable);
void StartCARD(void);
void StopCARD(void);
void _bu_init(void);
int _card_load(int chan);
int _card_info(int chan);
int _card_status(int chan);
int _card_wait(int chan);
int _card_clear(int chan);
int _card_chan(void);
int _card_read(int chan, int sector, uint8_t *buf);
int _card_write(int chan, int sector, uint8_t *buf);
void _new_card(void);
int SetRCnt(int spec, uint16_t target, int mode);
int GetRCnt(int spec);
int StartRCnt(int spec);
int StopRCnt(int spec);
int ResetRCnt(int spec);
void ChangeClearPAD(int mode);
void ChangeClearRCnt(int t, int m);
int OpenTh(uint32_t (*func)(), uint32_t sp, uint32_t gp);
int CloseTh(int thread);
int ChangeTh(int thread);
int Exec(struct EXEC *exec, int argc, const char **argv);
int LoadExec(const char *path, int argc, const char **argv);
void FlushCache(void);
void b_setjmp(struct JMP_BUF *buf);
void b_longjmp(const struct JMP_BUF *buf, int param);
void ResetEntryInt(void);
void HookEntryInt(const struct JMP_BUF *buf);
void ReturnFromException(void);
int SetConf(int evcb, int tcb, uint32_t sp);
void GetConf(int *evcb, int *tcb, uint32_t *sp);
void SetMem(int size);
int GetSystemInfo(int index);
void *GetB0Table(void);
void *GetC0Table(void);
void *alloc_kernel_memory(int size);
void free_kernel_memory(void *ptr);
void _boot(void);
#ifdef __cplusplus
}
#endif
|