aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b/psxgpu
diff options
context:
space:
mode:
authorspicyjpeg <thatspicyjpeg@gmail.com>2023-05-11 15:59:56 +0200
committerspicyjpeg <thatspicyjpeg@gmail.com>2023-05-11 15:59:56 +0200
commitca6b54f3c15a7b00a5ede64ba452f2955a421a1e (patch)
tree847ee5c32003f83ebaf7be4e20a93543c72a218f /libpsn00b/psxgpu
parent0a797d2964517ac88e818b0741c5e7674c6fa018 (diff)
downloadpsn00bsdk-ca6b54f3c15a7b00a5ede64ba452f2955a421a1e.tar.gz
Add MoveImage(), SetDrawOpType(), GPU IRQ support
Diffstat (limited to 'libpsn00b/psxgpu')
-rw-r--r--libpsn00b/psxgpu/common.c139
-rw-r--r--libpsn00b/psxgpu/env.c8
-rw-r--r--libpsn00b/psxgpu/image.c3
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));