Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
stride-sign-cross.c
Go to the documentation of this file.
1/*
2
3MIT License
4
5Copyright (c) 2026 PCSX-Redux authors
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26
27// Phase-19 stride-sign + cross-axis sweep. Six triangles, identical
28// 10x10 screen footprint to phase-18. Probes are the same five
29// screen positions across all families.
30
31// clang-format off
32
34
35// ---- T_NEG_U_K05: dU/dx = -0.5 (mirror of phase-18's K=5) -------------
36// A=(5,5)/(5,0) B=(15,5)/(0,0) C=(5,15)/(5,5)
37// u(x,y) = 7.5 - 0.5*x v(x,y) = 0.5*y - 2.5
38static void drawT_NEG_U_K05(void) {
39 rasterReset();
40 rasterClearTestRegion(0, 0, 24, 16);
41 setTexpage(TEX17_TX, TEX17_TY, 2);
42 setTextureWindow(0, 0, 0, 0);
43 rasterTexTri(TEX_MOD_NEUTRAL,
44 5, 5, 5, 0,
45 15, 5, 0, 0,
46 5, 15, 5, 5,
48 rasterFlushPrimitive();
49}
50
51// ---- T_NEG_V_K05: dV/dy = -0.5 ----------------------------------------
52// A=(5,5)/(0,5) B=(15,5)/(5,5) C=(5,15)/(0,0)
53// u(x,y) = 0.5*x - 2.5 v(x,y) = 7.5 - 0.5*y
54static void drawT_NEG_V_K05(void) {
55 rasterReset();
56 rasterClearTestRegion(0, 0, 24, 16);
57 setTexpage(TEX17_TX, TEX17_TY, 2);
58 setTextureWindow(0, 0, 0, 0);
59 rasterTexTri(TEX_MOD_NEUTRAL,
60 5, 5, 0, 5,
61 15, 5, 5, 5,
62 5, 15, 0, 0,
64 rasterFlushPrimitive();
65}
66
67// ---- T_NEG_BOTH_K05: dU/dx = -0.5, dV/dy = -0.5 -----------------------
68// A=(5,5)/(5,5) B=(15,5)/(0,5) C=(5,15)/(5,0)
69// u(x,y) = 7.5 - 0.5*x v(x,y) = 7.5 - 0.5*y
70static void drawT_NEG_BOTH_K05(void) {
71 rasterReset();
72 rasterClearTestRegion(0, 0, 24, 16);
73 setTexpage(TEX17_TX, TEX17_TY, 2);
74 setTextureWindow(0, 0, 0, 0);
75 rasterTexTri(TEX_MOD_NEUTRAL,
76 5, 5, 5, 5,
77 15, 5, 0, 5,
78 5, 15, 5, 0,
80 rasterFlushPrimitive();
81}
82
83// ---- T_NEG_U_K16: dU/dx = -1.6 (stretched negative) -------------------
84// A=(5,5)/(16,0) B=(15,5)/(0,0) C=(5,15)/(16,16)
85// u(x,y) = 24 - 1.6*x v(x,y) = 1.6*y - 8
86static void drawT_NEG_U_K16(void) {
87 rasterReset();
88 rasterClearTestRegion(0, 0, 24, 16);
89 setTexpage(TEX17_TX, TEX17_TY, 2);
90 setTextureWindow(0, 0, 0, 0);
91 rasterTexTri(TEX_MOD_NEUTRAL,
92 5, 5, 16, 0,
93 15, 5, 0, 0,
94 5, 15, 16, 16,
96 rasterFlushPrimitive();
97}
98
99// ---- T_CROSS_45_K05: 45-degree UV rotation, mild ----------------------
100// A=(5,5)/(5,0) B=(15,5)/(10,5) C=(5,15)/(0,5)
101// dU/dx = 0.5, dU/dy = -0.5, dV/dx = 0.5, dV/dy = 0.5
102// u(x,y) = 0.5*x - 0.5*y + 5 v(x,y) = 0.5*x + 0.5*y - 5
103static void drawT_CROSS_45_K05(void) {
104 rasterReset();
105 rasterClearTestRegion(0, 0, 24, 16);
106 setTexpage(TEX17_TX, TEX17_TY, 2);
107 setTextureWindow(0, 0, 0, 0);
108 rasterTexTri(TEX_MOD_NEUTRAL,
109 5, 5, 5, 0,
110 15, 5, 10, 5,
111 5, 15, 0, 5,
113 rasterFlushPrimitive();
114}
115
116// ---- T_CROSS_90_K16: 90-degree UV rotation, stretched -----------------
117// A=(5,5)/(0,0) B=(15,5)/(0,16) C=(5,15)/(16,0)
118// dU/dx = 0, dU/dy = 1.6, dV/dx = 1.6, dV/dy = 0
119// u(x,y) = 1.6*y - 8 v(x,y) = 1.6*x - 8
120static void drawT_CROSS_90_K16(void) {
121 rasterReset();
122 rasterClearTestRegion(0, 0, 24, 16);
123 setTexpage(TEX17_TX, TEX17_TY, 2);
124 setTextureWindow(0, 0, 0, 0);
125 rasterTexTri(TEX_MOD_NEUTRAL,
126 5, 5, 0, 0,
127 15, 5, 0, 16,
128 5, 15, 16, 0,
130 rasterFlushPrimitive();
131}
132
133) // CESTER_BODY
134
135// --------------------------------------------------------------------------
136// T_NEG_U_K05 probes
137// --------------------------------------------------------------------------
138
139CESTER_TEST(ar_neg_u_k05_vertex, gpu_raster_phase19,
140 drawT_NEG_U_K05();
142)
143
144CESTER_TEST(ar_neg_u_k05_top_near, gpu_raster_phase19,
145 drawT_NEG_U_K05();
147)
148
149CESTER_TEST(ar_neg_u_k05_left_near, gpu_raster_phase19,
150 drawT_NEG_U_K05();
152)
153
154CESTER_TEST(ar_neg_u_k05_interior, gpu_raster_phase19,
155 drawT_NEG_U_K05();
157)
158
159CESTER_TEST(ar_neg_u_k05_top_far, gpu_raster_phase19,
160 drawT_NEG_U_K05();
162)
163
164// --------------------------------------------------------------------------
165// T_NEG_V_K05 probes
166// --------------------------------------------------------------------------
167
168CESTER_TEST(ar_neg_v_k05_vertex, gpu_raster_phase19,
169 drawT_NEG_V_K05();
171)
172
173CESTER_TEST(ar_neg_v_k05_top_near, gpu_raster_phase19,
174 drawT_NEG_V_K05();
176)
177
178CESTER_TEST(ar_neg_v_k05_left_near, gpu_raster_phase19,
179 drawT_NEG_V_K05();
181)
182
183CESTER_TEST(ar_neg_v_k05_interior, gpu_raster_phase19,
184 drawT_NEG_V_K05();
186)
187
188CESTER_TEST(ar_neg_v_k05_top_far, gpu_raster_phase19,
189 drawT_NEG_V_K05();
191)
192
193// --------------------------------------------------------------------------
194// T_NEG_BOTH_K05 probes
195// --------------------------------------------------------------------------
196
197CESTER_TEST(ar_neg_both_k05_vertex, gpu_raster_phase19,
198 drawT_NEG_BOTH_K05();
200)
201
202CESTER_TEST(ar_neg_both_k05_top_near, gpu_raster_phase19,
203 drawT_NEG_BOTH_K05();
205)
206
207CESTER_TEST(ar_neg_both_k05_left_near, gpu_raster_phase19,
208 drawT_NEG_BOTH_K05();
210)
211
212CESTER_TEST(ar_neg_both_k05_interior, gpu_raster_phase19,
213 drawT_NEG_BOTH_K05();
215)
216
217CESTER_TEST(ar_neg_both_k05_top_far, gpu_raster_phase19,
218 drawT_NEG_BOTH_K05();
220)
221
222// --------------------------------------------------------------------------
223// T_NEG_U_K16 probes
224// --------------------------------------------------------------------------
225
226CESTER_TEST(ar_neg_u_k16_vertex, gpu_raster_phase19,
227 drawT_NEG_U_K16();
229)
230
231CESTER_TEST(ar_neg_u_k16_top_near, gpu_raster_phase19,
232 drawT_NEG_U_K16();
234)
235
236CESTER_TEST(ar_neg_u_k16_left_near, gpu_raster_phase19,
237 drawT_NEG_U_K16();
239)
240
241CESTER_TEST(ar_neg_u_k16_interior, gpu_raster_phase19,
242 drawT_NEG_U_K16();
244)
245
246CESTER_TEST(ar_neg_u_k16_top_far, gpu_raster_phase19,
247 drawT_NEG_U_K16();
249)
250
251// --------------------------------------------------------------------------
252// T_CROSS_45_K05 probes
253// --------------------------------------------------------------------------
254
255CESTER_TEST(ar_cross_45_k05_vertex, gpu_raster_phase19,
256 drawT_CROSS_45_K05();
258)
259
260CESTER_TEST(ar_cross_45_k05_top_near, gpu_raster_phase19,
261 drawT_CROSS_45_K05();
263)
264
265CESTER_TEST(ar_cross_45_k05_left_near, gpu_raster_phase19,
266 drawT_CROSS_45_K05();
268)
269
270CESTER_TEST(ar_cross_45_k05_interior, gpu_raster_phase19,
271 drawT_CROSS_45_K05();
273)
274
275CESTER_TEST(ar_cross_45_k05_top_far, gpu_raster_phase19,
276 drawT_CROSS_45_K05();
278)
279
280// --------------------------------------------------------------------------
281// T_CROSS_90_K16 probes
282// --------------------------------------------------------------------------
283
284CESTER_TEST(ar_cross_90_k16_vertex, gpu_raster_phase19,
285 drawT_CROSS_90_K16();
287)
288
289CESTER_TEST(ar_cross_90_k16_top_near, gpu_raster_phase19,
290 drawT_CROSS_90_K16();
292)
293
294CESTER_TEST(ar_cross_90_k16_left_near, gpu_raster_phase19,
295 drawT_CROSS_90_K16();
297)
298
299CESTER_TEST(ar_cross_90_k16_interior, gpu_raster_phase19,
300 drawT_CROSS_90_K16();
302)
303
304CESTER_TEST(ar_cross_90_k16_top_far, gpu_raster_phase19,
305 drawT_CROSS_90_K16();
307)
CESTER_TEST(cddaLevelHalf, test_instances, static const uint8_t atv[4]={0x40, 0x00, 0x40, 0x00};unsigned changes=0;int peak=cddaPeak(atv, 1, &changes);ramsyscall_printf("CD-DA level at half ATV: peak %i, %u sign changes\n", peak, changes);cester_assert_int_ge(peak, 11300);cester_assert_int_le(peak, 11800);cester_assert_uint_ge(changes, 4);) CESTER_TEST(cddaLevelClipped
CESTER_BODY(static uint16_t s_cddaCapture;static int cddaSpuDma(uint32_t spuAddr, void *buf, uint32_t bytes, int isRead) { const uint16_t tsa=spuAddr > > 3;const uint16_t mode=isRead ? 0x30 :0x20;SPU_RAM_DTA=tsa;for(int i=0;i< 0xf01 &&SPU_RAM_DTA !=tsa;i++);SPU_CTRL=(SPU_CTRL &~0x30)|mode;for(volatile int i=0;i< 60;i++);for(int i=0;i< 0xf01 &&(SPU_STATUS &0x30) !=mode;i++);CDDA_SPU_DELAY=(CDDA_SPU_DELAY &0xf0ffffff)|(isRead ? 0x22000000 :0x20000000);DMA_CTRL[DMA_SPU].MADR=(uint32_t) buf &0x1fffffff;DMA_CTRL[DMA_SPU].BCR=((bytes > > 6)<< 16)|0x10;DMA_CTRL[DMA_SPU].CHCR=isRead ? 0x01000200 :0x01000201;int ok=0;for(unsigned t=0;t< 4000000u;t++) { if((DMA_CTRL[DMA_SPU].CHCR &0x01000000)==0) { ok=1;break;} } SPU_CTRL=SPU_CTRL &~0x30;for(volatile int i=0;i< 60;i++);return ok;} static int cddaSimpleCmd(uint8_t cmd) { uint8_t response[16];CDROM_REG0=0;CDROM_REG1=cmd;uint32_t timeout=2000000;int ok=waitCDRomIRQWithTimeout(&timeout);ackCDRomCause();readResponse(response);return ok;} static void cddaWaitPauseComplete() { initializeTime();uint32_t elapsed=0;while(elapsed< 5000000u) { uint32_t budget=200000u;int ok=waitCDRomIRQWithTimeout(&budget);elapsed=budget;if(!ok) continue;uint8_t cause=ackCDRomCause();uint8_t response[16];readResponse(response);if(cause==2) return;} } static int cddaAudioSetup(const uint8_t atv[4], int demute) { if(!resetCDRom()) return 0;DPCR|=0x000b0000;SPU_CTRL=0;for(volatile int i=0;i< 20000;i++);SPU_VOL_MAIN_LEFT=0;SPU_VOL_MAIN_RIGHT=0;SPU_KEY_OFF_LOW=0xffff;SPU_KEY_OFF_HIGH=0xffff;SPU_RAM_DTC=4;SPU_CTRL=0x8001;for(volatile int i=0;i< 20000;i++);for(int i=0;i< 0x400;i++) s_cddaCapture[i]=CDDA_MARKER;if(!cddaSpuDma(0x000, s_cddaCapture, 0x800, 0)) return 0;if(!cddaSimpleCmd(demute ? CDL_DEMUTE :CDL_MUTE)) return 0;CDROM_REG0=2;CDROM_REG2=atv[0];CDROM_REG3=atv[1];CDROM_REG0=3;CDROM_REG1=atv[2];CDROM_REG2=atv[3];CDROM_REG0=3;CDROM_REG3=0x20;CDROM_REG0=0;SPU_VOL_CD_LEFT=0x7fff;SPU_VOL_CD_RIGHT=0x7fff;SPU_CTRL=SPU_CTRL|0x8001;return 1;} static int cddaBufferPeak(unsigned *signChanges) { int peak=0;unsigned changes=0;int prev=0;for(int i=0;i< 0x200;i++) { int v=(int16_t) s_cddaCapture[i];int a=v< 0 ? -v :v;if(a > peak) peak=a;int sign=v >=0 ? 1 :-1;if(i &&sign !=prev) changes++;prev=sign;} *signChanges=changes;return peak;} static int cddaCapturePeak(unsigned *signChanges) { int peak=0;for(unsigned attempt=0;attempt< 8;attempt++) { if(attempt) { initializeTime();while(updateTime()< 250000u);} if(!cddaSpuDma(0x000, s_cddaCapture, 0x800, 1)) return -1;peak=cddaBufferPeak(signChanges);if(peak) { if(attempt) ramsyscall_printf("capture was empty %u time(s) before audio\n", attempt);break;} } return peak;} static int cddaPeak(const uint8_t atv[4], int demute, unsigned *signChanges) { if(!cddaAudioSetup(atv, demute)) return -1;if(!setMode(0)) return -1;CDROM_REG0=0;CDROM_REG2=0x02;if(!cddaSimpleCmd(CDL_PLAY)) return -1;initializeTime();while(updateTime()< 1500000u);int peak=cddaCapturePeak(signChanges);CDROM_REG0=0;CDROM_REG1=CDL_PAUSE;cddaWaitPauseComplete();CDROM_REG0=0;CDROM_REG2=0x00;CDROM_REG2=0x02;CDROM_REG2=0x16;if(cddaSimpleCmd(CDL_SETLOC) &&cddaSimpleCmd(CDL_SEEKL)) cddaWaitPauseComplete();return peak;}[0x400])
Definition cdda.c:37
#define EXPECT_NEG_U_K05_INTERIOR
Definition raster-expected-phase19.h:83
#define EXPECT_CROSS_90_K16_TOP_NEAR
Definition raster-expected-phase19.h:161
#define EXPECT_NEG_U_K05_LEFT_NEAR
Definition raster-expected-phase19.h:82
#define EXPECT_NEG_U_K05_TOP_FAR
Definition raster-expected-phase19.h:84
#define EXPECT_CROSS_45_K05_INTERIOR
Definition raster-expected-phase19.h:147
#define EXPECT_NEG_U_K16_TOP_FAR
Definition raster-expected-phase19.h:132
#define EXPECT_NEG_V_K05_TOP_NEAR
Definition raster-expected-phase19.h:97
#define EXPECT_NEG_U_K16_TOP_NEAR
Definition raster-expected-phase19.h:129
#define EXPECT_NEG_U_K05_VERTEX
Definition raster-expected-phase19.h:80
#define EXPECT_NEG_V_K05_INTERIOR
Definition raster-expected-phase19.h:99
#define EXPECT_NEG_BOTH_K05_INTERIOR
Definition raster-expected-phase19.h:115
#define EXPECT_NEG_BOTH_K05_LEFT_NEAR
Definition raster-expected-phase19.h:114
#define EXPECT_CROSS_90_K16_INTERIOR
Definition raster-expected-phase19.h:163
#define EXPECT_CROSS_90_K16_VERTEX
Definition raster-expected-phase19.h:160
#define EXPECT_NEG_V_K05_TOP_FAR
Definition raster-expected-phase19.h:100
#define EXPECT_NEG_V_K05_VERTEX
Definition raster-expected-phase19.h:96
#define EXPECT_NEG_BOTH_K05_TOP_NEAR
Definition raster-expected-phase19.h:113
#define EXPECT_CROSS_90_K16_TOP_FAR
Definition raster-expected-phase19.h:164
#define EXPECT_NEG_U_K16_INTERIOR
Definition raster-expected-phase19.h:131
#define EXPECT_NEG_U_K16_LEFT_NEAR
Definition raster-expected-phase19.h:130
#define EXPECT_NEG_V_K05_LEFT_NEAR
Definition raster-expected-phase19.h:98
#define EXPECT_CROSS_45_K05_TOP_NEAR
Definition raster-expected-phase19.h:145
#define EXPECT_NEG_U_K05_TOP_NEAR
Definition raster-expected-phase19.h:81
#define EXPECT_NEG_U_K16_VERTEX
Definition raster-expected-phase19.h:128
#define EXPECT_CROSS_45_K05_VERTEX
Definition raster-expected-phase19.h:144
#define EXPECT_CROSS_90_K16_LEFT_NEAR
Definition raster-expected-phase19.h:162
#define EXPECT_NEG_BOTH_K05_TOP_FAR
Definition raster-expected-phase19.h:116
#define EXPECT_NEG_BOTH_K05_VERTEX
Definition raster-expected-phase19.h:112
#define EXPECT_CROSS_45_K05_TOP_FAR
Definition raster-expected-phase19.h:148
#define EXPECT_CROSS_45_K05_LEFT_NEAR
Definition raster-expected-phase19.h:146
#define TEX17_TY
Definition texture-fixture-phase17.h:58
#define TEX17_TPAGE
Definition texture-fixture-phase17.h:65
#define TEX17_TX
Definition texture-fixture-phase17.h:57
#define PHASE17_ASSERT_PIXEL_EQ(expected, x_, y_)
Definition texture-fixture-phase17.h:102
#define TEX17_CLUT_FIELD
Definition texture-fixture-phase17.h:66
#define TEX_MOD_NEUTRAL
Definition texture-fixtures.h:308