diff options
| author | spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> | 2022-06-29 12:40:46 +0200 |
|---|---|---|
| committer | spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> | 2022-06-29 12:40:46 +0200 |
| commit | 6120304537470e7e5ff94b3bf19a33787ca69083 (patch) | |
| tree | f489c6dceae0846184dddd38444ef8519f799f7b | |
| parent | 578181ace1374e72cb93d69d2c201ce7a0a2300c (diff) | |
| download | psn00bsdk-6120304537470e7e5ff94b3bf19a33787ca69083.tar.gz | |
Refactor libpsxgpu in C, add OT drawing queue
32 files changed, 722 insertions, 1661 deletions
diff --git a/examples/demos/n00bdemo/disp.c b/examples/demos/n00bdemo/disp.c index c134163..d8d2bbf 100644 --- a/examples/demos/n00bdemo/disp.c +++ b/examples/demos/n00bdemo/disp.c @@ -19,7 +19,7 @@ MATRIX mtx; void initDisplay() { - ResetGraph( 3 ); + ResetGraph( 0 ); if( GetVideoMode() == MODE_NTSC ) { SetDefDispEnv( &disp, 0, 0, 640, 480 ); diff --git a/examples/sound/vagsample/main.c b/examples/sound/vagsample/main.c index 2b04c34..5764541 100644 --- a/examples/sound/vagsample/main.c +++ b/examples/sound/vagsample/main.c @@ -127,7 +127,7 @@ void init(void) // Begin pad polling InitPAD( pad_buff[0], 34, pad_buff[1], 34 ); StartPAD(); - + ChangeClearPAD(0); } /* init */ // Display function diff --git a/libpsn00b/CMakeLists.txt b/libpsn00b/CMakeLists.txt index f9c4f9d..a662448 100644 --- a/libpsn00b/CMakeLists.txt +++ b/libpsn00b/CMakeLists.txt @@ -40,6 +40,8 @@ foreach(_library IN LISTS PSN00BSDK_LIBRARIES) psn00bsdk_add_library(${_library} STATIC ${_sources}) endforeach() +psn00bsdk_target_incbin(psxgpu PRIVATE _gpu_debug_font psxgpu/dbugfont.tim) + # Extract libgcc's contents and merge them into libc after building. # Unfortunately glob expressions won't work on Windows, so we have to manually # enumerate the contents of libgcc and save the list to a temporary file (as it diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h index f061219..53a24c9 100644 --- a/libpsn00b/include/psxgpu.h +++ b/libpsn00b/include/psxgpu.h @@ -1,6 +1,7 @@ #ifndef __PSXGPU_H #define __PSXGPU_H +#include <stddef.h> #include <sys/types.h> // Low-level display parameters for DISPENV_RAW. A leftover from prototyping @@ -17,10 +18,11 @@ #define DISP_MODE_NTSC 0 #define DISP_MODE_PAL 8 - -#define MODE_NTSC 0 -#define MODE_PAL 1 - +typedef enum _VIDEO_MODE +{ + MODE_NTSC = 0, + MODE_PAL = 1 +} VIDEO_MODE; // Vector macros @@ -89,6 +91,12 @@ #define setWH( p, _w, _h ) \ (p)->w = _w, (p)->h = _h +#define setXYWH( p, _x0, _y0, _w, _h ) \ + (p)->x0 = _x0, (p)->y0 = _y0, \ + (p)->x1 = _x0+(_w), (p)->y1 = _y0, \ + (p)->x2 = _x0, (p)->y2 = _y0+(_h), \ + (p)->x3 = _x0+(_w), (p)->y3 = _y0+(_h) + /* * Set texture coordinates */ @@ -569,50 +577,61 @@ typedef struct _TIM_IMAGE u_long *paddr; } TIM_IMAGE; +typedef struct _GsIMAGE +{ + u_long pmode; + short px, py, pw, ph; + u_long *pixel; + short cx, cy, cw, ch; + u_long *clut; +} GsIMAGE; #ifdef __cplusplus extern "C" { #endif -// Function definitions (asm) +// Function definitions void ResetGraph(int mode); -int GetVideoMode(void); -void SetVideoMode(int mode); +VIDEO_MODE GetVideoMode(void); +void SetVideoMode(VIDEO_MODE mode); int GetODE(void); -void PutDispEnvRaw(DISPENV_RAW *disp); /* obsolete */ -void PutDispEnv(DISPENV *disp); -void PutDrawEnv(DRAWENV *draw); +void PutDispEnvRaw(const DISPENV_RAW *env); /* obsolete */ +void PutDispEnv(const DISPENV *env); +void PutDrawEnv(DRAWENV *env); +void PutDrawEnvFast(DRAWENV *env); void SetDispMask(int mask); -int VSync(int m); -int DrawSync(int m); -void WaitGPUcmd(void); -void WaitGPUdma(void); +int VSync(int mode); +int DrawSync(int mode); +//void WaitGPUcmd(void); +//void WaitGPUdma(void); // Callback hook functions void *VSyncCallback(void (*func)(void)); void *DrawSyncCallback(void (*func)(void)); -void LoadImage(RECT *rect, u_long *data); -void StoreImage(RECT *rect, u_long *data); - -void ClearOTagR(u_long* ot, int n); -void DrawOTag(u_long* ot); -void DrawPrim(void *pri); +void LoadImage(const RECT *rect, const u_long *data); +void StoreImage(const RECT *rect, u_long *data); -void AddPrim(u_long* ot, void* pri); +void ClearOTagR(u_long *ot, size_t length); +void ClearOTag(u_long *ot, size_t length); +void DrawOTag(const u_long *ot); +void DrawOTag2(const u_long *ot); +void DrawOTagEnv(const u_long *ot, DRAWENV *env); +void DrawPrim(const u_long *pri); -// Function definitions (C) +void AddPrim(u_long *ot, const void *pri); -int GetTimInfo(const u_long *tim, TIM_IMAGE *timimg); /* ORIGINAL */ +int GsGetTimInfo(const u_long *tim, GsIMAGE *info); +int GetTimInfo(const u_long *tim, TIM_IMAGE *info); /* deprecated */ -DISPENV *SetDefDispEnv(DISPENV *disp, int x, int y, int w, int h); -DRAWENV *SetDefDrawEnv(DRAWENV *draw, int x, int y, int w, int h); +DISPENV *SetDefDispEnv(DISPENV *env, int x, int y, int w, int h); +DRAWENV *SetDefDrawEnv(DRAWENV *env, int x, int y, int w, int h); // Debug font functions diff --git a/libpsn00b/psxgpu/addprim.s b/libpsn00b/psxgpu/addprim.s deleted file mode 100644 index 1b66274..0000000 --- a/libpsn00b/psxgpu/addprim.s +++ /dev/null @@ -1,26 +0,0 @@ -.set noreorder -.set noat - -.section .text - - -.global AddPrim -.type AddPrim, @function -AddPrim: - - lw $v0, 0($a0) # Load OT entry - lw $v1, 0($a1) # Set packet length value (in words) - lui $at, 0x00ff - or $at, 0xffff - and $v0, $at # Mask off the upper 8 bits of OT entry - or $v1, $v0 # OR values together - sw $v1, 0($a1) # Store new address to primitive tag - lw $v0, 0($a0) # Load OT entry - and $a1, $at # Mask off the upper 8 bits of primitive tag - lui $at, 0xff00 - and $v0, $at # Mask off the first 24 bits of OT entry - or $v0, $a1 # OR values together - - jr $ra - sw $v0, 0($a0) # Store result to OT - diff --git a/libpsn00b/psxgpu/clearotagr.s b/libpsn00b/psxgpu/clearotagr.s deleted file mode 100644 index 562cad4..0000000 --- a/libpsn00b/psxgpu/clearotagr.s +++ /dev/null @@ -1,21 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.section .text - - -.global ClearOTagR -.type ClearOTagR, @function -ClearOTagR: - lui $a2, IOBASE - addi $v0, $a1, -1 - sll $v0, 2 - addu $a0, $v0 - sw $a0, DMA6_MADR($a2) - andi $a1, 0xffff - sw $a1, DMA6_BCR($a2) - lui $v0, 0x1100 - addiu $v0, 2 - jr $ra - sw $v0, DMA6_CHCR($a2) diff --git a/libpsn00b/psxgpu/common.c b/libpsn00b/psxgpu/common.c new file mode 100644 index 0000000..ee90225 --- /dev/null +++ b/libpsn00b/psxgpu/common.c @@ -0,0 +1,293 @@ +/* + * PSn00bSDK GPU library (common functions) + * (C) 2022 spicyjpeg - MPL licensed + */ + +#include <stdint.h> +#include <sys/types.h> +#include <stdio.h> +#include <psxetc.h> +#include <psxapi.h> +#include <psxgpu.h> +#include <hwregs_c.h> + +#define QUEUE_LENGTH 8 +#define DMA_CHUNK_LENGTH 8 +#define VSYNC_TIMEOUT 0x100000 + +/* Internal globals */ + +VIDEO_MODE _gpu_video_mode; + +static void (*_vsync_callback)(void); +static void (*_drawsync_callback)(void); + +static const u_long *volatile _draw_queue[QUEUE_LENGTH]; +static volatile uint8_t _queue_head, _queue_tail, _queue_length; +static volatile uint32_t _vblank_counter, _last_hblank; + +/* Interrupt handlers */ + +static void _vblank_handler(void) { + _vblank_counter++; + + if (_vsync_callback) + _vsync_callback(); +} + +static void _gpu_dma_handler(void) { + //while (DMA_CHCR(2) & (1 << 24)) + //__asm__ volatile(""); + while (!(GPU_GP1 & (1 << 28))) + __asm__ volatile(""); + + if (_queue_length) { + DrawOTag2(_draw_queue[_queue_head++]); + + _queue_length--; + _queue_head %= QUEUE_LENGTH; + } else { + GPU_GP1 = 0x04000000; // Disable DMA request + + if (_drawsync_callback) + _drawsync_callback(); + } +} + +/* GPU reset and system initialization */ + +void ResetGraph(int mode) { + // Perform some basic system initialization when ResetGraph() is called for + // the first time. + static int setup_done = 0; + if (!setup_done) { + EnterCriticalSection(); + + DMA_DPCR = 0x03333333; + DMA_DICR = 0; + IRQ_MASK = 0; + + InterruptCallback(0, &_vblank_handler); + DMACallback(2, &_gpu_dma_handler); + RestartCallback(); + _96_remove(); + + _gpu_video_mode = (GPU_GP1 >> 20) & 1; + setup_done = 1; + + ExitCriticalSection(); + printf("psxgpu: setup done, default mode is %s\n", _gpu_video_mode ? "PAL" : "NTSC"); + } + + if (mode == 3) { + GPU_GP1 = 0x01000000; // Reset command buffer + return; + } + + DMA_DPCR |= 0x0b000b00; // Enable DMA2 and DMA6 + DMA_CHCR(2) = 0x00000201; // Stop DMA2 + DMA_CHCR(6) = 0x00000200; // Stop DMA6 + + if (mode == 1) { + GPU_GP1 = 0x01000000; // Reset command buffer + return; + } + + 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_hblank = 0; +} + +/* Syncing API */ + +// TODO: add support for no$psx's "halt" register +static void _vsync_halt(void) { + int counter = _vblank_counter; + + for (int i = VSYNC_TIMEOUT; i; i--) { + if (counter != _vblank_counter) + return; + } + + printf("psxgpu: VSync() timeout\n"); + ChangeClearPAD(0); + ChangeClearRCnt(3, 0); + return; +} + +int VSync(int mode) { + if (mode < 0) + return _vblank_counter; + + uint32_t status = GPU_GP1; + + // If mode = 0, wait for one vertical blank event to occur. If mode = 1, do + // not wait. + for (int i = ((mode < 2) ? (mode ^ 1) : mode); i; i--) { + _vsync_halt(); + + // If interlaced mode is enabled, wait until the GPU starts displaying + // the next field. + if (status & (1 << 22)) { + while (!((GPU_GP1 ^ status) & (1 << 31))) + __asm__ volatile(""); + } + } + + // Update the horizontal blank counter and return the time elapsed since + // the last time it was updated. + uint16_t counter = TIMER_VALUE(1); + uint16_t delta = counter - _last_hblank; + + _last_hblank = counter; + return delta; +} + +int DrawSync(int mode) { + if (mode) + return (DMA_BCR(2) >> 16); + + // Wait for the queue to become empty, to make sure no . + // TODO: add a timeout + while (_queue_length) + __asm__ volatile(""); + + // Wait for any DMA transfer to finish if DMA is enabled. + if (GPU_GP1 & (3 << 29)) { + while (DMA_CHCR(2) & (1 << 24)) + __asm__ volatile(""); + while (!(GPU_GP1 & (1 << 28))) + __asm__ volatile(""); + } + + while (!(GPU_GP1 & (1 << 26))) + __asm__ volatile(""); + + return 0; +} + +void *VSyncCallback(void (*func)(void)) { + EnterCriticalSection(); + + void *old_callback = _vsync_callback; + _vsync_callback = func; + + ExitCriticalSection(); + return old_callback; +} + +void *DrawSyncCallback(void (*func)(void)) { + EnterCriticalSection(); + + void *old_callback = _drawsync_callback; + _drawsync_callback = func; + + ExitCriticalSection(); + return old_callback; +} + +/* OT and primitive drawing API */ + +void ClearOTagR(u_long *ot, size_t length) { + DMA_MADR(6) = (uint32_t) &ot[length - 1]; + DMA_BCR(6) = length & 0xffff; + DMA_CHCR(6) = 0x11000002; + + //while (DMA_CHCR(6) & (1 << 24)) + //__asm__ volatile(""); +} + +void ClearOTag(u_long *ot, size_t 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] = (u_long) &ot[i + 1] & 0x00ffffff; + + ot[length - 1] = 0x00ffffff; +} + +void DrawOTag(const u_long *ot) { + // If GPU DMA is currently busy, append the OT to the queue instead of + // drawing it immediately. + if (DMA_CHCR(2) & (1 << 24)) { + if (_queue_length >= QUEUE_LENGTH) { + printf("psxgpu: DrawOTag() failed, draw queue full\n"); + return; + } + + _draw_queue[_queue_tail++] = ot; + _queue_length++; + _queue_tail %= QUEUE_LENGTH; + return; + } + + DrawOTag2(ot); +} + +void DrawOTag2(const u_long *ot) { + GPU_GP1 = 0x04000002; + + while (!(GPU_GP1 & (1 << 26))) + __asm__ volatile(""); + + DMA_MADR(2) = (uint32_t) ot; + DMA_BCR(2) = 0; + DMA_CHCR(2) = 0x01000401; +} + +void DrawPrim(const u_long *pri) { + size_t length = getlen(pri); + + DrawSync(0); + GPU_GP1 = 0x04000002; + + // 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(2) = (uint32_t) &pri[1]; + if (length < DMA_CHUNK_LENGTH) + DMA_BCR(2) = 0x00010000 | length; + else + DMA_BCR(2) = DMA_CHUNK_LENGTH | ((length / DMA_CHUNK_LENGTH) << 16); + + DMA_CHCR(2) = 0x01000201; +} + +void AddPrim(u_long *ot, const void *pri) { + addPrim(ot, pri); +} + +/* Misc. functions */ + +VIDEO_MODE GetVideoMode(void) { + return _gpu_video_mode; +} + +void SetVideoMode(VIDEO_MODE mode) { + uint32_t _mode, stat = GPU_GP1; + + _gpu_video_mode = mode & 1; + + _mode = (mode & 1) << 3; + _mode |= (stat >> 17) & 0x37; // GPUSTAT 17-22 -> cmd bits 0-5 + _mode |= (stat >> 10) & 0x40; // GPUSTAT bit 16 -> cmd bit 6 + _mode |= (stat >> 7) & 0x80; // GPUSTAT bit 14 -> cmd bit 7 + + GPU_GP1 = 0x08000000 | mode; +} + +int GetODE(void) { + return (GPU_GP1 >> 31); +} + +void SetDispMask(int mask) { + GPU_GP1 = 0x03000000 | (mask ? 0 : 1); +} diff --git a/libpsn00b/psxgpu/dbugfont.c b/libpsn00b/psxgpu/dbugfont.c deleted file mode 100644 index ff21d84..0000000 --- a/libpsn00b/psxgpu/dbugfont.c +++ /dev/null @@ -1,144 +0,0 @@ -unsigned int dbugfont_size=2112; -unsigned char dbugfont[] = { -0x10,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x00,0xe0, -0x01,0x10,0x00,0x01,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x08,0x00,0x00,0x80,0x02,0x00,0x00, -0x20,0x00,0x20,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x01,0x01, -0x00,0x10,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x11, -0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x11,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01, -0x00,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x10,0x00,0x10,0x00,0x10,0x00, -0x01,0x00,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, -0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x00, -0x00,0x00,0x00,0x00,0x00,0x10,0x11,0x11,0x00,0x01,0x01,0x00,0x00,0x11,0x01, -0x01,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x00, -0x10,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x11, -0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x10,0x11, -0x00,0x00,0x10,0x10,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x10, -0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x11,0x00,0x00,0x11,0x11,0x01,0x00, -0x00,0x00,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00, -0x00,0x10,0x10,0x10,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x11, -0x11,0x00,0x00,0x01,0x01,0x00,0x00,0x01,0x01,0x00,0x01,0x10,0x01,0x00,0x00, -0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x01,0x01,0x01,0x00, -0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x01,0x00,0x00,0x10,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x10,0x10,0x11,0x00,0x01, -0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00, -0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x11,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x01, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x10,0x11,0x00,0x00,0x01, -0x00,0x01,0x00,0x10,0x01,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00, -0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x11, -0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x11,0x01,0x00,0x00, -0x11,0x01,0x00,0x00,0x10,0x01,0x00,0x10,0x11,0x11,0x00,0x00,0x10,0x01,0x00, -0x10,0x11,0x11,0x00,0x00,0x11,0x01,0x00,0x00,0x11,0x01,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x10,0x00, -0x00,0x00,0x00,0x11,0x01,0x00,0x00,0x11,0x11,0x00,0x00,0x11,0x00,0x00,0x10, -0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x01,0x00,0x10,0x00,0x00,0x00, -0x00,0x01,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, -0x00,0x00,0x11,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x10, -0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x01,0x00, -0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10, -0x00,0x10,0x00,0x10,0x00,0x00,0x11,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x01, -0x00,0x00,0x10,0x11,0x11,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x10, -0x10,0x01,0x01,0x00,0x10,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00, -0x10,0x11,0x11,0x00,0x10,0x11,0x01,0x00,0x10,0x11,0x01,0x00,0x00,0x00,0x01, -0x00,0x00,0x11,0x01,0x00,0x00,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, -0x00,0x01,0x00,0x10,0x10,0x01,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00, -0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10, -0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x11,0x11,0x00,0x00, -0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x10,0x11,0x00,0x00,0x10,0x00,0x00, -0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10, -0x00,0x10,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00, -0x01,0x00,0x00,0x11,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x10,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00, -0x10,0x11,0x11,0x00,0x10,0x11,0x11,0x00,0x00,0x11,0x01,0x00,0x00,0x00,0x01, -0x00,0x10,0x11,0x01,0x00,0x00,0x11,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x11, -0x01,0x00,0x00,0x11,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x11,0x00,0x00,0x00, -0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x00, -0x00,0x11,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, -0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x11,0x01, -0x00,0x00,0x11,0x01,0x00,0x10,0x11,0x01,0x00,0x10,0x11,0x11,0x00,0x10,0x11, -0x11,0x00,0x00,0x11,0x11,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x11,0x00,0x00, -0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00, -0x10,0x00,0x10,0x00,0x00,0x11,0x01,0x00,0x10,0x11,0x01,0x00,0x00,0x01,0x01, -0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00, -0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00, -0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00, -0x10,0x01,0x11,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, -0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00, -0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10, -0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x01,0x00, -0x10,0x00,0x00,0x00,0x10,0x10,0x10,0x00,0x10,0x01,0x10,0x00,0x10,0x00,0x10, -0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x01,0x00,0x10,0x00, -0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x10, -0x10,0x11,0x00,0x10,0x11,0x11,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x00, -0x10,0x11,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x10,0x10, -0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x11,0x00,0x10,0x00, -0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x10, -0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x10,0x00,0x00, -0x10,0x00,0x10,0x00,0x10,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10, -0x00,0x10,0x00,0x11,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x01,0x00,0x10,0x00, -0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, -0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00, -0x00,0x10,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00, -0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00, -0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x01,0x00,0x00,0x11,0x01,0x00,0x10, -0x11,0x01,0x00,0x10,0x11,0x11,0x00,0x10,0x00,0x00,0x00,0x00,0x11,0x01,0x00, -0x10,0x00,0x10,0x00,0x10,0x11,0x11,0x00,0x00,0x11,0x01,0x00,0x10,0x00,0x10, -0x00,0x10,0x11,0x11,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x11, -0x01,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x01,0x00,0x10, -0x11,0x01,0x00,0x00,0x11,0x01,0x00,0x10,0x11,0x11,0x00,0x10,0x00,0x10,0x00, -0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, -0x00,0x10,0x11,0x11,0x00,0x00,0x11,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x11, -0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x10, -0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x10,0x00,0x00, -0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, -0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x00,0x10,0x00, -0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00, -0x11,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00, -0x00,0x10,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, -0x00,0x00,0x01,0x01,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x01, -0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x01,0x11,0x00,0x00, -0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x11,0x01,0x00, -0x00,0x11,0x01,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, -0x00,0x10,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x10, -0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x00, -0x10,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x10, -0x00,0x10,0x00,0x10,0x00,0x10,0x10,0x10,0x00,0x00,0x01,0x01,0x00,0x00,0x10, -0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00, -0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x10,0x00,0x01,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x10,0x00, -0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x01,0x00,0x10,0x01,0x11,0x00,0x10,0x00, -0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, -0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x11,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x11,0x01, -0x00,0x00,0x10,0x00,0x00,0x00,0x11,0x01,0x00,0x00,0x10,0x00,0x00,0x10,0x00, -0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x10,0x11,0x11,0x00,0x00, -0x11,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x11,0x01,0x00,0x00,0x00,0x00,0x00, -0x11,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -}; diff --git a/libpsn00b/psxgpu/drawotag.s b/libpsn00b/psxgpu/drawotag.s deleted file mode 100644 index 3cb0db0..0000000 --- a/libpsn00b/psxgpu/drawotag.s +++ /dev/null @@ -1,38 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.section .text - - -.global DrawOTag -.type DrawOTag, @function -DrawOTag: - addiu $sp, -4 - sw $ra, 0($sp) - - lui $a3, IOBASE # I/O segment base - - lui $v0, 0x0400 # Set DMA direction to CPUtoGPU - ori $v0, 0x2 - sw $v0, GPU_GP1($a3) - -.Lgpu_wait: # Wait for GPU to be ready for commands & DMA - jal ReadGPUstat - nop - srl $v0, 26 - andi $v0, 1 - beqz $v0, .Lgpu_wait - nop - - sw $a0, DMA2_MADR($a3) # Set DMA base address to specified OT - sw $0 , DMA2_BCR($a3) - - lui $v0, 0x0100 # Begin OT transfer! - ori $v0, 0x0401 - sw $v0, DMA2_CHCR($a3) - - lw $ra, 0($sp) - addiu $sp, 4 - jr $ra - nop diff --git a/libpsn00b/psxgpu/drawprim.s b/libpsn00b/psxgpu/drawprim.s deleted file mode 100644 index d62c202..0000000 --- a/libpsn00b/psxgpu/drawprim.s +++ /dev/null @@ -1,41 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.text - -.global DrawPrim -.type DrawPrim, @function -DrawPrim: - - addiu $sp, -8 - sw $ra, 0($sp) - sw $s0, 4($sp) - - move $s0, $a0 # Wait for GPU to complete - jal DrawSync - move $a0, $0 - - lui $a3, IOBASE - lui $v0, 0x0400 # Set transfer direction to off - sw $v0, GPU_GP1($a3) - - move $a0, $s0 - lbu $a1, 3($a0) # Get length of primitive packet - addiu $a0, 4 - addiu $a1, -1 - -.Ltransfer_loop: - lw $v0, 0($a0) - addiu $a0, 4 - sw $v0, GPU_GP0($a3) - bgtz $a1, .Ltransfer_loop - addiu $a1, -1 - - jal DrawSync - move $a0, $0 - - lw $ra, 0($sp) - lw $s0, 4($sp) - jr $ra - addiu $sp, 8
\ No newline at end of file diff --git a/libpsn00b/psxgpu/drawsync.s b/libpsn00b/psxgpu/drawsync.s deleted file mode 100644 index b671b03..0000000 --- a/libpsn00b/psxgpu/drawsync.s +++ /dev/null @@ -1,67 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.section .text - - -.global DrawSync -.type DrawSync, @function -DrawSync: - - bnez $a0, .Lgetwords - lui $a0, IOBASE - - addiu $sp, -4 - sw $ra, 0($sp) - - jal ReadGPUstat # Check if DMA enabled - nop - srl $v0, 29 - andi $v0, 0x3 - - beqz $v0, .Lsimple_wait - nop - -.Ldma_wait: - lw $v0, DMA2_CHCR($a0) - nop - srl $v0, 24 - andi $v0, 0x1 - bnez $v0, .Ldma_wait - nop - -.Lgpu_wait: - jal ReadGPUstat - nop - srl $v0, 26 - andi $v0, 0x5 - bne $v0, 5, .Lgpu_wait - nop - - b .Lexit - nop - -.Lsimple_wait: # Wait for GPU to be ready for next DMA - jal ReadGPUstat - nop - srl $v0, 28 - andi $v0, 0x1 - beqz $v0, .Lsimple_wait - nop - -.Lexit: - - lw $ra, 0($sp) - addiu $sp, 4 - jr $ra - nop - -.Lgetwords: - - lw $v0, DMA2_BCR($a0) - nop - - jr $ra - srl $v0, 16 - diff --git a/libpsn00b/psxgpu/drawsynccallback.s b/libpsn00b/psxgpu/drawsynccallback.s deleted file mode 100644 index 22cfb7d..0000000 --- a/libpsn00b/psxgpu/drawsynccallback.s +++ /dev/null @@ -1,105 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.text - -.global DrawSyncCallback -.type DrawSyncCallback, @function -DrawSyncCallback: - - addiu $sp, -8 - sw $ra, 0($sp) - sw $a0, 4($sp) - - jal EnterCriticalSection - nop - - beqz $a0, .Luninstall - nop - - la $a1, _drawsync_handler - lw $a1, 4($sp) - jal DMACallback - li $a0, 2 - - b .Lcontinue - nop - -.Luninstall: - - move $a1, $0 - jal DMACallback - li $a0, 2 - -.Lcontinue: - - lw $a0, 4($sp) - la $v1, _drawsync_func - lw $v0, 0($v1) - sw $a0, 0($v1) - sw $v0, 4($sp) - -.Lexit: - - jal ExitCriticalSection - nop - - lw $ra, 0($sp) - lw $v0, 4($sp) - jr $ra - addiu $sp, 8 - - -.type _drawsync_handler, @function -_drawsync_handler: - -.Ldma_wait: - la $v0, _drawsync_func - lw $v0, 0($v0) - nop - beqz $v0, .Lskip - nop - - addiu $sp, -4 - sw $ra, 0($sp) - - lw $v0, DMA2_CHCR($a0) - nop - srl $v0, 24 - andi $v0, 0x1 - - bnez $v0, .Ldma_wait - nop - -.Lgpu_wait: - jal ReadGPUstat - nop - srl $v0, 28 - andi $v0, 0x1 - beqz $v0, .Lgpu_wait - nop - - la $v1, _drawsync_func - lw $v1, 0($v1) - - lui $v0, 0x0400 # Set DMA direction to off - sw $v0, GPU_GP1($a0) - - jalr $v1 - nop - - lw $ra, 0($sp) - addiu $sp, 4 - -.Lskip: - - jr $ra - nop - - -.data - -_drawsync_func: - .word 0 -
\ No newline at end of file diff --git a/libpsn00b/psxgpu/env.c b/libpsn00b/psxgpu/env.c new file mode 100644 index 0000000..8a74b7e --- /dev/null +++ b/libpsn00b/psxgpu/env.c @@ -0,0 +1,213 @@ +/* + * PSn00bSDK GPU library (DRAWENV/DISPENV functions) + * (C) 2022 spicyjpeg - MPL licensed + */ + +#include <stdint.h> +#include <sys/types.h> +#include <psxgpu.h> +#include <hwregs_c.h> + +#define _min(x, y) (((x) < (y)) ? (x) : (y)) + +extern VIDEO_MODE _gpu_video_mode; + +/* Drawing API */ + +DRAWENV *SetDefDrawEnv(DRAWENV *env, int x, int y, int w, int h) { + 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 = 0; + env->tw.h = 0; + + env->tpage = 0x0a; + env->dtd = 1; + env->dfe = 0; + env->isbg = 0; + setRGB0(env, 0, 0, 0); + + env->dr_env.tag = 0; + return env; +} + +void DrawOTagEnv(const u_long *ot, DRAWENV *env) { + DR_ENV *prim = &(env->dr_env); + + // All commands are grouped into a single display list packet for + // performance reasons (keep in mind that the GPU doesn't care about this + // as the display list is parsed by the DMA unit in the CPU and only the + // payload is sent to the GPU). + setaddr(prim, ot); + setlen(prim, 4); + + // Set drawing area top left + prim->code[0] = 0xe3000000; + prim->code[0] |= env->clip.x & 0x3ff; + prim->code[0] |= (env->clip.y & 0x3ff) << 10; + + // Set drawing area bottom right + prim->code[1] = 0xe4000000; + prim->code[1] |= (env->clip.x + (env->clip.w - 1)) & 0x3ff; + prim->code[1] |= ((env->clip.y + (env->clip.h - 1)) & 0x3ff) << 10; + + // Set drawing offset + prim->code[2] = 0xe5000000; + prim->code[2] |= (env->clip.x + env->ofs[0]) & 0x7ff; + prim->code[2] |= ((env->clip.y + env->ofs[1]) & 0x7ff) << 11; + + // Texture page (reset active page and set dither/mask bits) + prim->code[3] = 0xe1000000; + prim->code[3] |= (env->dtd & 1) << 9; + prim->code[3] |= (env->dfe & 1) << 10; + + if (env->isbg) { + setlen(prim, 7); + + // Rectangle fill + // FIXME: reportedly this command doesn't accept height values >511... + prim->code[4] = 0x02000000; + //prim->code[4] |= env->r0 | (env->g0 << 8) | (env->b0 << 16); + prim->code[4] |= *((const uint32_t *) &(env->isbg)) >> 8; + //prim->code[5] = env->clip.x; + //prim->code[5] |= env->clip.y << 16; + prim->code[5] = *((const uint32_t *) &(env->clip.x)); + prim->code[6] = env->clip.w; + prim->code[6] |= _min(env->clip.h, 0x1ff) << 16; + } + + //while (!(GPU_GP1 & (1 << 26))) + //__asm__ volatile(""); + + DrawOTag(prim); +} + +void PutDrawEnv(DRAWENV *env) { + DrawOTagEnv((const u_long *) 0x00ffffff, env); +} + +// This function skips rebuilding the cached packet whenever possible and is +// useful if the DRAWENV structure is never modified (which is the case most of +// the time). +void PutDrawEnvFast(DRAWENV *env) { + if (!(env->dr_env.tag)) { + DrawOTagEnv((const u_long *) 0x00ffffff, env); + return; + } + + DrawOTag(&(env->dr_env)); +} + +/* Display API */ + +DISPENV *SetDefDispEnv(DISPENV *env, int x, int y, int w, int h) { + env->disp.x = x; + env->disp.y = y; + env->disp.w = w; + env->disp.h = h; + + env->screen.x = 0; + env->screen.y = 0; + env->screen.w = 0; + env->screen.h = 0; + + env->isinter = 0; + env->isrgb24 = 0; + env->reverse = 0; + + return env; +} + +void PutDispEnv(const DISPENV *env) { + uint32_t h_range, v_range, mode, fb_pos; + + mode = _gpu_video_mode << 3; + mode |= (env->isrgb24 & 1) << 4; + mode |= (env->isinter & 1) << 5; + mode |= (env->reverse & 1) << 7; + + if (env->disp.h >= 256) + mode |= 1 << 2; + + // Calculate the horizontal display range values. The original code was + // this bad; in actual fact it was even worse due to being written in + // assembly and using slow multiplication even when not necessary. + int offset, span, default_span = 2560; + + if (env->disp.w > 560) { + // 640 pixels + mode |= 3; + offset = 620; + span = env->screen.w * 4; + } else if (env->disp.w > 400) { + // 512 pixels + mode |= 2; + offset = 615; + span = env->screen.w * 4 + env->screen.w; + } else if (env->disp.w > 352) { + // 384 pixels (this mode is weird) + mode |= 1 << 6; + offset = 539; + span = env->screen.w * 8 - env->screen.w; + default_span = 2688; + } else if (env->disp.w > 280) { + // 320 pixels + mode |= 1; + offset = 600; + span = env->screen.w * 8; + } else { + // 256 pixels + offset = 590; + span = env->screen.w * 8 + env->screen.w * 2; + } + + offset += env->screen.x * 4; + if (!span) + span = default_span; + + h_range = offset & 0xfff; + h_range |= ((offset + span) & 0xfff) << 12; + + // Calculate the vertical display range values. + offset = 16 + env->screen.y; + span = env->screen.h ? env->screen.h : 240; + + v_range = offset & 0x3ff; + v_range |= ((offset + span) & 0x3ff) << 10; + + fb_pos = env->disp.x & 0x3ff; + fb_pos |= (env->disp.y & 0x1ff) << 10; + + GPU_GP1 = 0x06000000 | h_range; // Set horizontal display range + GPU_GP1 = 0x07000000 | v_range; // Set vertical display range + GPU_GP1 = 0x08000000 | mode; // Set video mode + GPU_GP1 = 0x05000000 | fb_pos; // Set VRAM location to display +} + +/* Deprecated "raw" display API */ + +void PutDispEnvRaw(const DISPENV_RAW *env) { + uint32_t h_range, v_range, fb_pos; + + h_range = 608 + env->vid_xpos; + h_range |= (3168 + env->vid_xpos) << 12; + + // FIXME: these hardcoded values are for NTSC displays. + v_range = (136 - 120 + env->vid_ypos) & 0x3ff; + v_range |= ((136 + 120 + env->vid_ypos) & 0x3ff) << 12; + + fb_pos = env->fb_x & 0x3ff; + fb_pos |= (env->fb_y & 0x1ff) << 10; + + GPU_GP1 = 0x06000000 | h_range; // Set horizontal display range + GPU_GP1 = 0x07000000 | v_range; // Set vertical display range + GPU_GP1 = 0x08000000 | env->vid_mode; // Set video mode + GPU_GP1 = 0x05000000 | fb_pos; // Set VRAM location to display +} diff --git a/libpsn00b/psxgpu/fntsort.c b/libpsn00b/psxgpu/fntsort.c deleted file mode 100644 index 9358793..0000000 --- a/libpsn00b/psxgpu/fntsort.c +++ /dev/null @@ -1,48 +0,0 @@ -#include <sys/types.h> -#include <stdio.h> -#include <ctype.h> -#include <psxgpu.h> - -extern unsigned short _font_tpage; -extern unsigned short _font_clut; - -char *FntSort(u_long *ot, char *pri, int x, int y, const char *text) { - - DR_TPAGE *tpage; - SPRT_8 *sprt = (SPRT_8*)pri; - int i; - - while( *text != 0 ) { - - i = toupper( *text )-32; - - if( i > 0 ) { - - i--; - setSprt8( sprt ); - setRGB0( sprt, 128, 128, 128 ); - setXY0( sprt, x, y ); - setUV0( sprt, (i%16)<<3, (i>>4)<<3 ); - sprt->clut = _font_clut; - addPrim( ot, sprt ); - sprt++; - - } - - x += 8; - text++; - - } - - pri = (char*)sprt; - - tpage = (DR_TPAGE*)pri; - tpage->code[0] = _font_tpage; - setlen( tpage, 1 ); - setcode( tpage, 0xe1 ); - addPrim( ot, pri ); - pri += sizeof(DR_TPAGE); - - return pri; - -}
\ No newline at end of file diff --git a/libpsn00b/psxgpu/font.c b/libpsn00b/psxgpu/font.c index 4c715a9..7a8137c 100644 --- a/libpsn00b/psxgpu/font.c +++ b/libpsn00b/psxgpu/font.c @@ -21,14 +21,14 @@ static int _nstreams = 0; u_short _font_tpage; u_short _font_clut; -extern u_char dbugfont[]; +extern u_char _gpu_debug_font[]; void FntLoad(int x, int y) { RECT pos; TIM_IMAGE tim; - GetTimInfo( (u_long*)dbugfont, &tim ); + GetTimInfo( (const u_long *) _gpu_debug_font, &tim ); // Load font image pos = *tim.prect; @@ -223,4 +223,45 @@ char *FntFlush(int id) { return _stream[id].pribuff; -}
\ No newline at end of file +} + +char *FntSort(u_long *ot, char *pri, int x, int y, const char *text) { + + DR_TPAGE *tpage; + SPRT_8 *sprt = (SPRT_8*)pri; + int i; + + while( *text != 0 ) { + + i = toupper( *text )-32; + + if( i > 0 ) { + + i--; + setSprt8( sprt ); + setRGB0( sprt, 128, 128, 128 ); + setXY0( sprt, x, y ); + setUV0( sprt, (i%16)<<3, (i>>4)<<3 ); + sprt->clut = _font_clut; + addPrim( ot, sprt ); + sprt++; + + } + + x += 8; + text++; + + } + + pri = (char*)sprt; + + tpage = (DR_TPAGE*)pri; + tpage->code[0] = _font_tpage; + setlen( tpage, 1 ); + setcode( tpage, 0xe1 ); + addPrim( ot, pri ); + pri += sizeof(DR_TPAGE); + + return pri; + +} diff --git a/libpsn00b/psxgpu/getode.s b/libpsn00b/psxgpu/getode.s deleted file mode 100644 index 5dc1e70..0000000 --- a/libpsn00b/psxgpu/getode.s +++ /dev/null @@ -1,20 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.section .text - - -.global GetODE -.type GetODE, @function -GetODE: - addiu $sp, -4 - sw $ra, 0($sp) - jal ReadGPUstat - nop - srl $v0, 31 - andi $v0, 1 - lw $ra, 0($sp) - addiu $sp, 4 - jr $ra - nop diff --git a/libpsn00b/psxgpu/gettimimage.c b/libpsn00b/psxgpu/gettimimage.c deleted file mode 100644 index 5598e07..0000000 --- a/libpsn00b/psxgpu/gettimimage.c +++ /dev/null @@ -1,40 +0,0 @@ -#include <sys/types.h> -#include <psxgpu.h> - -int GetTimInfo(const u_long *tim, TIM_IMAGE *timimg) { - - u_long *rtim; - - // Check ID - if( ( tim[0]&0xff ) != 0x10 ) { - return 1; - } - - // Check version - if( ( (tim[0]>>8)&0xff ) != 0x0 ) { - return 2; - } - - timimg->mode = tim[1]; - rtim = tim+2; - - // Clut present? - if( timimg->mode & 0x8 ) { - - timimg->crect = (RECT*)(rtim+1); - timimg->caddr = (u_long*)(rtim+3); - - rtim += rtim[0]>>2; - - } else { - - timimg->caddr = 0; - - } - - timimg->prect = (RECT*)(rtim+1); - timimg->paddr = (u_long*)(rtim+3); - - return 0; - -} diff --git a/libpsn00b/psxgpu/getvideomode.s b/libpsn00b/psxgpu/getvideomode.s deleted file mode 100644 index 6f1613c..0000000 --- a/libpsn00b/psxgpu/getvideomode.s +++ /dev/null @@ -1,14 +0,0 @@ -.set noreorder - - -.section .text - -.global GetVideoMode -.type GetVideoMode, @function -GetVideoMode: - - la $v0, _gpu_standard - lw $v0, 0($v0) - - jr $ra - nop diff --git a/libpsn00b/psxgpu/image.c b/libpsn00b/psxgpu/image.c new file mode 100644 index 0000000..3633c7c --- /dev/null +++ b/libpsn00b/psxgpu/image.c @@ -0,0 +1,116 @@ +/* + * PSn00bSDK GPU library (image and VRAM transfer functions) + * (C) 2022 spicyjpeg - MPL licensed + */ + +#include <stdint.h> +#include <sys/types.h> +#include <stdio.h> +#include <psxgpu.h> +#include <hwregs_c.h> + +#define DMA_CHUNK_LENGTH 8 + +/* Common internal load/store function */ + +static void _load_store_image( + uint32_t command, + int mode, + const RECT *rect, + uint32_t *data +) { + size_t length = rect->w * rect->h; + if (length % 2) + printf("psxgpu: can't transfer an odd number of pixels\n"); + + length /= 2; + if ((length >= DMA_CHUNK_LENGTH) && (length % DMA_CHUNK_LENGTH)) + printf("psxgpu: transfer data length (%d) is not a multiple of %d\n", length, DMA_CHUNK_LENGTH); + + DrawSync(0); + GPU_GP1 = 0x04000000; // Disable DMA request + GPU_GP0 = 0x01000000; // Flush cache + + GPU_GP0 = command; + //GPU_GP0 = rect->x | (rect->y << 16); + GPU_GP0 = *((const uint32_t *) &(rect->x)); + //GPU_GP0 = rect->w | (rect->h << 16); + GPU_GP0 = *((const uint32_t *) &(rect->w)); + + // Enable DMA request, route to GP0 (2) or from GPU_READ (3) + GPU_GP1 = 0x04000000 | mode; + + DMA_MADR(2) = (uint32_t) data; + if (length < DMA_CHUNK_LENGTH) + DMA_BCR(2) = 0x00010000 | length; + else + DMA_BCR(2) = DMA_CHUNK_LENGTH | ((length / DMA_CHUNK_LENGTH) << 16); + + DMA_CHCR(2) = 0x01000200 | !(mode & 1); +} + +/* Public VRAM API */ + +void LoadImage(const RECT *rect, const u_long *data) { + _load_store_image(0xa0000000, 2, rect, (uint32_t *) data); +} + +void StoreImage(const RECT *rect, u_long *data) { + _load_store_image(0xc0000000, 3, rect, (uint32_t *) data); +} + +/* .TIM image parsers */ + +// This is the only libgs function PSn00bSDK is ever going to implement. The +// difference from GetTimInfo() is that it copies RECTs rather than merely +// returning pointers to them, which become useless once the .TIM file is +// unloaded from main RAM. +int GsGetTimInfo(const u_long *tim, GsIMAGE *info) { + if ((*(tim++) & 0xffff) != 0x0010) + return 1; + + info->pmode = *(tim++); + if (info->pmode & 8) { + const u_long *palette_end = tim; + palette_end += *(tim++) / 4; + + *((u_long *) &(info->cx)) = *(tim++); + *((u_long *) &(info->cw)) = *(tim++); + info->clut = (u_long *) tim; + + tim = palette_end; + } else { + info->clut = 0; + } + + tim++; + *((u_long *) &(info->px)) = *(tim++); + *((u_long *) &(info->pw)) = *(tim++); + info->pixel = (u_long *) tim; + + return 0; +} + +int GetTimInfo(const u_long *tim, TIM_IMAGE *info) { + if ((*(tim++) & 0xffff) != 0x0010) + return 1; + + info->mode = *(tim++); + if (info->mode & 8) { + const u_long *palette_end = tim; + palette_end += *(tim++) / 4; + + info->crect = (RECT *) tim; + info->caddr = (u_long *) &tim[2]; + + tim = palette_end; + } else { + info->caddr = 0; + } + + tim++; + info->prect = (RECT *) tim; + info->paddr = (u_long *) &tim[2]; + + return 0; +} diff --git a/libpsn00b/psxgpu/loadimage.s b/libpsn00b/psxgpu/loadimage.s deleted file mode 100644 index 45f152f..0000000 --- a/libpsn00b/psxgpu/loadimage.s +++ /dev/null @@ -1,70 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.set RECT_x, 0 -.set RECT_y, 2 -.set RECT_w, 4 -.set RECT_h, 6 - -.section .text - - -.global LoadImage -.type LoadImage, @function -LoadImage: - addiu $sp, -8 - sw $ra, 0($sp) - sw $s0, 4($sp) - - lui $s0, IOBASE # Set I/O segment base address - -.Lgpu_wait: # Wait for GPU to be ready for commands and DMA - jal ReadGPUstat - nop - srl $v0, 0x1a - andi $v0, 0x5 - li $v1, 5 - #srl $v0, 28 - #andi $v0, 1 - bne $v0, $v1, .Lgpu_wait - nop - - lui $v0, 0x400 # Set DMA direction to off - sw $v0, GPU_GP1($s0) - - lui $v0, 0x0100 # Clear GPU cache - sw $v0, GPU_GP0($s0) - - lui $v1, 0xa000 # Load image to VRAM - sw $v1, GPU_GP0($s0) - lw $v0, RECT_x($a0) # Set XY and dimensions of image - lw $v1, RECT_w($a0) - sw $v0, GPU_GP0($s0) - sw $v1, GPU_GP0($s0) - - lui $v0, 0x400 # Set DMA direction to CPUtoVRAM - ori $v0, 0x2 - sw $v0, GPU_GP1($s0) - - lhu $v0, RECT_w($a0) # Get rectangle size - lhu $v1, RECT_h($a0) - nop - mult $v0, $v1 # Calculate BCR value - mflo $v1 - srl $v1, 0x4 - sll $v1, 0x10 - ori $v1, 0x8 - - sw $a1, DMA2_MADR($s0) # Set DMA base address and transfer length - sw $v1, DMA2_BCR($s0) - - lui $v0, 0x100 # Start DMA transfer - ori $v0, 0x201 - sw $v0, DMA2_CHCR($s0) - - lw $ra, 0($sp) - lw $s0, 4($sp) - jr $ra - addiu $sp, 8 - diff --git a/libpsn00b/psxgpu/putdispenv.s b/libpsn00b/psxgpu/putdispenv.s deleted file mode 100644 index fc09454..0000000 --- a/libpsn00b/psxgpu/putdispenv.s +++ /dev/null @@ -1,174 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.set DISP_dx, 0 -.set DISP_dy, 2 -.set DISP_dw, 4 -.set DISP_dh, 6 -.set DISP_sx, 8 -.set DISP_sy, 10 -.set DISP_sw, 12 -.set DISP_sh, 14 -.set DISP_inter, 16 -.set DISP_isrgb24, 17 -.set DISP_reverse, 18 - -.section .text - - -.global PutDispEnv -.type PutDispEnv, @function -PutDispEnv: - - lui $a3, IOBASE - - # Horizontal resolution stuff - - lh $a2, DISP_dw($a0) # Get X resolution - - lh $v0, DISP_sx($a0) - lh $v1, DISP_sw($a0) # Get X screen width - - move $a1, $0 # To use as mode value - - bgt $a2, 560, .Lmode_640 - nop - bgt $a2, 400, .Lmode_512 - nop - bgt $a2, 352, .Lmode_384 - nop - bgt $a2, 280, .Lmode_320 - nop - - .set noat - -.Lmode_256: - li $at, 10 - mult $at, $v1 - li $a2, 0x24e - sll $v0, 2 - add $a2, $v0 - b .Lmode_end - li $v1, 0xa00 -.Lmode_320: - li $at, 8 - mult $at, $v1 - li $a2, 0x258 - ori $a1, 0x01 - sll $v0, 2 - add $a2, $v0 - b .Lmode_end - li $v1, 0xa00 -.Lmode_384: - li $at, 7 - mult $at, $v1 - li $a2, 0x21b - ori $a1, 0x64 - sll $v0, 2 - add $a2, $v0 - b .Lmode_end - li $v1, 0xa80 -.Lmode_512: - li $at, 5 - mult $at, $v1 - li $a2, 0x267 - ori $a1, 0x02 - sll $v0, 2 - add $a2, $v0 - b .Lmode_end - li $v1, 0xa00 -.Lmode_640: - li $at, 4 - mult $at, $v1 - li $a2, 0x26c - ori $a1, 0x03 - sll $v0, 2 - add $a2, $v0 - li $v1, 0xa00 -.Lmode_end: - - .set at - - mflo $v0 - bnez $v0, .Lno_default # Check if screen with is non zero - nop - move $v0, $v1 # Use default if screen width is 0 -.Lno_default: - - addu $v0, $a2 # Apply horizontal display coordinates - sll $v0, 12 - andi $a2, 0xfff - or $a2, $v0 - lui $v0, 0x0600 - or $v0, $a2 - sw $v0, GPU_GP1($a3) - - # Vertical resolution - - lh $v0, DISP_dh($a0) - li $a2, 0x10 - ble $v0, 256, .Lmode_low - nop - -.Lmode_high: - ori $a1, 0x04 -.Lmode_low: - lh $v0, DISP_sy($a0) - lh $v1, DISP_sh($a0) - add $a2, $v0 - bnez $v1, .Lno_default_vert - nop - li $v1, 0xf0 -.Lno_default_vert: - add $v1, $a2 - and $a2, 0x3ff - sll $v1, 10 - or $v1, $a2 - lui $v0, 0x0700 - or $v1, $v0 - sw $v1, GPU_GP1($a3) - - # Video mode - - la $v0, _gpu_standard - lbu $v0, 0($v0) - nop - beqz $v0, .Lconfig_ntsc - nop -.Lconfig_pal: - ori $a1, 0x08 -.Lconfig_ntsc: - - lbu $v0, DISP_inter($a0) - lbu $v1, DISP_isrgb24($a0) - beqz $v0, .Lno_inter - nop - or $a1, 0x20 -.Lno_inter: - beqz $v1, .Lno_rgb24 - nop - or $a1, 0x10 -.Lno_rgb24: - lbu $v0, DISP_inter($a0) - nop - beqz $v0, .Lno_reverse - nop - or $a1, 0x80 -.Lno_reverse: - - lui $v0, 0x800 # Apply mode - or $a1, $v0 - sw $a1, GPU_GP1($a3) - - lhu $v0, DISP_dx($a0) # Set VRAM XY offset - lhu $v1, DISP_dy($a0) - andi $v0, 0x3ff - andi $v1, 0x1ff - sll $v1, 10 - or $v0, $v1 - lui $v1, 0x500 - or $v0, $v1 - - jr $ra - sw $v0, GPU_GP1($a3) diff --git a/libpsn00b/psxgpu/putdispenvraw.s b/libpsn00b/psxgpu/putdispenvraw.s deleted file mode 100644 index 747796f..0000000 --- a/libpsn00b/psxgpu/putdispenvraw.s +++ /dev/null @@ -1,71 +0,0 @@ -.set noreorder -.set noat - -.include "hwregs_a.h" - -.set DISP_mode, 0 -.set DISP_vxpos, 4 -.set DISP_vypos, 6 -.set DISP_fbx, 8 -.set DISP_fby, 10 - -.section .text - - -.global PutDispEnvRaw -.type PutDispEnvRaw, @function -PutDispEnvRaw: - addiu $sp, -8 - sw $ra, 0($sp) - sw $s0, 4($sp) - - lui $s0, IOBASE - - lh $at, DISP_vxpos($a0) # Set horizontal display range - li $v0, 608 - add $v0, $at - li $v1, 3168 - add $v1, $at - sll $v1, 12 - or $v0, $v1 - lui $v1, 0x600 - or $v1, $v0 - sw $v1, GPU_GP1($s0) - - lh $at, DISP_vypos($a0) # Set vertical display range (for NTSC) - li $v1, 120 # (values differet for PAL modes) - sub $v1, $at - li $v0, 136 - sub $v0, $v1 - andi $v0, 0x1ff - li $v1, 120 - add $v1, $at - li $at, 136 - add $at, $v1 - andi $at, 0x1ff - sll $at, 10 - or $v0, $at - lui $at, 0x700 - or $v0, $at - sw $v0, GPU_GP1($s0) - - lw $v0, DISP_mode($a0) # Set video mode - lui $at, 0x800 - or $v0, $at - sw $v0, GPU_GP1($s0) - - lhu $v0, DISP_fbx($a0) # Set VRAM XY offset - lhu $v1, DISP_fby($a0) - andi $v0, 0x3ff - andi $v1, 0x1ff - sll $v1, 10 - or $v0, $v1 - lui $v1, 0x500 - or $v0, $v1 - sw $v0, GPU_GP1($s0) - - lw $ra, 0($sp) - lw $s0, 4($sp) - jr $ra - addiu $sp, 8 - diff --git a/libpsn00b/psxgpu/putdrawenv.s b/libpsn00b/psxgpu/putdrawenv.s deleted file mode 100644 index c0d5676..0000000 --- a/libpsn00b/psxgpu/putdrawenv.s +++ /dev/null @@ -1,142 +0,0 @@ -.set noreorder -.set noat - -.include "hwregs_a.h" - -.set DRAW_x, 0 # Drawing area -.set DRAW_y, 2 -.set DRAW_w, 4 -.set DRAW_h, 6 -.set DRAW_ofx, 8 # Draw offset -.set DRAW_ofy, 10 -.set DRAW_tx, 12 # Texture window -.set DRAW_ty, 14 -.set DRAW_tw, 16 -.set DRAW_th, 18 -.set DRAW_tpage, 20 # TPage values -.set DRAW_dtd, 22 -.set DRAW_dfe, 23 -.set DRAW_isbg, 24 # Clear draw area -.set DRAW_r0, 25 -.set DRAW_g0, 26 -.set DRAW_b0, 27 -.set DRAW_env, 28 - - -.section .text - -.global PutDrawEnv -.type PutDrawEnv, @function -PutDrawEnv: - addiu $sp, -4 - sw $ra, 0($sp) - - addiu $a1, $a0, DRAW_env - - li $v0, 0x04ffffff # Packet header (length+terminator) - sw $v0, 0($a1) - - lhu $v0, DRAW_x($a0) # Set draw area top-left - lhu $v1, DRAW_y($a0) - andi $v0, 0x3ff - andi $v1, 0x1ff - sll $v1, 10 - or $v0, $v1 - lui $v1, 0xe300 - or $v0, $v1 - sw $v0, 4($a1) # 1 - - .set noat - - lhu $v0, DRAW_w($a0) # Set draw area bottom-right - lhu $at, DRAW_x($a0) - addiu $v0, -1 - addu $at, $v0 - andi $at, 0x3ff - lhu $v1, DRAW_h($a0) - lhu $v0, DRAW_y($a0) - addiu $v1, -1 - addu $v0, $v1 - andi $v0, 0x1ff - sll $v0, 10 - or $at, $v0 - lui $v0, 0xe400 - or $at, $v0 - sw $at, 8($a1) # 2 - - lhu $v0, DRAW_x($a0) # Set drawing offset - lhu $v1, DRAW_ofx($a0) - nop - add $v0, $v1 - andi $at, $v0, 0x7ff - lhu $v0, DRAW_y($a0) - lhu $v1, DRAW_ofy($a0) - nop - add $v0, $v1 - andi $v0, 0x7ff - sll $v0, 11 - or $at, $v0 - lui $v0, 0xe500 - or $at, $v0 - sw $at, 12($a1) # 3 - - lhu $at, DRAW_tpage($a0) # Set tpage - lbu $v0, DRAW_dtd($a0) - lbu $v1, DRAW_dfe($a0) - andi $v0, 1 - and $v1, 1 - sll $v0, 9 - sll $v1, 10 - or $at, $v0 - or $at, $v1 - lui $v0, 0xe100 - or $at, $v0 - sw $at, 16($a1) # 4 - - .set at - - lbu $v0, DRAW_isbg($a0) - nop - beqz $v0, .Lno_fillVRAM - nop - - lw $v0, DRAW_isbg($a0) # FillVRAM - lui $v1, 0x0200 - srl $v0, 8 - or $v0, $v1 - sw $v0, 20($a1) # 5 - lw $v0, DRAW_x($a0) - lw $v1, DRAW_w($a0) - sw $v0, 24($a1) # 6 - - srl $v0, $v1, 16 # Workaround as rectangle primitives - blt $v0, 511, .Lno_overflow # don't accept a height of 512 - nop - - li $v0, 511 - sll $v0, 16 - andi $v1, 0xffff - or $v1, $v0 - -.Lno_overflow: - sw $v1, 28($a1) # 7 - li $v0, 0x07ffffff # Packet header (length+terminator) - sw $v0, 0($a1) - -.Lno_fillVRAM: - -.Lgpu_wait: # Wait for GPU to become ready for commands and DMA - jal ReadGPUstat - nop - srl $v0, 26 - andi $v0, 1 - beqz $v0, .Lgpu_wait - nop - - jal DrawOTag - move $a0, $a1 - - lw $ra, 0($sp) - addiu $sp, 4 - jr $ra - nop diff --git a/libpsn00b/psxgpu/readgpustat.s b/libpsn00b/psxgpu/readgpustat.s deleted file mode 100644 index ffff4d7..0000000 --- a/libpsn00b/psxgpu/readgpustat.s +++ /dev/null @@ -1,14 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.section .text - - -.global ReadGPUstat -.type ReadGPUstat, @function -ReadGPUstat: - lui $v0, IOBASE - lw $v0, GPU_GP1($v0) - jr $ra - nop diff --git a/libpsn00b/psxgpu/readme.txt b/libpsn00b/psxgpu/readme.txt index b626e1d..2963b6a 100644 --- a/libpsn00b/psxgpu/readme.txt +++ b/libpsn00b/psxgpu/readme.txt @@ -3,25 +3,19 @@ PSX GPU library, part of PSn00bSDK Licensed under Mozilla Public License - Open source implementation of the GPU library written mostly in MIPS -assembly. Supports DMA transfers for ordering table draw and transferring -image data to and from VRAM. The syntax is intentionally made to closely -resemble Sony's syntax for familiarity and to make porting homebrew made -using the official SDK to PSn00bSDK a little easier. - +Open source implementation of the GPU library written entirely in C. Supports +DMA transfers for drawing OTs (with an internal queue so DrawOTag() can be +called even when another OT is being drawn) and transferring image data to and +from VRAM. The syntax is intentionally made to closely resemble Sony's syntax +for familiarity and to make porting homebrew made using the official SDK to +PSn00bSDK a little easier. Library developer(s): - Lameguy64 - + Lameguy64 (initial implementation in assembly, debug font API) + spicyjpeg Library header(s): hwregs_a.h (GNU assembler port defs) psxgpu.h - - -Todo list: - - * ClearOTag() function (non reverse version of ClearOTagR()) yet to be - implemented (but should be trivial). diff --git a/libpsn00b/psxgpu/resetgraph.s b/libpsn00b/psxgpu/resetgraph.s deleted file mode 100644 index 6327f02..0000000 --- a/libpsn00b/psxgpu/resetgraph.s +++ /dev/null @@ -1,363 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.section .text - -.set ISR_STACK_SIZE, 4096 - -.global ResetGraph # Resets the GPU and installs a -.type ResetGraph, @function # VSync event handler -ResetGraph: - addiu $sp, -8 # C style stack allocation (required if - sw $ra, 0($sp) # you call BIOS functions from asm) - sw $a0, 4($sp) - - la $a0, resetgraph_msg - move $a1, $0 - move $a2, $0 - la $a1, _irq_func_table - la $a2, _custom_exit - jal printf - addiu $sp, -16 - addiu $sp, 16 - - la $a0, sr_msg - mfc0 $a1, $12 - jal printf - addiu $sp, -16 - addiu $sp, 16 - - la $v0, _hooks_installed # Skip installing hooks if this function - lbu $v0, 0($v0) # has already been called before once - nop - bnez $v0, .Lskip_hook_init - nop - - jal EnterCriticalSection # Disable interrupts as LoadExec() keeps - nop # interrupts enabled when transferring - # execution to the loaded program - - lui $a3, IOBASE # Base address for I/O - - lui $v0, 0x3b33 # Enables DMA channel 6 (for ClearOTag) - ori $v0, 0x3b33 # Enables DMA channel 2 - sw $v0, DMA_DPCR($a3) - sw $0 , DMA_DICR($a3) # Clear DICR (not needed) - - sw $0 , IRQ_MASK($a3) # Clear IRQ settings - - la $v0, _hooks_installed # Set installed flag - li $v1, 0x1 - sb $v1, 0($v0) - - la $v0, _vsync_cb_func # Clear VSync callback function - sw $0 , 0($v0) - - la $a1, _vsync_irq_callback # Install VSync interrupt callback - jal InterruptCallback - li $a0, 0 - - jal RestartCallback - nop - - la $a0, cbhooks_msg - jal printf - addiu $sp, -16 - addiu $sp, 16 - - jal _96_remove # Remove CD handling left by the BIOS - nop - - la $a0, abouttoen_msg - jal printf - addiu $sp, -16 - addiu $sp, 16 - - jal ExitCriticalSection # Re-enable interrupts - nop - - la $a0, enableint_msg - jal printf - addiu $sp, -16 - addiu $sp, 16 - -.Lskip_hook_init: - - lui $a3, IOBASE - - lw $v0, GPU_GP1($a3) # Get video standard - lui $v1, 0x0010 - and $v0, $v1 - la $v1, _gpu_standard - beqz $v0, .Lnot_pal - sw $0 , 0($v1) - li $v0, 1 - sw $v0, 0($v1) -.Lnot_pal: - - lw $a0, 4($sp) # Get argument value - - lui $a3, IOBASE # Set base I/O again (likely destroyed - # by previous calls) - - li $v0, 0x1d00 # Configure timer 1 as Hblank counter - sw $v0, TIMER1_CTRL($a3) # Set timer 1 value - - beq $a0, 1, .Lgpu_init_1 - nop - beq $a0, 3, .Lgpu_init_3 - nop - - sw $0 , GPU_GP1($a3) # Reset the GPU - - b .Linit_done - nop - -.Lgpu_init_1: - - sw $0 , DMA2_CHCR($a3) # Stop any DMA - -.Lgpu_init_3: - - li $v0, 0x1 # Reset the command buffer - sw $v0, GPU_GP1($a3) - -.Linit_done: - - lw $ra, 0($sp) - lw $a0, 4($sp) # Return - jr $ra - addiu $sp, 8 - - -.global VSync # VSync function -.type VSync, @function -VSync: - - addiu $sp, -12 - sw $ra, 0($sp) - sw $s0, 4($sp) - - lui $a3, IOBASE # Get GPU status (for interlace sync) - lw $s0, GPU_GP1($a3) - -.Lhwait_loop: # Get Hblank time - lw $v0, TIMER1_VALUE($a3) - nop - lw $v1, TIMER1_VALUE($a3) - nop - bne $v0, $v1, .Lhwait_loop - nop - - la $a3, _vsync_lasthblank # Calculate Hblank time since last - lw $v1, 0($a3) - nop - subu $v0, $v1 - andi $v0, 0xffff - - beq $a0, 1, .Lhblank_exit # Return Hblank time only, no VSync - sw $v0, 8($sp) # Stored as return value - - bgez $a0, .Lvsync # Vsync if argument is 0 and up - nop - - la $v0, _vsync_rcnt # Return VSync count only - lw $v0, 0($v0) - nop - b .Lvsync_exit - sw $v0, 8($sp) - -.Lvsync: - - bnez $a0, .Lnot_zero - nop - li $a0, 1 - -.Lnot_zero: - - la $v0, _vsync_rcnt # Call vsync sub function (with timeout) - lw $v0, 0($v0) - addiu $a1, $a0, 1 - jal _vsync_sub - addu $a0, $v0, $a0 - - lui $v0, 0x40 - and $v0, $s0, $v0 - beqz $v0, .Lhblank_exit - nop - - lui $a3, IOBASE # Interlace wait logic - - lw $v0, GPU_GP1($a3) - nop - xor $v0, $s0, $v0 - bltz $v0, .Lhblank_exit - lui $a0, 0x8000 - -.Linterlace_wait: - lw $v0, GPU_GP1($a3) - nop - xor $v0, $s0, $v0 - and $v0, $a0 - beqz $v0, .Linterlace_wait - nop - -.Lhblank_exit: # Set current Hblank as last value - - la $a2, _vsync_lasthblank - -.Lhwait2_loop: - lw $v0, TIMER1_VALUE($a3) - nop - lw $v1, TIMER1_VALUE($a3) - sw $v0, 0($a2) - bne $v0, $v1, .Lhwait2_loop - nop - -.Lvsync_exit: - - lw $ra, 0($sp) - lw $s0, 4($sp) - lw $v0, 8($sp) - jr $ra - addiu $sp, 12 - - -.type _vsync_sub, @function -_vsync_sub: - - # a0 - VSync destination count - # a1 - Timeout ratio (number of vsyncs to wait relative to vsync count) - - addiu $sp, -4 - sw $ra, 0($sp) - - sll $a1, 15 # Timeout counter - - la $v0, _vsync_rcnt - lw $v0, 0($v0) - nop - bge $v0, $a0, .Lvsync_sub_exit - nop - -.Lvsync_wait: - - addiu $a1, -1 - - la $v1, 0xffffffff - bne $a1, $v1, .Lnot_timeout - nop - - la $a0, vsynctimeout_msg - jal puts - addiu $sp, -8 - - jal ChangeClearPAD - move $a0, $0 - - li $a0, 3 - jal ChangeClearRCnt - move $a1, $0 - - addiu $sp, 8 - b .Lvsync_sub_exit - li $v0, -1 - -.Lnot_timeout: - - la $v0, _vsync_rcnt - lw $v0, 0($v0) - nop - blt $v0, $a0, .Lvsync_wait - nop - -.Lvsync_sub_exit: - - lw $ra, 0($sp) - addiu $sp, 4 - jr $ra - move $v0, $0 - - - -.type _vsync_irq_callback, @function -_vsync_irq_callback: - - lui $a0, IOBASE - - la $v1, _vsync_rcnt # Increment VSync root counter - lw $v0, 0($v1) - nop - addiu $v0, 1 - sw $v0, 0($v1) - - la $v0, _vsync_cb_func # Check if a callback function is set - lw $v0, 0($v0) - nop - beqz $v0, .Lno_callback - nop - - addiu $sp, -4 # Save return address - sw $ra, 0($sp) - jalr $v0 # Execute user callback function - nop - lw $ra, 0($sp) # Restore previous return address - addiu $sp, 4 - - lui $a0, IOBASE - -.Lno_callback: - - jr $ra - nop - - -.section .data - -# VSync root counter -.type _vsync_rcnt, @object -_vsync_rcnt: - .word 0 - -.type _vsync_lasthblank, @object -_vsync_lasthblank: - .word 0 - -.comm _vsync_cb_func, 4, 4 - -.comm _gpu_standard, 4, 4 -.comm _gpu_current_field, 4, 4 -.comm _hooks_installed, 4, 4 - - -.type vsynctimeout_msg, @object -vsynctimeout_msg: - .asciiz "VSync: timeout\n" - -.type resetgraph_msg, @object -resetgraph_msg: - .asciiz "ResetGraph:itb=%08x,ehk=%08x\n" - -.type enableint_msg, @object -enableint_msg: - .asciiz "ResetGraph:Interrupts enabled!\n" - -.type cbhooks_msg, @object -cbhooks_msg: - .asciiz "ResetGraph:Interrupt hooks enabled.\n" - -.type abouttoen_msg, @object -abouttoen_msg: - .asciiz "ResetGraph:About to init interrupts.\n" - -.type sr_msg, @object -sr_msg: - .asciiz "ResetGraph:SR=%x\n" - -.global psxgpu_credits -.type psxgpu_credits, @object -psxgpu_credits: - .ascii "psxgpu programs by Lameguy64\n" - .asciiz "2020 PSn00bSDK Project / Meido-Tek Productions\n" -
\ No newline at end of file diff --git a/libpsn00b/psxgpu/setdefdispenv.c b/libpsn00b/psxgpu/setdefdispenv.c deleted file mode 100644 index 2d7b2b4..0000000 --- a/libpsn00b/psxgpu/setdefdispenv.c +++ /dev/null @@ -1,22 +0,0 @@ -#include <sys/types.h> -#include <psxgpu.h> - -DISPENV *SetDefDispEnv(DISPENV *disp, int x, int y, int w, int h) { - - disp->disp.x = x; - disp->disp.y = y; - disp->disp.w = w; - disp->disp.h = h; - - disp->screen.x = 0; - disp->screen.y = 0; - disp->screen.w = 0; - disp->screen.h = 0; - - disp->isinter = 0; - disp->isrgb24 = 0; - disp->reverse = 0; - - return disp; - -} diff --git a/libpsn00b/psxgpu/setdefdrawenv.c b/libpsn00b/psxgpu/setdefdrawenv.c deleted file mode 100644 index 6fd6086..0000000 --- a/libpsn00b/psxgpu/setdefdrawenv.c +++ /dev/null @@ -1,27 +0,0 @@ -#include <sys/types.h> -#include <psxgpu.h> - -DRAWENV *SetDefDrawEnv(DRAWENV *draw, int x, int y, int w, int h) { - - draw->clip.x = x; - draw->clip.y = y; - draw->clip.w = w; - draw->clip.h = h; - - draw->ofs[0] = 0; - draw->ofs[1] = 0; - - draw->tw.x = 0; - draw->tw.y = 0; - draw->tw.w = 0; - draw->tw.h = 0; - - draw->tpage = 0x0a; - draw->dtd = 1; - draw->dfe = 0; - draw->isbg = 0; - setRGB0( draw, 0, 0, 0 ); - - return draw; - -} diff --git a/libpsn00b/psxgpu/setdispmask.s b/libpsn00b/psxgpu/setdispmask.s deleted file mode 100644 index d79006c..0000000 --- a/libpsn00b/psxgpu/setdispmask.s +++ /dev/null @@ -1,19 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.section .text - - -.global SetDispMask -.type SetDispMask, @function -SetDispMask: - lui $v1, IOBASE - andi $a0, 0x1 - lui $v0, 0x300 - ori $v0, 0x1 - sub $v0, $a0 - sw $v0, GPU_GP1($v1) - jr $ra - nop - diff --git a/libpsn00b/psxgpu/setvideomode.s b/libpsn00b/psxgpu/setvideomode.s deleted file mode 100644 index b89b285..0000000 --- a/libpsn00b/psxgpu/setvideomode.s +++ /dev/null @@ -1,50 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - - -.section .text - -.global SetVideoMode -.type SetVideoMode, @function -SetVideoMode: - addiu $sp, -4 - sw $ra, 0($sp) - - jal ReadGPUstat - nop - - srl $a1, $v0, 17 - andi $a1, 0x1f - - srl $v1, $v0, 14 # Reverse flag - andi $v1, 1 - sll $v1, 6 - or $a1, $v1 - - srl $v1, $v0, 16 # Horizontal resolution 2 - andi $v1, 1 - sll $v1, 6 - or $a1, $v1 - - andi $a1, 0xf7 # Mask off PAL bit - - la $v0, _gpu_standard - beqz $a0, .Lset_done - sw $0 , 0($v0) - li $v1, 1 - sw $v1, 0($v0) - b .Lset_done - or $a1, 0x8 -.Lset_done: - - lui $v0, 0x800 # Apply new mode - or $a1, $v0 - lui $v0, IOBASE - sw $a1, GPU_GP1($v0) - - lw $ra, 0($sp) - addiu $sp, 4 - jr $ra - nop - diff --git a/libpsn00b/psxgpu/storeimage.s b/libpsn00b/psxgpu/storeimage.s deleted file mode 100644 index 554e83c..0000000 --- a/libpsn00b/psxgpu/storeimage.s +++ /dev/null @@ -1,76 +0,0 @@ -.set noreorder - -.include "hwregs_a.h" - -.set RECT_x, 0 -.set RECT_y, 2 -.set RECT_w, 4 -.set RECT_h, 6 - -.section .text - - -.global StoreImage -.type StoreImage, @function -StoreImage: - addiu $sp, -8 - sw $ra, 0($sp) - sw $s0, 4($sp) - - lui $s0, IOBASE # Set I/O segment base address - -.Lgpu_wait: # Wait for GPU to be ready for commands and DMA - jal ReadGPUstat - nop - srl $v0, 0x1a - andi $v0, 0x5 - li $v1, 5 - bne $v0, $v1, .Lgpu_wait - nop - - lui $v0, 0x400 # Set DMA direction to off - sw $v0, GPU_GP1($s0) - - lui $v0, 0x0100 # Clear GPU cache - sw $v0, GPU_GP0($s0) - - lui $v1, 0xc000 # Store image from VRAM - sw $v1, GPU_GP0($s0) - lw $v0, RECT_x($a0) # Set XY and dimensions of image - lw $v1, RECT_w($a0) - sw $v0, GPU_GP0($s0) - sw $v1, GPU_GP0($s0) - - lui $v0, 0x400 # Set DMA direction to VRAMtoCPU - ori $v0, 0x3 - sw $v0, GPU_GP1($s0) - - lhu $v0, RECT_w($a0) # Get rectangle size - lhu $v1, RECT_h($a0) - nop - mult $v0, $v1 # Calculate BCR value - mflo $v1 - srl $v1, 0x4 - sll $v1, 0x10 - ori $v1, 0x8 - - sw $a1, DMA2_MADR($s0) # Set DMA base address and transfer length - sw $v1, DMA2_BCR($s0) - -.Lgpu_wait_2: # Wait for GPU to be ready for commands and DMA - jal ReadGPUstat - nop - srl $v0, 27 - andi $v0, 0x1 - beqz $v0, .Lgpu_wait_2 - nop - - lui $v0, 0x100 # Start DMA transfer - ori $v0, 0x200 - sw $v0, DMA2_CHCR($s0) - - lw $ra, 0($sp) - lw $s0, 4($sp) - jr $ra - addiu $sp, 8 - diff --git a/libpsn00b/psxgpu/vsynccallback.s b/libpsn00b/psxgpu/vsynccallback.s deleted file mode 100644 index 4be29c8..0000000 --- a/libpsn00b/psxgpu/vsynccallback.s +++ /dev/null @@ -1,25 +0,0 @@ -.set noreorder - -.section .text - -.global VSyncCallback -.type VSyncCallback, @function -VSyncCallback: - addiu $sp, -8 - sw $ra, 0($sp) - - jal EnterCriticalSection - sw $a0, 4($sp) - - lw $a0, 4($sp) - la $v0, _vsync_cb_func - sw $a0, 0($v0) - - jal ExitCriticalSection - nop - - lw $ra, 0($sp) - addiu $sp, 8 - jr $ra - nop - |
