From 50faf92a8cb099420aa956dcac3a8105067e117c Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Wed, 28 Dec 2022 14:27:34 +0100 Subject: Re-enable MoveImage(), add tagless primitive structs --- libpsn00b/include/psxgpu.h | 212 ++++++++++++++++++++++++--------------------- 1 file changed, 111 insertions(+), 101 deletions(-) (limited to 'libpsn00b/include/psxgpu.h') diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h index 26e560f..4dbcc6c 100644 --- a/libpsn00b/include/psxgpu.h +++ b/libpsn00b/include/psxgpu.h @@ -101,9 +101,12 @@ typedef enum _GPU_VideoMode { #define setlen(p, _len) (((P_TAG *) (p))->len = (uint8_t) (_len)) #define setaddr(p, _addr) (((P_TAG *) (p))->addr = (uint32_t) (_addr)) #define setcode(p, _code) (((P_TAG *) (p))->code = (uint8_t) (_code)) +#define setcode_T(p, _code) (((P_TAG_T *) (p))->code = (uint8_t) (_code)) + #define getlen(p) (((P_TAG *) (p))->len) #define getaddr(p) (((P_TAG *) (p))->addr) #define getcode(p) (((P_TAG *) (p))->code) +#define getcode_T(p) (((P_TAG_T *) (p))->code) #define nextPrim(p) (void *) (0x80000000 | (((P_TAG *) (p))->addr)) #define isendprim(p) ((((P_TAG *) (p))->addr) == 0xffffff) @@ -147,16 +150,41 @@ typedef enum _GPU_VideoMode { #define setTile(p) setlen(p, 3), setcode(p, 0x60) #define setLineF2(p) setlen(p, 3), setcode(p, 0x40) #define setLineG2(p) setlen(p, 4), setcode(p, 0x50) -#define setLineF3(p) setlen(p, 5), setcode(p, 0x48), \ - (p)->pad = 0x55555555 -#define setLineG3(p) setlen(p, 7), setcode(p, 0x58), \ - (p)->pad = 0x55555555, (p)->p1 = 0, (p)->p2 = 0 -#define setLineF4(p) setlen(p, 6), setcode(p, 0x4c), \ - (p)->pad = 0x55555555 -#define setLineG4(p) setlen(p, 9), setcode(p, 0x5c), \ - (p)->pad = 0x55555555, (p)->p1 = 0, (p)->p2 = 0, (p)->p3 = 0 -#define setFill(p) setlen(p, 3), setcode(p, 0x02) -#define setVram2Vram(p) setlen(p, 8), setcode(p, 0x80), \ +#define setLineF3(p) setlen(p, 5), setcode(p, 0x48), (p)->pad = 0x55555555 +#define setLineG3(p) setlen(p, 7), setcode(p, 0x58), (p)->pad = 0x55555555, \ + (p)->p1 = 0, (p)->p2 = 0 +#define setLineF4(p) setlen(p, 6), setcode(p, 0x4c), (p)->pad = 0x55555555 +#define setLineG4(p) setlen(p, 9), setcode(p, 0x5c), (p)->pad = 0x55555555, \ + (p)->p1 = 0, (p)->p2 = 0, (p)->p3 = 0 +#define setFill(p) setlen(p, 3), setcode(p, 0x02) +#define setBlit(p) setlen(p, 8), setcode(p, 0x80), \ + (p)->pad[0] = 0, (p)->pad[1] = 0, (p)->pad[2] = 0, (p)->pad[3] = 0 + +#define setPolyF3_T(p) setcode_T(p, 0x20) +#define setPolyFT3_T(p) setcode_T(p, 0x24) +#define setPolyG3_T(p) setcode_T(p, 0x30) +#define setPolyGT3_T(p) setcode_T(p, 0x34) +#define setPolyF4_T(p) setcode_T(p, 0x28) +#define setPolyFT4_T(p) setcode_T(p, 0x2c) +#define setPolyG4_T(p) setcode_T(p, 0x38) +#define setPolyGT4_T(p) setcode_T(p, 0x3c) +#define setSprt8_T(p) setcode_T(p, 0x74) +#define setSprt16_T(p) setcode_T(p, 0x7c) +#define setSprt_T(p) setcode_T(p, 0x64) +#define setTile1_T(p) setcode_T(p, 0x68) +#define setTile8_T(p) setcode_T(p, 0x70) +#define setTile16_T(p) setcode_T(p, 0x78) +#define setTile_T(p) setcode_T(p, 0x60) +#define setLineF2_T(p) setcode_T(p, 0x40) +#define setLineG2_T(p) setcode_T(p, 0x50) +#define setLineF3_T(p) setcode_T(p, 0x48), (p)->pad = 0x55555555 +#define setLineG3_T(p) setcode_T(p, 0x58), (p)->pad = 0x55555555, \ + (p)->p1 = 0, (p)->p2 = 0 +#define setLineF4_T(p) setcode_T(p, 0x4c), (p)->pad = 0x55555555 +#define setLineG4_T(p) setcode_T(p, 0x5c), (p)->pad = 0x55555555, \ + (p)->p1 = 0, (p)->p2 = 0, (p)->p3 = 0 +#define setFill_T(p) setcode_T(p, 0x02) +#define setBlit_T(p) setcode_T(p, 0x80), \ (p)->pad[0] = 0, (p)->pad[1] = 0, (p)->pad[2] = 0, (p)->pad[3] = 0 #define setDrawTPage(p, dfe, dtd, tpage) \ @@ -200,6 +228,11 @@ typedef enum _GPU_VideoMode { /* Primitive structure definitions */ +typedef struct _P_TAG_T { + uint32_t color:24; + uint32_t code:8; +} P_TAG_T; + typedef struct _P_TAG { uint32_t addr:24; uint32_t len:8; @@ -212,25 +245,31 @@ typedef struct _P_COLOR { uint32_t pad:8; } P_COLOR; -typedef struct _POLY_F3 { - uint32_t tag; +// These macros are used to define two variants of each primitive, a regular one +// and a "tagless" one (_T suffix) without the OT/display list header. +#define _DEF_PRIM(name, ...) \ + typedef struct _##name##_T { __VA_ARGS__ } name##_T; \ + typedef struct _##name { uint32_t tag; __VA_ARGS__ } name; +#define _DEF_ALIAS(name, target) \ + typedef struct _##target##_T name##_T; \ + typedef struct _##target name; + +_DEF_PRIM(POLY_F3, uint8_t r0, g0, b0, code; int16_t x0, y0; int16_t x1, y1; int16_t x2, y2; -} POLY_F3; +) -typedef struct _POLY_F4 { - uint32_t tag; +_DEF_PRIM(POLY_F4, uint8_t r0, g0, b0, code; int16_t x0, y0; int16_t x1, y1; int16_t x2, y2; int16_t x3, y3; -} POLY_F4; +) -typedef struct _POLY_FT3 { - uint32_t tag; +_DEF_PRIM(POLY_FT3, uint8_t r0, g0, b0, code; int16_t x0, y0; uint8_t u0, v0; @@ -241,10 +280,9 @@ typedef struct _POLY_FT3 { int16_t x2, y2; uint8_t u2, v2; uint16_t pad; -} POLY_FT3; +) -typedef struct _POLY_FT4 { - uint32_t tag; +_DEF_PRIM(POLY_FT4, uint8_t r0, g0, b0, code; uint16_t x0, y0; uint8_t u0, v0; @@ -258,20 +296,18 @@ typedef struct _POLY_FT4 { int16_t x3, y3; uint8_t u3, v3; uint16_t pad1; -} POLY_FT4; +) -typedef struct _POLY_G3 { - uint32_t tag; +_DEF_PRIM(POLY_G3, uint8_t r0, g0, b0, code; int16_t x0, y0; uint8_t r1, g1, b1, pad0; int16_t x1, y1; uint8_t r2, g2, b2, pad1; int16_t x2, y2; -} POLY_G3; +) -typedef struct _POLY_G4 { - uint32_t tag; +_DEF_PRIM(POLY_G4, uint8_t r0, g0, b0, code; int16_t x0, y0; uint8_t r1, g1, b1, pad0; @@ -280,10 +316,9 @@ typedef struct _POLY_G4 { int16_t x2, y2; uint8_t r3, g3, b3, pad2; int16_t x3, y3; -} POLY_G4; +) -typedef struct _POLY_GT3 { - uint32_t tag; +_DEF_PRIM(POLY_GT3, uint8_t r0, g0, b0, code; int16_t x0, y0; uint8_t u0, v0; @@ -296,10 +331,9 @@ typedef struct _POLY_GT3 { int16_t x2, y2; uint8_t u2, v2; uint16_t pad2; -} POLY_GT3; +) -typedef struct _POLY_GT4 { - uint32_t tag; +_DEF_PRIM(POLY_GT4, uint8_t r0, g0, b0, code; int16_t x0, y0; uint8_t u0, v0; @@ -316,34 +350,30 @@ typedef struct _POLY_GT4 { int16_t x3, y3; uint8_t u3, v3; uint16_t pad4; -} POLY_GT4; +) -typedef struct _LINE_F2 { - uint32_t tag; +_DEF_PRIM(LINE_F2, uint8_t r0, g0, b0, code; int16_t x0, y0; int16_t x1, y1; -} LINE_F2; +) -typedef struct _LINE_G2 { - uint32_t tag; +_DEF_PRIM(LINE_G2, uint8_t r0, g0, b0, code; int16_t x0, y0; uint8_t r1, g1, b1, p1; int16_t x1, y1; -} LINE_G2; +) -typedef struct _LINE_F3 { - uint32_t tag; +_DEF_PRIM(LINE_F3, uint8_t r0, g0, b0, code; int16_t x0, y0; int16_t x1, y1; int16_t x2, y2; uint32_t pad; -} LINE_F3; +) -typedef struct _LINE_G3 { - uint32_t tag; +_DEF_PRIM(LINE_G3, uint8_t r0, g0, b0, code; int16_t x0, y0; uint8_t r1, g1, b1, p1; @@ -351,20 +381,18 @@ typedef struct _LINE_G3 { uint8_t r2, g2, b2, p2; int16_t x2, y2; uint32_t pad; -} LINE_G3; +) -typedef struct _LINE_F4 { - uint32_t tag; +_DEF_PRIM(LINE_F4, uint8_t r0, g0, b0, code; int16_t x0, y0; int16_t x1, y1; int16_t x2, y2; int16_t x3, y3; uint32_t pad; -} LINE_F4; +) -typedef struct _LINE_G4 { - uint32_t tag; +_DEF_PRIM(LINE_G4, uint8_t r0, g0, b0, code; int16_t x0, y0; uint8_t r1, g1, b1, p1; @@ -374,88 +402,70 @@ typedef struct _LINE_G4 { uint8_t r3, g3, b3, p3; int16_t x3, y3; uint32_t pad; -} LINE_G4; +) -typedef struct _TILE { - uint32_t tag; +_DEF_PRIM(TILE, uint8_t r0, g0, b0, code; int16_t x0, y0; int16_t w, h; -} TILE; +) -struct _TILE_FIXED { - uint32_t tag; +_DEF_PRIM(TILE_1, uint8_t r0, g0, b0, code; int16_t x0, y0; -}; -typedef struct _TILE_FIXED TILE_1; -typedef struct _TILE_FIXED TILE_8; -typedef struct _TILE_FIXED TILE_16; +) +_DEF_ALIAS(TILE_8, TILE_1) +_DEF_ALIAS(TILE_16, TILE_1) -typedef struct _SPRT { - uint32_t tag; +_DEF_PRIM(SPRT, uint8_t r0, g0, b0, code; int16_t x0, y0; uint8_t u0, v0; uint16_t clut; uint16_t w, h; -} SPRT; +) -struct _SPRT_FIXED { - uint32_t tag; +_DEF_PRIM(SPRT_1, uint8_t r0, g0, b0, code; int16_t x0, y0; uint8_t u0, v0; uint16_t clut; -}; -typedef struct _SPRT_FIXED SPRT_8; -typedef struct _SPRT_FIXED SPRT_16; +) +_DEF_ALIAS(SPRT_8, SPRT_1) +_DEF_ALIAS(SPRT_16, SPRT_1) -typedef struct _DR_ENV { - uint32_t tag; +_DEF_PRIM(DR_ENV, uint32_t code[8]; -} DR_ENV; - -typedef struct _DR_AREA { - uint32_t tag; +) +_DEF_PRIM(DR_AREA, uint32_t code[2]; -} DR_AREA; - -typedef struct _DR_OFFSET { - uint32_t tag; +) +_DEF_PRIM(DR_OFFSET, uint32_t code[1]; -} DR_OFFSET; - -typedef struct _DR_TWIN { - uint32_t tag; +) +_DEF_PRIM(DR_TWIN, uint32_t code[2]; -} DR_TWIN; - -typedef struct _DR_TPAGE { - uint32_t tag; +) +_DEF_PRIM(DR_TPAGE, uint32_t code[1]; -} DR_TPAGE; - -typedef struct _DR_MASK { - uint32_t tag; +) +_DEF_PRIM(DR_MASK, uint32_t code[1]; -} DR_MASK; +) -typedef struct _FILL { - uint32_t tag; +_DEF_PRIM(FILL, uint8_t r0, g0, b0, code; - uint16_t x0, y0; // Note: coordinates must be in 16 pixel steps + uint16_t x0, y0; uint16_t w, h; -} FILL; +) -typedef struct _VRAM2VRAM { - uint32_t tag; +_DEF_PRIM(BLIT, uint8_t p0, p1, p2, code; uint16_t x0, y0; uint16_t x1, y1; uint16_t w, h; uint32_t pad[4]; -} VRAM2VRAM; +) /* Structure definitions */ @@ -536,10 +546,10 @@ void *DrawSyncCallback(void (*func)(void)); int LoadImage(const RECT *rect, const uint32_t *data); int StoreImage(const RECT *rect, uint32_t *data); -//int MoveImage(const RECT *rect, int x, int y); +int MoveImage(const RECT *rect, int x, int y); void LoadImage2(const RECT *rect, const uint32_t *data); void StoreImage2(const RECT *rect, uint32_t *data); -//void MoveImage2(const RECT *rect, int x, int y); +void MoveImage2(const RECT *rect, int x, int y); void ClearOTagR(uint32_t *ot, size_t length); void ClearOTag(uint32_t *ot, size_t length); -- cgit v1.2.3 From 3095b4571dabc8d6cee90673d679f3e77b21b164 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Fri, 13 Jan 2023 18:04:49 +0100 Subject: Fix VSync() rate limiter, add missing tagless packets --- libpsn00b/include/psxetc.h | 9 +++-- libpsn00b/include/psxgpu.h | 90 ++++++++++++++++++++++++++-------------------- libpsn00b/psxgpu/common.c | 58 +++++++++++++++++------------- libpsn00b/psxgpu/env.c | 60 +++++++++++++------------------ libpsn00b/psxgpu/image.c | 13 +++++-- 5 files changed, 128 insertions(+), 102 deletions(-) (limited to 'libpsn00b/include/psxgpu.h') diff --git a/libpsn00b/include/psxetc.h b/libpsn00b/include/psxetc.h index ebf7966..e45abf4 100644 --- a/libpsn00b/include/psxetc.h +++ b/libpsn00b/include/psxetc.h @@ -1,6 +1,6 @@ /* * PSn00bSDK interrupt management library - * (C) 2019-2022 Lameguy64, spicyjpeg - MPL licensed + * (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed */ /** @@ -68,7 +68,7 @@ extern "C" { * | ID | Channel | Used by | * | --: | :--------------- | :-------------------------------------- | * | 0 | IRQ_VBLANK | psxgpu (use VSyncCallback() instead) | - * | 1 | IRQ_GPU | | + * | 1 | IRQ_GPU | psxgpu (use DrawSyncCallback() instead) | * | 2 | IRQ_CD | psxcd (use CdReadyCallback() instead) | * | 3 | IRQ_DMA | psxetc (use DMACallback() instead) | * | 4 | IRQ_TIMER0 | | @@ -227,6 +227,11 @@ void RestartCallback(void); * Note that interrupts are (obviously) disabled until RestartCallback() is * called. * + * WARNING: any ongoing background processing or DMA transfer must be stopped + * before calling StopCallback(), otherwise crashes may occur. This includes + * flushing psxgpu's command queue using DrawSync(), stopping CD-ROM reading + * and calling StopPAD() to disable the BIOS controller driver if used. + * * @see RestartCallback() */ void StopCallback(void); diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h index 4dbcc6c..2329908 100644 --- a/libpsn00b/include/psxgpu.h +++ b/libpsn00b/include/psxgpu.h @@ -1,6 +1,6 @@ /* * PSn00bSDK GPU library - * (C) 2019-2022 Lameguy64, spicyjpeg - MPL licensed + * (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed */ #ifndef __PSXGPU_H @@ -117,9 +117,13 @@ typedef enum _GPU_VideoMode { #define setSemiTrans(p, abe) \ ((abe) ? (getcode(p) |= 2) : (getcode(p) &= ~2)) +#define setSemiTrans_T(p, abe) \ + ((abe) ? (getcode_T(p) |= 2) : (getcode_T(p) &= ~2)) #define setShadeTex(p, tge) \ ((tge) ? (getcode(p) |= 1) : (getcode(p) &= ~1)) +#define setShadeTex_T(p, tge) \ + ((tge) ? (getcode_T(p) |= 1) : (getcode_T(p) &= ~1)) #define getTPage(tp, abr, x, y) ( \ (((x) / 64) & 15) | \ @@ -187,27 +191,26 @@ typedef enum _GPU_VideoMode { #define setBlit_T(p) setcode_T(p, 0x80), \ (p)->pad[0] = 0, (p)->pad[1] = 0, (p)->pad[2] = 0, (p)->pad[3] = 0 -#define setDrawTPage(p, dfe, dtd, tpage) \ - setlen(p, 1), \ +#define setDrawTPage_T(p, dfe, dtd, tpage) \ (p)->code[0] = (0xe1000000 | \ (tpage) | \ ((dtd) << 9) | \ ((dfe) << 10) \ ) +#define setDrawTPage(p, dfe, dtd, tpage) \ + setlen(p, 1), setDrawTPage_T(p, dfe, dtd, tpage) -#define setDrawOffset(p, _x, _y) \ - setlen(p, 1), \ - (p)->code[0] = (0xe5000000 | \ - ((_x) % 1024) | \ - (((_y) % 1024) << 11) \ +#define setTexWindow_T(p, r) \ + (p)->code[0] = (0xe2000000 | \ + ((r)->w % 32) | \ + (((r)->h % 32) << 5) | \ + (((r)->x % 32) << 10) | \ + (((r)->y % 32) << 15) \ ) +#define setTexWindow(p, r) \ + setlen(p, 1), setTexWindow_T(p, r) -#define setDrawMask(p, sb, mt) \ - setlen(p, 1), \ - (p)->code[0] = (0xe6000000 | (sb) | ((mt) << 1)) - -#define setDrawArea(p, r) \ - setlen(p, 2), \ +#define setDrawArea_T(p, r) \ (p)->code[0] = (0xe3000000 | \ ((r)->x % 1024) | \ (((r)->y % 1024) << 10) \ @@ -216,15 +219,21 @@ typedef enum _GPU_VideoMode { (((r)->x + (r)->w - 1) % 1024) | \ ((((r)->y + (r)->h - 1) % 1024) << 10) \ ) +#define setDrawArea(p, r) \ + setlen(p, 2), setDrawArea_T(p, r) -#define setTexWindow(p, r) \ - setlen(p, 1), \ - (p)->code[0] = (0xe2000000 | \ - ((r)->w % 32) | \ - (((r)->h % 32) << 5) | \ - (((r)->x % 32) << 10) | \ - (((r)->y % 32) << 15) \ +#define setDrawOffset_T(p, _x, _y) \ + (p)->code[0] = (0xe5000000 | \ + ((_x) % 1024) | \ + (((_y) % 1024) << 11) \ ) +#define setDrawOffset(p, _x, _y) \ + setlen(p, 1), setDrawOffset_T(p, _x, _y) + +#define setDrawMask_T(p, sb, mt) \ + (p)->code[0] = (0xe6000000 | (sb) | ((mt) << 1)) +#define setDrawMask(p, sb, mt) \ + setlen(p, 1), setDrawMask_T(p, sb, mt) /* Primitive structure definitions */ @@ -434,9 +443,20 @@ _DEF_PRIM(SPRT_1, _DEF_ALIAS(SPRT_8, SPRT_1) _DEF_ALIAS(SPRT_16, SPRT_1) -_DEF_PRIM(DR_ENV, - uint32_t code[8]; +_DEF_PRIM(FILL, + uint8_t r0, g0, b0, code; + uint16_t x0, y0; + uint16_t w, h; ) + +_DEF_PRIM(BLIT, + uint8_t p0, p1, p2, code; + uint16_t x0, y0; + uint16_t x1, y1; + uint16_t w, h; + uint32_t pad[4]; +) + _DEF_PRIM(DR_AREA, uint32_t code[2]; ) @@ -444,7 +464,7 @@ _DEF_PRIM(DR_OFFSET, uint32_t code[1]; ) _DEF_PRIM(DR_TWIN, - uint32_t code[2]; + uint32_t code[1]; ) _DEF_PRIM(DR_TPAGE, uint32_t code[1]; @@ -453,18 +473,12 @@ _DEF_PRIM(DR_MASK, uint32_t code[1]; ) -_DEF_PRIM(FILL, - uint8_t r0, g0, b0, code; - uint16_t x0, y0; - uint16_t w, h; -) - -_DEF_PRIM(BLIT, - uint8_t p0, p1, p2, code; - uint16_t x0, y0; - uint16_t x1, y1; - uint16_t w, h; - uint32_t pad[4]; +_DEF_PRIM(DR_ENV, + DR_TPAGE_T tpage; + DR_TWIN_T twin; + DR_AREA_T area; + DR_OFFSET_T offset; + FILL_T fill; ) /* Structure definitions */ @@ -488,13 +502,13 @@ typedef struct _DISPENV { typedef struct _DRAWENV { RECT clip; // Drawing area int16_t ofs[2]; // GPU draw offset (relative to draw area) - RECT tw; // Texture window (doesn't do anything atm) + RECT tw; // Texture window uint16_t tpage; // Initial tpage value uint8_t dtd; // Dither processing flag (simply OR'ed to tpage) uint8_t dfe; // Drawing to display area blocked/allowed (simply OR'ed to tpage) uint8_t isbg; // Clear draw area if non-zero uint8_t r0, g0, b0; // Draw area clear color (if isbg iz nonzero) - DR_ENV dr_env; // Draw mode packet area (used by PutDrawEnv) + DR_ENV dr_env; // GPU primitive cache area (used internally) } DRAWENV; typedef struct _TIM_IMAGE { diff --git a/libpsn00b/psxgpu/common.c b/libpsn00b/psxgpu/common.c index 8d2119b..c52ab8a 100644 --- a/libpsn00b/psxgpu/common.c +++ b/libpsn00b/psxgpu/common.c @@ -1,6 +1,6 @@ /* * PSn00bSDK GPU library (common functions) - * (C) 2022 spicyjpeg - MPL licensed + * (C) 2022-2023 spicyjpeg - MPL licensed */ #include @@ -11,7 +11,7 @@ #include #define QUEUE_LENGTH 16 -#define DMA_CHUNK_LENGTH 8 +#define DMA_CHUNK_LENGTH 16 #define VSYNC_TIMEOUT 0x100000 static void _default_vsync_halt(void); @@ -33,7 +33,7 @@ static void (*_drawsync_callback)(void) = (void *) 0; static volatile QueueEntry _draw_queue[QUEUE_LENGTH]; static volatile uint8_t _queue_head, _queue_tail, _queue_length; -static volatile uint32_t _vblank_counter; +static volatile uint32_t _vblank_counter, _last_vblank; static volatile uint16_t _last_hblank; /* Private interrupt handlers */ @@ -47,9 +47,7 @@ static void _vblank_handler(void) { static void _gpu_dma_handler(void) { if (GPU_GP1 & (1 << 24)) - GPU_GP1 = 0x02000000; - while (!(GPU_GP1 & (1 << 26))) - __asm__ volatile(""); + GPU_GP1 = 0x02000000; // Reset IRQ if (--_queue_length) { int head = _queue_head; @@ -82,8 +80,14 @@ void ResetGraph(int mode) { _sdk_log("setup done, default mode is %s\n", _gpu_video_mode ? "PAL" : "NTSC"); } - if (mode == 3) { + _queue_head = 0; + _queue_tail = 0; + _queue_length = 0; + + if (mode == 1) { GPU_GP1 = 0x01000000; // Reset command buffer + GPU_GP1 = 0x02000000; // Reset IRQ + GPU_GP1 = 0x04000000; // Disable DMA request return; } @@ -92,20 +96,20 @@ void ResetGraph(int mode) { DMA_CHCR(DMA_GPU) = 0x00000201; // Stop DMA DMA_CHCR(DMA_OTC) = 0x00000200; // Stop DMA - if (mode == 1) { + if (mode) { GPU_GP1 = 0x01000000; // Reset command buffer - return; + GPU_GP1 = 0x02000000; // Reset IRQ + GPU_GP1 = 0x04000000; // Disable DMA request + } else { + GPU_GP1 = 0x00000000; // Reset GPU } - GPU_GP1 = 0x00000000; // Reset GPU - TIMER_CTRL(0) = 0x0500; - TIMER_CTRL(1) = 0x0500; - - _queue_head = 0; - _queue_tail = 0; - _queue_length = 0; _vblank_counter = 0; + _last_vblank = 0; _last_hblank = 0; + + TIMER_CTRL(0) = 0x0500; + TIMER_CTRL(1) = 0x0500; } /* VSync() API */ @@ -129,11 +133,13 @@ int VSync(int mode) { return delta; if (mode < 0) return _vblank_counter; + if (!mode) + mode = 1; // VSync(0) = wait for one vblank - uint32_t status = GPU_GP1; - - // Wait for at least one vertical blank event to occur. - do { + // Wait for at least one vertical blank event since the last call to + // VSync() to occur. + for (uint32_t target = _last_vblank + mode; _vblank_counter < target;) { + uint32_t status = GPU_GP1; _vsync_halt_func(); // If interlaced mode is enabled, wait until the GPU starts displaying @@ -142,9 +148,11 @@ int VSync(int mode) { while (!((GPU_GP1 ^ status) & (1 << 31))) __asm__ volatile(""); } - } while ((--mode) > 0); + } + _last_vblank = _vblank_counter; _last_hblank = TIMER_VALUE(1); + return delta; } @@ -269,8 +277,10 @@ void ClearOTag(uint32_t *ot, size_t length) { // https://problemkaputt.de/psx-spx.htm#dmachannels for (int i = 0; i < (length - 1); i++) ot[i] = (uint32_t) &ot[i + 1] & 0x00ffffff; + //setaddr(&ot[i], &ot[i + 1]); ot[length - 1] = 0x00ffffff; + //termPrim(&ot[length - 1]); } void AddPrim(uint32_t *ot, const void *pri) { @@ -281,7 +291,7 @@ void DrawPrim(const uint32_t *pri) { size_t length = getlen(pri); DrawSync(0); - GPU_GP1 = 0x04000002; + GPU_GP1 = 0x04000002; // Enable DMA request, route to GP0 // NOTE: if length >= DMA_CHUNK_LENGTH then it also has to be a multiple of // DMA_CHUNK_LENGTH, otherwise the DMA channel will get stuck waiting for @@ -301,9 +311,9 @@ int DrawOTag(const uint32_t *ot) { } void DrawOTag2(const uint32_t *ot) { - GPU_GP1 = 0x04000002; + GPU_GP1 = 0x04000002; // Enable DMA request, route to GP0 - while (!(GPU_GP1 & (1 << 26)) || (DMA_CHCR(DMA_GPU) & (1 << 24))) + while (DMA_CHCR(DMA_GPU) & (1 << 24)) __asm__ volatile(""); DMA_MADR(DMA_GPU) = (uint32_t) ot; diff --git a/libpsn00b/psxgpu/env.c b/libpsn00b/psxgpu/env.c index 96e065e..b90a431 100644 --- a/libpsn00b/psxgpu/env.c +++ b/libpsn00b/psxgpu/env.c @@ -1,6 +1,6 @@ /* * PSn00bSDK GPU library (DRAWENV/DISPENV functions) - * (C) 2022 spicyjpeg - MPL licensed + * (C) 2022-2023 spicyjpeg - MPL licensed */ #include @@ -60,54 +60,42 @@ DRAWENV *SetDefDrawEnv(DRAWENV *env, int x, int y, int w, int h) { } int DrawOTagEnv(const uint32_t *ot, DRAWENV *env) { - DR_ENV *prim = &(env->dr_env); - // All commands are grouped into a single display list packet for - // performance reasons (the GPU does not care about the grouping as the - // display list is parsed by the DMA unit in the CPU). + // performance reasons using tagless primitives (the GPU does not care + // about the grouping as the display list is parsed by the CPU). + DR_ENV *prim = &(env->dr_env); setaddr(prim, ot); setlen(prim, 5); // Texture page (reset active page and set dither/mask bits) - prim->code[0] = 0xe1000000 | env->tpage; - prim->code[0] |= (env->dtd & 1) << 9; - prim->code[0] |= (env->dfe & 1) << 10; + setDrawTPage_T(&(prim->tpage), env->dfe & 1, env->dtd & 1, env->tpage); // Texture window - prim->code[1] = 0xe2000000; - prim->code[1] |= _get_window_mask(env->tw.w); - prim->code[1] |= _get_window_mask(env->tw.h) << 5; - prim->code[1] |= (env->tw.x & 0xf8) << 7; // ((tw.x / 8) & 0x1f) << 10 - prim->code[1] |= (env->tw.y & 0xf8) << 12; // ((tw.y / 8) & 0x1f) << 15 - - // Set drawing area top left - prim->code[2] = 0xe3000000; - prim->code[2] |= env->clip.x & 0x3ff; - prim->code[2] |= (env->clip.y & 0x3ff) << 10; - - // Set drawing area bottom right - prim->code[3] = 0xe4000000; - prim->code[3] |= (env->clip.x + (env->clip.w - 1)) & 0x3ff; - prim->code[3] |= ((env->clip.y + (env->clip.h - 1)) & 0x3ff) << 10; - - // Set drawing offset - prim->code[4] = 0xe5000000; - prim->code[4] |= (env->clip.x + env->ofs[0]) & 0x7ff; - prim->code[4] |= ((env->clip.y + env->ofs[1]) & 0x7ff) << 11; + //setTexWindow_T(&(prim->twin), &(env->tw)); + prim->twin.code[0] = 0xe2000000; + prim->twin.code[0] |= _get_window_mask(env->tw.w); + prim->twin.code[0] |= _get_window_mask(env->tw.h) << 5; + prim->twin.code[0] |= (env->tw.x & 0xf8) << 7; // ((tw.x / 8) & 0x1f) << 10 + prim->twin.code[0] |= (env->tw.y & 0xf8) << 12; // ((tw.y / 8) & 0x1f) << 15 + + // Set drawing area + setDrawArea_T(&(prim->area), &(env->clip)); + setDrawOffset_T( + &(prim->offset), + env->clip.x + env->ofs[0], + env->clip.y + env->ofs[1] + ); if (env->isbg) { + FILL_T *fill = &(prim->fill); setlen(prim, 8); // Rectangle fill // FIXME: reportedly this command doesn't accept height values >511... - prim->code[5] = 0x02000000; - //prim->code[5] |= env->r0 | (env->g0 << 8) | (env->b0 << 16); - //prim->code[6] = env->clip.x; - //prim->code[6] |= env->clip.y << 16; - prim->code[5] |= *((const uint32_t *) &(env->isbg)) >> 8; - prim->code[6] = *((const uint32_t *) &(env->clip.x)); - prim->code[7] = env->clip.w; - prim->code[7] |= _min(env->clip.h, 0x1ff) << 16; + setFill_T(fill); + setColor0(fill, *((const uint32_t *) &(env->isbg)) >> 8); + setXY0(fill, env->clip.x, env->clip.y); + setWH(fill, env->clip.w, _min(env->clip.h, 0x1ff)); } return EnqueueDrawOp((void *) &DrawOTag2, (uint32_t) prim, 0, 0); diff --git a/libpsn00b/psxgpu/image.c b/libpsn00b/psxgpu/image.c index 09c7ab9..61ac484 100644 --- a/libpsn00b/psxgpu/image.c +++ b/libpsn00b/psxgpu/image.c @@ -1,6 +1,6 @@ /* * PSn00bSDK GPU library (image and VRAM transfer functions) - * (C) 2022 spicyjpeg - MPL licensed + * (C) 2022-2023 spicyjpeg - MPL licensed * * TODO: MoveImage() is currently commented out as it won't trigger a DMA IRQ, * making it unusable as a draw queue command. A way around this (perhaps using @@ -14,7 +14,7 @@ #include #define QUEUE_LENGTH 16 -#define DMA_CHUNK_LENGTH 8 +#define DMA_CHUNK_LENGTH 16 /* Internal globals */ @@ -38,6 +38,9 @@ static void _dma_transfer(const RECT *rect, uint32_t *data, int write) { length += DMA_CHUNK_LENGTH - 1; } + while (!(GPU_GP1 & (1 << 26))) + __asm__ volatile(""); + GPU_GP1 = 0x04000000; // Disable DMA request GPU_GP0 = 0x01000000; // Flush cache @@ -50,6 +53,9 @@ static void _dma_transfer(const RECT *rect, uint32_t *data, int write) { // Enable DMA request, route to GP0 (2) or from GPU_READ (3) GPU_GP1 = 0x04000002 | (write ^ 1); + while (DMA_CHCR(DMA_GPU) & (1 << 24)) + __asm__ volatile(""); + DMA_MADR(DMA_GPU) = (uint32_t) data; if (length < DMA_CHUNK_LENGTH) DMA_BCR(DMA_GPU) = 0x00010000 | length; @@ -103,6 +109,9 @@ void StoreImage2(const RECT *rect, uint32_t *data) { } void MoveImage2(const RECT *rect, int x, int y) { + while (!(GPU_GP1 & (1 << 26))) + __asm__ volatile(""); + GPU_GP0 = 0x80000000; //GPU_GP0 = rect->x | (rect->y << 16); GPU_GP0 = *((const uint32_t *) &(rect->x)); -- cgit v1.2.3 From 8e3a757d4d7d5dfc62f69ce4ede08f1cf79e3461 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Tue, 4 Apr 2023 00:46:20 +0200 Subject: Add IsIdleGPU(), tweak psxgpu.h, fix mdec/strvideo --- examples/demos/n00bdemo/main.c | 29 ++++++++++++------------- examples/mdec/strvideo/main.c | 19 +++++++++++------ libpsn00b/include/psxgpu.h | 48 +++++++++++++++++++++++++++--------------- libpsn00b/include/psxpress.h | 5 ++--- libpsn00b/psxgpu/common.c | 15 +++++++++++++ libpsn00b/psxpress/vlc2.c | 11 ++++------ 6 files changed, 78 insertions(+), 49 deletions(-) (limited to 'libpsn00b/include/psxgpu.h') diff --git a/examples/demos/n00bdemo/main.c b/examples/demos/n00bdemo/main.c index c9ca3ce..55dbbc4 100644 --- a/examples/demos/n00bdemo/main.c +++ b/examples/demos/n00bdemo/main.c @@ -358,10 +358,9 @@ void stencilstuff() { /* The stencil demo is achieved by utilizing the mask bit setting primitive GP0(E6h). The structure of this primitive is defined as - DR_MASK initialized and set by setDrawMask(). These are not available - in Sony's SDK by default. + DR_STP initialized and set by setDrawStp(). - The DR_MASK primitive controls mask bit operations for drawing + The DR_STP primitive controls mask bit operations for drawing primitives such as setting mask bits on every pixel drawn or mask bit test where pixels won't be drawn on pixels with the mask bit set. It applies to most graphics drawing primitives except VRAM fill. @@ -373,10 +372,10 @@ void stencilstuff() { bit operation disabled. The stencil effect featured in this demo is achieved by enabling set - mask bit with DR_MASK, drawing semi-transparent primitives using + mask bit with DR_STP, drawing semi-transparent primitives using additive blending but color is all zero to make it completely invisible but is enough to update the mask bits, disable mask set bit but enable - mask test with DR_MASK and then drawing a rectangle that fills the + mask test with DR_STP and then drawing a rectangle that fills the entire screen. Semi-transparency mask in textures must not be used when drawing the scene that will be 'below' the mask layer. */ @@ -384,7 +383,7 @@ void stencilstuff() { int spin=0; - DR_MASK *mask; + DR_STP *mask; TILE *rect; SC_OT s_ot; @@ -430,10 +429,10 @@ void stencilstuff() { // Sort mask primitive that enables setting mask bits - mask = (DR_MASK*)nextpri; - setDrawMask( mask, 1, 0 ); + mask = (DR_STP*)nextpri; + setDrawStp( mask, 1, 0 ); addPrim( ot[db]+20, mask ); - nextpri += sizeof(DR_MASK); + nextpri += sizeof(DR_STP); // Sort the stars @@ -465,10 +464,10 @@ void stencilstuff() { // Sort mask primitive that enables mask bit test - mask = (DR_MASK*)nextpri; - setDrawMask( mask, 0, 1 ); + mask = (DR_STP*)nextpri; + setDrawStp( mask, 0, 1 ); addPrim( ot[db]+18, mask ); - nextpri += sizeof(DR_MASK); + nextpri += sizeof(DR_STP); // Sort rectangle that fills the screen @@ -482,10 +481,10 @@ void stencilstuff() { // Clear all mask settings - mask = (DR_MASK*)nextpri; - setDrawMask( mask, 0, 0 ); + mask = (DR_STP*)nextpri; + setDrawStp( mask, 0, 0 ); addPrim( ot[db]+15, mask ); - nextpri += sizeof(DR_MASK); + nextpri += sizeof(DR_STP); // Sort overlay then display diff --git a/examples/mdec/strvideo/main.c b/examples/mdec/strvideo/main.c index 57cb6ef..853e0c2 100644 --- a/examples/mdec/strvideo/main.c +++ b/examples/mdec/strvideo/main.c @@ -189,8 +189,15 @@ void cd_sector_handler(void) { return; // If this sector is actually part of a new frame, validate the sectors - // that have been read so far and flip the bitstream data buffers. - if (sector_header.frame_id != str_ctx.frame_id) { + // that have been read so far and flip the bitstream data buffers. If the + // frame number is actually lower than the current one, assume the drive + // has started reading another .STR file and stop playback. + if ((int) sector_header.frame_id < str_ctx.frame_id) { + str_ctx.frame_ready = -1; + return; + } + + if ((int) sector_header.frame_id > str_ctx.frame_id) { // Do not set the ready flag if any sector has been missed. if (str_ctx.sector_count) str_ctx.dropped_frames++; @@ -263,11 +270,9 @@ void init_stream(void) { CdReadyCallback(&cd_event_handler); ExitCriticalSection(); - // Set the maximum amount of data DecDCTvlc() can output and copy the - // lookup table used for decompression to the scratchpad area. This is - // optional but makes the decompressor slightly faster. See the libpsxpress - // documentation for more details. - DecDCTvlcSize(0x8000); + // Copy the lookup table used for frame decompression to the scratchpad + // area. This is optional but makes the decompressor slightly faster. See + // the libpsxpress documentation for more details. DecDCTvlcCopyTableV3((VLC_TableV3 *) 0x1f800000); str_ctx.cur_frame = 0; diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h index 2329908..78d8342 100644 --- a/libpsn00b/include/psxgpu.h +++ b/libpsn00b/include/psxgpu.h @@ -83,7 +83,7 @@ typedef enum _GPU_VideoMode { (p)->u0 = (_u0), (p)->v0 = (_v0), \ (p)->u1 = (_u1), (p)->v1 = (_v1), \ (p)->u2 = (_u2), (p)->v2 = (_v2) - + #define setUV4(p, _u0, _v0, _u1, _v1, _u2, _v2, _u3, _v3) \ (p)->u0 = (_u0), (p)->v0 = (_v0), \ (p)->u1 = (_u1), (p)->v1 = (_v1), \ @@ -202,38 +202,48 @@ typedef enum _GPU_VideoMode { #define setTexWindow_T(p, r) \ (p)->code[0] = (0xe2000000 | \ - ((r)->w % 32) | \ - (((r)->h % 32) << 5) | \ - (((r)->x % 32) << 10) | \ - (((r)->y % 32) << 15) \ + ((r)->w & 0x1f) | \ + (((r)->h & 0x1f) << 5) | \ + (((r)->x & 0x1f) << 10) | \ + (((r)->y & 0x1f) << 15) \ ) #define setTexWindow(p, r) \ setlen(p, 1), setTexWindow_T(p, r) -#define setDrawArea_T(p, r) \ +#define setDrawAreaXY_T(p, _x0, _y0, _x1, _y1) \ (p)->code[0] = (0xe3000000 | \ - ((r)->x % 1024) | \ - (((r)->y % 1024) << 10) \ + ((_x0) & 0x3ff) | \ + (((_y0) & 0x3ff) << 10) \ ), \ (p)->code[1] = (0xe4000000 | \ - (((r)->x + (r)->w - 1) % 1024) | \ - ((((r)->y + (r)->h - 1) % 1024) << 10) \ + ((_x1) & 0x3ff) | \ + (((_y1) & 0x3ff) << 10) \ + ) +#define setDrawAreaXY(p, _x0, _y0, _x1, _y1) \ + setlen(p, 2), setDrawAreaXY_T(p, _x0, _y0, _x1, _y1) + +#define setDrawArea_T(p, r) \ + setDrawAreaXY_T(p, \ + (r)->x, \ + (r)->y, \ + (r)->x + (r)->w - 1, \ + (r)->y + (r)->h - 1 \ ) #define setDrawArea(p, r) \ setlen(p, 2), setDrawArea_T(p, r) #define setDrawOffset_T(p, _x, _y) \ (p)->code[0] = (0xe5000000 | \ - ((_x) % 1024) | \ - (((_y) % 1024) << 11) \ + ((_x) & 0x7ff) | \ + (((_y) & 0x7ff) << 11) \ ) #define setDrawOffset(p, _x, _y) \ setlen(p, 1), setDrawOffset_T(p, _x, _y) -#define setDrawMask_T(p, sb, mt) \ - (p)->code[0] = (0xe6000000 | (sb) | ((mt) << 1)) -#define setDrawMask(p, sb, mt) \ - setlen(p, 1), setDrawMask_T(p, sb, mt) +#define setDrawStp_T(p, pbw, mt) \ + (p)->code[0] = (0xe6000000 | (pbw) | ((mt) << 1)) +#define setDrawStp(p, pbw, mt) \ + setlen(p, 1), setDrawStp_T(p, pbw, mt) /* Primitive structure definitions */ @@ -469,7 +479,7 @@ _DEF_PRIM(DR_TWIN, _DEF_PRIM(DR_TPAGE, uint32_t code[1]; ) -_DEF_PRIM(DR_MASK, +_DEF_PRIM(DR_STP, uint32_t code[1]; ) @@ -481,6 +491,9 @@ _DEF_PRIM(DR_ENV, FILL_T fill; ) +#undef _DEF_PRIM +#undef _DEF_ALIAS + /* Structure definitions */ typedef struct _RECT { @@ -545,6 +558,7 @@ void PutDrawEnv(DRAWENV *env); void PutDrawEnvFast(DRAWENV *env); int GetODE(void); +int IsIdleGPU(int timeout); int VSync(int mode); void *VSyncHaltFunction(void (*func)(void)); void *VSyncCallback(void (*func)(void)); diff --git a/libpsn00b/include/psxpress.h b/libpsn00b/include/psxpress.h index c3b13f4..ea0c2ec 100644 --- a/libpsn00b/include/psxpress.h +++ b/libpsn00b/include/psxpress.h @@ -246,8 +246,6 @@ int DecDCToutSync(int mode); * can be different). If max_size = 0, the entire frame will always be decoded * in one shot. * - * Only bitstream version 2 is currently supported. - * * WARNING: InitGeom() must be called prior to using DecDCTvlcStart() for the * first time. Attempting to call this function with the GTE disabled will * result in a crash. @@ -411,7 +409,8 @@ void DecDCTvlcCopyTableV3(VLC_TableV3 *addr); * buffer can be different). If max_size = 0, the entire frame will always be * decoded in one shot. * - * Only bitstream version 2 is currently supported. + * This function only supports decoding version 1 and 2 bitstreams. Use + * DecDCTvlcStart() to decode a version 3 bitstream. * * @param ctx Pointer to VLC_Context structure (which will be initialized) * @param buf diff --git a/libpsn00b/psxgpu/common.c b/libpsn00b/psxgpu/common.c index 537f672..e354261 100644 --- a/libpsn00b/psxgpu/common.c +++ b/libpsn00b/psxgpu/common.c @@ -321,3 +321,18 @@ void DrawOTag2(const uint32_t *ot) { DMA_BCR(DMA_GPU) = 0; DMA_CHCR(DMA_GPU) = 0x01000401; } + +/* Queue pause/resume API */ + +int IsIdleGPU(int timeout) { + if (timeout <= 0) + timeout = 1; + + for (; timeout; timeout--) { + if (GPU_GP1 & (1 << 26)) + return 0; + } + + //_sdk_log("IsIdleGPU() timeout\n"); + return -1; +} diff --git a/libpsn00b/psxpress/vlc2.c b/libpsn00b/psxpress/vlc2.c index 24c54ce..7d9d9f3 100644 --- a/libpsn00b/psxpress/vlc2.c +++ b/libpsn00b/psxpress/vlc2.c @@ -123,7 +123,7 @@ int __attribute__((optimize(3))) DecDCTvlcContinue2( *output = (uint16_t) _get_bits_unsigned(22); _advance_window(22); } else if (window >> 24) { - // The first lookup table is for codes that not start with + // The first lookup table is for codes that do not start with // 00000000. value = _vlc_huffman_table2->ac[_get_bits_unsigned(13)]; _advance_window(value >> 16); @@ -136,12 +136,9 @@ int __attribute__((optimize(3))) DecDCTvlcContinue2( *output = (uint16_t) value; } } else { - // Parse the DC (first) coefficient for this block. Version 2 - // simply stores the signed 10-bit value as-is, while version 3 - // uses a delta encoding combined with a compression method similar - // to exp-Golomb. + // Parse the DC (first) coefficient for this block. if (is_v3) { - // TODO: version 3 is currently not supported. + // This implementation does not support version 3. return -1; } else { value = _get_bits_unsigned(10); @@ -161,7 +158,7 @@ int __attribute__((optimize(3))) DecDCTvlcContinue2( // time and processes each 16-bit word starting from the the MSB, so an // endianness conversion is necessary to preserve bit order when // reading 32 bits at a time. Also note that the PS1 CPU is not capable - // of shifting by more than 31 bits - it will shift by 0 bits instead! + // of shifting by >=31 bits - it will shift by (N % 32) bits instead! if (bit_offset < 0) { window = next_window << (-bit_offset); bit_offset += 32; -- cgit v1.2.3 From b4242acc35c522bd4d4a951a84933ba6f80d2015 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Wed, 5 Apr 2023 01:30:55 +0200 Subject: Clean up all headers, add and rename some BIOS APIs --- examples/system/childexec/parent.c | 2 +- examples/system/console/main.c | 2 +- libpsn00b/include/assert.h | 9 +-- libpsn00b/include/ctype.h | 5 +- libpsn00b/include/dlfcn.h | 5 +- libpsn00b/include/elf.h | 18 +----- libpsn00b/include/hwregs_c.h | 5 +- libpsn00b/include/inline_c.h | 5 +- libpsn00b/include/ioctl.h | 19 ------ libpsn00b/include/lzconfig.h | 68 ---------------------- libpsn00b/include/lzp/lzp.h | 34 ++++++----- libpsn00b/include/lzp/lzqlp.h | 32 +++++++++- libpsn00b/include/malloc.h | 8 --- libpsn00b/include/psxapi.h | 116 +++++++++++++++++++++++++------------ libpsn00b/include/psxcd.h | 5 +- libpsn00b/include/psxetc.h | 5 +- libpsn00b/include/psxgpu.h | 22 +++++-- libpsn00b/include/psxgte.h | 5 +- libpsn00b/include/psxkernel.h | 45 -------------- libpsn00b/include/psxpad.h | 5 +- libpsn00b/include/psxpress.h | 5 +- libpsn00b/include/psxsio.h | 5 +- libpsn00b/include/psxsn.h | 5 +- libpsn00b/include/psxspu.h | 27 +++++++-- libpsn00b/include/stdio.h | 41 +++++-------- libpsn00b/include/stdlib.h | 7 +-- libpsn00b/include/string.h | 7 +-- libpsn00b/include/strings.h | 5 +- libpsn00b/include/sys/fcntl.h | 12 ++-- libpsn00b/include/sys/ioctl.h | 13 +++++ libpsn00b/include/sys/types.h | 12 ++-- libpsn00b/lzp/bit.h | 7 +-- libpsn00b/lzp/compress.c | 16 ++--- libpsn00b/lzp/lzconfig.h | 42 ++++++++++++++ libpsn00b/lzp/lzp.h | 34 ++++++----- libpsn00b/lzp/lzqlp.h | 32 +++++++++- libpsn00b/psxapi/drivers.s | 32 +++++----- libpsn00b/psxapi/fs.s | 18 ++++-- libpsn00b/psxapi/stdio.s | 36 ++++++++++-- libpsn00b/psxapi/stubs.json | 62 ++++++++++++++++---- libpsn00b/psxapi/sys.s | 58 +++++++++++++------ libpsn00b/psxetc/interrupts.c | 4 +- libpsn00b/psxsio/tty.c | 10 ++-- tools/CMakeLists.txt | 6 +- tools/lzpack/lzp/lzconfig.h | 68 ---------------------- 45 files changed, 491 insertions(+), 488 deletions(-) delete mode 100644 libpsn00b/include/ioctl.h delete mode 100644 libpsn00b/include/lzconfig.h delete mode 100644 libpsn00b/include/malloc.h delete mode 100644 libpsn00b/include/psxkernel.h create mode 100644 libpsn00b/include/sys/ioctl.h create mode 100644 libpsn00b/lzp/lzconfig.h delete mode 100644 tools/lzpack/lzp/lzconfig.h (limited to 'libpsn00b/include/psxgpu.h') diff --git a/examples/system/childexec/parent.c b/examples/system/childexec/parent.c index 79c81f1..cfed11c 100644 --- a/examples/system/childexec/parent.c +++ b/examples/system/childexec/parent.c @@ -273,7 +273,7 @@ extern char child_exe[]; void run_child(void) { // Arguments for the child program - char *args[] = + const char *args[] = { "SAMPLE=0", "SESSION=1", diff --git a/examples/system/console/main.c b/examples/system/console/main.c index b4f91b4..845ca95 100644 --- a/examples/system/console/main.c +++ b/examples/system/console/main.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libpsn00b/include/assert.h b/libpsn00b/include/assert.h index 26b2023..8f8df74 100644 --- a/libpsn00b/include/assert.h +++ b/libpsn00b/include/assert.h @@ -2,12 +2,11 @@ * PSn00bSDK assert macro and internal logging * (C) 2022-2023 spicyjpeg - MPL licensed * - * Note that the _sdk_log() macro is used internally by PSn00bSDK to output - * debug messages and warnings. + * The _sdk_*() macros are used internally by PSn00bSDK to output messages when + * building in debug mode. */ -#ifndef __ASSERT_H -#define __ASSERT_H +#pragma once #include @@ -59,5 +58,3 @@ void _assert_abort(const char *file, int line, const char *expr); } #endif - -#endif diff --git a/libpsn00b/include/ctype.h b/libpsn00b/include/ctype.h index ad78397..2fe0a42 100644 --- a/libpsn00b/include/ctype.h +++ b/libpsn00b/include/ctype.h @@ -3,8 +3,7 @@ * (C) 2019-2023 PSXSDK authors, Lameguy64, spicyjpeg - MPL licensed */ -#ifndef __CTYPE_H -#define __CTYPE_H +#pragma once #ifdef __cplusplus extern "C" { @@ -23,5 +22,3 @@ int toupper(int ch); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/dlfcn.h b/libpsn00b/include/dlfcn.h index 6192430..5e1e3b6 100644 --- a/libpsn00b/include/dlfcn.h +++ b/libpsn00b/include/dlfcn.h @@ -3,8 +3,7 @@ * (C) 2021-2022 spicyjpeg - MPL licensed */ -#ifndef __DLFCN_H -#define __DLFCN_H +#pragma once #include #include @@ -215,5 +214,3 @@ void *DL_GetDLLSymbol(const DLL *dll, const char *name); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/elf.h b/libpsn00b/include/elf.h index abfb3d5..b0ddf71 100644 --- a/libpsn00b/include/elf.h +++ b/libpsn00b/include/elf.h @@ -9,8 +9,7 @@ * converted to enums. */ -#ifndef __ELF_H -#define __ELF_H +#pragma once #include @@ -121,18 +120,3 @@ typedef enum { STT_LOPROC = 13, /* Start of processor-specific */ STT_HIPROC = 15 /* End of processor-specific */ } Elf32_st_type; - -// If you need to add more constants, you may use the following Python snippet -// to quickly convert #defines to enums: -/* -import re -t = """""" -t = re.sub( - r"(0x[0-9a-f]+|0b[01]+|[0-9]+)", - lambda m: f"= {m.group(1)},", - t.replace("#define ", "\t").replace("#define\t", "\t") -) -print("typedef enum {\n" + t + "\n} NAME;") -*/ - -#endif diff --git a/libpsn00b/include/hwregs_c.h b/libpsn00b/include/hwregs_c.h index 7015101..3fd5b2c 100644 --- a/libpsn00b/include/hwregs_c.h +++ b/libpsn00b/include/hwregs_c.h @@ -3,8 +3,7 @@ * (C) 2022 spicyjpeg - MPL licensed */ -#ifndef __HWREGS_C_H -#define __HWREGS_C_H +#pragma once #include @@ -130,5 +129,3 @@ #define BUS_EXP2_CFG _MMIO32(IOBASE | 0x101c) #define BUS_COM_DELAY _MMIO32(IOBASE | 0x1020) #define BUS_RAM_SIZE _MMIO32(IOBASE | 0x1060) - -#endif diff --git a/libpsn00b/include/inline_c.h b/libpsn00b/include/inline_c.h index 5facc1c..cb550b9 100644 --- a/libpsn00b/include/inline_c.h +++ b/libpsn00b/include/inline_c.h @@ -16,8 +16,7 @@ * compiled object files. */ -#ifndef _INLINE_C_H -#define _INLINE_C_H +#pragma once /* GTE load macros */ @@ -1612,5 +1611,3 @@ : "g"( r0 ) ) #define gte_mvmva_b(sf, mx, v, cv, lm) gte_mvmva_core_b( 0x0400012 | \ ((sf)<<19) | ((mx)<<17) | ((v)<<15) | ((cv)<<13) | ((lm)<<10) ) - -#endif // _INLINE_C_H diff --git a/libpsn00b/include/ioctl.h b/libpsn00b/include/ioctl.h deleted file mode 100644 index 5c56422..0000000 --- a/libpsn00b/include/ioctl.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _IOCTL_H -#define _IOCTL_H - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef EOF -#define EOF -1 -#endif - -// General -#define FIONBLOCK (('f'<<8)|1) -#define FIOCSCAN (('f'<<8)|2) - -// disk -#define DIO_FORMAT (('d'<<8)|1) - -#endif \ No newline at end of file diff --git a/libpsn00b/include/lzconfig.h b/libpsn00b/include/lzconfig.h deleted file mode 100644 index cb8a830..0000000 --- a/libpsn00b/include/lzconfig.h +++ /dev/null @@ -1,68 +0,0 @@ -/*! \file lzconfig.h - * \brief Library configuration header - * \details Define settings will only take effect when you recompile the library. - */ - -#ifndef _LZP_CONFIG_H -#define _LZP_CONFIG_H - - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - - -/* Set to TRUE to compile without data compression routines useful if you - * plan to use this library on a program that does not require said routines - * especially on a platform with limited memory (such as the PlayStation). - * - * This define will rule out lzCompress(), lzSetHashSizes() and - * lzResetHashSizes() functions and their associated functions. - */ -#define LZP_NO_COMPRESS TRUE - - -/* Set to TRUE to make default compression table sizes to maximum and works best - * when compressing large amounts of data. LZP_USE_MALLOC must be set to TRUE to - * prevent stack overflow errors. - * - * Do not enable this if you plan to compile for a platform with limited memory - * otherwise, the library will consume all memory and crash the system. - * - * This define only affects lzCompress(). - */ -#define LZP_MAX_COMPRESS FALSE - - -/* Uncomment to make the library use malloc() instead of array initializers to - * allocate hash tables. Enabling this is a must if you plan to use large hash - * and window table sizes. - */ -#define LZP_USE_MALLOC FALSE - - -/* Hash table sizes (in power-of-two multiple units) - * - * These define only affect lzCompress(). - */ -#if LZP_MAX_COMPRESS == TRUE - -// Minimal defaults -#define LZP_WINDOW_SIZE 17 -#define LZP_HASH1_SIZE 8 -#define LZP_HASH2_SIZE 10 - -#else - -// Maximum defaults -#define LZP_WINDOW_SIZE 17 -#define LZP_HASH1_SIZE 22 -#define LZP_HASH2_SIZE 24 - -#endif - - -#endif // _LZP_CONFIG_H diff --git a/libpsn00b/include/lzp/lzp.h b/libpsn00b/include/lzp/lzp.h index 456de02..1aeea30 100644 --- a/libpsn00b/include/lzp/lzp.h +++ b/libpsn00b/include/lzp/lzp.h @@ -1,20 +1,29 @@ -/*! \file lzp.h - * \brief Main library header +/* + * liblzp data compression library + * (C) 2019 Lameguy64 - MPL licensed */ -/*! \mainpage - * \version 0.20b - * \author John Wilbert 'Lameguy64' Villamor +/** + * @file lzp.h + * @brief Utility library for file bundling and compression * - * \section creditsSection Credits - * - LZ77 data compression/decompression routines based from Ilya Muravyov's - * crush.cpp released under public domain. Refined and ported to C by Lameguy64. - * - CRC calculation routines based from Lammert Bies' lib_crc routines. + * @details This library implements a simple in-memory archive format which + * can be used to package and compress assets for faster loading, as well as a + * generic LZ77 compressor and matching decompressor. Two archive formats are + * supported, one uncompressed (.QLP) and one with individually compressed + * entries (.LZP). * + * This header provides the LZ77 compression API and functions to parse and + * decompress .LZP archives after they have been loaded into memory. + * + * @section creditsSection Credits + * - LZ77 data compression/decompression routines based from Ilya Muravyov's + * crush.cpp released under public domain. Refined and ported to C by + * Lameguy64. + * - CRC calculation routines based from Lammert Bies' lib_crc routines. */ -#ifndef _LZPACK_H -#define _LZPACK_H +#pragma once #include #ifdef _WIN32 @@ -218,6 +227,3 @@ int lzpUnpackFile(void* buff, const LZP_HEAD* lzpack, int fileNum); #ifdef __cplusplus } #endif - - -#endif // _LZPACK_H diff --git a/libpsn00b/include/lzp/lzqlp.h b/libpsn00b/include/lzp/lzqlp.h index 32ce0d7..127f263 100644 --- a/libpsn00b/include/lzp/lzqlp.h +++ b/libpsn00b/include/lzp/lzqlp.h @@ -1,5 +1,23 @@ -#ifndef _QLP_H -#define _QLP_H +/* + * liblzp data compression library + * (C) 2019 Lameguy64 - MPL licensed + */ + +/** + * @file lzqlp.h + * @brief Utility library for file bundling + * + * @details This library implements a simple in-memory archive format which + * can be used to package and compress assets for faster loading, as well as a + * generic LZ77 compressor and matching decompressor. Two archive formats are + * supported, one uncompressed (.QLP) and one with individually compressed + * entries (.LZP). + * + * This header provides functions to parse .QLP archives and retrieve pointers + * to their contents after they have been loaded into memory. + */ + +#pragma once #include #ifdef _WIN32 @@ -23,9 +41,17 @@ typedef struct { uint32_t offs; } QLP_FILE; + +// Function prototypes +#ifdef __cplusplus +extern "C" { +#endif + int qlpFileCount(const QLP_HEAD* qlpfile); const QLP_FILE* qlpFileEntry(int index, const QLP_HEAD* qlpfile); const void* qlpFileAddr(int index, const QLP_HEAD* qlpfile); int qlpFindFile(char* fileName, const QLP_HEAD* qlpfile); -#endif // _QLP_H \ No newline at end of file +#ifdef __cplusplus +} +#endif diff --git a/libpsn00b/include/malloc.h b/libpsn00b/include/malloc.h deleted file mode 100644 index 75c3711..0000000 --- a/libpsn00b/include/malloc.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _MALLOC_H -#define _MALLOC_H - -#warning " is deprecated, include instead" - -#include - -#endif // _MALLOC_H \ No newline at end of file diff --git a/libpsn00b/include/psxapi.h b/libpsn00b/include/psxapi.h index 7353ed2..35ee040 100644 --- a/libpsn00b/include/psxapi.h +++ b/libpsn00b/include/psxapi.h @@ -1,10 +1,21 @@ /* * PSn00bSDK kernel API library - * (C) 2019-2022 Lameguy64, spicyjpeg - MPL licensed + * (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed */ -#ifndef __PSXAPI_H -#define __PSXAPI_H +/** + * @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 #include @@ -12,13 +23,38 @@ /* Definitions */ -#define DescHW 0xf0000000 -#define DescSW 0xf4000000 - -#define HwCARD (DescHW|0x11) -#define HwCARD_1 (DescHW|0x12) -#define HwCARD_0 (DescHW|0x13) -#define SwCARD (DescHW|0x02) +// 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 @@ -135,8 +171,6 @@ struct JMP_BUF { uint32_t gp; }; -// Not recommended to use these functions to install IRQ handlers - typedef struct { uint32_t *next; uint32_t *func2; @@ -158,7 +192,8 @@ typedef struct { #define FastExitCriticalSection() \ (IRQ_MASK = __saved_irq_mask) -/*#define FastEnterCriticalSection() { \ +#if 0 +#define FastEnterCriticalSection() { \ uint32_t r0, r1; \ __asm__ volatile( \ "mfc0 %0, $12;" \ @@ -179,9 +214,10 @@ typedef struct { "nop;" \ : "=r"(r0) :: \ ); \ -}*/ +} +#endif -/* API */ +/* BIOS API */ #ifdef __cplusplus extern "C" { @@ -199,23 +235,28 @@ int DisableEvent(int event); void DeliverEvent(uint32_t cl, uint32_t spec); void UnDeliverEvent(uint32_t cl, uint32_t spec); -int open(const char *name, int mode); +int open(const char *path, int mode); int close(int fd); -int seek(int fd, uint32_t offset, int mode); -int read(int fd, uint8_t *buff, size_t len); -int write(int fd, const uint8_t *buff, size_t len); +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 *name); -int chdir(const char *path); +int erase(const char *path); +int undelete(const char *path); +int cd(const char *path); -//#define cd(p) chdir(p) +int _get_errno(void); +int _get_error(int fd); -int AddDev(DCB *dcb); -int DelDev(const char *name); -void ListDev(void); -void AddDummyTty(void); +int AddDrv(DCB *dcb); +int DelDrv(const char *name); +void ListDrv(void); +void add_nullcon_driver(void); int EnterCriticalSection(void); void ExitCriticalSection(void); @@ -254,30 +295,33 @@ int ResetRCnt(int spec); void ChangeClearPAD(int mode); void ChangeClearRCnt(int t, int m); -uint32_t OpenTh(uint32_t (*func)(), uint32_t sp, uint32_t gp); -int CloseTh(uint32_t thread); -int ChangeTh(uint32_t thread); +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, char **argv); +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 SetDefaultExitFromException(void); -void SetCustomExitFromException(const struct JMP_BUF *buf); +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 *_kernel_malloc(int size); -void _kernel_free(void *ptr); +void *alloc_kernel_memory(int size); +void free_kernel_memory(void *ptr); void _boot(void); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/psxcd.h b/libpsn00b/include/psxcd.h index 78c90db..fc9c391 100644 --- a/libpsn00b/include/psxcd.h +++ b/libpsn00b/include/psxcd.h @@ -21,8 +21,7 @@ * library extension is considered for future development. */ -#ifndef __PSXCD_H -#define __PSXCD_H +#pragma once #include @@ -1073,5 +1072,3 @@ int CdLoadSession(int session); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/psxetc.h b/libpsn00b/include/psxetc.h index e45abf4..8dd1dd5 100644 --- a/libpsn00b/include/psxetc.h +++ b/libpsn00b/include/psxetc.h @@ -13,8 +13,7 @@ * separate header). */ -#ifndef __PSXETC_H -#define __PSXETC_H +#pragma once /* IRQ and DMA channel definitions */ @@ -239,5 +238,3 @@ void StopCallback(void); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h index 78d8342..9b99fe9 100644 --- a/libpsn00b/include/psxgpu.h +++ b/libpsn00b/include/psxgpu.h @@ -3,8 +3,24 @@ * (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed */ -#ifndef __PSXGPU_H -#define __PSXGPU_H +/** + * @file psxgpu.h + * @brief GPU library header + * + * @details This library provides access to the PS1's GPU through a fully + * asynchronous command queue, which allows GPU commands to be batched and sent + * efficiently in the background without stalling the CPU. Helper structures + * and macros to initialize, generate and link GPU display lists in memory are + * also provided, in addition to support for asynchronous VRAM data transfers + * and a debug font API that can be used to easily draw text overlays for + * debugging purposes. + * + * This library is for the most part a drop-in replacement for the official + * SDK's GPU library and is only missing a handful of functions, mainly related + * to Kanji debug fonts and command queue pausing. + */ + +#pragma once #include #include @@ -603,5 +619,3 @@ char *FntFlush(int id); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/psxgte.h b/libpsn00b/include/psxgte.h index 91dfd6a..2200a55 100644 --- a/libpsn00b/include/psxgte.h +++ b/libpsn00b/include/psxgte.h @@ -14,8 +14,7 @@ * registers and issue commands to the GTE. */ -#ifndef __PSXGTE_H -#define __PSXGTE_H +#pragma once #include @@ -259,5 +258,3 @@ void Square0(VECTOR *v0, VECTOR *v1); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/psxkernel.h b/libpsn00b/include/psxkernel.h deleted file mode 100644 index 0c55bcb..0000000 --- a/libpsn00b/include/psxkernel.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _PSXKERNEL_H -#define _PSXKERNEL_H - -// Event descriptors -#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 - -// Hardware events -#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) // Memory card (unused) -#define HwCard_1 (DescHW|0x13) // Memory card (unused) -#define SwCARD (DescSW|0x01) // Memory card (higher level BIOS functions) -#define SwMATH (DescSW|0x02) // Libmath related apparently, unknown purpose - -#define RCntCNT0 (DescRC|0x00) // Root counter 0 (dot clock) -#define RCntCNT1 (DescRC|0x01) // Horizontal sync -#define RCntCNT2 (DescRC|0x02) // 1/8 of system clock -#define RCntCNT3 (DescRC|0x03) // Vertical blank - -#define RCntMdINTR 0x1000 // General interrupt -#define RCntMdNOINTR 0x2000 // New device -#define RCntMdSC 0x0001 // Counter becomes zero -#define RCntMdSP 0x0000 // Unknown purpose -#define RCntMdFR 0x0000 -#define RCntMdGATE 0x0010 // Command acknowledged - -#endif // _PSXKERNEL_H \ No newline at end of file diff --git a/libpsn00b/include/psxpad.h b/libpsn00b/include/psxpad.h index 32f7f8a..09f28c4 100644 --- a/libpsn00b/include/psxpad.h +++ b/libpsn00b/include/psxpad.h @@ -11,8 +11,7 @@ * Reference: https://gist.github.com/scanlime/5042071 */ -#ifndef _PSXPAD_H -#define _PSXPAD_H +#pragma once #include @@ -234,5 +233,3 @@ typedef struct __attribute__((packed)) _MemCardRequest { uint8_t checksum; // = lba_h ^ lba_l ^ data (CMD_WRITE only) uint8_t dummy2[3]; } MemCardRequest; - -#endif \ No newline at end of file diff --git a/libpsn00b/include/psxpress.h b/libpsn00b/include/psxpress.h index ea0c2ec..f26e030 100644 --- a/libpsn00b/include/psxpress.h +++ b/libpsn00b/include/psxpress.h @@ -22,8 +22,7 @@ * anyway. */ -#ifndef __PSXPRESS_H -#define __PSXPRESS_H +#pragma once #include #include @@ -512,5 +511,3 @@ void DecDCTvlcBuild(DECDCTTAB *table); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/psxsio.h b/libpsn00b/include/psxsio.h index 449e43a..8932830 100644 --- a/libpsn00b/include/psxsio.h +++ b/libpsn00b/include/psxsio.h @@ -18,8 +18,7 @@ * debugging purposes. */ -#ifndef __PSXSIO_H -#define __PSXSIO_H +#pragma once #include @@ -280,5 +279,3 @@ void DelSIO(void); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/psxsn.h b/libpsn00b/include/psxsn.h index 53a3cd9..1acbc18 100644 --- a/libpsn00b/include/psxsn.h +++ b/libpsn00b/include/psxsn.h @@ -18,8 +18,7 @@ * in PSn00bSDK they are part of libpsxapi. */ -#ifndef __PSXSN_H -#define __PSXSN_H +#pragma once #include @@ -50,5 +49,3 @@ int PClseek(int fd, int offset, PCDRV_SeekMode mode); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/psxspu.h b/libpsn00b/include/psxspu.h index cdc3ac7..d829821 100644 --- a/libpsn00b/include/psxspu.h +++ b/libpsn00b/include/psxspu.h @@ -1,10 +1,25 @@ /* * PSn00bSDK SPU library - * (C) 2019-2022 Lameguy64, spicyjpeg - MPL licensed + * (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed */ -#ifndef __PSXSPU_H -#define __PSXSPU_H +/** + * @file psxspu.h + * @brief SPU library header + * + * @details The PSn00bSDK SPU library allows for SPU initialization, DMA + * transfers (both sample data uploads and capture buffer reads) and provides + * helper macros for accessing SPU control registers, which can be used to + * control sample playback on each channel, configure reverb and enable more + * advanced features such as interrupts. + * + * This library currently has fewer functions than its Sony SDK counterpart, in + * part because it is not yet complete but also since the vast majority of the + * Sony library's functions are redundant, inefficient and can be replaced with + * simple SPU register writes. + */ + +#pragma once #include #include @@ -12,6 +27,7 @@ /* Definitions */ +#if 0 typedef enum _SPU_AttrMask { SPU_VOICE_VOLL = 1 << 0, // Left volume SPU_VOICE_VOLR = 1 << 1, // Right volume @@ -33,6 +49,7 @@ typedef enum _SPU_AttrMask { SPU_VOICE_ADSR_ADSR1 = 1 << 17, SPU_VOICE_ADSR_ADSR2 = 1 << 18 } SPU_AttrMask; +#endif typedef enum _SPU_TransferMode { SPU_TRANSFER_BY_DMA = 0, @@ -46,6 +63,7 @@ typedef enum _SPU_WaitMode { /* Structure definitions */ +#if 0 typedef struct _SpuVolume { int16_t left, right; } SpuVolume; @@ -72,6 +90,7 @@ typedef struct _SpuCommonAttr { SpuVolume mvol, mvolmode, mvolx; SpuExtAttr cd, ext; } SpuCommonAttr; +#endif /* Macros */ @@ -143,5 +162,3 @@ int SpuIsTransferCompleted(int mode); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/stdio.h b/libpsn00b/include/stdio.h index 8aaf4c7..1bb5b74 100644 --- a/libpsn00b/include/stdio.h +++ b/libpsn00b/include/stdio.h @@ -1,39 +1,26 @@ -#ifndef _STDIO_H -#define _STDIO_H +/* + * PSn00bSDK standard library + * (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed + */ -#include +#pragma once -// BIOS seek modes -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif -#ifndef SEEK_END -#define SEEK_END 2 /* warning: reportedly buggy */ -#endif +#include #ifdef __cplusplus extern "C" { #endif -// The following functions use the BIOS -extern void printf (const char *__format, ...); - -extern int getc(int __fd); -extern int putc(int __char, int __fd); +/* String I/O API (provided by BIOS) */ -#define fputc(__char, __fd) putc(__char, __fd) -#define fgetc(__char, __fd) getc(__char, __fd) +int printf(const char *fmt, ...); +char *gets(char *str); +void puts(const char *str); +int getchar(void); +void putchar(int ch); -// Console TTY -extern void gets(char *__s); -extern void puts(const char *__s); -extern int getchar(void); -extern void putchar(int __c); +/* String formatting API (built-in) */ -// The following functions do not use the BIOS int vsnprintf(char *string, unsigned int size, const char *fmt, va_list ap); int vsprintf(char *string, const char *fmt, va_list ap); int sprintf(char *string, const char *fmt, ...); @@ -45,5 +32,3 @@ int sscanf(const char *str, const char *fmt, ...); #ifdef __cplusplus } #endif - -#endif // _STDIO_H \ No newline at end of file diff --git a/libpsn00b/include/stdlib.h b/libpsn00b/include/stdlib.h index 49ae7b9..19761df 100644 --- a/libpsn00b/include/stdlib.h +++ b/libpsn00b/include/stdlib.h @@ -1,10 +1,9 @@ /* * PSn00bSDK standard library - * (C) 2019-2022 PSXSDK authors, Lameguy64, spicyjpeg - MPL licensed + * (C) 2019-2023 PSXSDK authors, Lameguy64, spicyjpeg - MPL licensed */ -#ifndef __STDLIB_H -#define __STDLIB_H +#pragma once #include @@ -59,5 +58,3 @@ void free(void *ptr); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/string.h b/libpsn00b/include/string.h index 84afbae..6310b1a 100644 --- a/libpsn00b/include/string.h +++ b/libpsn00b/include/string.h @@ -1,10 +1,9 @@ /* * PSn00bSDK standard library - * (C) 2019-2022 PSXSDK authors, Lameguy64, spicyjpeg - MPL licensed + * (C) 2019-2023 PSXSDK authors, Lameguy64, spicyjpeg - MPL licensed */ -#ifndef __STRING_H -#define __STRING_H +#pragma once #include @@ -39,5 +38,3 @@ char *strtok(char *str, const char *delim); #ifdef __cplusplus } #endif - -#endif diff --git a/libpsn00b/include/strings.h b/libpsn00b/include/strings.h index 7223ab9..0595637 100644 --- a/libpsn00b/include/strings.h +++ b/libpsn00b/include/strings.h @@ -3,8 +3,7 @@ * (C) 2019-2022 PSXSDK authors, Lameguy64, spicyjpeg - MPL licensed */ -#ifndef __STRINGS_H -#define __STRINGS_H +#pragma once #include @@ -15,5 +14,3 @@ #define bcmp(b1, b2, len) memcmp(b1, b2, len) #define index(s, c) strchr(s, c) #define rindex(s, c) strrchr(s, c) - -#endif diff --git a/libpsn00b/include/sys/fcntl.h b/libpsn00b/include/sys/fcntl.h index dfbf5b2..54c2d05 100644 --- a/libpsn00b/include/sys/fcntl.h +++ b/libpsn00b/include/sys/fcntl.h @@ -1,8 +1,10 @@ -#ifndef _SYS_FCNTL_H -#define _SYS_FCNTL_H +/* + * PSn00bSDK kernel API library + * (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed + */ + +#pragma once -// File control mode flags for BIOS file functions -// (many weren't documented in nocash docs) #define FREAD 0x1 // Read #define FWRITE 0x2 // Write #define FNBLOCK 0x4 // Non-blocking read access @@ -16,5 +18,3 @@ #define FNBUF 0x4000 // No ring buffer and terminal interrupt #define FASYNC 0x8000 // Asynchronous I/O #define FNBLOCKS(a) (a<<16) // Number of blocks? (from nocash docs) - -#endif \ No newline at end of file diff --git a/libpsn00b/include/sys/ioctl.h b/libpsn00b/include/sys/ioctl.h new file mode 100644 index 0000000..af65e5d --- /dev/null +++ b/libpsn00b/include/sys/ioctl.h @@ -0,0 +1,13 @@ +/* + * PSn00bSDK kernel API library + * (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed + */ + +#pragma once + +#define EOF -1 + +#define FIONBLOCK (('f'<<8)|1) +#define FIOCSCAN (('f'<<8)|2) + +#define DIOFORMAT (('d'<<8)|1) diff --git a/libpsn00b/include/sys/types.h b/libpsn00b/include/sys/types.h index da43590..9075b5e 100644 --- a/libpsn00b/include/sys/types.h +++ b/libpsn00b/include/sys/types.h @@ -1,13 +1,13 @@ -#ifndef _TYPES_H -#define _TYPES_H +/* + * PSn00bSDK standard library + * (C) 2019-2023 Lameguy64, spicyjpeg - MPL licensed + */ -//#warning " and u_* types are deprecated, include instead" +#pragma once -//#include +//#warning " and u_* types are deprecated, use instead" typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned long u_long; - -#endif // _TYPES_H \ No newline at end of file diff --git a/libpsn00b/lzp/bit.h b/libpsn00b/lzp/bit.h index 321160a..5e7ed23 100644 --- a/libpsn00b/lzp/bit.h +++ b/libpsn00b/lzp/bit.h @@ -1,5 +1,5 @@ -#ifndef _LZP_BIT_H -#define _LZP_BIT_H + +#pragma once extern const unsigned char* inPtr; extern int inBytes; @@ -21,6 +21,3 @@ int get_bits(int n); #ifdef __cplusplus } #endif - - -#endif // _LZP_BIT_H diff --git a/libpsn00b/lzp/compress.c b/libpsn00b/lzp/compress.c index 9cfc64d..16cb606 100644 --- a/libpsn00b/lzp/compress.c +++ b/libpsn00b/lzp/compress.c @@ -1,7 +1,7 @@ // Based on ilia muraviev's CRUSH compressor program which falls under public domain #include -#if LZP_USE_MALLOC == TRUE +#ifdef LZP_USE_MALLOC #include #endif @@ -11,7 +11,7 @@ // Internal structure for hash table allocation sizes -#if LZP_NO_COMPRESS == FALSE +#ifndef LZP_NO_COMPRESS struct { short WindowSize; // Window size (17 - 23) @@ -67,7 +67,7 @@ struct { // LZ77 // -#if LZP_NO_COMPRESS == FALSE +#ifndef LZP_NO_COMPRESS int update_hash1(int h, int c) { @@ -108,13 +108,13 @@ int get_penalty(int a, int b) { int lzCompress(void* outBuff, const void* inBuff, int inSize, int level) { - #if LZP_USE_MALLOC == FALSE +#ifndef LZP_USE_MALLOC int head[HASH1_SIZE+HASH2_SIZE]; int prev[W_SIZE]; - #else +#else int* head = malloc(4*(HASH1_SIZE+HASH2_SIZE)); int* prev = malloc(4*W_SIZE); - #endif +#endif int max_chain[] = {4, 256, 1<<12}; @@ -319,10 +319,10 @@ int lzCompress(void* outBuff, const void* inBuff, int inSize, int level) { flush_bits(); - #if LZP_USE_MALLOC == TRUE +#ifdef LZP_USE_MALLOC free(head); free(prev); - #endif +#endif return(outBytes); diff --git a/libpsn00b/lzp/lzconfig.h b/libpsn00b/lzp/lzconfig.h new file mode 100644 index 0000000..83579a3 --- /dev/null +++ b/libpsn00b/lzp/lzconfig.h @@ -0,0 +1,42 @@ +/*! \file lzconfig.h + * \brief Library configuration header + * \details Define settings will only take effect when you recompile the library. + */ + +#pragma once + +/* Uncomment to make default compression table sizes to maximum and works best + * when compressing large amounts of data. LZP_USE_MALLOC must be set to TRUE to + * prevent stack overflow errors. + * + * Do not enable this if you plan to compile for a platform with limited memory + * otherwise, the library will consume all memory and crash the system. + * + * This define only affects lzCompress(). + */ +//#define LZP_MAX_COMPRESS + +/* Uncomment to make the library use malloc() instead of array initializers to + * allocate hash tables. Enabling this is a must if you plan to use large hash + * and window table sizes. + */ +//#define LZP_USE_MALLOC + + +#if defined(PSN00BSDK) && !defined(LZP_MAX_COMPRESS) + +// Minimal defaults +#define LZP_WINDOW_SIZE 17 +#define LZP_HASH1_SIZE 8 +#define LZP_HASH2_SIZE 10 + +#else + +#define LZP_USE_MALLOC + +// Maximum defaults +#define LZP_WINDOW_SIZE 17 +#define LZP_HASH1_SIZE 22 +#define LZP_HASH2_SIZE 24 + +#endif diff --git a/libpsn00b/lzp/lzp.h b/libpsn00b/lzp/lzp.h index 456de02..1aeea30 100644 --- a/libpsn00b/lzp/lzp.h +++ b/libpsn00b/lzp/lzp.h @@ -1,20 +1,29 @@ -/*! \file lzp.h - * \brief Main library header +/* + * liblzp data compression library + * (C) 2019 Lameguy64 - MPL licensed */ -/*! \mainpage - * \version 0.20b - * \author John Wilbert 'Lameguy64' Villamor +/** + * @file lzp.h + * @brief Utility library for file bundling and compression * - * \section creditsSection Credits - * - LZ77 data compression/decompression routines based from Ilya Muravyov's - * crush.cpp released under public domain. Refined and ported to C by Lameguy64. - * - CRC calculation routines based from Lammert Bies' lib_crc routines. + * @details This library implements a simple in-memory archive format which + * can be used to package and compress assets for faster loading, as well as a + * generic LZ77 compressor and matching decompressor. Two archive formats are + * supported, one uncompressed (.QLP) and one with individually compressed + * entries (.LZP). * + * This header provides the LZ77 compression API and functions to parse and + * decompress .LZP archives after they have been loaded into memory. + * + * @section creditsSection Credits + * - LZ77 data compression/decompression routines based from Ilya Muravyov's + * crush.cpp released under public domain. Refined and ported to C by + * Lameguy64. + * - CRC calculation routines based from Lammert Bies' lib_crc routines. */ -#ifndef _LZPACK_H -#define _LZPACK_H +#pragma once #include #ifdef _WIN32 @@ -218,6 +227,3 @@ int lzpUnpackFile(void* buff, const LZP_HEAD* lzpack, int fileNum); #ifdef __cplusplus } #endif - - -#endif // _LZPACK_H diff --git a/libpsn00b/lzp/lzqlp.h b/libpsn00b/lzp/lzqlp.h index 32ce0d7..127f263 100644 --- a/libpsn00b/lzp/lzqlp.h +++ b/libpsn00b/lzp/lzqlp.h @@ -1,5 +1,23 @@ -#ifndef _QLP_H -#define _QLP_H +/* + * liblzp data compression library + * (C) 2019 Lameguy64 - MPL licensed + */ + +/** + * @file lzqlp.h + * @brief Utility library for file bundling + * + * @details This library implements a simple in-memory archive format which + * can be used to package and compress assets for faster loading, as well as a + * generic LZ77 compressor and matching decompressor. Two archive formats are + * supported, one uncompressed (.QLP) and one with individually compressed + * entries (.LZP). + * + * This header provides functions to parse .QLP archives and retrieve pointers + * to their contents after they have been loaded into memory. + */ + +#pragma once #include #ifdef _WIN32 @@ -23,9 +41,17 @@ typedef struct { uint32_t offs; } QLP_FILE; + +// Function prototypes +#ifdef __cplusplus +extern "C" { +#endif + int qlpFileCount(const QLP_HEAD* qlpfile); const QLP_FILE* qlpFileEntry(int index, const QLP_HEAD* qlpfile); const void* qlpFileAddr(int index, const QLP_HEAD* qlpfile); int qlpFindFile(char* fileName, const QLP_HEAD* qlpfile); -#endif // _QLP_H \ No newline at end of file +#ifdef __cplusplus +} +#endif diff --git a/libpsn00b/psxapi/drivers.s b/libpsn00b/psxapi/drivers.s index d991f90..c601201 100644 --- a/libpsn00b/psxapi/drivers.s +++ b/libpsn00b/psxapi/drivers.s @@ -32,10 +32,10 @@ _96_remove: jr $t2 li $t1, 0x72 -.section .text.AddDummyTty -.global AddDummyTty -.type AddDummyTty, @function -AddDummyTty: +.section .text.add_nullcon_driver +.global add_nullcon_driver +.type add_nullcon_driver, @function +add_nullcon_driver: li $t2, 0xa0 jr $t2 li $t1, 0x99 @@ -66,26 +66,26 @@ _card_clear: ## B0 table functions (12) -.section .text.AddDev -.global AddDev -.type AddDev, @function -AddDev: +.section .text.AddDrv +.global AddDrv +.type AddDrv, @function +AddDrv: li $t2, 0xb0 jr $t2 li $t1, 0x47 -.section .text.DelDev -.global DelDev -.type DelDev, @function -DelDev: +.section .text.DelDrv +.global DelDrv +.type DelDrv, @function +DelDrv: li $t2, 0xb0 jr $t2 li $t1, 0x48 -.section .text.ListDev -.global ListDev -.type ListDev, @function -ListDev: +.section .text.ListDrv +.global ListDrv +.type ListDrv, @function +ListDrv: li $t2, 0xb0 jr $t2 li $t1, 0x49 diff --git a/libpsn00b/psxapi/fs.s b/libpsn00b/psxapi/fs.s index f225d64..8b6d57a 100644 --- a/libpsn00b/psxapi/fs.s +++ b/libpsn00b/psxapi/fs.s @@ -6,12 +6,12 @@ .set noreorder -## B0 table functions (5) +## B0 table functions (6) -.section .text.chdir -.global chdir -.type chdir, @function -chdir: +.section .text.cd +.global cd +.type cd, @function +cd: li $t2, 0xb0 jr $t2 li $t1, 0x40 @@ -48,3 +48,11 @@ erase: jr $t2 li $t1, 0x45 +.section .text.undelete +.global undelete +.type undelete, @function +undelete: + li $t2, 0xb0 + jr $t2 + li $t1, 0x46 + diff --git a/libpsn00b/psxapi/stdio.s b/libpsn00b/psxapi/stdio.s index e65f871..14c6d03 100644 --- a/libpsn00b/psxapi/stdio.s +++ b/libpsn00b/psxapi/stdio.s @@ -6,7 +6,7 @@ .set noreorder -## A0 table functions (13) +## A0 table functions (14) .section .text.open .global open @@ -16,10 +16,10 @@ open: jr $t2 li $t1, 0x00 -.section .text.seek -.global seek -.type seek, @function -seek: +.section .text.lseek +.global lseek +.type lseek, @function +lseek: li $t2, 0xa0 jr $t2 li $t1, 0x01 @@ -56,6 +56,14 @@ ioctl: jr $t2 li $t1, 0x05 +.section .text.isatty +.global isatty +.type isatty, @function +isatty: + li $t2, 0xa0 + jr $t2 + li $t1, 0x07 + .section .text.getc .global getc .type getc, @function @@ -112,3 +120,21 @@ printf: jr $t2 li $t1, 0x3f +## B0 table functions (2) + +.section .text._get_errno +.global _get_errno +.type _get_errno, @function +_get_errno: + li $t2, 0xb0 + jr $t2 + li $t1, 0x54 + +.section .text._get_error +.global _get_error +.type _get_error, @function +_get_error: + li $t2, 0xb0 + jr $t2 + li $t1, 0x55 + diff --git a/libpsn00b/psxapi/stubs.json b/libpsn00b/psxapi/stubs.json index 50ffb55..afa83c6 100644 --- a/libpsn00b/psxapi/stubs.json +++ b/libpsn00b/psxapi/stubs.json @@ -8,7 +8,7 @@ { "type": "a", "id": 1, - "name": "seek", + "name": "lseek", "file": "stdio.s" }, { @@ -35,6 +35,12 @@ "name": "ioctl", "file": "stdio.s" }, + { + "type": "a", + "id": 7, + "name": "isatty", + "file": "stdio.s" + }, { "type": "a", "id": 8, @@ -107,6 +113,12 @@ "name": "FlushCache", "file": "sys.s" }, + { + "type": "a", + "id": 81, + "name": "LoadExec", + "file": "sys.s" + }, { "type": "a", "id": 85, @@ -128,7 +140,7 @@ { "type": "a", "id": 153, - "name": "AddDummyTty", + "name": "add_nullcon_driver", "file": "drivers.s" }, { @@ -137,6 +149,18 @@ "name": "SetConf", "file": "sys.s" }, + { + "type": "a", + "id": 157, + "name": "GetConf", + "file": "sys.s" + }, + { + "type": "a", + "id": 159, + "name": "SetMem", + "file": "sys.s" + }, { "type": "a", "id": 160, @@ -170,13 +194,13 @@ { "type": "b", "id": 0, - "name": "_kernel_malloc", + "name": "alloc_kernel_memory", "file": "sys.s" }, { "type": "b", "id": 1, - "name": "_kernel_free", + "name": "free_kernel_memory", "file": "sys.s" }, { @@ -296,13 +320,13 @@ { "type": "b", "id": 24, - "name": "SetDefaultExitFromException", + "name": "ResetEntryInt", "file": "sys.s" }, { "type": "b", "id": 25, - "name": "SetCustomExitFromException", + "name": "HookEntryInt", "file": "sys.s" }, { @@ -314,7 +338,7 @@ { "type": "b", "id": 64, - "name": "chdir", + "name": "cd", "file": "fs.s" }, { @@ -341,22 +365,28 @@ "name": "erase", "file": "fs.s" }, + { + "type": "b", + "id": 70, + "name": "undelete", + "file": "fs.s" + }, { "type": "b", "id": 71, - "name": "AddDev", + "name": "AddDrv", "file": "drivers.s" }, { "type": "b", "id": 72, - "name": "DelDev", + "name": "DelDrv", "file": "drivers.s" }, { "type": "b", "id": 73, - "name": "ListDev", + "name": "ListDrv", "file": "drivers.s" }, { @@ -395,6 +425,18 @@ "name": "_new_card", "file": "drivers.s" }, + { + "type": "b", + "id": 84, + "name": "_get_errno", + "file": "stdio.s" + }, + { + "type": "b", + "id": 85, + "name": "_get_error", + "file": "stdio.s" + }, { "type": "b", "id": 86, diff --git a/libpsn00b/psxapi/sys.s b/libpsn00b/psxapi/sys.s index e2505e1..40dcdff 100644 --- a/libpsn00b/psxapi/sys.s +++ b/libpsn00b/psxapi/sys.s @@ -6,7 +6,7 @@ .set noreorder -## A0 table functions (8) +## A0 table functions (11) .section .text.b_setjmp .global b_setjmp @@ -48,6 +48,14 @@ FlushCache: jr $t2 li $t1, 0x44 +.section .text.LoadExec +.global LoadExec +.type LoadExec, @function +LoadExec: + li $t2, 0xa0 + jr $t2 + li $t1, 0x51 + .section .text.SetConf .global SetConf .type SetConf, @function @@ -56,6 +64,22 @@ SetConf: jr $t2 li $t1, 0x9c +.section .text.GetConf +.global GetConf +.type GetConf, @function +GetConf: + li $t2, 0xa0 + jr $t2 + li $t1, 0x9d + +.section .text.SetMem +.global SetMem +.type SetMem, @function +SetMem: + li $t2, 0xa0 + jr $t2 + li $t1, 0x9f + .section .text._boot .global _boot .type _boot, @function @@ -74,18 +98,18 @@ GetSystemInfo: ## B0 table functions (27) -.section .text._kernel_malloc -.global _kernel_malloc -.type _kernel_malloc, @function -_kernel_malloc: +.section .text.alloc_kernel_memory +.global alloc_kernel_memory +.type alloc_kernel_memory, @function +alloc_kernel_memory: li $t2, 0xb0 jr $t2 li $t1, 0x00 -.section .text._kernel_free -.global _kernel_free -.type _kernel_free, @function -_kernel_free: +.section .text.free_kernel_memory +.global free_kernel_memory +.type free_kernel_memory, @function +free_kernel_memory: li $t2, 0xb0 jr $t2 li $t1, 0x01 @@ -242,18 +266,18 @@ ReturnFromException: jr $t2 li $t1, 0x17 -.section .text.SetDefaultExitFromException -.global SetDefaultExitFromException -.type SetDefaultExitFromException, @function -SetDefaultExitFromException: +.section .text.ResetEntryInt +.global ResetEntryInt +.type ResetEntryInt, @function +ResetEntryInt: li $t2, 0xb0 jr $t2 li $t1, 0x18 -.section .text.SetCustomExitFromException -.global SetCustomExitFromException -.type SetCustomExitFromException, @function -SetCustomExitFromException: +.section .text.HookEntryInt +.global HookEntryInt +.type HookEntryInt, @function +HookEntryInt: li $t2, 0xb0 jr $t2 li $t1, 0x19 diff --git a/libpsn00b/psxetc/interrupts.c b/libpsn00b/psxetc/interrupts.c index b7bbd07..8bd11fc 100644 --- a/libpsn00b/psxetc/interrupts.c +++ b/libpsn00b/psxetc/interrupts.c @@ -210,7 +210,7 @@ void RestartCallback(void) { // Install the ISR hook and prevent the kernel's internal handlers from // automatically acknowledging SPI and timer IRQs. - SetCustomExitFromException(&_isr_jmp_buf); + HookEntryInt(&_isr_jmp_buf); ChangeClearPAD(0); ChangeClearRCnt(0, 0); ChangeClearRCnt(1, 0); @@ -237,7 +237,7 @@ void StopCallback(void) { DMA_DPCR = _saved_dma_dpcr & 0x07777777; DMA_DICR = 0; - SetDefaultExitFromException(); + ResetEntryInt(); ChangeClearPAD(1); ChangeClearRCnt(0, 1); ChangeClearRCnt(1, 1); diff --git a/libpsn00b/psxsio/tty.c b/libpsn00b/psxsio/tty.c index a1b33c8..a88af85 100644 --- a/libpsn00b/psxsio/tty.c +++ b/libpsn00b/psxsio/tty.c @@ -8,7 +8,7 @@ * critical section or even from an interrupt handler. */ -#include +#include #include #include #include @@ -93,8 +93,8 @@ void AddSIO(int baud) { close(0); close(1); - DelDev(_sio_dcb.name); - AddDev(&_sio_dcb); + DelDrv(_sio_dcb.name); + AddDrv(&_sio_dcb); open(_sio_dcb.name, 2); open(_sio_dcb.name, 1); } @@ -102,6 +102,6 @@ void AddSIO(int baud) { void DelSIO(void) { SIO_Quit(); - DelDev(_sio_dcb.name); - AddDummyTty(); + DelDrv(_sio_dcb.name); + add_nullcon_driver(); } diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index c48bc10..9246e19 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -38,11 +38,7 @@ file( ) add_library(lzp STATIC ${_sources}) -target_include_directories( - lzp PUBLIC - lzpack/lzp - ${LIBPSN00B_PATH}/include/lzp -) +target_include_directories(lzp PUBLIC ${LIBPSN00B_PATH}/lzp) ## Executables diff --git a/tools/lzpack/lzp/lzconfig.h b/tools/lzpack/lzp/lzconfig.h deleted file mode 100644 index 65e623c..0000000 --- a/tools/lzpack/lzp/lzconfig.h +++ /dev/null @@ -1,68 +0,0 @@ -/*! \file lzconfig.h - * \brief Library configuration header - * \details Define settings will only take effect when you recompile the library. - */ - -#ifndef _LZP_CONFIG_H -#define _LZP_CONFIG_H - - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - - -/* Set to TRUE to compile without data compression routines useful if you - * plan to use this library on a program that does not require said routines - * especially on a platform with limited memory (such as the PlayStation). - * - * This define will rule out lzCompress(), lzSetHashSizes() and - * lzResetHashSizes() functions and their associated functions. - */ -#define LZP_NO_COMPRESS FALSE - - -/* Set to TRUE to make default compression table sizes to maximum and works best - * when compressing large amounts of data. LZP_USE_MALLOC must be set to TRUE to - * prevent stack overflow errors. - * - * Do not enable this if you plan to compile for a platform with limited memory - * otherwise, the library will consume all memory and crash the system. - * - * This define only affects lzCompress(). - */ -#define LZP_MAX_COMPRESS TRUE - - -/* Uncomment to make the library use malloc() instead of array initializers to - * allocate hash tables. Enabling this is a must if you plan to use large hash - * and window table sizes. - */ -#define LZP_USE_MALLOC TRUE - - -/* Hash table sizes (in power-of-two multiple units) - * - * These define only affect lzCompress(). - */ -#if LZP_MAX_COMPRESS == TRUE - -// Minimal defaults -#define LZP_WINDOW_SIZE 17 -#define LZP_HASH1_SIZE 8 -#define LZP_HASH2_SIZE 10 - -#else - -// Maximum defaults -#define LZP_WINDOW_SIZE 17 -#define LZP_HASH1_SIZE 22 -#define LZP_HASH2_SIZE 24 - -#endif - - -#endif // _LZP_CONFIG_H -- cgit v1.2.3 From ca6b54f3c15a7b00a5ede64ba452f2955a421a1e Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Thu, 11 May 2023 15:59:56 +0200 Subject: Add MoveImage(), SetDrawOpType(), GPU IRQ support --- libpsn00b/include/hwregs_c.h | 38 ++++++------ libpsn00b/include/psxgpu.h | 40 ++++++++----- libpsn00b/include/psxspu.h | 2 + libpsn00b/psxgpu/common.c | 139 ++++++++++++++++++++++++------------------- libpsn00b/psxgpu/env.c | 8 +-- libpsn00b/psxgpu/image.c | 3 + libpsn00b/psxspu/common.c | 8 +++ 7 files changed, 137 insertions(+), 101 deletions(-) (limited to 'libpsn00b/include/psxgpu.h') diff --git a/libpsn00b/include/hwregs_c.h b/libpsn00b/include/hwregs_c.h index 3fd5b2c..2152986 100644 --- a/libpsn00b/include/hwregs_c.h +++ b/libpsn00b/include/hwregs_c.h @@ -34,7 +34,7 @@ #define CD_DATA _MMIO8(IOBASE | 0x1802) #define CD_IRQ _MMIO8(IOBASE | 0x1803) -#define CD_REG(N) _MMIO8(IOBASE | 0x1800 + (N)) +#define CD_REG(N) _MMIO8((IOBASE | 0x1800) + (N)) /* SPU */ @@ -73,13 +73,13 @@ // These are not named SPU_VOICE_* to avoid name clashes with SPU attribute // flags defined in psxspu.h. -#define SPU_CH_VOL_L(N) _MMIO16(IOBASE | 0x1c00 + 16 * (N)) -#define SPU_CH_VOL_R(N) _MMIO16(IOBASE | 0x1c02 + 16 * (N)) -#define SPU_CH_FREQ(N) _MMIO16(IOBASE | 0x1c04 + 16 * (N)) -#define SPU_CH_ADDR(N) _MMIO16(IOBASE | 0x1c06 + 16 * (N)) -#define SPU_CH_ADSR1(N) _MMIO16(IOBASE | 0x1c08 + 16 * (N)) -#define SPU_CH_ADSR2(N) _MMIO16(IOBASE | 0x1c0a + 16 * (N)) -#define SPU_CH_LOOP_ADDR(N) _MMIO16(IOBASE | 0x1c0e + 16 * (N)) +#define SPU_CH_VOL_L(N) _MMIO16((IOBASE | 0x1c00) + (16 * (N))) +#define SPU_CH_VOL_R(N) _MMIO16((IOBASE | 0x1c02) + (16 * (N))) +#define SPU_CH_FREQ(N) _MMIO16((IOBASE | 0x1c04) + (16 * (N))) +#define SPU_CH_ADDR(N) _MMIO16((IOBASE | 0x1c06) + (16 * (N))) +#define SPU_CH_ADSR1(N) _MMIO16((IOBASE | 0x1c08) + (16 * (N))) +#define SPU_CH_ADSR2(N) _MMIO16((IOBASE | 0x1c0a) + (16 * (N))) +#define SPU_CH_LOOP_ADDR(N) _MMIO16((IOBASE | 0x1c0e) + (16 * (N))) /* MDEC */ @@ -91,11 +91,11 @@ // IMPORTANT: even though SIO_DATA is a 32-bit register, it should only be // accessed as 8-bit. Reading it as 16 or 32-bit works fine on real hardware, // but leads to problems in some emulators. -#define SIO_DATA(N) _MMIO8 (IOBASE | 0x1040 + 16 * (N)) -#define SIO_STAT(N) _MMIO16(IOBASE | 0x1044 + 16 * (N)) -#define SIO_MODE(N) _MMIO16(IOBASE | 0x1048 + 16 * (N)) -#define SIO_CTRL(N) _MMIO16(IOBASE | 0x104a + 16 * (N)) -#define SIO_BAUD(N) _MMIO16(IOBASE | 0x104e + 16 * (N)) +#define SIO_DATA(N) _MMIO8 ((IOBASE | 0x1040) + (16 * (N))) +#define SIO_STAT(N) _MMIO16((IOBASE | 0x1044) + (16 * (N))) +#define SIO_MODE(N) _MMIO16((IOBASE | 0x1048) + (16 * (N))) +#define SIO_CTRL(N) _MMIO16((IOBASE | 0x104a) + (16 * (N))) +#define SIO_BAUD(N) _MMIO16((IOBASE | 0x104e) + (16 * (N))) /* IRQ controller */ @@ -107,15 +107,15 @@ #define DMA_DPCR _MMIO32(IOBASE | 0x10f0) #define DMA_DICR _MMIO32(IOBASE | 0x10f4) -#define DMA_MADR(N) _MMIO32(IOBASE | 0x1080 + 16 * (N)) -#define DMA_BCR(N) _MMIO32(IOBASE | 0x1084 + 16 * (N)) -#define DMA_CHCR(N) _MMIO32(IOBASE | 0x1088 + 16 * (N)) +#define DMA_MADR(N) _MMIO32((IOBASE | 0x1080) + (16 * (N))) +#define DMA_BCR(N) _MMIO32((IOBASE | 0x1084) + (16 * (N))) +#define DMA_CHCR(N) _MMIO32((IOBASE | 0x1088) + (16 * (N))) /* Timers */ -#define TIMER_VALUE(N) _MMIO32(IOBASE | 0x1100 + 16 * (N)) -#define TIMER_CTRL(N) _MMIO32(IOBASE | 0x1104 + 16 * (N)) -#define TIMER_RELOAD(N) _MMIO32(IOBASE | 0x1108 + 16 * (N)) +#define TIMER_VALUE(N) _MMIO32((IOBASE | 0x1100) + (16 * (N))) +#define TIMER_CTRL(N) _MMIO32((IOBASE | 0x1104) + (16 * (N))) +#define TIMER_RELOAD(N) _MMIO32((IOBASE | 0x1108) + (16 * (N))) /* Memory/bus control */ diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h index 9b99fe9..2e9e4eb 100644 --- a/libpsn00b/include/psxgpu.h +++ b/libpsn00b/include/psxgpu.h @@ -44,6 +44,11 @@ typedef enum _GPU_VideoMode { MODE_PAL = 1 } GPU_VideoMode; +typedef enum _GPU_DrawOpType { + DRAWOP_TYPE_DMA = 1, + DRAWOP_TYPE_GPU_IRQ = 2 +} GPU_DrawOpType; + /* Structure macros */ #define setVector(v, _x, _y, _z) \ @@ -142,11 +147,11 @@ typedef enum _GPU_VideoMode { ((tge) ? (getcode_T(p) |= 1) : (getcode_T(p) &= ~1)) #define getTPage(tp, abr, x, y) ( \ - (((x) / 64) & 15) | \ - ((((y) / 256) & 1) << 4) | \ - (((abr) & 3) << 5) | \ - (((tp) & 3) << 7) | \ - ((((y) / 512) & 1) << 11) \ + (((x) & 0x3c0) >> 6) | \ + (((y) & 0x100) >> 4) | \ + (((y) & 0x200) << 2) | \ + (((abr) & 3) << 5) | \ + (((tp) & 3) << 7) \ ) #define getClut(x, y) (((y) << 6) | (((x) >> 4) & 0x3f)) @@ -210,8 +215,8 @@ typedef enum _GPU_VideoMode { #define setDrawTPage_T(p, dfe, dtd, tpage) \ (p)->code[0] = (0xe1000000 | \ (tpage) | \ - ((dtd) << 9) | \ - ((dfe) << 10) \ + (((dtd) & 1) << 9) | \ + (((dfe) & 1) << 10) \ ) #define setDrawTPage(p, dfe, dtd, tpage) \ setlen(p, 1), setDrawTPage_T(p, dfe, dtd, tpage) @@ -261,6 +266,11 @@ typedef enum _GPU_VideoMode { #define setDrawStp(p, pbw, mt) \ setlen(p, 1), setDrawStp_T(p, pbw, mt) +#define setDrawIRQ_T(p) \ + (p)->code[0] = 0x1f000000 +#define setDrawIRQ(p) \ + setlen(p, 1), setDrawIRQ_T(p) + /* Primitive structure definitions */ typedef struct _P_TAG_T { @@ -475,12 +485,11 @@ _DEF_PRIM(FILL, uint16_t w, h; ) -_DEF_PRIM(BLIT, +_DEF_PRIM(DR_MOVE, uint8_t p0, p1, p2, code; uint16_t x0, y0; uint16_t x1, y1; uint16_t w, h; - uint32_t pad[4]; ) _DEF_PRIM(DR_AREA, @@ -498,6 +507,9 @@ _DEF_PRIM(DR_TPAGE, _DEF_PRIM(DR_STP, uint32_t code[1]; ) +_DEF_PRIM(DR_IRQ, + uint32_t code[1]; +) _DEF_PRIM(DR_ENV, DR_TPAGE_T tpage; @@ -579,12 +591,8 @@ int VSync(int mode); void *VSyncHaltFunction(void (*func)(void)); void *VSyncCallback(void (*func)(void)); -int EnqueueDrawOp( - void (*func)(uint32_t, uint32_t, uint32_t), - uint32_t arg1, - uint32_t arg2, - uint32_t arg3 -); +void SetDrawOpType(GPU_DrawOpType type); +int EnqueueDrawOp(void (*func)(), uint32_t arg1, uint32_t arg2, uint32_t arg3); int DrawSync(int mode); void *DrawSyncCallback(void (*func)(void)); @@ -600,6 +608,8 @@ void ClearOTag(uint32_t *ot, size_t length); int DrawOTag(const uint32_t *ot); int DrawOTagEnv(const uint32_t *ot, DRAWENV *env); void DrawOTag2(const uint32_t *ot); +int DrawBuffer(const uint32_t *buf, size_t length); +void DrawBuffer2(const uint32_t *buf, size_t length); void DrawPrim(const uint32_t *pri); void AddPrim(uint32_t *ot, const void *pri); diff --git a/libpsn00b/include/psxspu.h b/libpsn00b/include/psxspu.h index d829821..b544952 100644 --- a/libpsn00b/include/psxspu.h +++ b/libpsn00b/include/psxspu.h @@ -156,7 +156,9 @@ size_t SpuRead(uint32_t *data, size_t size); size_t SpuWrite(const uint32_t *data, size_t size); size_t SpuWritePartly(const uint32_t *data, size_t size); SPU_TransferMode SpuSetTransferMode(SPU_TransferMode mode); +SPU_TransferMode SpuGetTransferMode(void); uint32_t SpuSetTransferStartAddr(uint32_t addr); +uint32_t SpuGetTransferStartAddr(void); int SpuIsTransferCompleted(int mode); #ifdef __cplusplus diff --git a/libpsn00b/psxgpu/common.c b/libpsn00b/psxgpu/common.c index 46f87bc..8af6c5b 100644 --- a/libpsn00b/psxgpu/common.c +++ b/libpsn00b/psxgpu/common.c @@ -10,9 +10,8 @@ #include #include -#define QUEUE_LENGTH 16 -#define DMA_CHUNK_LENGTH 16 -#define VSYNC_TIMEOUT 0x100000 +#define QUEUE_LENGTH 16 +#define VSYNC_TIMEOUT 0x100000 static void _default_vsync_halt(void); @@ -21,7 +20,7 @@ static void _default_vsync_halt(void); typedef struct { void (*func)(uint32_t, uint32_t, uint32_t); uint32_t arg1, arg2, arg3; -} QueueEntry; +} DrawOp; /* Internal globals */ @@ -31,10 +30,10 @@ static void (*_vsync_halt_func)(void) = &_default_vsync_halt; static void (*_vsync_callback)(void) = (void *) 0; static void (*_drawsync_callback)(void) = (void *) 0; -static volatile QueueEntry _draw_queue[QUEUE_LENGTH]; -static volatile uint8_t _queue_head, _queue_tail, _queue_length; -static volatile uint32_t _vblank_counter, _last_vblank; -static volatile uint16_t _last_hblank; +static volatile DrawOp _draw_queue[QUEUE_LENGTH]; +static volatile uint8_t _queue_head, _queue_tail, _queue_length, _drawop_type; +static volatile uint32_t _vblank_counter, _last_vblank; +static volatile uint16_t _last_hblank; /* Private interrupt handlers */ @@ -45,15 +44,16 @@ static void _vblank_handler(void) { _vsync_callback(); } -static void _gpu_dma_handler(void) { - if (GPU_GP1 & (1 << 24)) - GPU_GP1 = 0x02000000; // Reset IRQ +static void _process_drawop(void) { + int length = _queue_length; + if (!length) + return; - if (--_queue_length) { + if (--length) { int head = _queue_head; _queue_head = (head + 1) % QUEUE_LENGTH; - volatile QueueEntry *entry = &_draw_queue[head]; + volatile DrawOp *entry = &_draw_queue[head]; entry->func(entry->arg1, entry->arg2, entry->arg3); } else { GPU_GP1 = 0x04000000; // Disable DMA request @@ -61,17 +61,36 @@ static void _gpu_dma_handler(void) { if (_drawsync_callback) _drawsync_callback(); } + + _queue_length = length; +} + +static void _gpu_irq_handler(void) { + GPU_GP1 = 0x02000000; // Reset IRQ + + if (_drawop_type == DRAWOP_TYPE_GPU_IRQ) + _process_drawop(); +} + +static void _gpu_dma_handler(void) { + if (_drawop_type == DRAWOP_TYPE_DMA) + _process_drawop(); } /* GPU reset and system initialization */ void ResetGraph(int mode) { + _queue_head = 0; + _queue_tail = 0; + _queue_length = 0; + _drawop_type = 0; + // Perform some basic system initialization when ResetGraph() is called for // the first time. if (!ResetCallback()) { EnterCriticalSection(); InterruptCallback(IRQ_VBLANK, &_vblank_handler); - InterruptCallback(IRQ_GPU, &_gpu_dma_handler); + InterruptCallback(IRQ_GPU, &_gpu_irq_handler); DMACallback(DMA_GPU, &_gpu_dma_handler); _gpu_video_mode = (GPU_GP1 >> 20) & 1; @@ -80,15 +99,15 @@ void ResetGraph(int mode) { _sdk_log("setup done, default mode is %s\n", _gpu_video_mode ? "PAL" : "NTSC"); } - _queue_head = 0; - _queue_tail = 0; - _queue_length = 0; - - if (mode == 1) { + if (mode) { GPU_GP1 = 0x01000000; // Reset command buffer GPU_GP1 = 0x02000000; // Reset IRQ GPU_GP1 = 0x04000000; // Disable DMA request - return; + + if (mode == 1) + return; + } else { + GPU_GP1 = 0x00000000; // Reset GPU } SetDMAPriority(DMA_GPU, 3); @@ -96,20 +115,12 @@ void ResetGraph(int mode) { DMA_CHCR(DMA_GPU) = 0x00000201; // Stop DMA DMA_CHCR(DMA_OTC) = 0x00000200; // Stop DMA - if (mode) { - GPU_GP1 = 0x01000000; // Reset command buffer - GPU_GP1 = 0x02000000; // Reset IRQ - GPU_GP1 = 0x04000000; // Disable DMA request - } else { - GPU_GP1 = 0x00000000; // Reset GPU - } + TIMER_CTRL(0) = 0x0500; + TIMER_CTRL(1) = 0x0500; _vblank_counter = 0; _last_vblank = 0; _last_hblank = 0; - - TIMER_CTRL(0) = 0x0500; - TIMER_CTRL(1) = 0x0500; } /* VSync() API */ @@ -179,14 +190,11 @@ void *VSyncCallback(void (*func)(void)) { /* Command queue API */ -// This function is normally only used internally, but it is exposed for -// advanced use cases. -int EnqueueDrawOp( - void (*func)(uint32_t, uint32_t, uint32_t), - uint32_t arg1, - uint32_t arg2, - uint32_t arg3 -) { +void SetDrawOpType(GPU_DrawOpType type) { + _drawop_type = type; +} + +int EnqueueDrawOp(void (*func)(), uint32_t arg1, uint32_t arg2, uint32_t arg3) { _sdk_validate_args(func, -1); // If GPU DMA is currently busy, append the command to the queue instead of @@ -216,7 +224,7 @@ int EnqueueDrawOp( _queue_tail = (tail + 1) % QUEUE_LENGTH; _queue_length = length + 1; - volatile QueueEntry *entry = &_draw_queue[tail]; + volatile DrawOp *entry = &_draw_queue[tail]; entry->func = func; entry->arg1 = arg1; entry->arg2 = arg2; @@ -283,10 +291,10 @@ void ClearOTag(uint32_t *ot, size_t length) { // slower than ClearOTagR(). // https://problemkaputt.de/psx-spx.htm#dmachannels for (int i = 0; i < (length - 1); i++) - ot[i] = (uint32_t) &ot[i + 1] & 0x00ffffff; + ot[i] = (uint32_t) &ot[i + 1] & 0x7fffff; //setaddr(&ot[i], &ot[i + 1]); - ot[length - 1] = 0x00ffffff; + ot[length - 1] = 0xffffff; //termPrim(&ot[length - 1]); } @@ -296,27 +304,6 @@ void AddPrim(uint32_t *ot, const void *pri) { addPrim(ot, pri); } -void DrawPrim(const uint32_t *pri) { - _sdk_validate_args_void(pri); - - size_t length = getlen(pri); - - DrawSync(0); - GPU_GP1 = 0x04000002; // Enable DMA request, route to GP0 - - // NOTE: if length >= DMA_CHUNK_LENGTH then it also has to be a multiple of - // DMA_CHUNK_LENGTH, otherwise the DMA channel will get stuck waiting for - // more data indefinitely. - DMA_MADR(DMA_GPU) = (uint32_t) &pri[1]; - if (length < DMA_CHUNK_LENGTH) - DMA_BCR(DMA_GPU) = 0x00010000 | length; - else - DMA_BCR(DMA_GPU) = DMA_CHUNK_LENGTH | - ((length / DMA_CHUNK_LENGTH) << 16); - - DMA_CHCR(DMA_GPU) = 0x01000201; -} - int DrawOTag(const uint32_t *ot) { _sdk_validate_args(ot, -1); @@ -326,6 +313,7 @@ int DrawOTag(const uint32_t *ot) { void DrawOTag2(const uint32_t *ot) { _sdk_validate_args_void(ot); + SetDrawOpType(DRAWOP_TYPE_DMA); GPU_GP1 = 0x04000002; // Enable DMA request, route to GP0 while (DMA_CHCR(DMA_GPU) & (1 << 24)) @@ -336,6 +324,33 @@ void DrawOTag2(const uint32_t *ot) { DMA_CHCR(DMA_GPU) = 0x01000401; } +int DrawBuffer(const uint32_t *buf, size_t length) { + _sdk_validate_args(buf && length && (length <= 0xffff), -1); + + return EnqueueDrawOp((void *) &DrawBuffer2, (uint32_t) buf, length, 0); +} + +void DrawBuffer2(const uint32_t *buf, size_t length) { + _sdk_validate_args_void(buf && length && (length <= 0xffff)); + + SetDrawOpType(DRAWOP_TYPE_DMA); + GPU_GP1 = 0x04000002; // Enable DMA request, route to GP0 + + while (DMA_CHCR(DMA_GPU) & (1 << 24)) + __asm__ volatile(""); + + DMA_MADR(DMA_GPU) = (uint32_t) buf; + DMA_BCR(DMA_GPU) = 0x00000001 | (length << 16); + DMA_CHCR(DMA_GPU) = 0x01000201; +} + +void DrawPrim(const uint32_t *pri) { + _sdk_validate_args_void(pri); + + DrawSync(0); + DrawBuffer2(&pri[1], getlen(pri)); +} + /* Queue pause/resume API */ int IsIdleGPU(int timeout) { diff --git a/libpsn00b/psxgpu/env.c b/libpsn00b/psxgpu/env.c index cfe09c0..c9e6142 100644 --- a/libpsn00b/psxgpu/env.c +++ b/libpsn00b/psxgpu/env.c @@ -86,9 +86,7 @@ int DrawOTagEnv(const uint32_t *ot, DRAWENV *env) { // Set drawing area setDrawArea_T(&(prim->area), &(env->clip)); setDrawOffset_T( - &(prim->offset), - env->clip.x + env->ofs[0], - env->clip.y + env->ofs[1] + &(prim->offset), env->clip.x + env->ofs[0], env->clip.y + env->ofs[1] ); if (env->isbg) { @@ -109,7 +107,7 @@ int DrawOTagEnv(const uint32_t *ot, DRAWENV *env) { void PutDrawEnv(DRAWENV *env) { _sdk_validate_args_void(env); - DrawOTagEnv((const uint32_t *) 0x00ffffff, env); + DrawOTagEnv((const uint32_t *) 0xffffff, env); } // This function skips rebuilding the cached packet whenever possible and is @@ -119,7 +117,7 @@ void PutDrawEnvFast(DRAWENV *env) { _sdk_validate_args_void(env); if (!(env->dr_env.tag)) - DrawOTagEnv((const uint32_t *) 0x00ffffff, env); + DrawOTagEnv((const uint32_t *) 0xffffff, env); else DrawOTag((const uint32_t *) &(env->dr_env)); } diff --git a/libpsn00b/psxgpu/image.c b/libpsn00b/psxgpu/image.c index 63bceb6..a08e293 100644 --- a/libpsn00b/psxgpu/image.c +++ b/libpsn00b/psxgpu/image.c @@ -41,6 +41,7 @@ static void _dma_transfer(const RECT *rect, uint32_t *data, int write) { while (!(GPU_GP1 & (1 << 26))) __asm__ volatile(""); + SetDrawOpType(DRAWOP_TYPE_DMA); GPU_GP1 = 0x04000000; // Disable DMA request GPU_GP0 = 0x01000000; // Flush cache @@ -124,6 +125,8 @@ void MoveImage2(const RECT *rect, int x, int y) { while (!(GPU_GP1 & (1 << 26))) __asm__ volatile(""); + SetDrawOpType(DRAWOP_TYPE_GPU_IRQ); + GPU_GP0 = 0x80000000; //GPU_GP0 = rect->x | (rect->y << 16); GPU_GP0 = *((const uint32_t *) &(rect->x)); diff --git a/libpsn00b/psxspu/common.c b/libpsn00b/psxspu/common.c index efe1d9e..64c6d1b 100644 --- a/libpsn00b/psxspu/common.c +++ b/libpsn00b/psxspu/common.c @@ -198,6 +198,10 @@ SPU_TransferMode SpuSetTransferMode(SPU_TransferMode mode) { return mode; } +SPU_TransferMode SpuGetTransferMode(void) { + return _transfer_mode; +} + uint32_t SpuSetTransferStartAddr(uint32_t addr) { if (addr > 0x7ffff) return 0; @@ -206,6 +210,10 @@ uint32_t SpuSetTransferStartAddr(uint32_t addr) { return addr; } +uint32_t SpuGetTransferStartAddr(void) { + return _transfer_addr * 8; +} + int SpuIsTransferCompleted(int mode) { if (!mode) return ((SPU_STAT >> 10) & 1) ^ 1; -- cgit v1.2.3 From 2021cdfca29dc5c98e570a674ac97f92f47a1129 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Thu, 11 May 2023 23:08:11 +0200 Subject: Add GPU IRQ variants of all display list APIs --- doc/drawing_queue.md | 105 ++++++++++++++++++++++++++++++++ libpsn00b/include/psxgpu.h | 5 ++ libpsn00b/psxgpu/common.c | 81 ------------------------- libpsn00b/psxgpu/drawing.c | 148 +++++++++++++++++++++++++++++++++++++++++++++ libpsn00b/psxgpu/env.c | 86 ++++++++++++++++---------- libpsn00b/psxgpu/image.c | 12 +++- 6 files changed, 323 insertions(+), 114 deletions(-) create mode 100644 doc/drawing_queue.md create mode 100644 libpsn00b/psxgpu/drawing.c (limited to 'libpsn00b/include/psxgpu.h') diff --git a/doc/drawing_queue.md b/doc/drawing_queue.md new file mode 100644 index 0000000..4fa83f7 --- /dev/null +++ b/doc/drawing_queue.md @@ -0,0 +1,105 @@ + +# GPU drawing queue + +`libpsxgpu` manages access to the GPU by implementing a software driven queue. +This queue, separate from the GPU's internal command FIFO, allows for high-level +management of GPU operations such as display list sending, VRAM image uploads +and framebuffer readback, in a similar way to the drawing queue system +implemented behind the scenes by the official SDK. + +The queue is managed internally by the library and can hold up to 16 drawing +operations ("DrawOps"). Each DrawOp is represented by a pointer to a function, +alongside any arguments to be passed to it. Whenever the GPU is idle, +`libpsxgpu` fetches a DrawOp from the queue and calls its respective function, +which should then proceed to actually send commands to the GPU or set up and +start a DMA transfer. `DrawSync()` can be called to wait for the queue to become +empty or get its current length, while `DrawSyncCallback()` may be used to +register a callback that will be invoked once the GPU is idle and no more +DrawOps are pending. + +Completion of each DrawOp (and transition of the GPU from busy to idle state) is +signalled through one of two means: + +- the DMA channel 2 IRQ, fired automatically by the DMA unit when a data + transfer such as a VRAM upload or a display list has finished executing; +- the GPU IRQ, triggered manually using the `GP0(0x1f)` command or the `DR_IRQ` + primitive. + +Note that the end of a DMA transfer does not necessarily imply that the GPU has +finished executing all commands; the last command issued may not yet be done, +hence the ability to use the GPU IRQ instead is provided as a more reliable way +to detect the completion of certain commands. + +## Built-in DrawOps + +The library includes a number of built-in DrawOps for the most common use cases. +The following APIs are wrappers around DrawOps: + +- `DrawBuffer()` and `DrawBufferIRQ()` queue a new DrawOp to start a DMA + transfer in chunked mode (sending one word at a time) with the specified + starting address and number of words. `DrawBuffer2()` and `DrawBufferIRQ2()` + are the underlying DrawOp functions respectively. +- `DrawOTag()` and `DrawOTagIRQ()` queue a new DrawOp to start a DMA transfer in + linked-list mode with the specified starting address, with `DrawOTag2()` and + `DrawOTagIRQ2()` being the respective DrawOp functions. +- `PutDrawEnv()`, `PutDrawEnvFast()`, `DrawOTagEnv()` and `DrawOTagEnvIRQ()` + insert drawing environment setup commands as the first (or only) item in a + display list, then proceed to pass it to `DrawOTag()`. The setup packet + linked into the display list is stored as part of the `DRAWENV` structure. +- `LoadImage()` and `StoreImage()` copy the provided coordinates into a + temporary buffer, then proceed to enqueue a DrawOp to actually start the VRAM + transfer. The synchronous variants of these APIs are `LoadImage2()` and + `StoreImage2()` respectively. +- `MoveImage()` saves the provided coordinates into a temporary buffer, then + enqueues a DrawOp that will issue a `GP0(0x80)` VRAM blitting command. As + this command is handled entirely by the GPU with no DMA transfers involved, + the GPU IRQ is used to detect its completion. + +## Custom DrawOps + +Unlike the official SDK, `libpsxgpu` exposes the drawing queue by providing a +way to enqueue arbitrary custom DrawOps. This can be useful for profiling +purposes or to work around specific GPU bugs (see the use cases section). + +Custom DrawOps can be pushed into the queue by calling `EnqueueDrawOp()` and +passing a pointer to the callback function in charge of issuing the DrawOp's +commands to the GPU, as well as up to 3 arguments to be passed through to it. +The function must: + +- call `SetDrawOpType()` to let the library know which type of IRQ it shall wait + for before moving onto the next DrawOp (either `DRAWOP_TYPE_DMA` or + `DRAWOP_TYPE_GPU_IRQ`); +- wait until the GPU is ready to accept commands by polling the status bits in + `GPU_STAT` and make sure DMA channel 2 is also idle before proceeding; +- issue any commands to the GPU's GP0 register and/or set up a DMA transfer, + terminating them with a `GP0(0x1f)` IRQ command if appropriate. + +Note that DrawOps are called from within the exception handler's context and +must thus not block for significant periods of time, manipulate COP0 registers +or wait for any IRQs to occur. They are also restricted from manipulating the +drawing queue by e.g. calling `EnqueueDrawOp()`, `DrawOTag()` or any other +function that enqueues a DrawOp. + +## Use cases + +### Scissoring commands + +The GPU provides commands to set the origin of all X/Y coordinates passed to it +as well as a scissoring region, all pixels outside of which are automatically +masked out during drawing. These commands are issued to the GP0 register and can +be inserted in a display list through the `DR_OFFSET` and `DR_AREA` primitives, +however they will *not* go through the GPU's command FIFO like most other +primitives. They will instead take effect immediately, resulting in graphical +glitches if the GPU is already busy processing a drawing command (i.e. if they +are not the very first commands in a display list). + +The software-driven drawing queue provides a way around this. By splitting up a +frame's display list into multiple chunks, one for each scissoring command +issued, it is possible to always place scissoring commands at the beginning of a +chunk. Each chunk can be terminated with a `DR_IRQ` primitive and queued for +drawing using `DrawOTagIRQ()` to ensure the GPU goes idle before the next chunk +is sent, preventing scissoring commands from being received by the GPU while +busy. + +----------------------------------------- +_Last updated on 2023-05-11 by spicyjpeg_ diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h index 2e9e4eb..d7f1ad5 100644 --- a/libpsn00b/include/psxgpu.h +++ b/libpsn00b/include/psxgpu.h @@ -606,10 +606,15 @@ void MoveImage2(const RECT *rect, int x, int y); void ClearOTagR(uint32_t *ot, size_t length); void ClearOTag(uint32_t *ot, size_t length); int DrawOTag(const uint32_t *ot); +int DrawOTagIRQ(const uint32_t *ot); int DrawOTagEnv(const uint32_t *ot, DRAWENV *env); +int DrawOTagEnvIRQ(const uint32_t *ot, DRAWENV *env); void DrawOTag2(const uint32_t *ot); +void DrawOTagIRQ2(const uint32_t *ot); int DrawBuffer(const uint32_t *buf, size_t length); +int DrawBufferIRQ(const uint32_t *buf, size_t length); void DrawBuffer2(const uint32_t *buf, size_t length); +void DrawBufferIRQ2(const uint32_t *buf, size_t length); void DrawPrim(const uint32_t *pri); void AddPrim(uint32_t *ot, const void *pri); diff --git a/libpsn00b/psxgpu/common.c b/libpsn00b/psxgpu/common.c index 8af6c5b..7e0758b 100644 --- a/libpsn00b/psxgpu/common.c +++ b/libpsn00b/psxgpu/common.c @@ -270,87 +270,6 @@ void *DrawSyncCallback(void (*func)(void)) { return old_callback; } -/* OT and primitive drawing API */ - -void ClearOTagR(uint32_t *ot, size_t length) { - _sdk_validate_args_void(ot && length); - - DMA_MADR(DMA_OTC) = (uint32_t) &ot[length - 1]; - DMA_BCR(DMA_OTC) = length & 0xffff; - DMA_CHCR(DMA_OTC) = 0x11000002; - - while (DMA_CHCR(DMA_OTC) & (1 << 24)) - __asm__ volatile(""); -} - -void ClearOTag(uint32_t *ot, size_t length) { - _sdk_validate_args_void(ot && length); - - // DMA6 only supports writing to RAM in reverse order (last to first), so - // the OT has to be cleared in software here. This function is thus much - // slower than ClearOTagR(). - // https://problemkaputt.de/psx-spx.htm#dmachannels - for (int i = 0; i < (length - 1); i++) - ot[i] = (uint32_t) &ot[i + 1] & 0x7fffff; - //setaddr(&ot[i], &ot[i + 1]); - - ot[length - 1] = 0xffffff; - //termPrim(&ot[length - 1]); -} - -void AddPrim(uint32_t *ot, const void *pri) { - _sdk_validate_args_void(ot && pri); - - addPrim(ot, pri); -} - -int DrawOTag(const uint32_t *ot) { - _sdk_validate_args(ot, -1); - - return EnqueueDrawOp((void *) &DrawOTag2, (uint32_t) ot, 0, 0); -} - -void DrawOTag2(const uint32_t *ot) { - _sdk_validate_args_void(ot); - - SetDrawOpType(DRAWOP_TYPE_DMA); - GPU_GP1 = 0x04000002; // Enable DMA request, route to GP0 - - while (DMA_CHCR(DMA_GPU) & (1 << 24)) - __asm__ volatile(""); - - DMA_MADR(DMA_GPU) = (uint32_t) ot; - DMA_BCR(DMA_GPU) = 0; - DMA_CHCR(DMA_GPU) = 0x01000401; -} - -int DrawBuffer(const uint32_t *buf, size_t length) { - _sdk_validate_args(buf && length && (length <= 0xffff), -1); - - return EnqueueDrawOp((void *) &DrawBuffer2, (uint32_t) buf, length, 0); -} - -void DrawBuffer2(const uint32_t *buf, size_t length) { - _sdk_validate_args_void(buf && length && (length <= 0xffff)); - - SetDrawOpType(DRAWOP_TYPE_DMA); - GPU_GP1 = 0x04000002; // Enable DMA request, route to GP0 - - while (DMA_CHCR(DMA_GPU) & (1 << 24)) - __asm__ volatile(""); - - DMA_MADR(DMA_GPU) = (uint32_t) buf; - DMA_BCR(DMA_GPU) = 0x00000001 | (length << 16); - DMA_CHCR(DMA_GPU) = 0x01000201; -} - -void DrawPrim(const uint32_t *pri) { - _sdk_validate_args_void(pri); - - DrawSync(0); - DrawBuffer2(&pri[1], getlen(pri)); -} - /* Queue pause/resume API */ int IsIdleGPU(int timeout) { diff --git a/libpsn00b/psxgpu/drawing.c b/libpsn00b/psxgpu/drawing.c new file mode 100644 index 0000000..161b2f7 --- /dev/null +++ b/libpsn00b/psxgpu/drawing.c @@ -0,0 +1,148 @@ +/* + * PSn00bSDK GPU library (drawing/display list functions) + * (C) 2022-2023 spicyjpeg - MPL licensed + */ + +#include +#include +#include +#include +#include + +/* Private utilities */ + +// This function is actually referenced in env.c as well, so it can't be static. +void _send_linked_list(GPU_DrawOpType type, const uint32_t *ot) { + SetDrawOpType(type); + GPU_GP1 = 0x04000002; // Enable DMA request, route to GP0 + + while (DMA_CHCR(DMA_GPU) & (1 << 24)) + __asm__ volatile(""); + + DMA_MADR(DMA_GPU) = (uint32_t) ot; + DMA_BCR(DMA_GPU) = 0; + DMA_CHCR(DMA_GPU) = 0x01000401; +} + +static void _send_buffer( + GPU_DrawOpType type, const uint32_t *buf, size_t length +) { + SetDrawOpType(type); + GPU_GP1 = 0x04000002; // Enable DMA request, route to GP0 + + while (DMA_CHCR(DMA_GPU) & (1 << 24)) + __asm__ volatile(""); + + DMA_MADR(DMA_GPU) = (uint32_t) buf; + DMA_BCR(DMA_GPU) = 0x00000001 | (length << 16); + DMA_CHCR(DMA_GPU) = 0x01000201; +} + +/* Buffer and primitive drawing API */ + +int DrawOTag(const uint32_t *ot) { + _sdk_validate_args(ot, -1); + + return EnqueueDrawOp( + (void *) &_send_linked_list, + (uint32_t) DRAWOP_TYPE_DMA, + (uint32_t) ot, + 0 + ); +} + +int DrawOTagIRQ(const uint32_t *ot) { + _sdk_validate_args(ot, -1); + + return EnqueueDrawOp( + (void *) &_send_linked_list, + (uint32_t) DRAWOP_TYPE_GPU_IRQ, + (uint32_t) ot, + 0 + ); +} + +int DrawBuffer(const uint32_t *buf, size_t length) { + _sdk_validate_args(buf && length && (length <= 0xffff), -1); + + return EnqueueDrawOp( + (void *) &DrawBuffer2, + (uint32_t) DRAWOP_TYPE_DMA, + (uint32_t) buf, + (uint32_t) length + ); +} + +int DrawBufferIRQ(const uint32_t *buf, size_t length) { + _sdk_validate_args(buf && length && (length <= 0xffff), -1); + + return EnqueueDrawOp( + (void *) &DrawBuffer2, + (uint32_t) DRAWOP_TYPE_GPU_IRQ, + (uint32_t) buf, + (uint32_t) length + ); +} + +void DrawOTag2(const uint32_t *ot) { + _sdk_validate_args_void(ot); + + _send_linked_list(DRAWOP_TYPE_DMA, ot); +} + +void DrawOTagIRQ2(const uint32_t *ot) { + _sdk_validate_args_void(ot); + + _send_linked_list(DRAWOP_TYPE_GPU_IRQ, ot); +} + +void DrawBuffer2(const uint32_t *buf, size_t length) { + _sdk_validate_args_void(buf && length && (length <= 0xffff)); + + _send_buffer(DRAWOP_TYPE_DMA, buf, length); +} + +void DrawBufferIRQ2(const uint32_t *buf, size_t length) { + _sdk_validate_args_void(buf && length && (length <= 0xffff)); + + _send_buffer(DRAWOP_TYPE_GPU_IRQ, buf, length); +} + +void DrawPrim(const uint32_t *pri) { + _sdk_validate_args_void(pri); + + DrawSync(0); + DrawBuffer2(&pri[1], getlen(pri)); +} + +/* Helper functions */ + +void ClearOTagR(uint32_t *ot, size_t length) { + _sdk_validate_args_void(ot && length); + + DMA_MADR(DMA_OTC) = (uint32_t) &ot[length - 1]; + DMA_BCR(DMA_OTC) = length & 0xffff; + DMA_CHCR(DMA_OTC) = 0x11000002; + + while (DMA_CHCR(DMA_OTC) & (1 << 24)) + __asm__ volatile(""); +} + +void ClearOTag(uint32_t *ot, size_t length) { + _sdk_validate_args_void(ot && length); + + // DMA6 only supports writing to RAM in reverse order (last to first), so + // the OT has to be cleared in software here. This function is thus much + // slower than ClearOTagR(). + // https://problemkaputt.de/psx-spx.htm#dmachannels + for (int i = 0; i < (length - 1); i++) + ot[i] = (uint32_t) &ot[i + 1] & 0x7fffff; + + ot[length - 1] = 0xffffff; +} + +void AddPrim(uint32_t *ot, const void *pri) { + _sdk_validate_args_void(ot && pri); + + addPrim(ot, pri); +} diff --git a/libpsn00b/psxgpu/env.c b/libpsn00b/psxgpu/env.c index c9e6142..236ae4b 100644 --- a/libpsn00b/psxgpu/env.c +++ b/libpsn00b/psxgpu/env.c @@ -34,37 +34,7 @@ static inline uint32_t _get_window_mask(int size) { return mask & 0x1f; } -/* Drawing API */ - -DRAWENV *SetDefDrawEnv(DRAWENV *env, int x, int y, int w, int h) { - _sdk_validate_args(env && (w > 0) && (h > 0), 0); - - env->clip.x = x; - env->clip.y = y; - env->clip.w = w; - env->clip.h = h; - - env->ofs[0] = 0; - env->ofs[1] = 0; - - env->tw.x = 0; - env->tw.y = 0; - env->tw.w = 256; - env->tw.h = 256; - - env->tpage = 0x0a; - env->dtd = 1; - env->dfe = 0; - env->isbg = 0; - setRGB0(env, 0, 0, 0); - - env->dr_env.tag = 0; - return env; -} - -int DrawOTagEnv(const uint32_t *ot, DRAWENV *env) { - _sdk_validate_args(ot && env, -1); - +static const uint32_t *_build_drawenv_ot(const uint32_t *ot, DRAWENV *env) { // All commands are grouped into a single display list packet for // performance reasons using tagless primitives (the GPU does not care // about the grouping as the display list is parsed by the CPU). @@ -101,7 +71,59 @@ int DrawOTagEnv(const uint32_t *ot, DRAWENV *env) { setWH(fill, env->clip.w, _min(env->clip.h, 0x1ff)); } - return EnqueueDrawOp((void *) &DrawOTag2, (uint32_t) prim, 0, 0); + return (const uint32_t *) prim; +} + +/* Drawing API */ + +void _send_linked_list(GPU_DrawOpType type, const uint32_t *ot); + +DRAWENV *SetDefDrawEnv(DRAWENV *env, int x, int y, int w, int h) { + _sdk_validate_args(env && (w > 0) && (h > 0), 0); + + env->clip.x = x; + env->clip.y = y; + env->clip.w = w; + env->clip.h = h; + + env->ofs[0] = 0; + env->ofs[1] = 0; + + env->tw.x = 0; + env->tw.y = 0; + env->tw.w = 256; + env->tw.h = 256; + + env->tpage = 0x0a; + env->dtd = 1; + env->dfe = 0; + env->isbg = 0; + setRGB0(env, 0, 0, 0); + + env->dr_env.tag = 0; + return env; +} + +int DrawOTagEnv(const uint32_t *ot, DRAWENV *env) { + _sdk_validate_args(ot && env, -1); + + return EnqueueDrawOp( + (void *) &_send_linked_list, + (uint32_t) DRAWOP_TYPE_DMA, + (uint32_t) _build_drawenv_ot(ot, env), + 0 + ); +} + +int DrawOTagEnvIRQ(const uint32_t *ot, DRAWENV *env) { + _sdk_validate_args(ot && env, -1); + + return EnqueueDrawOp( + (void *) &_send_linked_list, + (uint32_t) DRAWOP_TYPE_GPU_IRQ, + (uint32_t) _build_drawenv_ot(ot, env), + 0 + ); } void PutDrawEnv(DRAWENV *env) { diff --git a/libpsn00b/psxgpu/image.c b/libpsn00b/psxgpu/image.c index a08e293..e02c3c2 100644 --- a/libpsn00b/psxgpu/image.c +++ b/libpsn00b/psxgpu/image.c @@ -104,7 +104,17 @@ int StoreImage(const RECT *rect, uint32_t *data) { int MoveImage(const RECT *rect, int x, int y) { _sdk_validate_args(rect, -1); - return EnqueueDrawOp((void *) &MoveImage2, (uint32_t) rect, x, y); + int index = _next_saved_rect; + + _saved_rects[index] = *rect; + _next_saved_rect = (index + 1) % QUEUE_LENGTH; + + return EnqueueDrawOp( + (void *) &MoveImage2, + (uint32_t) &_saved_rects[index], + (uint32_t) x, + (uint32_t) y + ); } void LoadImage2(const RECT *rect, const uint32_t *data) { -- cgit v1.2.3