aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b/psxgpu/env.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpsn00b/psxgpu/env.c')
-rw-r--r--libpsn00b/psxgpu/env.c154
1 files changed, 102 insertions, 52 deletions
diff --git a/libpsn00b/psxgpu/env.c b/libpsn00b/psxgpu/env.c
index 8784947..236ae4b 100644
--- a/libpsn00b/psxgpu/env.c
+++ b/libpsn00b/psxgpu/env.c
@@ -1,9 +1,10 @@
/*
* PSn00bSDK GPU library (DRAWENV/DISPENV functions)
- * (C) 2022 spicyjpeg - MPL licensed
+ * (C) 2022-2023 spicyjpeg - MPL licensed
*/
#include <stdint.h>
+#include <assert.h>
#include <psxgpu.h>
#include <hwregs_c.h>
@@ -33,9 +34,53 @@ static inline uint32_t _get_window_mask(int size) {
return mask & 0x1f;
}
+static const uint32_t *_build_drawenv_ot(const uint32_t *ot, DRAWENV *env) {
+ // All commands are grouped into a single display list packet for
+ // performance reasons using tagless primitives (the GPU does not care
+ // about the grouping as the display list is parsed by the CPU).
+ DR_ENV *prim = &(env->dr_env);
+ setaddr(prim, ot);
+ setlen(prim, 5);
+
+ // Texture page (reset active page and set dither/mask bits)
+ setDrawTPage_T(&(prim->tpage), env->dfe & 1, env->dtd & 1, env->tpage);
+
+ // Texture window
+ //setTexWindow_T(&(prim->twin), &(env->tw));
+ prim->twin.code[0] = 0xe2000000;
+ prim->twin.code[0] |= _get_window_mask(env->tw.w);
+ prim->twin.code[0] |= _get_window_mask(env->tw.h) << 5;
+ prim->twin.code[0] |= (env->tw.x & 0xf8) << 7; // ((tw.x / 8) & 0x1f) << 10
+ prim->twin.code[0] |= (env->tw.y & 0xf8) << 12; // ((tw.y / 8) & 0x1f) << 15
+
+ // 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]
+ );
+
+ if (env->isbg) {
+ FILL_T *fill = &(prim->fill);
+ setlen(prim, 8);
+
+ // Rectangle fill
+ // FIXME: reportedly this command doesn't accept height values >511...
+ setFill_T(fill);
+ setColor0(fill, *((const uint32_t *) &(env->isbg)) >> 8);
+ setXY0(fill, env->clip.x, env->clip.y);
+ setWH(fill, env->clip.w, _min(env->clip.h, 0x1ff));
+ }
+
+ return (const uint32_t *) prim;
+}
+
/* Drawing API */
+void _send_linked_list(GPU_DrawOpType type, const uint32_t *ot);
+
DRAWENV *SetDefDrawEnv(DRAWENV *env, int x, int y, int w, int h) {
+ _sdk_validate_args(env && (w > 0) && (h > 0), 0);
+
env->clip.x = x;
env->clip.y = y;
env->clip.w = w;
@@ -60,69 +105,41 @@ DRAWENV *SetDefDrawEnv(DRAWENV *env, int x, int y, int w, int h) {
}
int DrawOTagEnv(const uint32_t *ot, DRAWENV *env) {
- DR_ENV *prim = &(env->dr_env);
-
- // All commands are grouped into a single display list packet for
- // performance reasons (the GPU does not care about the grouping as the
- // display list is parsed by the DMA unit in the CPU).
- setaddr(prim, ot);
- setlen(prim, 5);
-
- // Texture page (reset active page and set dither/mask bits)
- prim->code[0] = 0xe1000000 | env->tpage;
- prim->code[0] |= (env->dtd & 1) << 9;
- prim->code[0] |= (env->dfe & 1) << 10;
+ _sdk_validate_args(ot && env, -1);
+
+ return EnqueueDrawOp(
+ (void *) &_send_linked_list,
+ (uint32_t) DRAWOP_TYPE_DMA,
+ (uint32_t) _build_drawenv_ot(ot, env),
+ 0
+ );
+}
- // Texture window
- prim->code[1] = 0xe2000000;
- prim->code[1] |= _get_window_mask(env->tw.w);
- prim->code[1] |= _get_window_mask(env->tw.h) << 5;
- prim->code[1] |= (env->tw.x & 0xf8) << 7; // ((tw.x / 8) & 0x1f) << 10
- prim->code[1] |= (env->tw.y & 0xf8) << 12; // ((tw.y / 8) & 0x1f) << 15
-
- // Set drawing area top left
- prim->code[2] = 0xe3000000;
- prim->code[2] |= env->clip.x & 0x3ff;
- prim->code[2] |= (env->clip.y & 0x3ff) << 10;
-
- // Set drawing area bottom right
- prim->code[3] = 0xe4000000;
- prim->code[3] |= (env->clip.x + (env->clip.w - 1)) & 0x3ff;
- prim->code[3] |= ((env->clip.y + (env->clip.h - 1)) & 0x3ff) << 10;
-
- // Set drawing offset
- prim->code[4] = 0xe5000000;
- prim->code[4] |= (env->clip.x + env->ofs[0]) & 0x7ff;
- prim->code[4] |= ((env->clip.y + env->ofs[1]) & 0x7ff) << 11;
+int DrawOTagEnvIRQ(const uint32_t *ot, DRAWENV *env) {
+ _sdk_validate_args(ot && env, -1);
- if (env->isbg) {
- setlen(prim, 8);
-
- // Rectangle fill
- // FIXME: reportedly this command doesn't accept height values >511...
- prim->code[5] = 0x02000000;
- //prim->code[5] |= env->r0 | (env->g0 << 8) | (env->b0 << 16);
- //prim->code[6] = env->clip.x;
- //prim->code[6] |= env->clip.y << 16;
- prim->code[5] |= *((const uint32_t *) &(env->isbg)) >> 8;
- prim->code[6] = *((const uint32_t *) &(env->clip.x));
- prim->code[7] = env->clip.w;
- prim->code[7] |= _min(env->clip.h, 0x1ff) << 16;
- }
-
- return EnqueueDrawOp((void *) &DrawOTag2, (uint32_t) prim, 0, 0);
+ return EnqueueDrawOp(
+ (void *) &_send_linked_list,
+ (uint32_t) DRAWOP_TYPE_GPU_IRQ,
+ (uint32_t) _build_drawenv_ot(ot, env),
+ 0
+ );
}
void PutDrawEnv(DRAWENV *env) {
- DrawOTagEnv((const uint32_t *) 0x00ffffff, env);
+ _sdk_validate_args_void(env);
+
+ DrawOTagEnv((const uint32_t *) 0xffffff, 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) {
+ _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));
}
@@ -130,6 +147,8 @@ void PutDrawEnvFast(DRAWENV *env) {
/* Display API */
DISPENV *SetDefDispEnv(DISPENV *env, int x, int y, int w, int h) {
+ _sdk_validate_args(env && (w > 0) && (h > 0), 0);
+
env->disp.x = x;
env->disp.y = y;
env->disp.w = w;
@@ -148,6 +167,8 @@ DISPENV *SetDefDispEnv(DISPENV *env, int x, int y, int w, int h) {
}
void PutDispEnv(const DISPENV *env) {
+ _sdk_validate_args_void(env);
+
uint32_t h_range, v_range, mode, fb_pos;
mode = _gpu_video_mode << 3;
@@ -216,6 +237,8 @@ void PutDispEnv(const DISPENV *env) {
/* Deprecated "raw" display API */
void PutDispEnvRaw(const DISPENV_RAW *env) {
+ _sdk_validate_args_void(env);
+
uint32_t h_range, v_range, fb_pos;
h_range = 608 + env->vid_xpos;
@@ -233,3 +256,30 @@ void PutDispEnvRaw(const DISPENV_RAW *env) {
GPU_GP1 = 0x08000000 | env->vid_mode; // Set video mode
GPU_GP1 = 0x05000000 | fb_pos; // Set VRAM location to display
}
+
+/* Misc. display functions */
+
+GPU_VideoMode GetVideoMode(void) {
+ return _gpu_video_mode;
+}
+
+void SetVideoMode(GPU_VideoMode mode) {
+ uint32_t _mode, stat = GPU_GP1;
+
+ _gpu_video_mode = mode & 1;
+
+ _mode = (mode & 1) << 3;
+ _mode |= (stat >> 17) & 0x37; // GPUSTAT bits 17-22 -> command bits 0-5
+ _mode |= (stat >> 10) & 0x40; // GPUSTAT bit 16 -> command bit 6
+ _mode |= (stat >> 7) & 0x80; // GPUSTAT bit 14 -> command bit 7
+
+ GPU_GP1 = 0x08000000 | _mode;
+}
+
+int GetODE(void) {
+ return (GPU_GP1 >> 31);
+}
+
+void SetDispMask(int mask) {
+ GPU_GP1 = 0x03000000 | (mask ? 0 : 1);
+}