diff options
Diffstat (limited to 'libpsn00b/psxgpu/env.c')
| -rw-r--r-- | libpsn00b/psxgpu/env.c | 154 |
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); +} |
