diff options
| author | spicyjpeg <thatspicyjpeg@gmail.com> | 2023-05-11 15:59:56 +0200 |
|---|---|---|
| committer | spicyjpeg <thatspicyjpeg@gmail.com> | 2023-05-11 15:59:56 +0200 |
| commit | ca6b54f3c15a7b00a5ede64ba452f2955a421a1e (patch) | |
| tree | 847ee5c32003f83ebaf7be4e20a93543c72a218f /libpsn00b/psxgpu | |
| parent | 0a797d2964517ac88e818b0741c5e7674c6fa018 (diff) | |
| download | psn00bsdk-ca6b54f3c15a7b00a5ede64ba452f2955a421a1e.tar.gz | |
Add MoveImage(), SetDrawOpType(), GPU IRQ support
Diffstat (limited to 'libpsn00b/psxgpu')
| -rw-r--r-- | libpsn00b/psxgpu/common.c | 139 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/env.c | 8 | ||||
| -rw-r--r-- | libpsn00b/psxgpu/image.c | 3 |
3 files changed, 83 insertions, 67 deletions
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 <psxgpu.h> #include <hwregs_c.h> -#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)); |
