From d190785c9d3c6eba8c956b926ab6da4c2f14fd88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Czekan=CC=81ski?= Date: Fri, 29 Nov 2019 20:01:37 +0100 Subject: [PATCH] gpu/mask-bit test --- Makefile | 1 + README.md | 1 + gpu/mask-bit/Makefile | 3 ++ gpu/mask-bit/main.c | 59 +++++++++++++++++++++++++++ gpu/mask-bit/psx.log | 7 ++++ gpu/mask-bit/stdint.h | 14 +++++++ gpu/mask-bit/tests.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++ gpu/mask-bit/vram.c | 74 ++++++++++++++++++++++++++++++++++ gpu/mask-bit/vram.h | 14 +++++++ 9 files changed, 264 insertions(+) create mode 100644 gpu/mask-bit/Makefile create mode 100644 gpu/mask-bit/main.c create mode 100644 gpu/mask-bit/psx.log create mode 100644 gpu/mask-bit/stdint.h create mode 100644 gpu/mask-bit/tests.cpp create mode 100644 gpu/mask-bit/vram.c create mode 100644 gpu/mask-bit/vram.h diff --git a/Makefile b/Makefile index e064514..fdf2a6b 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ IMAGES = gpu/bandwidth \ gpu/lines \ gpu/rectangles \ gpu/texture-overflow \ + gpu/mask-bit \ gte-fuzz \ spu/test \ spu/stereo \ diff --git a/README.md b/README.md index 35d881b..61f9101 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ gpu/triangle | Draws Gouroud shaded equilateral triangle gpu/lines | Draws lines using different modes - for verifying Bresenham implementation, color blending, polyline handling gpu/rectangles | Draws all combinations of Rectangle commands gpu/texture-overflow | Draws textured rectangle with UV overflowing VRAM width +gpu/mask-bit | Check Mask bit behavior during VRAM copy operations gte-fuzz | Executes GTE opcodes with random parameters, can be used to verify against real console spu/test | Check SPU behavior (data is lost randomly on 32bit access, ok on 16bit) spu/stereo | Play samples on first two voices diff --git a/gpu/mask-bit/Makefile b/gpu/mask-bit/Makefile new file mode 100644 index 0000000..7e10a58 --- /dev/null +++ b/gpu/mask-bit/Makefile @@ -0,0 +1,3 @@ +include $(PSN00BSDK)/sdk-common.mk + +TARGET = mask-bit.elf \ No newline at end of file diff --git a/gpu/mask-bit/main.c b/gpu/mask-bit/main.c new file mode 100644 index 0000000..9fe2962 --- /dev/null +++ b/gpu/mask-bit/main.c @@ -0,0 +1,59 @@ +#include +#include +#include "vram.h" +#include "stdint.h" + +DISPENV disp; +DRAWENV draw; + +#define SCR_W 320 +#define SCR_H 240 + +void setResolution(int w, int h) { + SetDefDispEnv(&disp, 0, 0, w, h); + SetDefDrawEnv(&draw, 0, 0, w, h); + + PutDispEnv(&disp); + PutDrawEnv(&draw); +} + +void initVideo() +{ + ResetGraph(0); + setResolution(SCR_W, SCR_H); + SetDispMask(1); +} + +void fillRect(int x, int y, int w, int h, int r, int g, int b) { + FILL f; + setFill(&f); + setRGB0(&f, r, g, b); + setXY0(&f, x, y); + setWH(&f, w, h); + + DrawPrim(&f); +} + +void clearScreen() { + fillRect(0, 0, 512, 256, 0, 0, 0); + fillRect(512, 0, 512, 256, 0, 0, 0); + fillRect(0, 256, 512, 256, 0, 0, 0); + fillRect(512, 256, 0x3f1, 256, 0, 0, 0); +} + +void runTests(); + +int main() { + initVideo(); + printf("\ngpu/mask-bit\n"); + + setMaskBitSetting(false, false); + clearScreen(); + + runTests(); + + for (;;) { + VSync(0); + } + return 0; +} diff --git a/gpu/mask-bit/psx.log b/gpu/mask-bit/psx.log new file mode 100644 index 0000000..edcd4d0 --- /dev/null +++ b/gpu/mask-bit/psx.log @@ -0,0 +1,7 @@ +gpu/mask-bit +pass - testWriteAndRead +pass - testSetBit +pass - testCheckMaskBit +pass - testCheckIsMaskBitStickyManually +pass - testCheckIsMaskBitStickySetBit +Done. \ No newline at end of file diff --git a/gpu/mask-bit/stdint.h b/gpu/mask-bit/stdint.h new file mode 100644 index 0000000..3ceeccd --- /dev/null +++ b/gpu/mask-bit/stdint.h @@ -0,0 +1,14 @@ +#pragma once + +#ifndef __cplusplus +#define true 1 +#define false 0 +typedef char bool; +#endif + +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; diff --git a/gpu/mask-bit/tests.cpp b/gpu/mask-bit/tests.cpp new file mode 100644 index 0000000..934a8e9 --- /dev/null +++ b/gpu/mask-bit/tests.cpp @@ -0,0 +1,91 @@ +#include +#include "vram.h" +#include "stdint.h" + +#define assertEquals(given, expected) \ +do { \ + auto GIVEN = (given); \ + auto EXPECTED = (expected); \ + if (GIVEN == EXPECTED) { \ + printf("pass - %s\n", __FUNCTION__); \ + } else { \ + printf("fail - %s:%d `"#given" == "#expected"`," \ + " given: 0x%04x, expected: 0x%04x\n", \ + __FUNCTION__, __LINE__, GIVEN, EXPECTED); \ + } \ +} while(0) + +// Check if read pixel == written pixel +void testWriteAndRead() { + int x = 32; + int y = 32; + + setMaskBitSetting(false, false); + + vramPut(x, y, 0x1234); + + assertEquals(vramGet(x, y), 0x1234); +} + +// Check if GP0(0xE6) bit0 (Set mask while drawing) works +void testSetBit() { + int x = 33; + int y = 32; + + setMaskBitSetting(true, false); + vramPut(x, y, 0); + + assertEquals(vramGet(x, y), 0x8000); +} + +// Check if GP0(0xE6) bit1 (Check mask before draw) works +void testCheckMaskBit() { + int x = 34; + int y = 32; + + // Disable mask bit set + setMaskBitSetting(false, false); + vramPut(x, y, 0x8000); // Write mask bit + + // Enable check mask bit + setMaskBitSetting(false, true); + vramPut(x, y, 0x1234); + + assertEquals(vramGet(x, y), 0x8000); +} + +// Check mask bit (written manually) can be overwritten +void testCheckIsMaskBitStickyManually() { + int x = 35; + int y = 32; + + setMaskBitSetting(false, false); + vramPut(x, y, 0x8123); // Write mask bit manually + vramPut(x, y, 0x0456); // Try clearing it + + assertEquals(vramGet(x, y), 0x0456); +} + +// Check mask bit (written automatically) can be overwritten +void testCheckIsMaskBitStickySetBit() { + int x = 36; + int y = 32; + + setMaskBitSetting(true, false); + vramPut(x, y, 0x0000); // Write mask bit using HW + + setMaskBitSetting(false, false); + vramPut(x, y, 0x0456); // Try clearing it + + assertEquals(vramGet(x, y), 0x0456); +} + +extern "C" void runTests() { + testWriteAndRead(); + testSetBit(); + testCheckMaskBit(); + testCheckIsMaskBitStickyManually(); + testCheckIsMaskBitStickySetBit(); + + printf("Done.\n"); +} \ No newline at end of file diff --git a/gpu/mask-bit/vram.c b/gpu/mask-bit/vram.c new file mode 100644 index 0000000..8d1429c --- /dev/null +++ b/gpu/mask-bit/vram.c @@ -0,0 +1,74 @@ +#include "vram.h" +#include + +typedef struct CPU2VRAM { + unsigned int tag; + unsigned char p0,p1,p2,code; + unsigned short x0,y0; + unsigned short w,h; + unsigned int data; // Single pixel +} CPU2VRAM; + +typedef struct VRAM2CPU { + unsigned int tag; + unsigned char p0,p1,p2,code; + unsigned short x0,y0; + unsigned short w,h; +} VRAM2CPU; + +uint32_t ReadGPUstat(); + +// TODO: Remove when #9 in PSn00bSDK is merged +#undef setDrawMask +#define setDrawMask( p, sb, mt ) \ + setlen( p, 1 ), (p)->code[0] = sb|(mt<<1), setcode( p, 0xe6 ) + +void setMaskBitSetting(bool setBit, bool checkBit) { + DR_MASK mask; + setDrawMask(&mask, setBit, checkBit); + DrawPrim(&mask); +} + +void writeGP1(uint8_t cmd, uint32_t data) { + uint32_t *GP1 = (uint32_t*)0x1f801814; + (*GP1) = (cmd << 24) | (data&0xffffff); +} + +uint32_t readGPU() { + uint32_t* GPUREAD = (uint32_t*)0x1f801810; + return *GPUREAD; +} + +void vramPut(int x, int y, uint16_t pixel) { + CPU2VRAM buf = {0}; + setcode(&buf, 0xA0); // CPU -> VRAM + setlen(&buf, 4); + + buf.x0 = x; // VRAM position + buf.y0 = y; + buf.w = 1; // Transfer size - 1x1 + buf.h = 1; + buf.data = pixel; // pixel (lower 16bit) + + DrawPrim(&buf); +} + +uint32_t vramGet(int x, int y) { + VRAM2CPU buf = {0}; + setcode(&buf, 0xC0); // CPU -> VRAM + setlen(&buf, 3); + + buf.x0 = x; // VRAM position + buf.y0 = y; + buf.w = 1; // Transfer size - 1x1 + buf.h = 1; + + DrawPrim(&buf); + + writeGP1(4, 3); // DMA Direction - VRAM -> CPU + + // Wait for VRAM to CPU ready + while ((ReadGPUstat() & (1<<27)) == 0); + + return readGPU(); +} diff --git a/gpu/mask-bit/vram.h b/gpu/mask-bit/vram.h new file mode 100644 index 0000000..6e7b5e9 --- /dev/null +++ b/gpu/mask-bit/vram.h @@ -0,0 +1,14 @@ +#pragma once +#include "stdint.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void setMaskBitSetting(bool setBit, bool checkBit); +void vramPut(int x, int y, uint16_t pixel); +uint32_t vramGet(int x, int y) ; + +#ifdef __cplusplus +} +#endif \ No newline at end of file