|
Nugget
Bare-metal libraries and examples for the original PlayStation
|
#include "common/hardware/dma.h"#include "common/hardware/gpu.h"#include "common/hardware/hwregs.h"#include "common/hardware/irq.h"#include "common/syscalls/syscalls.h"#include "exotic/cester.h"#include "raster-helpers.h"
Macros | |
| #define | PCSX_TESTS 0 |
| #define | CESTER_MAYBE_TEST CESTER_TEST |
| #define | CESTER_NO_SIGNAL |
| #define | CESTER_NO_TIME |
| #define | EXIT_SUCCESS 0 |
| #define | EXIT_FAILURE 1 |
| #define | BG 0x0010u /* R5=16, bit15 clear */ |
| #define | BG_MASKED 0x8010u |
| #define | POLL_MAX 20000000u |
| #define | QX0 64 |
| #define | QY0 16 |
| #define | FX 48 |
| #define | FY 0 |
| #define | FW 288 |
| #define | FH 232 |
| #define | EX0 400 |
| #define | EY0 32 |
| #define | ESZ 16 |
| #define | TPAGE_FIELD ((768 / 64) | (1u << 5)) /* tx=12, ABR=1, 4bpp */ |
| #define | CLUT_FIELD ((768 / 16) | (256u << 6)) |
| #define | TEXEL_FOG 0x211fu |
| #define | HOLE_FOG 0x2118u |
| #define | E_VARIANT(name, setup, want) |
Functions | |
| CESTER_BODY (static int s_ie;#define BG #define BG_MASKED #define POLL_MAX static uint32_t s_chain[80] __attribute__((aligned(8)));static unsigned s_n;static uint16_t s_row[512];static uint32_t s_nodes[8][40] __attribute__((aligned(8)));static unsigned s_brk[8], s_nb;static void chainBegin(void) { s_n=0;s_nb=0;} static void put(uint32_t w) { s_chain[1+s_n++]=w;} static void nodeBreak(void) { s_brk[s_nb++]=s_n;} static uintptr_t buildNodes(char *desc) { if(s_nb==0) { s_chain[0]=((uint32_t) s_n<< 24)|0x00ffffffu;desc[0]=0;return(uintptr_t) s_chain;} unsigned start=0, k;char *d=desc;for(k=0;k<=s_nb;k++) { unsigned end=k< s_nb ? s_brk[k] :s_n;unsigned n=end - start;for(unsigned i=0;i< n;i++) s_nodes[k][1+i]=s_chain[1+start+i];uint32_t next=k< s_nb ?((uintptr_t) s_nodes[k+1] &0x00ffffffu) :0x00ffffffu;s_nodes[k][0]=((uint32_t) n<< 24)|next;if(n >=10) *d++='0'+n/10; *d++='0'+n % 10; *d++=k< s_nb ? '+' :0;start=end;} return(uintptr_t) s_nodes[0];} static unsigned waitIdle(void) { unsigned p=0;while((GPU_STATUS &0x14000000u) !=0x14000000u &&p< POLL_MAX) p++;return p;} static void chainRun(const char *tag) { unsigned pre=waitIdle();char desc[40];uintptr_t head=buildNodes(desc);GPU_STATUS=0x04000002u;DMA_CTRL[DMA_GPU].MADR=head &0x00ffffffu;DMA_CTRL[DMA_GPU].BCR=0;DMA_CTRL[DMA_GPU].CHCR=0x01000401u;unsigned dp=0;while((DMA_CTRL[DMA_GPU].CHCR &0x01000000u) &&dp< POLL_MAX) dp++;uint32_t statDone=GPU_STATUS;unsigned ip=waitIdle();uint32_t statIdle=GPU_STATUS;GPU_STATUS=0x04000001u;ramsyscall_printf("DMA %s words=%u nodes=[%s] prePolls=%u dmaPolls=%u statAtDmaDone=%08x idlePolls=%u statIdle=%08x\n", tag, s_n, s_nb ? desc :"single", pre, dp,(unsigned) statDone, ip,(unsigned) statIdle);} static void cpuRun(const char *tag, const unsigned *lens, unsigned ncmd) { unsigned idx=1, maxp=0;for(unsigned c=0;c< ncmd;c++) { unsigned p=waitIdle();if(p > maxp) maxp=p;for(unsigned i=0;i< lens[c];i++) GPU_DATA=s_chain[idx++];} unsigned p=waitIdle();ramsyscall_printf("CPU %s words=%u cmds=%u maxIdlePolls=%u finalIdlePolls=%u\n", tag, idx - 1, ncmd, maxp, p);} static void fillBg(int16_t x, int16_t y, int16_t w, int16_t h) { waitIdle();GPU_DATA=0x02000080u;GPU_DATA=((uint32_t)(uint16_t) y<< 16)|(uint32_t)(uint16_t) x;GPU_DATA=((uint32_t)(uint16_t) h<< 16)|(uint32_t)(uint16_t) w;waitIdle();} static unsigned verifyRegion(const char *tag, int16_t x, int16_t y, int16_t w, int16_t h, uint16_t v) { unsigned bad=0, first=0xffffffffu;for(int16_t yy=y;yy< y+h;yy++) { rasterReadStrip(x, yy, w, s_row);for(int i=0;i< w;i++) { if(s_row[i] !=v) { if(bad==0) first=((unsigned) yy<< 16)|(unsigned)(x+i)|0;bad++;} } } ramsyscall_printf("FILL %s region=(%d,%d %dx%d) want=%04x mismatches=%u first@y=%u,x=%u\n", tag, x, y, w, h,(unsigned) v, bad, first > > 16, first &0xffff);return bad;} static unsigned measureQuad(const char *tag, int16_t x0, int16_t y0, int16_t x1, int16_t y1) { unsigned in15=0, inTotal=0, inMasked=0, inBg=0, inOther=0, ring15=0;unsigned otherVal=0;int16_t rx=x0 - 2, rw=(x1 - x0)+4;int runStart=-1;unsigned runCnt=0, runFx=0, runLx=0;ramsyscall_printf("ROWS %s:", tag);for(int16_t yy=y0 - 2;yy< y1+2;yy++) { rasterReadStrip(rx, yy, rw, s_row);unsigned rc=0, fx=0xffff, lx=0xffff;for(int i=0;i< rw;i++) { int16_t xx=rx+i;uint16_t v=s_row[i];int inside=xx >=x0 &&xx< x1 &&yy >=y0 &&yy< y1;if(inside) { inTotal++;if(v &0x8000u) { in15++;rc++;if(fx==0xffff) fx=xx;lx=xx;} if(v==BG_MASKED) inMasked++;else if(v==BG) inBg++;else { if(inOther==0) otherVal=v;inOther++;} } else if(v &0x8000u) { ring15++;} } if(yy >=y0 &&yy< y1) { if(runStart >=0 &&rc==runCnt &&fx==runFx &&lx==runLx) continue;if(runStart >=0) ramsyscall_printf(" [y%d..%d c=%u x%u..%u]", runStart, yy - 1, runCnt, runFx, runLx);runStart=yy;runCnt=rc;runFx=fx;runLx=lx;} } if(runStart >=0) ramsyscall_printf(" [y%d..%d c=%u x%u..%u]", runStart, y1 - 1, runCnt, runFx, runLx);ramsyscall_printf("\n");ramsyscall_printf("RES %s bit15=%u/%u eq8010=%u eq0010=%u other=%u (first other=%04x) ring_bit15=%u\n", tag, in15, inTotal, inMasked, inBg, inOther, otherVal, ring15);return in15==inTotal &&ring15==0 &&inMasked==inTotal ? 1 :0;} static void putQuadSemi(uint32_t col, int16_t x0, int16_t y0, int16_t x1, int16_t y1) { put(0x2a000000u|(col &0xffffffu));put(((uint32_t)(uint16_t) y0<< 16)|(uint16_t) x0);put(((uint32_t)(uint16_t) y0<< 16)|(uint16_t) x1);put(((uint32_t)(uint16_t) y1<< 16)|(uint16_t) x0);put(((uint32_t)(uint16_t) y1<< 16)|(uint16_t) x1);} #define QX0 #define QY0 #define FX #define FY #define FW #define FH static int maskArm(const char *tag, int16_t w, int16_t h, int mode) { rasterReset();rasterSetAbr(1);fillBg(FX, FY, FW, FH);unsigned bad=verifyRegion(tag, FX, FY, FW, FH, BG);chainBegin();put(0xe6000001u);putQuadSemi(0x000000u, QX0, QY0, QX0+w, QY0+h);if(mode==2) { put(0x01000000u);put(0x80000000u);put((500u<< 16)|1000u);put((500u<< 16)|1002u);put((1u<< 16)|1u);} put(0xe6000000u);if(mode==1) { static const unsigned lens[]={1, 5, 1};cpuRun(tag, lens, 3);} else { chainRun(tag);} uint32_t stat=GPU_STATUS;ramsyscall_printf("STAT %s gpustat=%08x (bit11 setmask=%u bit12 checkmask=%u)\n", tag,(unsigned) stat,(unsigned)((stat > > 11) &1),(unsigned)((stat > > 12) &1));int ok=measureQuad(tag, QX0, QY0, QX0+w, QY0+h);rasterSetAbr(0);return bad==0 &&ok;} #define EX0 #define EY0 #define ESZ #define TPAGE_FIELD #define CLUT_FIELD #define TEXEL_FOG #define HOLE_FOG static void uploadTex(void) { waitIdle();GPU_DATA=0xa0000000u;GPU_DATA=(0u<< 16)|768u;GPU_DATA=(16u<< 16)|4u;for(int y=0;y< 16;y++) { GPU_DATA=0x00000000u;GPU_DATA=0x11111111u;} waitIdle();GPU_DATA=0xa0000000u;GPU_DATA=(256u<< 16)|768u;GPU_DATA=(1u<< 16)|16u;GPU_DATA=0x001f0000u;for(int i=1;i< 8;i++) GPU_DATA=0x7fff7fffu;waitIdle();rasterReadStrip(768, 256, 2, s_row);unsigned c0=s_row[0], c1=s_row[1];rasterReadStrip(768, 5, 4, s_row);ramsyscall_printf("TEX clut0=%04x clut1=%04x texrow5=%04x %04x %04x %04x\n", c0, c1, s_row[0], s_row[1], s_row[2], s_row[3]);} static unsigned s_texCmd=0x2d000000u;static unsigned s_tpExtra=0;static int s_fogGouraud=0;static int s_sz=ESZ;static void putStage1(void) { put(0xe6000001u);putQuadSemi(0x000000u, EX0, EY0, EX0+s_sz, EY0+s_sz);put(0xe6000000u);put(s_texCmd);put(((uint32_t) EY0<< 16)|EX0);put(((uint32_t) CLUT_FIELD<< 16)|(0u<< 8)|0u);put(((uint32_t) EY0<< 16)|(EX0+s_sz));put(((uint32_t)(TPAGE_FIELD|s_tpExtra)<< 16)|(0u<< 8)|16u);put(((uint32_t)(EY0+s_sz)<< 16)|EX0);put((16u<< 8)|0u);put(((uint32_t)(EY0+s_sz)<< 16)|(EX0+s_sz));put((16u<< 8)|16u);} static void putStage2(void) { put(0xe6000002u);if(s_fogGouraud) { put(0x3a404040u);put(((uint32_t) EY0<< 16)|EX0);put(0x404040u);put(((uint32_t) EY0<< 16)|(EX0+s_sz));put(0x404040u);put(((uint32_t)(EY0+s_sz)<< 16)|EX0);put(0x404040u);put(((uint32_t)(EY0+s_sz)<< 16)|(EX0+s_sz));} else { putQuadSemi(0x404040u, EX0, EY0, EX0+s_sz, EY0+s_sz);} put(0xe6000000u);} static int measureE(const char *tag, uint16_t wantHole, uint16_t wantTex) { unsigned h15=0, hOk=0, t15=0, tOk=0, hOther=0, tOther=0;uint16_t hv=0, tv=0;unsigned tot=(unsigned) s_sz *(unsigned) s_sz/2;unsigned nP=0, nTF=0, nHF=0, nT=0, nB=0, nO=0;uint16_t oV=0;for(int y=0;y< s_sz;y++) { rasterReadStrip(EX0, EY0+y, s_sz, s_row);for(int x=0;x< s_sz;x++) { uint16_t v=s_row[x];if(v==0x8010u) nP++;else if(v==TEXEL_FOG) nTF++;else if(v==HOLE_FOG) nHF++;else if(v==0x001fu) nT++;else if(v==0x0010u) nB++;else { if(!nO) oV=v;nO++;} if(x< s_sz/2) { if(v &0x8000u) h15++;if(v==wantHole) hOk++;else { if(!hOther) hv=v;hOther++;} } else { if(v &0x8000u) t15++;if(v==wantTex) tOk++;else { if(!tOther) tv=v;tOther++;} } } } ramsyscall_printf("HIST %s total=%u hole_protected(8010)=%u texel_fog(211f)=%u HOLE_FOGGED(2118)=%u texel_nofog(001f)=%u bg_nomask(0010)=%u other=%u(first %04x)\n", tag, tot *2, nP, nTF, nHF, nT, nB, nO, oV);int hx=EX0+3 *s_sz/16, tx=EX0+12 *s_sz/16, py=EY0+s_sz/2;uint16_t hole=rasterReadPixel(hx, py);uint16_t tex=rasterReadPixel(tx, py);ramsyscall_printf("PIX %s hole(%d,%d)=%04x r=%u g=%u b=%u m=%u | texel(%d,%d)=%04x r=%u g=%u b=%u m=%u\n", tag, hx, py, hole, hole &31,(hole > > 5) &31,(hole > > 10) &31, hole > > 15, tx, py, tex, tex &31,(tex > > 5) &31,(tex > > 10) &31, tex > > 15);ramsyscall_printf("RES %s holes: bit15=%u/%u eq%04x=%u firstOther=%04x | texels: bit15=%u/%u eq%04x=%u firstOther=%04x\n", tag, h15, tot, wantHole, hOk, hv, t15, tot, wantTex, tOk, tv);return nP+(wantTex==TEXEL_FOG ? nTF :nT)==tot *2 &&wantHole==BG_MASKED;} static void eSetup(const char *tag) { rasterReset();rasterSetAbr(1);uploadTex();fillBg(384, 0, 288, 256);verifyRegion(tag, EX0 - 4, EY0 - 4, s_sz+8, s_sz+8, BG);} static void prepStage2Bg(void) { waitIdle();GPU_DATA=0xa0000000u;GPU_DATA=((uint32_t) EY0<< 16)|EX0;GPU_DATA=((uint32_t) ESZ<< 16)|ESZ;for(int y=0;y< ESZ;y++) for(int i=0;i< ESZ/2;i++) GPU_DATA=i< 4 ? 0x80108010u :0x001f001fu;waitIdle();}) CESTER_BEFORE_ALL(gpu_dma_node | |
| rasterFullReset () | |
| ramsyscall_printf ("\n=== gpu_dma_node: E6 ordering vs queued polygons ===\n") | |
| ramsyscall_printf ("Grep '^RES|^PIX|^DMA|^CPU|^FILL|^ROWS|^STAT'\n") | |
| CESTER_AFTER_ALL (CESTER_TEST(gpu_dma_node, if(s_ie) leaveCriticalSection();) | |
| cpuRun ("E_cpu_full", lens, 7) | |
| cester_assert_int_eq (1, measureE("E_cpu_full", BG_MASKED, TEXEL_FOG)) | |
| CESTER_TEST (armE_s1_chain, CESTER_TEST(gpu_dma_node, eSetup("E_s1_chain");chainBegin();putStage1();chainRun("E_s1_chain");cester_assert_int_eq(1, measureE("E_s1_chain", BG_MASKED, 0x001fu));) | |
| CESTER_MAYBE_TEST (armG_dots_after_4x4, CESTER_MAYBE_TEST(gpu_dma_node, cester_assert_int_eq(0, dotArm("G_dots_after_4x4", 4, 4, 0));) | |
| nodeBreak () | |
| putStage2 () | |
| chainRun ("H_gouraudfog_split") | |
| measureE ("H_gouraudfog_split", BG_MASKED, TEXEL_FOG) | |
| CESTER_TEST (armH_big160_split, gpu_dma_node, s_texCmd=0x2d000000u;s_tpExtra=0;s_fogGouraud=0;s_sz=160;eSetup("H_big160_split");chainBegin();put(0xe6000001u);putQuadSemi(0, EX0, EY0, EX0+s_sz, EY0+s_sz);put(0xe6000000u);nodeBreak();{ unsigned m=s_n;putStage1();for(unsigned i=0;i< 9;i++) s_chain[1+m+i]=s_chain[1+m+7+i];s_n=m+9;} nodeBreak();putStage2();chainRun("H_big160_split");measureE("H_big160_split", BG_MASKED, TEXEL_FOG);s_sz=ESZ;) | |
| CESTER_TEST (armS_sweep_short, CESTER_TEST(gpu_dma_node, for(int k=2;k<=5;k++) cester_assert_int_eq(1, dotSweep(k));) | |
| for (unsigned i=0;i< sizeof(ks)/sizeof(ks[0]);i++) cester_assert_int_eq(0 | |
| dotSweep (ks[i])) | |
Variables | |
| s_ie = enterCriticalSection() | |
| IMASK = 0 | |
| IREG = 0 | |
| s_fogGouraud = 0 | |
| #define BG 0x0010u /* R5=16, bit15 clear */ |
| #define BG_MASKED 0x8010u |
| #define CESTER_MAYBE_TEST CESTER_TEST |
| #define CESTER_NO_SIGNAL |
| #define CESTER_NO_TIME |
| #define CLUT_FIELD ((768 / 16) | (256u << 6)) |
| #define E_VARIANT | ( | name, | |
| setup, | |||
| want | |||
| ) |
| #define ESZ 16 |
| #define EX0 400 |
| #define EXIT_FAILURE 1 |
| #define EXIT_SUCCESS 0 |
| #define EY0 32 |
| #define FH 232 |
| #define FW 288 |
| #define FX 48 |
| #define FY 0 |
| #define HOLE_FOG 0x2118u |
| #define PCSX_TESTS 0 |
| #define POLL_MAX 20000000u |
| #define QX0 64 |
| #define QY0 16 |
| #define TEXEL_FOG 0x211fu |
| #define TPAGE_FIELD ((768 / 64) | (1u << 5)) /* tx=12, ABR=1, 4bpp */ |
| CESTER_AFTER_ALL | ( | CESTER_TEST( | gpu_dma_node, |
| if(s_ie) leaveCriticalSection(); | |||
| ) |
| CESTER_BODY | ( | static int s_ie;#define BG #define BG_MASKED #define POLL_MAX static uint32_t s_chain __attribute__((aligned(8)));static unsigned s_n;static uint16_t s_row;static uint32_t s_nodes __attribute__((aligned(8)));static unsigned | s_brk[80][512][8][40][8], |
| s_nb;static void chainBegin(void) { s_n=0;s_nb=0;} static void put(uint32_t w) { s_chain[1+s_n++]=w;} static void nodeBreak(void) { s_brk[s_nb++]=s_n;} static uintptr_t buildNodes(char *desc) { if(s_nb==0) { s_chain[0]=((uint32_t) s_n<< 24)|0x00ffffffu;desc[0]=0;return(uintptr_t) s_chain;} unsigned start=0, k;char *d=desc;for(k=0;k<=s_nb;k++) { unsigned end=k< s_nb ? s_brk[k] :s_n;unsigned n=end - start;for(unsigned i=0;i< n;i++) s_nodes[k][1+i]=s_chain[1+start+i];uint32_t next=k< s_nb ?((uintptr_t) s_nodes[k+1] &0x00ffffffu) :0x00ffffffu;s_nodes[k][0]=((uint32_t) n<< 24)|next;if(n >=10) *d++='0'+n/10; *d++='0'+n % 10; *d++=k< s_nb ? '+' :0;start=end;} return(uintptr_t) s_nodes[0];} static unsigned waitIdle(void) { unsigned p=0;while((GPU_STATUS &0x14000000u) !=0x14000000u &&p< POLL_MAX) p++;return p;} static void chainRun(const char *tag) { unsigned pre=waitIdle();char desc[40];uintptr_t head=buildNodes(desc);GPU_STATUS=0x04000002u;DMA_CTRL[DMA_GPU].MADR=head &0x00ffffffu;DMA_CTRL[DMA_GPU].BCR=0;DMA_CTRL[DMA_GPU].CHCR=0x01000401u;unsigned dp=0;while((DMA_CTRL[DMA_GPU].CHCR &0x01000000u) &&dp< POLL_MAX) dp++;uint32_t statDone=GPU_STATUS;unsigned ip=waitIdle();uint32_t statIdle=GPU_STATUS;GPU_STATUS=0x04000001u;ramsyscall_printf("DMA %s words=%u nodes=[%s] prePolls=%u dmaPolls=%u statAtDmaDone=%08x idlePolls=%u statIdle=%08x\n", tag, s_n, s_nb ? desc :"single", pre, dp,(unsigned) statDone, ip,(unsigned) statIdle);} static void cpuRun(const char *tag, const unsigned *lens, unsigned ncmd) { unsigned idx=1, maxp=0;for(unsigned c=0;c< ncmd;c++) { unsigned p=waitIdle();if(p > maxp) maxp=p;for(unsigned i=0;i< lens[c];i++) GPU_DATA=s_chain[idx++];} unsigned p=waitIdle();ramsyscall_printf("CPU %s words=%u cmds=%u maxIdlePolls=%u finalIdlePolls=%u\n", tag, idx - 1, ncmd, maxp, p);} static void fillBg(int16_t x, int16_t y, int16_t w, int16_t h) { waitIdle();GPU_DATA=0x02000080u;GPU_DATA=((uint32_t)(uint16_t) y<< 16)|(uint32_t)(uint16_t) x;GPU_DATA=((uint32_t)(uint16_t) h<< 16)|(uint32_t)(uint16_t) w;waitIdle();} static unsigned verifyRegion(const char *tag, int16_t x, int16_t y, int16_t w, int16_t h, uint16_t v) { unsigned bad=0, first=0xffffffffu;for(int16_t yy=y;yy< y+h;yy++) { rasterReadStrip(x, yy, w, s_row);for(int i=0;i< w;i++) { if(s_row[i] !=v) { if(bad==0) first=((unsigned) yy<< 16)|(unsigned)(x+i)|0;bad++;} } } ramsyscall_printf("FILL %s region=(%d,%d %dx%d) want=%04x mismatches=%u first@y=%u,x=%u\n", tag, x, y, w, h,(unsigned) v, bad, first > > 16, first &0xffff);return bad;} static unsigned measureQuad(const char *tag, int16_t x0, int16_t y0, int16_t x1, int16_t y1) { unsigned in15=0, inTotal=0, inMasked=0, inBg=0, inOther=0, ring15=0;unsigned otherVal=0;int16_t rx=x0 - 2, rw=(x1 - x0)+4;int runStart=-1;unsigned runCnt=0, runFx=0, runLx=0;ramsyscall_printf("ROWS %s:", tag);for(int16_t yy=y0 - 2;yy< y1+2;yy++) { rasterReadStrip(rx, yy, rw, s_row);unsigned rc=0, fx=0xffff, lx=0xffff;for(int i=0;i< rw;i++) { int16_t xx=rx+i;uint16_t v=s_row[i];int inside=xx >=x0 &&xx< x1 &&yy >=y0 &&yy< y1;if(inside) { inTotal++;if(v &0x8000u) { in15++;rc++;if(fx==0xffff) fx=xx;lx=xx;} if(v==BG_MASKED) inMasked++;else if(v==BG) inBg++;else { if(inOther==0) otherVal=v;inOther++;} } else if(v &0x8000u) { ring15++;} } if(yy >=y0 &&yy< y1) { if(runStart >=0 &&rc==runCnt &&fx==runFx &&lx==runLx) continue;if(runStart >=0) ramsyscall_printf(" [y%d..%d c=%u x%u..%u]", runStart, yy - 1, runCnt, runFx, runLx);runStart=yy;runCnt=rc;runFx=fx;runLx=lx;} } if(runStart >=0) ramsyscall_printf(" [y%d..%d c=%u x%u..%u]", runStart, y1 - 1, runCnt, runFx, runLx);ramsyscall_printf("\n");ramsyscall_printf("RES %s bit15=%u/%u eq8010=%u eq0010=%u other=%u (first other=%04x) ring_bit15=%u\n", tag, in15, inTotal, inMasked, inBg, inOther, otherVal, ring15);return in15==inTotal &&ring15==0 &&inMasked==inTotal ? 1 :0;} static void putQuadSemi(uint32_t col, int16_t x0, int16_t y0, int16_t x1, int16_t y1) { put(0x2a000000u|(col &0xffffffu));put(((uint32_t)(uint16_t) y0<< 16)|(uint16_t) x0);put(((uint32_t)(uint16_t) y0<< 16)|(uint16_t) x1);put(((uint32_t)(uint16_t) y1<< 16)|(uint16_t) x0);put(((uint32_t)(uint16_t) y1<< 16)|(uint16_t) x1);} #define QX0 #define QY0 #define FX #define FY #define FW #define FH static int maskArm(const char *tag, int16_t w, int16_t h, int mode) { rasterReset();rasterSetAbr(1);fillBg(FX, FY, FW, FH);unsigned bad=verifyRegion(tag, FX, FY, FW, FH, BG);chainBegin();put(0xe6000001u);putQuadSemi(0x000000u, QX0, QY0, QX0+w, QY0+h);if(mode==2) { put(0x01000000u);put(0x80000000u);put((500u<< 16)|1000u);put((500u<< 16)|1002u);put((1u<< 16)|1u);} put(0xe6000000u);if(mode==1) { static const unsigned lens[]={1, 5, 1};cpuRun(tag, lens, 3);} else { chainRun(tag);} uint32_t stat=GPU_STATUS;ramsyscall_printf("STAT %s gpustat=%08x (bit11 setmask=%u bit12 checkmask=%u)\n", tag,(unsigned) stat,(unsigned)((stat > > 11) &1),(unsigned)((stat > > 12) &1));int ok=measureQuad(tag, QX0, QY0, QX0+w, QY0+h);rasterSetAbr(0);return bad==0 &&ok;} #define EX0 #define EY0 #define ESZ #define TPAGE_FIELD #define CLUT_FIELD #define TEXEL_FOG #define HOLE_FOG static void uploadTex(void) { waitIdle();GPU_DATA=0xa0000000u;GPU_DATA=(0u<< 16)|768u;GPU_DATA=(16u<< 16)|4u;for(int y=0;y< 16;y++) { GPU_DATA=0x00000000u;GPU_DATA=0x11111111u;} waitIdle();GPU_DATA=0xa0000000u;GPU_DATA=(256u<< 16)|768u;GPU_DATA=(1u<< 16)|16u;GPU_DATA=0x001f0000u;for(int i=1;i< 8;i++) GPU_DATA=0x7fff7fffu;waitIdle();rasterReadStrip(768, 256, 2, s_row);unsigned c0=s_row[0], c1=s_row[1];rasterReadStrip(768, 5, 4, s_row);ramsyscall_printf("TEX clut0=%04x clut1=%04x texrow5=%04x %04x %04x %04x\n", c0, c1, s_row[0], s_row[1], s_row[2], s_row[3]);} static unsigned | s_texCmd = 0x2d000000u; static unsigned s_tpExtra = 0; static int s_fogGouraud = 0; static int s_sz = ESZ; static void putStage1(void) { put(0xe6000001u); putQuadSemi(0x000000u, EX0, EY0, EX0 + s_sz, EY0 + s_sz); put(0xe6000000u); put(s_texCmd); put(((uint32_t)EY0 << 16) | EX0); put(((uint32_t)CLUT_FIELD << 16) | (0u << 8) | 0u); put(((uint32_t)EY0 << 16) | (EX0 + s_sz)); put(((uint32_t)(TPAGE_FIELD | s_tpExtra) << 16) | (0u << 8) | 16u); put(((uint32_t)(EY0 + s_sz) << 16) | EX0); put((16u << 8) | 0u); put(((uint32_t)(EY0 + s_sz) << 16) | (EX0 + s_sz)); put((16u << 8) | 16u); } static void putStage2(void) { put(0xe6000002u); if (s_fogGouraud) { put(0x3a404040u); put(((uint32_t)EY0 << 16) | EX0); put(0x404040u); put(((uint32_t)EY0 << 16) | (EX0 + s_sz)); put(0x404040u); put(((uint32_t)(EY0 + s_sz) << 16) | EX0); put(0x404040u); put(((uint32_t)(EY0 + s_sz) << 16) | (EX0 + s_sz)); } else { putQuadSemi(0x404040u, EX0, EY0, EX0 + s_sz, EY0 + s_sz); } put(0xe6000000u); } static int measureE(const char *tag, uint16_t wantHole, uint16_t wantTex) { unsigned h15 = 0, hOk = 0, t15 = 0, tOk = 0, hOther = 0, tOther = 0; uint16_t hv = 0, tv = 0; unsigned tot = (unsigned)s_sz * (unsigned)s_sz / 2; unsigned nP = 0, nTF = 0, nHF = 0, nT = 0, nB = 0, nO = 0; uint16_t oV = 0; for (int y = 0; y < s_sz; y++) { rasterReadStrip(EX0, EY0 + y, s_sz, s_row); for (int x = 0; x < s_sz; x++) { uint16_t v = s_row[x]; if (v == 0x8010u) nP++; else if (v == TEXEL_FOG) nTF++; else if (v == HOLE_FOG) nHF++; else if (v == 0x001fu) nT++; else if (v == 0x0010u) nB++; else { if (!nO) oV = v; nO++; } if (x < s_sz / 2) { if (v & 0x8000u) h15++; if (v == wantHole) hOk++; else { if (!hOther) hv = v; hOther++; } } else { if (v & 0x8000u) t15++; if (v == wantTex) tOk++; else { if (!tOther) tv = v; tOther++; } } } } ramsyscall_printf("HIST %s total=%u hole_protected(8010)=%u texel_fog(211f)=%u HOLE_FOGGED(2118)=%u texel_nofog(001f)=%u bg_nomask(0010)=%u other=%u(first %04x)\n", tag, tot * 2, nP, nTF, nHF, nT, nB, nO, oV); int hx = EX0 + 3 * s_sz / 16, tx = EX0 + 12 * s_sz / 16, py = EY0 + s_sz / 2; uint16_t hole = rasterReadPixel(hx, py); uint16_t tex = rasterReadPixel(tx, py); ramsyscall_printf("PIX %s hole(%d,%d)=%04x r=%u g=%u b=%u m=%u | texel(%d,%d)=%04x r=%u g=%u b=%u m=%u\n", tag, hx, py, hole, hole & 31, (hole >> 5) & 31, (hole >> 10) & 31, hole >> 15, tx, py, tex, tex & 31, (tex >> 5) & 31, (tex >> 10) & 31, tex >> 15); ramsyscall_printf("RES %s holes: bit15=%u/%u eq%04x=%u firstOther=%04x | texels: bit15=%u/%u eq%04x=%u firstOther=%04x\n", tag, h15, tot, wantHole, hOk, hv, t15, tot, wantTex, tOk, tv); return nP + (wantTex == TEXEL_FOG ? nTF : nT) == tot * 2 && wantHole == BG_MASKED; } static void eSetup(const char *tag) { rasterReset(); rasterSetAbr(1); uploadTex(); fillBg(384, 0, 288, 256); verifyRegion(tag, EX0 - 4, EY0 - 4, s_sz + 8, s_sz + 8, BG); } static void prepStage2Bg(void) { waitIdle(); GPU_DATA = 0xa0000000u; GPU_DATA = ((uint32_t)EY0 << 16) | EX0; GPU_DATA = ((uint32_t)ESZ << 16) | ESZ; for (int y = 0; y < ESZ; y++) for (int i = 0; i < ESZ / 2; i++) GPU_DATA = i < 4 ? 0x80108010u : 0x001f001fu; waitIdle(); } |
||
| ) |
| CESTER_MAYBE_TEST | ( | armG_dots_after_4x4 | , |
| CESTER_MAYBE_TEST( | gpu_dma_node, | ||
| cester_assert_int_eq(0, dotArm("G_dots_after_4x4", 4, 4, 0)); | |||
| ) |
| CESTER_TEST | ( | armE_s1_chain | , |
| CESTER_TEST( | gpu_dma_node, | ||
| eSetup("E_s1_chain");chainBegin();putStage1();chainRun("E_s1_chain");cester_assert_int_eq(1, measureE("E_s1_chain", BG_MASKED, 0x001fu)); | |||
| ) |
| CESTER_TEST | ( | armH_big160_split | , |
| gpu_dma_node | , | ||
| s_texCmd | = 0x2d000000u; s_tpExtra = 0; s_fogGouraud = 0; s_sz = 160; eSetup("H_big160_split"); chainBegin(); put(0xe6000001u); putQuadSemi(0, EX0, EY0, EX0 + s_sz, EY0 + s_sz); put(0xe6000000u); nodeBreak(); { unsigned m = s_n; putStage1(); for (unsigned i = 0; i < 9; i++) s_chain[1 + m + i] = s_chain[1 + m + 7 + i]; s_n = m + 9; } nodeBreak(); putStage2(); chainRun("H_big160_split"); measureE("H_big160_split", BG_MASKED, TEXEL_FOG); s_sz = ESZ; |
||
| ) |
| CESTER_TEST | ( | armS_sweep_short | , |
| CESTER_TEST( | gpu_dma_node, | ||
| for(int k=2;k<=5;k++) cester_assert_int_eq(1, dotSweep(k)); | |||
| ) |
| chainRun | ( | "H_gouraudfog_split" | ) |
| cpuRun | ( | "E_cpu_full" | , |
| lens | , | ||
| 7 | |||
| ) |
| dotSweep | ( | ks | [i] | ) |
| for | ( | ) |
| nodeBreak | ( | ) |
| putStage2 | ( | ) |
| ramsyscall_printf | ( | ) |
| ramsyscall_printf | ( | "Grep '^RES|^PIX|^DMA|^CPU|^FILL|^ROWS|^STAT'\n" | ) |
| rasterFullReset | ( | ) |
| IMASK = 0 |
| IREG = 0 |
| s_fogGouraud = 0 |
| s_ie = enterCriticalSection() |