Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
gouraud-color.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// Gouraud color precision suite. PS1 GPU gouraud interpolation uses
28// integer-truncated per-row and per-pixel-X color deltas. This suite
29// probes the resulting truncation behavior in three independent
30// dimensions:
31//
32// 1. Triangle size sweep (small / medium / large). Small triangles
33// have lossy per-row deltas; large triangles drift across many
34// rows. Same shape, different precision pressure.
35//
36// 2. R-only single-axis gradients (vertical and horizontal). Strip
37// one axis of variation so the OBS log directly shows where the
38// accumulator landed at each step.
39//
40// 3. Vertex-order permutations. Hardware should be order-independent
41// and the soft renderer's longest-edge sort should produce the
42// same accumulators regardless of caller-supplied ordering.
43
44// clang-format off
45
47
48// --------------------------------------------------------------------------
49// GC: Canonical RGB-vertex triangle at three sizes
50// --------------------------------------------------------------------------
51
52static void drawGC1(void) {
53 rasterReset();
54 rasterClearTestRegion(0, 0, 16, 16);
55 rasterGouraudTri(RASTER_CMD_RED, 0, 0,
56 RASTER_CMD_GREEN, 7, 0,
57 RASTER_CMD_BLUE, 0, 7);
58 rasterFlushPrimitive();
59}
60
61static void drawGC2(void) {
62 rasterReset();
63 rasterClearTestRegion(0, 0, 48, 48);
64 rasterGouraudTri(RASTER_CMD_RED, 0, 0,
65 RASTER_CMD_GREEN, 31, 0,
66 RASTER_CMD_BLUE, 0, 31);
67 rasterFlushPrimitive();
68}
69
70static void drawGC3(void) {
71 rasterReset();
72 /* Draw region just over 128x128 so we can probe out-of-tri sentinels too. */
73 rasterClearTestRegion(0, 0, 144, 144);
74 rasterGouraudTri(RASTER_CMD_RED, 0, 0,
75 RASTER_CMD_GREEN, 127, 0,
76 RASTER_CMD_BLUE, 0, 127);
77 rasterFlushPrimitive();
78}
79
80// --------------------------------------------------------------------------
81// GV: R-only vertical gradient. Apex (0,0) at max R, base at R=0.
82// Width matches height so the triangle is the same shape as GC but
83// only the R channel varies. Probe column x=0 to read the left-edge
84// accumulator directly.
85// --------------------------------------------------------------------------
86
87static void drawGV(int n) {
88 /* R apex, R=0 elsewhere. */
89 rasterReset();
90 rasterClearTestRegion(0, 0, 32, 32);
91 rasterGouraudTri(RASTER_CMD_RED, 0, 0,
92 0u, (int16_t)n, 0,
93 0u, 0, (int16_t)n);
94 rasterFlushPrimitive();
95}
96
97// --------------------------------------------------------------------------
98// GH: R-only horizontal gradient. Top edge interpolates R 31->0 across
99// W. Left edge stays at R=31 down the height (apex and v2 both R=31).
100// --------------------------------------------------------------------------
101
102static void drawGH(int n) {
103 rasterReset();
104 rasterClearTestRegion(0, 0, 32, 32);
105 rasterGouraudTri(RASTER_CMD_RED, 0, 0,
106 0u, (int16_t)n, 0,
107 RASTER_CMD_RED, 0, (int16_t)n);
108 rasterFlushPrimitive();
109}
110
111// --------------------------------------------------------------------------
112// GS: Saturation / vertex-exactness probes.
113// --------------------------------------------------------------------------
114
115static void drawGSNearMax(void) {
116 /* Apex R=31, others R=30 (1 LSB below max in 5-bit space). 16x16. */
117 rasterReset();
118 rasterClearTestRegion(0, 0, 32, 32);
119 rasterGouraudTri(rasterCmdColor(31, 0, 0), 0, 0,
120 rasterCmdColor(30, 0, 0), 16, 0,
121 rasterCmdColor(30, 0, 0), 0, 16);
122 rasterFlushPrimitive();
123}
124
125static void drawGSNearMin(void) {
126 /* Apex R=0, others R=1 (1 LSB above min). 16x16. */
127 rasterReset();
128 rasterClearTestRegion(0, 0, 32, 32);
129 rasterGouraudTri(rasterCmdColor(0, 0, 0), 0, 0,
130 rasterCmdColor(1, 0, 0), 16, 0,
131 rasterCmdColor(1, 0, 0), 0, 16);
132 rasterFlushPrimitive();
133}
134
135static void drawGSHalfOfLSB(void) {
136 /* Apex R=1, others R=0. 8x8. The accumulator drops smoothly past
137 the 5-bit truncation point - hardware may keep R=1 for the first
138 few rows and quantize to 0 below. */
139 rasterReset();
140 rasterClearTestRegion(0, 0, 16, 16);
141 rasterGouraudTri(rasterCmdColor(1, 0, 0), 0, 0,
142 rasterCmdColor(0, 0, 0), 8, 0,
143 rasterCmdColor(0, 0, 0), 0, 8);
144 rasterFlushPrimitive();
145}
146
147// --------------------------------------------------------------------------
148// GD: Dither ON for the canonical 32x32 triangle.
149// --------------------------------------------------------------------------
150
151static void drawGD(void) {
152 rasterReset();
153 rasterClearTestRegion(0, 0, 48, 48);
154 rasterSetDither(1);
155 rasterGouraudTri(RASTER_CMD_RED, 0, 0,
156 RASTER_CMD_GREEN, 31, 0,
157 RASTER_CMD_BLUE, 0, 31);
158 rasterFlushPrimitive();
159 rasterSetDither(0);
160}
161
162// --------------------------------------------------------------------------
163// GO: Vertex-order permutations of the GC1 triangle.
164// Same three vertex/color pairs, six orderings.
165// --------------------------------------------------------------------------
166
167#define GO_TRI_R_FIRST_GB() \
168 rasterGouraudTri(RASTER_CMD_RED, 0, 0, RASTER_CMD_GREEN, 7, 0, RASTER_CMD_BLUE, 0, 7)
169#define GO_TRI_R_FIRST_BG() \
170 rasterGouraudTri(RASTER_CMD_RED, 0, 0, RASTER_CMD_BLUE, 0, 7, RASTER_CMD_GREEN, 7, 0)
171#define GO_TRI_G_FIRST_RB() \
172 rasterGouraudTri(RASTER_CMD_GREEN, 7, 0, RASTER_CMD_RED, 0, 0, RASTER_CMD_BLUE, 0, 7)
173#define GO_TRI_G_FIRST_BR() \
174 rasterGouraudTri(RASTER_CMD_GREEN, 7, 0, RASTER_CMD_BLUE, 0, 7, RASTER_CMD_RED, 0, 0)
175#define GO_TRI_B_FIRST_RG() \
176 rasterGouraudTri(RASTER_CMD_BLUE, 0, 7, RASTER_CMD_RED, 0, 0, RASTER_CMD_GREEN, 7, 0)
177#define GO_TRI_B_FIRST_GR() \
178 rasterGouraudTri(RASTER_CMD_BLUE, 0, 7, RASTER_CMD_GREEN, 7, 0, RASTER_CMD_RED, 0, 0)
179
180static void drawGOPerm(int perm) {
181 rasterReset();
182 rasterClearTestRegion(0, 0, 16, 16);
183 switch (perm) {
184 case 0: GO_TRI_R_FIRST_GB(); break;
185 case 1: GO_TRI_R_FIRST_BG(); break;
186 case 2: GO_TRI_G_FIRST_RB(); break;
187 case 3: GO_TRI_G_FIRST_BR(); break;
188 case 4: GO_TRI_B_FIRST_RG(); break;
189 case 5: GO_TRI_B_FIRST_GR(); break;
190 }
191 rasterFlushPrimitive();
192}
193
194) // CESTER_BODY
195
196// --------------------------------------------------------------------------
197// GC1: 8x8 canonical RGB triangle
198// --------------------------------------------------------------------------
199
200CESTER_TEST(gc1_v0_apex_red, gpu_raster_phase7,
201 drawGC1();
202 /* Apex pixel = pure R at vertex 0. */
204)
205
206CESTER_TEST(gc1_top_x4, gpu_raster_phase7,
207 drawGC1();
208 /* Mid R-G edge at (4, 0). Top-left rule includes top edge. */
210)
211
212CESTER_TEST(gc1_left_y4, gpu_raster_phase7,
213 drawGC1();
214 /* Mid R-B edge at (0, 4). Left edge included. */
216)
217
218CESTER_TEST(gc1_interior_1_1, gpu_raster_phase7,
219 drawGC1();
221)
222
223CESTER_TEST(gc1_interior_2_2, gpu_raster_phase7,
224 drawGC1();
226)
227
228CESTER_TEST(gc1_interior_3_3, gpu_raster_phase7,
229 drawGC1();
231)
232
233CESTER_TEST(gc1_interior_1_3, gpu_raster_phase7,
234 drawGC1();
235 /* Below diagonal: more B weight than G. */
237)
238
239CESTER_TEST(gc1_interior_3_1, gpu_raster_phase7,
240 drawGC1();
241 /* Above diagonal: more G weight than B. */
243)
244
245// --------------------------------------------------------------------------
246// GC2: 32x32 canonical RGB triangle
247// --------------------------------------------------------------------------
248
249CESTER_TEST(gc2_v0_apex_red, gpu_raster_phase7,
250 drawGC2();
252)
253
254CESTER_TEST(gc2_top_x16, gpu_raster_phase7,
255 drawGC2();
257)
258
259CESTER_TEST(gc2_left_y16, gpu_raster_phase7,
260 drawGC2();
262)
263
264CESTER_TEST(gc2_interior_8_8, gpu_raster_phase7,
265 drawGC2();
267)
268
269CESTER_TEST(gc2_interior_16_8, gpu_raster_phase7,
270 drawGC2();
272)
273
274CESTER_TEST(gc2_interior_8_16, gpu_raster_phase7,
275 drawGC2();
277)
278
279CESTER_TEST(gc2_interior_1_1, gpu_raster_phase7,
280 drawGC2();
282)
283
284CESTER_TEST(gc2_interior_30_0, gpu_raster_phase7,
285 drawGC2();
286 /* Near right vertex (32,0). Top edge included, top-left includes
287 this pixel if right xmax includes it. */
289)
290
291// --------------------------------------------------------------------------
292// GC3: 128x128 canonical RGB triangle
293// --------------------------------------------------------------------------
294
295CESTER_TEST(gc3_v0_apex_red, gpu_raster_phase7,
296 drawGC3();
298)
299
300CESTER_TEST(gc3_top_x64, gpu_raster_phase7,
301 drawGC3();
303)
304
305CESTER_TEST(gc3_left_y64, gpu_raster_phase7,
306 drawGC3();
308)
309
310CESTER_TEST(gc3_interior_32_32, gpu_raster_phase7,
311 drawGC3();
313)
314
315CESTER_TEST(gc3_interior_1_1, gpu_raster_phase7,
316 drawGC3();
318)
319
320CESTER_TEST(gc3_interior_64_32, gpu_raster_phase7,
321 drawGC3();
323)
324
325CESTER_TEST(gc3_interior_32_64, gpu_raster_phase7,
326 drawGC3();
328)
329
330CESTER_TEST(gc3_interior_96_16, gpu_raster_phase7,
331 drawGC3();
333)
334
335// --------------------------------------------------------------------------
336// GV: Vertical R-only gradient
337// --------------------------------------------------------------------------
338
339CESTER_TEST(gv3_x0_y0, gpu_raster_phase7,
340 drawGV(3);
342)
343CESTER_TEST(gv3_x0_y1, gpu_raster_phase7,
344 drawGV(3);
346)
347CESTER_TEST(gv3_x0_y2, gpu_raster_phase7,
348 drawGV(3);
350)
351
352CESTER_TEST(gv5_x0_y0, gpu_raster_phase7,
353 drawGV(5);
355)
356CESTER_TEST(gv5_x0_y1, gpu_raster_phase7,
357 drawGV(5);
359)
360CESTER_TEST(gv5_x0_y2, gpu_raster_phase7,
361 drawGV(5);
363)
364CESTER_TEST(gv5_x0_y3, gpu_raster_phase7,
365 drawGV(5);
367)
368CESTER_TEST(gv5_x0_y4, gpu_raster_phase7,
369 drawGV(5);
371)
372
373CESTER_TEST(gv7_x0_y0, gpu_raster_phase7, drawGV(7); ASSERT_PIXEL_EQ(GV7_X0_Y0, 0, 0); )
374CESTER_TEST(gv7_x0_y1, gpu_raster_phase7, drawGV(7); ASSERT_PIXEL_EQ(GV7_X0_Y1, 0, 1); )
375CESTER_TEST(gv7_x0_y2, gpu_raster_phase7, drawGV(7); ASSERT_PIXEL_EQ(GV7_X0_Y2, 0, 2); )
376CESTER_TEST(gv7_x0_y3, gpu_raster_phase7, drawGV(7); ASSERT_PIXEL_EQ(GV7_X0_Y3, 0, 3); )
377CESTER_TEST(gv7_x0_y4, gpu_raster_phase7, drawGV(7); ASSERT_PIXEL_EQ(GV7_X0_Y4, 0, 4); )
378CESTER_TEST(gv7_x0_y5, gpu_raster_phase7, drawGV(7); ASSERT_PIXEL_EQ(GV7_X0_Y5, 0, 5); )
379CESTER_TEST(gv7_x0_y6, gpu_raster_phase7, drawGV(7); ASSERT_PIXEL_EQ(GV7_X0_Y6, 0, 6); )
380
381CESTER_TEST(gv11_x0_y0, gpu_raster_phase7, drawGV(11); ASSERT_PIXEL_EQ(GV11_X0_Y0, 0, 0); )
382CESTER_TEST(gv11_x0_y2, gpu_raster_phase7, drawGV(11); ASSERT_PIXEL_EQ(GV11_X0_Y2, 0, 2); )
383CESTER_TEST(gv11_x0_y4, gpu_raster_phase7, drawGV(11); ASSERT_PIXEL_EQ(GV11_X0_Y4, 0, 4); )
384CESTER_TEST(gv11_x0_y6, gpu_raster_phase7, drawGV(11); ASSERT_PIXEL_EQ(GV11_X0_Y6, 0, 6); )
385CESTER_TEST(gv11_x0_y8, gpu_raster_phase7, drawGV(11); ASSERT_PIXEL_EQ(GV11_X0_Y8, 0, 8); )
386CESTER_TEST(gv11_x0_y10, gpu_raster_phase7, drawGV(11); ASSERT_PIXEL_EQ(GV11_X0_Y10, 0, 10); )
387
388// --------------------------------------------------------------------------
389// GH: Horizontal R-only gradient
390// --------------------------------------------------------------------------
391
392CESTER_TEST(gh3_y0_x0, gpu_raster_phase7, drawGH(3); ASSERT_PIXEL_EQ(GH3_Y0_X0, 0, 0); )
393CESTER_TEST(gh3_y0_x1, gpu_raster_phase7, drawGH(3); ASSERT_PIXEL_EQ(GH3_Y0_X1, 1, 0); )
394CESTER_TEST(gh3_y0_x2, gpu_raster_phase7, drawGH(3); ASSERT_PIXEL_EQ(GH3_Y0_X2, 2, 0); )
395
396CESTER_TEST(gh5_y0_x0, gpu_raster_phase7, drawGH(5); ASSERT_PIXEL_EQ(GH5_Y0_X0, 0, 0); )
397CESTER_TEST(gh5_y0_x1, gpu_raster_phase7, drawGH(5); ASSERT_PIXEL_EQ(GH5_Y0_X1, 1, 0); )
398CESTER_TEST(gh5_y0_x2, gpu_raster_phase7, drawGH(5); ASSERT_PIXEL_EQ(GH5_Y0_X2, 2, 0); )
399CESTER_TEST(gh5_y0_x3, gpu_raster_phase7, drawGH(5); ASSERT_PIXEL_EQ(GH5_Y0_X3, 3, 0); )
400CESTER_TEST(gh5_y0_x4, gpu_raster_phase7, drawGH(5); ASSERT_PIXEL_EQ(GH5_Y0_X4, 4, 0); )
401
402CESTER_TEST(gh7_y0_x0, gpu_raster_phase7, drawGH(7); ASSERT_PIXEL_EQ(GH7_Y0_X0, 0, 0); )
403CESTER_TEST(gh7_y0_x1, gpu_raster_phase7, drawGH(7); ASSERT_PIXEL_EQ(GH7_Y0_X1, 1, 0); )
404CESTER_TEST(gh7_y0_x2, gpu_raster_phase7, drawGH(7); ASSERT_PIXEL_EQ(GH7_Y0_X2, 2, 0); )
405CESTER_TEST(gh7_y0_x3, gpu_raster_phase7, drawGH(7); ASSERT_PIXEL_EQ(GH7_Y0_X3, 3, 0); )
406CESTER_TEST(gh7_y0_x4, gpu_raster_phase7, drawGH(7); ASSERT_PIXEL_EQ(GH7_Y0_X4, 4, 0); )
407CESTER_TEST(gh7_y0_x5, gpu_raster_phase7, drawGH(7); ASSERT_PIXEL_EQ(GH7_Y0_X5, 5, 0); )
408CESTER_TEST(gh7_y0_x6, gpu_raster_phase7, drawGH(7); ASSERT_PIXEL_EQ(GH7_Y0_X6, 6, 0); )
409
410CESTER_TEST(gh11_y0_x0, gpu_raster_phase7, drawGH(11); ASSERT_PIXEL_EQ(GH11_Y0_X0, 0, 0); )
411CESTER_TEST(gh11_y0_x2, gpu_raster_phase7, drawGH(11); ASSERT_PIXEL_EQ(GH11_Y0_X2, 2, 0); )
412CESTER_TEST(gh11_y0_x4, gpu_raster_phase7, drawGH(11); ASSERT_PIXEL_EQ(GH11_Y0_X4, 4, 0); )
413CESTER_TEST(gh11_y0_x6, gpu_raster_phase7, drawGH(11); ASSERT_PIXEL_EQ(GH11_Y0_X6, 6, 0); )
414CESTER_TEST(gh11_y0_x8, gpu_raster_phase7, drawGH(11); ASSERT_PIXEL_EQ(GH11_Y0_X8, 8, 0); )
415CESTER_TEST(gh11_y0_x10, gpu_raster_phase7, drawGH(11); ASSERT_PIXEL_EQ(GH11_Y0_X10, 10, 0); )
416
417// --------------------------------------------------------------------------
418// GS: Saturation / vertex-exactness
419// --------------------------------------------------------------------------
420
421CESTER_TEST(gs_near_max_apex, gpu_raster_phase7,
422 drawGSNearMax();
424)
425
426CESTER_TEST(gs_near_max_interior, gpu_raster_phase7,
427 drawGSNearMax();
428 /* Deep interior should be R=30 (the base color), not drift up to 31. */
430)
431
432CESTER_TEST(gs_near_min_apex, gpu_raster_phase7,
433 drawGSNearMin();
435)
436
437CESTER_TEST(gs_near_min_interior, gpu_raster_phase7,
438 drawGSNearMin();
439 /* Deep interior should be R=1, not underflow to 31. */
441)
442
443CESTER_TEST(gs_half_of_lsb_apex, gpu_raster_phase7,
444 drawGSHalfOfLSB();
446)
447
448CESTER_TEST(gs_half_of_lsb_y2, gpu_raster_phase7,
449 drawGSHalfOfLSB();
451)
452
453CESTER_TEST(gs_half_of_lsb_y4, gpu_raster_phase7,
454 drawGSHalfOfLSB();
456)
457
458CESTER_TEST(gs_half_of_lsb_y6, gpu_raster_phase7,
459 drawGSHalfOfLSB();
461)
462
463// --------------------------------------------------------------------------
464// GD: Dither overlay - 4x4 Bayer pattern probe
465// --------------------------------------------------------------------------
466
467CESTER_TEST(gd_8_8, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_8_8, 8, 8); )
468CESTER_TEST(gd_9_8, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_9_8, 9, 8); )
469CESTER_TEST(gd_10_8, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_10_8, 10, 8); )
470CESTER_TEST(gd_11_8, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_11_8, 11, 8); )
471CESTER_TEST(gd_8_9, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_8_9, 8, 9); )
472CESTER_TEST(gd_9_9, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_9_9, 9, 9); )
473CESTER_TEST(gd_10_9, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_10_9, 10, 9); )
474CESTER_TEST(gd_11_9, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_11_9, 11, 9); )
475CESTER_TEST(gd_8_10, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_8_10, 8, 10); )
476CESTER_TEST(gd_9_10, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_9_10, 9, 10); )
477CESTER_TEST(gd_10_10, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_10_10, 10, 10); )
478CESTER_TEST(gd_11_10, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_11_10, 11, 10); )
479CESTER_TEST(gd_8_11, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_8_11, 8, 11); )
480CESTER_TEST(gd_9_11, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_9_11, 9, 11); )
481CESTER_TEST(gd_10_11, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_10_11, 10, 11); )
482CESTER_TEST(gd_11_11, gpu_raster_phase7, drawGD(); ASSERT_PIXEL_EQ(GD_11_11, 11, 11); )
483
484// --------------------------------------------------------------------------
485// GO: Vertex-order permutations
486// All six permutations should produce identical interior pixels.
487// --------------------------------------------------------------------------
488
489CESTER_TEST(go_perm0_R_GB_2_2, gpu_raster_phase7,
490 drawGOPerm(0); ASSERT_PIXEL_EQ(GO_PERM_INTERIOR_2_2, 2, 2);
491)
492CESTER_TEST(go_perm1_R_BG_2_2, gpu_raster_phase7,
493 drawGOPerm(1); ASSERT_PIXEL_EQ(GO_PERM_INTERIOR_2_2, 2, 2);
494)
495CESTER_TEST(go_perm2_G_RB_2_2, gpu_raster_phase7,
496 drawGOPerm(2); ASSERT_PIXEL_EQ(GO_PERM_INTERIOR_2_2, 2, 2);
497)
498CESTER_TEST(go_perm3_G_BR_2_2, gpu_raster_phase7,
499 drawGOPerm(3); ASSERT_PIXEL_EQ(GO_PERM_INTERIOR_2_2, 2, 2);
500)
501CESTER_TEST(go_perm4_B_RG_2_2, gpu_raster_phase7,
502 drawGOPerm(4); ASSERT_PIXEL_EQ(GO_PERM_INTERIOR_2_2, 2, 2);
503)
504CESTER_TEST(go_perm5_B_GR_2_2, gpu_raster_phase7,
505 drawGOPerm(5); ASSERT_PIXEL_EQ(GO_PERM_INTERIOR_2_2, 2, 2);
506)
507
508CESTER_TEST(go_perm0_R_GB_1_3, gpu_raster_phase7,
509 drawGOPerm(0); ASSERT_PIXEL_EQ(GO_PERM_INTERIOR_1_3, 1, 3);
510)
511CESTER_TEST(go_perm1_R_BG_1_3, gpu_raster_phase7,
512 drawGOPerm(1); ASSERT_PIXEL_EQ(GO_PERM_INTERIOR_1_3, 1, 3);
513)
514CESTER_TEST(go_perm2_G_RB_1_3, gpu_raster_phase7,
515 drawGOPerm(2); ASSERT_PIXEL_EQ(GO_PERM_INTERIOR_1_3, 1, 3);
516)
517CESTER_TEST(go_perm3_G_BR_1_3, gpu_raster_phase7,
518 drawGOPerm(3); ASSERT_PIXEL_EQ(GO_PERM_INTERIOR_1_3, 1, 3);
519)
520CESTER_TEST(go_perm4_B_RG_1_3, gpu_raster_phase7,
521 drawGOPerm(4); ASSERT_PIXEL_EQ(GO_PERM_INTERIOR_1_3, 1, 3);
522)
523CESTER_TEST(go_perm5_B_GR_1_3, gpu_raster_phase7,
524 drawGOPerm(5); ASSERT_PIXEL_EQ(GO_PERM_INTERIOR_1_3, 1, 3);
525)
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 GO_TRI_G_FIRST_BR()
#define GO_TRI_B_FIRST_RG()
#define GO_TRI_G_FIRST_RB()
#define GO_TRI_R_FIRST_BG()
#define GO_TRI_B_FIRST_GR()
#define GO_TRI_R_FIRST_GB()
#define GC3_TOP_X64
Definition raster-expected-phase7.h:112
#define GV3_X0_Y1
Definition raster-expected-phase7.h:129
#define GV5_X0_Y3
Definition raster-expected-phase7.h:136
#define GC2_INTERIOR_1_1
Definition raster-expected-phase7.h:107
#define GC3_INTERIOR_32_64
Definition raster-expected-phase7.h:117
#define GC2_INTERIOR_8_8
Definition raster-expected-phase7.h:104
#define GC1_INTERIOR_2_2
Definition raster-expected-phase7.h:95
#define GS_NEAR_MIN_INTERIOR
Definition raster-expected-phase7.h:217
#define GH7_Y0_X5
Definition raster-expected-phase7.h:185
#define GD_10_11
Definition raster-expected-phase7.h:247
#define GV11_X0_Y10
Definition raster-expected-phase7.h:157
#define GS_NEAR_MIN_APEX
Definition raster-expected-phase7.h:216
#define GD_8_10
Definition raster-expected-phase7.h:241
#define GC1_LEFT_Y4
Definition raster-expected-phase7.h:93
#define GD_11_10
Definition raster-expected-phase7.h:244
#define GV5_X0_Y4
Definition raster-expected-phase7.h:137
#define GS_HALF_OF_LSB_Y4
Definition raster-expected-phase7.h:220
#define GH11_Y0_X10
Definition raster-expected-phase7.h:194
#define GV7_X0_Y4
Definition raster-expected-phase7.h:147
#define GV7_X0_Y1
Definition raster-expected-phase7.h:144
#define GD_11_11
Definition raster-expected-phase7.h:248
#define GV3_X0_Y0
Definition raster-expected-phase7.h:128
#define GV7_X0_Y2
Definition raster-expected-phase7.h:145
#define GC2_INTERIOR_16_8
Definition raster-expected-phase7.h:105
#define GH7_Y0_X6
Definition raster-expected-phase7.h:186
#define GV7_X0_Y3
Definition raster-expected-phase7.h:146
#define GC2_V0_R
Definition raster-expected-phase7.h:101
#define GS_HALF_OF_LSB_Y6
Definition raster-expected-phase7.h:221
#define GV7_X0_Y5
Definition raster-expected-phase7.h:148
#define GV11_X0_Y0
Definition raster-expected-phase7.h:152
#define GV11_X0_Y8
Definition raster-expected-phase7.h:156
#define GH3_Y0_X0
Definition raster-expected-phase7.h:168
#define GC2_INTERIOR_8_16
Definition raster-expected-phase7.h:106
#define GC3_INTERIOR_1_1
Definition raster-expected-phase7.h:115
#define GD_9_11
Definition raster-expected-phase7.h:246
#define GC3_INTERIOR_96_16
Definition raster-expected-phase7.h:118
#define GH5_Y0_X0
Definition raster-expected-phase7.h:173
#define GH11_Y0_X2
Definition raster-expected-phase7.h:190
#define GV11_X0_Y4
Definition raster-expected-phase7.h:154
#define GH5_Y0_X2
Definition raster-expected-phase7.h:175
#define GD_8_9
Definition raster-expected-phase7.h:237
#define GS_HALF_OF_LSB_Y2
Definition raster-expected-phase7.h:219
#define GD_8_11
Definition raster-expected-phase7.h:245
#define GH5_Y0_X4
Definition raster-expected-phase7.h:177
#define GH7_Y0_X2
Definition raster-expected-phase7.h:182
#define GC2_TOP_X16
Definition raster-expected-phase7.h:102
#define GS_NEAR_MAX_INTERIOR
Definition raster-expected-phase7.h:215
#define GV5_X0_Y1
Definition raster-expected-phase7.h:134
#define GO_PERM_INTERIOR_2_2
Definition raster-expected-phase7.h:256
#define GC3_INTERIOR_32_32
Definition raster-expected-phase7.h:114
#define GD_10_8
Definition raster-expected-phase7.h:235
#define GV7_X0_Y6
Definition raster-expected-phase7.h:149
#define GV11_X0_Y6
Definition raster-expected-phase7.h:155
#define GH7_Y0_X0
Definition raster-expected-phase7.h:180
#define GS_HALF_OF_LSB_APEX
Definition raster-expected-phase7.h:218
#define GD_10_10
Definition raster-expected-phase7.h:243
#define GD_10_9
Definition raster-expected-phase7.h:239
#define GC1_INTERIOR_1_1
Definition raster-expected-phase7.h:94
#define GH5_Y0_X1
Definition raster-expected-phase7.h:174
#define GH11_Y0_X6
Definition raster-expected-phase7.h:192
#define GC3_LEFT_Y64
Definition raster-expected-phase7.h:113
#define GV7_X0_Y0
Definition raster-expected-phase7.h:143
#define GV11_X0_Y2
Definition raster-expected-phase7.h:153
#define GV5_X0_Y2
Definition raster-expected-phase7.h:135
#define GC1_INTERIOR_3_1
Definition raster-expected-phase7.h:98
#define GD_11_9
Definition raster-expected-phase7.h:240
#define GV3_X0_Y2
Definition raster-expected-phase7.h:130
#define GC2_INTERIOR_30_0
Definition raster-expected-phase7.h:108
#define GD_11_8
Definition raster-expected-phase7.h:236
#define GC1_INTERIOR_3_3
Definition raster-expected-phase7.h:96
#define GC2_LEFT_Y16
Definition raster-expected-phase7.h:103
#define GC1_V0_R
Definition raster-expected-phase7.h:91
#define GH7_Y0_X1
Definition raster-expected-phase7.h:181
#define GC3_INTERIOR_64_32
Definition raster-expected-phase7.h:116
#define GH11_Y0_X4
Definition raster-expected-phase7.h:191
#define GD_9_10
Definition raster-expected-phase7.h:242
#define GH5_Y0_X3
Definition raster-expected-phase7.h:176
#define GD_9_8
Definition raster-expected-phase7.h:234
#define GH7_Y0_X4
Definition raster-expected-phase7.h:184
#define GH7_Y0_X3
Definition raster-expected-phase7.h:183
#define GH11_Y0_X0
Definition raster-expected-phase7.h:189
#define GS_NEAR_MAX_APEX
Definition raster-expected-phase7.h:214
#define GC1_TOP_X4
Definition raster-expected-phase7.h:92
#define GO_PERM_INTERIOR_1_3
Definition raster-expected-phase7.h:257
#define GH11_Y0_X8
Definition raster-expected-phase7.h:193
#define GH3_Y0_X2
Definition raster-expected-phase7.h:170
#define GC1_INTERIOR_1_3
Definition raster-expected-phase7.h:97
#define GH3_Y0_X1
Definition raster-expected-phase7.h:169
#define GV5_X0_Y0
Definition raster-expected-phase7.h:133
#define GD_9_9
Definition raster-expected-phase7.h:238
#define GD_8_8
Definition raster-expected-phase7.h:233
#define GC3_V0_R
Definition raster-expected-phase7.h:111
#define RASTER_CMD_BLUE
Definition raster-helpers.h:128
#define RASTER_CMD_RED
Definition raster-helpers.h:124
#define RASTER_CMD_GREEN
Definition raster-helpers.h:126
#define ASSERT_PIXEL_EQ(expected, x_, y_)
Definition raster-helpers.h:473