aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b/psxgpu/image.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpsn00b/psxgpu/image.c')
-rw-r--r--libpsn00b/psxgpu/image.c64
1 files changed, 56 insertions, 8 deletions
diff --git a/libpsn00b/psxgpu/image.c b/libpsn00b/psxgpu/image.c
index fc018a4..e02c3c2 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
@@ -9,11 +9,12 @@
#include <stdint.h>
#include <assert.h>
+#include <psxetc.h>
#include <psxgpu.h>
#include <hwregs_c.h>
#define QUEUE_LENGTH 16
-#define DMA_CHUNK_LENGTH 8
+#define DMA_CHUNK_LENGTH 16
/* Internal globals */
@@ -37,6 +38,10 @@ static void _dma_transfer(const RECT *rect, uint32_t *data, int write) {
length += DMA_CHUNK_LENGTH - 1;
}
+ while (!(GPU_GP1 & (1 << 26)))
+ __asm__ volatile("");
+
+ SetDrawOpType(DRAWOP_TYPE_DMA);
GPU_GP1 = 0x04000000; // Disable DMA request
GPU_GP0 = 0x01000000; // Flush cache
@@ -49,18 +54,24 @@ 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);
- DMA_MADR(2) = (uint32_t) data;
+ while ((DMA_CHCR(DMA_GPU) & (1 << 24)) || !(GPU_GP1 & (1 << 28)))
+ __asm__ volatile("");
+
+ DMA_MADR(DMA_GPU) = (uint32_t) data;
if (length < DMA_CHUNK_LENGTH)
- DMA_BCR(2) = 0x00010000 | length;
+ DMA_BCR(DMA_GPU) = 0x00010000 | length;
else
- DMA_BCR(2) = DMA_CHUNK_LENGTH | ((length / DMA_CHUNK_LENGTH) << 16);
+ DMA_BCR(DMA_GPU) = DMA_CHUNK_LENGTH |
+ ((length / DMA_CHUNK_LENGTH) << 16);
- DMA_CHCR(2) = 0x01000200 | write;
+ DMA_CHCR(DMA_GPU) = 0x01000200 | write;
}
/* VRAM transfer API */
int LoadImage(const RECT *rect, const uint32_t *data) {
+ _sdk_validate_args(rect && data, -1);
+
int index = _next_saved_rect;
_saved_rects[index] = *rect;
@@ -75,6 +86,8 @@ int LoadImage(const RECT *rect, const uint32_t *data) {
}
int StoreImage(const RECT *rect, uint32_t *data) {
+ _sdk_validate_args(rect && data, -1);
+
int index = _next_saved_rect;
_saved_rects[index] = *rect;
@@ -88,22 +101,53 @@ int StoreImage(const RECT *rect, uint32_t *data) {
);
}
+int MoveImage(const RECT *rect, int x, int y) {
+ _sdk_validate_args(rect, -1);
+
+ 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) {
+ _sdk_validate_args_void(rect && data);
+
_dma_transfer(rect, (uint32_t *) data, 1);
}
void StoreImage2(const RECT *rect, uint32_t *data) {
+ _sdk_validate_args_void(rect && data);
+
_dma_transfer(rect, data, 0);
}
-/*void MoveImage2(const RECT *rect, int x, int y) {
+void MoveImage2(const RECT *rect, int x, int y) {
+ _sdk_validate_args_void(rect);
+
+ 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));
GPU_GP0 = (x & 0xffff) | (y << 16);
//GPU_GP0 = rect->w | (rect->h << 16);
GPU_GP0 = *((const uint32_t *) &(rect->w));
-}*/
+
+ // As no DMA transfer is performed by this command, the GPU IRQ is used
+ // instead of the DMA IRQ to trigger the draw queue callback.
+ GPU_GP0 = 0x1f000000;
+}
/* .TIM image parsers */
@@ -112,6 +156,8 @@ void StoreImage2(const RECT *rect, uint32_t *data) {
// returning pointers to them, which become useless once the .TIM file is
// unloaded from main RAM.
int GsGetTimInfo(const uint32_t *tim, GsIMAGE *info) {
+ _sdk_validate_args(tim && info, 1);
+
if ((*(tim++) & 0xffff) != 0x0010)
return 1;
@@ -138,6 +184,8 @@ int GsGetTimInfo(const uint32_t *tim, GsIMAGE *info) {
}
int GetTimInfo(const uint32_t *tim, TIM_IMAGE *info) {
+ _sdk_validate_args(tim && info, 1);
+
if ((*(tim++) & 0xffff) != 0x0010)
return 1;