Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
Macros | Functions | Variables
gpu-dma-node.c File Reference
#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"
Include dependency graph for gpu-dma-node.c:

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
 

Macro Definition Documentation

◆ BG

#define BG   0x0010u /* R5=16, bit15 clear */

◆ BG_MASKED

#define BG_MASKED   0x8010u

◆ CESTER_MAYBE_TEST

#define CESTER_MAYBE_TEST   CESTER_TEST

◆ CESTER_NO_SIGNAL

#define CESTER_NO_SIGNAL

◆ CESTER_NO_TIME

#define CESTER_NO_TIME

◆ CLUT_FIELD

#define CLUT_FIELD   ((768 / 16) | (256u << 6))

◆ E_VARIANT

#define E_VARIANT (   name,
  setup,
  want 
)
Value:
CESTER_TEST(name, gpu_dma_node, \
s_texCmd = 0x2d000000u; s_tpExtra = 0; s_fogGouraud = 0; s_sz = ESZ; \
setup; \
eSetup(#name); \
if (s_tpExtra & 0x200) sendGPUData(0xe1000600u | (1u << 5)); \
chainBegin(); putStage1(); putStage2(); \
chainRun(#name); \
int ok = measureE(#name, BG_MASKED, TEXEL_FOG); \
if (want) cester_assert_int_eq(1, ok); \
s_sz = ESZ; \
)
int ok
Definition cdlstop.c:75
sendGPUData(0xe1000000)
#define TEXEL_FOG
measureE("H_gouraudfog_split", 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));)
Definition gpu-dma-node.c:416
cester_assert_int_eq(1, measureE("E_cpu_full", BG_MASKED, TEXEL_FOG))
s_fogGouraud
Definition gpu-dma-node.c:514
#define ESZ
#define BG_MASKED
putStage2()

◆ ESZ

#define ESZ   16

◆ EX0

#define EX0   400

◆ EXIT_FAILURE

#define EXIT_FAILURE   1

◆ EXIT_SUCCESS

#define EXIT_SUCCESS   0

◆ EY0

#define EY0   32

◆ FH

#define FH   232

◆ FW

#define FW   288

◆ FX

#define FX   48

◆ FY

#define FY   0

◆ HOLE_FOG

#define HOLE_FOG   0x2118u

◆ PCSX_TESTS

#define PCSX_TESTS   0

◆ POLL_MAX

#define POLL_MAX   20000000u

◆ QX0

#define QX0   64

◆ QY0

#define QY0   16

◆ TEXEL_FOG

#define TEXEL_FOG   0x211fu

◆ TPAGE_FIELD

#define TPAGE_FIELD   ((768 / 64) | (1u << 5)) /* tx=12, ABR=1, 4bpp */

Function Documentation

◆ CESTER_AFTER_ALL()

CESTER_AFTER_ALL ( CESTER_TEST(  gpu_dma_node,
if(s_ie) leaveCriticalSection();   
)

◆ cester_assert_int_eq()

cester_assert_int_eq ( 1  ,
measureE("E_cpu_full", BG_MASKED, TEXEL_FOG)   
)

◆ CESTER_BODY()

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()

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() [1/3]

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() [2/3]

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() [3/3]

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()

chainRun ( "H_gouraudfog_split"  )

◆ cpuRun()

cpuRun ( "E_cpu_full"  ,
lens  ,
7   
)

◆ dotSweep()

dotSweep ( ks  [i])

◆ for()

for ( )

◆ measureE()

measureE ( "H_gouraudfog_split"  ,
BG_MASKED  ,
TEXEL_FOG   
)

◆ nodeBreak()

nodeBreak ( )

◆ putStage2()

putStage2 ( )

◆ ramsyscall_printf() [1/2]

ramsyscall_printf ( )

◆ ramsyscall_printf() [2/2]

ramsyscall_printf ( "Grep '^RES|^PIX|^DMA|^CPU|^FILL|^ROWS|^STAT'\n"  )

◆ rasterFullReset()

rasterFullReset ( )

Variable Documentation

◆ IMASK

IMASK = 0

◆ IREG

IREG = 0

◆ s_fogGouraud

s_fogGouraud = 0

◆ s_ie

s_ie = enterCriticalSection()