diff options
| author | spicyjpeg <thatspicyjpeg@gmail.com> | 2023-05-11 23:08:11 +0200 |
|---|---|---|
| committer | spicyjpeg <thatspicyjpeg@gmail.com> | 2023-05-11 23:08:11 +0200 |
| commit | 2021cdfca29dc5c98e570a674ac97f92f47a1129 (patch) | |
| tree | a7355b8852ae4e9d217560b0cab2dcc02ab8c249 /libpsn00b/psxgpu/drawing.c | |
| parent | 3b696fc431a9c3f2aa7ea4f27aec20ce5dd67859 (diff) | |
| download | psn00bsdk-2021cdfca29dc5c98e570a674ac97f92f47a1129.tar.gz | |
Add GPU IRQ variants of all display list APIs
Diffstat (limited to 'libpsn00b/psxgpu/drawing.c')
| -rw-r--r-- | libpsn00b/psxgpu/drawing.c | 148 |
1 files changed, 148 insertions, 0 deletions
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 <stdint.h> +#include <assert.h> +#include <psxetc.h> +#include <psxgpu.h> +#include <hwregs_c.h> + +/* 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); +} |
