Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
abr-matrix.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// ABR mode matrix. The four PS1 semi-trans modes are:
28// ABR=0: B/2 + F/2 (average)
29// ABR=1: B + F (additive, clamp at max)
30// ABR=2: B - F (subtractive, clamp at 0)
31// ABR=3: B + F/4 (add quarter, clamp at max)
32//
33// where B is the existing VRAM pixel ("background") and F is the
34// incoming foreground from the primitive. Per psx-spx the blend runs
35// in 8-bit channel space: VRAM 5-bit B is conceptually shifted up by
36// 3 to form B8, blended with the 8-bit F, then truncated back to 5
37// bits for VRAM. We use 5-bit-boundary-aligned channel values (R5 *
38// 8) so the round-trip is exact and the captured 5-bit output maps
39// cleanly to the documented formulas.
40
41// clang-format off
42
44
45// Convenience: build an R-only 24-bit command color from R5 (5-bit
46// value 0..31). Foreground sent to the GPU as 8-bit; we put R8 = R5
47// * 8 in the low byte. G and B are zero so the test focuses on R.
48static inline uint32_t cmdR5(uint8_t r5) {
49 return (uint32_t)(r5 & 0x1f) << 3;
50}
51
52// Pre-fill the test region with an R-only background. b5 is the
53// 5-bit R channel; the rest is zero (which equals 0 in VRAM 5:5:5).
54static inline void fillR(int16_t x, int16_t y, int16_t w, int16_t h,
55 uint8_t b5) {
56 uint16_t pixel = rasterVram555((uint8_t)(b5 & 0x1f), 0, 0);
57 rasterFillRect(x, y, w, h, pixel);
58}
59
60// Draw a 12x12 semi-trans triangle of color F at (0, 0). The
61// triangle is wide enough that probing the deep interior at (4, 4)
62// captures a pixel that's far from the top-left edge artifacts.
63static void drawAbrTri(uint8_t b5, uint8_t f5, uint8_t abr) {
64 rasterReset();
65 fillR(0, 0, 32, 32, b5);
66 rasterSetAbr(abr);
67 rasterFlatTriSemi(cmdR5(f5),
68 0, 0,
69 11, 0,
70 0, 11);
71 rasterFlushPrimitive();
72 rasterSetAbr(0); /* restore default for next test */
73}
74
75static void drawAbrQuad(uint8_t b5, uint8_t f5, uint8_t abr) {
76 rasterReset();
77 fillR(0, 0, 32, 32, b5);
78 rasterSetAbr(abr);
79 rasterFlatQuadSemi(cmdR5(f5),
80 0, 0,
81 11, 0,
82 0, 11,
83 11, 11);
84 rasterFlushPrimitive();
85 rasterSetAbr(0);
86}
87
88static void drawAbrRect(uint8_t b5, uint8_t f5, uint8_t abr) {
89 rasterReset();
90 fillR(0, 0, 32, 32, b5);
91 rasterSetAbr(abr);
92 rasterFlatRectSemi(cmdR5(f5), 0, 0, 12, 12);
93 rasterFlushPrimitive();
94 rasterSetAbr(0);
95}
96
97static void drawAbrLine(uint8_t b5, uint8_t f5, uint8_t abr) {
98 rasterReset();
99 fillR(0, 0, 32, 8, b5);
100 rasterSetAbr(abr);
101 rasterFlatLineSemi(cmdR5(f5), 0, 4, 11, 4);
102 rasterFlushPrimitive();
103 rasterSetAbr(0);
104}
105
106// GP0(0x26) semi-trans textured triangle. The texpage's ABR field
107// would normally drive blend, but tests set E1 ABR explicitly via
108// rasterSetAbr right before the draw - the soft renderer reads ABR
109// from the cached texpage state set most recently via E1 or via the
110// last textured primitive's embedded tpage word.
111static inline void rasterTexTriSemi(uint32_t cmdColor,
112 int16_t x0, int16_t y0, uint8_t u0, uint8_t v0,
113 int16_t x1, int16_t y1, uint8_t u1, uint8_t v1,
114 int16_t x2, int16_t y2, uint8_t u2, uint8_t v2,
115 uint16_t clut_field, uint16_t tpage_field) {
116 waitGPU();
117 GPU_DATA = 0x26000000u | (cmdColor & 0x00ffffffu);
118 GPU_DATA = ((uint32_t)(uint16_t)y0 << 16) | (uint32_t)(uint16_t)x0;
119 GPU_DATA = ((uint32_t)clut_field << 16) |
120 ((uint32_t)v0 << 8) | (uint32_t)u0;
121 GPU_DATA = ((uint32_t)(uint16_t)y1 << 16) | (uint32_t)(uint16_t)x1;
122 GPU_DATA = ((uint32_t)tpage_field << 16) |
123 ((uint32_t)v1 << 8) | (uint32_t)u1;
124 GPU_DATA = ((uint32_t)(uint16_t)y2 << 16) | (uint32_t)(uint16_t)x2;
125 GPU_DATA = (0u << 16) | ((uint32_t)v2 << 8) | (uint32_t)u2;
126}
127
128// Draw a textured semi-trans triangle using the masked CLUT (every
129// entry has bit-15 set). Probe pixel (4, 2) samples texel (4, 2) -
130// 4-bit CLUT entry [4] = vram555(4, 27, 0) | 0x8000.
131static void drawAbrTexTriMasked(uint8_t b5, uint8_t abr) {
132 rasterReset();
133 fillR(0, 0, 32, 16, b5);
134 /* Build texpage with the requested ABR field embedded so the GPU
135 sees the right blend mode even if E1 wasn't re-set. */
136 uint16_t tpage = (uint16_t)((TEX4_TX & 0xf) | ((TEX4_TY & 1) << 4)
137 | ((abr & 3) << 5) | (0u << 7));
138 setTexpage(TEX4_TX, TEX4_TY, 0);
139 rasterSetAbr(abr);
140 setTextureWindow(0, 0, 0, 0);
141 rasterTexTriSemi(TEX_MOD_NEUTRAL,
142 0, 0, 0, 0,
143 11, 0, 11, 0,
144 0, 8, 0, 8,
145 CLUT4_FIELD, tpage);
146 rasterFlushPrimitive();
147 rasterSetAbr(0);
148}
149
150// Semi-trans triangle with E6 SET-MASK enabled. Output should be the
151// blended value with bit-15 OR'd in.
152static void drawAbrTriSetMask(uint8_t b5, uint8_t f5, uint8_t abr) {
153 rasterReset();
154 fillR(0, 0, 32, 32, b5);
155 rasterSetAbr(abr);
156 rasterSetMaskCtrl(1, 0);
157 rasterFlatTriSemi(cmdR5(f5),
158 0, 0, 11, 0, 0, 11);
159 rasterFlushPrimitive();
160 rasterSetMaskCtrl(0, 0);
161 rasterSetAbr(0);
162}
163
164// Semi-trans triangle with E6 CHECK-MASK enabled. Background pre-fill
165// has bit-15 set so the check-mask SKIPS those pixels (no blend
166// applied, sentinel-ish stays).
167static void drawAbrTriCheckMask(uint8_t b5, uint8_t f5, uint8_t abr) {
168 rasterReset();
169 /* Pre-fill with bit-15 already set */
170 uint16_t bg = (uint16_t)(rasterVram555((uint8_t)(b5 & 0x1f), 0, 0) | 0x8000u);
171 rasterFillRect(0, 0, 32, 32, bg);
172 rasterSetAbr(abr);
173 rasterSetMaskCtrl(0, 1);
174 rasterFlatTriSemi(cmdR5(f5),
175 0, 0, 11, 0, 0, 11);
176 rasterFlushPrimitive();
177 rasterSetMaskCtrl(0, 0);
178 rasterSetAbr(0);
179}
180
181) // CESTER_BODY
182
183// ============================================================================
184// ABR_TRI: math sweep across the 4 modes and 9 (B, F) pairs.
185// All probes at (4, 4) - interior of the 12x12 semi-trans tri.
186// B, F values chosen on 5-bit boundaries: 0, 16, 31 (8-bit: 0, 128,
187// 248). 9 pairs cover (0,0), (0,16), (0,31), (16,0), (16,16),
188// (16,31), (31,0), (31,16), (31,31). Each pair tested in all 4 modes
189// = 36 tests.
190// ============================================================================
191
192CESTER_TEST(abr0_tri_b00_f00, gpu_raster_phase12, drawAbrTri(0, 0, 0); ASSERT_PIXEL_EQ(ABR0_B00_F00, 4, 4); )
193CESTER_TEST(abr0_tri_b00_f16, gpu_raster_phase12, drawAbrTri(0, 16, 0); ASSERT_PIXEL_EQ(ABR0_B00_F16, 4, 4); )
194CESTER_TEST(abr0_tri_b00_f31, gpu_raster_phase12, drawAbrTri(0, 31, 0); ASSERT_PIXEL_EQ(ABR0_B00_F31, 4, 4); )
195CESTER_TEST(abr0_tri_b16_f00, gpu_raster_phase12, drawAbrTri(16, 0, 0); ASSERT_PIXEL_EQ(ABR0_B16_F00, 4, 4); )
196CESTER_TEST(abr0_tri_b16_f16, gpu_raster_phase12, drawAbrTri(16, 16, 0); ASSERT_PIXEL_EQ(ABR0_B16_F16, 4, 4); )
197CESTER_TEST(abr0_tri_b16_f31, gpu_raster_phase12, drawAbrTri(16, 31, 0); ASSERT_PIXEL_EQ(ABR0_B16_F31, 4, 4); )
198CESTER_TEST(abr0_tri_b31_f00, gpu_raster_phase12, drawAbrTri(31, 0, 0); ASSERT_PIXEL_EQ(ABR0_B31_F00, 4, 4); )
199CESTER_TEST(abr0_tri_b31_f16, gpu_raster_phase12, drawAbrTri(31, 16, 0); ASSERT_PIXEL_EQ(ABR0_B31_F16, 4, 4); )
200CESTER_TEST(abr0_tri_b31_f31, gpu_raster_phase12, drawAbrTri(31, 31, 0); ASSERT_PIXEL_EQ(ABR0_B31_F31, 4, 4); )
201
202CESTER_TEST(abr1_tri_b00_f00, gpu_raster_phase12, drawAbrTri(0, 0, 1); ASSERT_PIXEL_EQ(ABR1_B00_F00, 4, 4); )
203CESTER_TEST(abr1_tri_b00_f16, gpu_raster_phase12, drawAbrTri(0, 16, 1); ASSERT_PIXEL_EQ(ABR1_B00_F16, 4, 4); )
204CESTER_TEST(abr1_tri_b00_f31, gpu_raster_phase12, drawAbrTri(0, 31, 1); ASSERT_PIXEL_EQ(ABR1_B00_F31, 4, 4); )
205CESTER_TEST(abr1_tri_b16_f00, gpu_raster_phase12, drawAbrTri(16, 0, 1); ASSERT_PIXEL_EQ(ABR1_B16_F00, 4, 4); )
206CESTER_TEST(abr1_tri_b16_f16, gpu_raster_phase12, drawAbrTri(16, 16, 1); ASSERT_PIXEL_EQ(ABR1_B16_F16, 4, 4); )
207CESTER_TEST(abr1_tri_b16_f31, gpu_raster_phase12, drawAbrTri(16, 31, 1); ASSERT_PIXEL_EQ(ABR1_B16_F31, 4, 4); )
208CESTER_TEST(abr1_tri_b31_f00, gpu_raster_phase12, drawAbrTri(31, 0, 1); ASSERT_PIXEL_EQ(ABR1_B31_F00, 4, 4); )
209CESTER_TEST(abr1_tri_b31_f16, gpu_raster_phase12, drawAbrTri(31, 16, 1); ASSERT_PIXEL_EQ(ABR1_B31_F16, 4, 4); )
210CESTER_TEST(abr1_tri_b31_f31, gpu_raster_phase12, drawAbrTri(31, 31, 1); ASSERT_PIXEL_EQ(ABR1_B31_F31, 4, 4); )
211
212CESTER_TEST(abr2_tri_b00_f00, gpu_raster_phase12, drawAbrTri(0, 0, 2); ASSERT_PIXEL_EQ(ABR2_B00_F00, 4, 4); )
213CESTER_TEST(abr2_tri_b00_f16, gpu_raster_phase12, drawAbrTri(0, 16, 2); ASSERT_PIXEL_EQ(ABR2_B00_F16, 4, 4); )
214CESTER_TEST(abr2_tri_b00_f31, gpu_raster_phase12, drawAbrTri(0, 31, 2); ASSERT_PIXEL_EQ(ABR2_B00_F31, 4, 4); )
215CESTER_TEST(abr2_tri_b16_f00, gpu_raster_phase12, drawAbrTri(16, 0, 2); ASSERT_PIXEL_EQ(ABR2_B16_F00, 4, 4); )
216CESTER_TEST(abr2_tri_b16_f16, gpu_raster_phase12, drawAbrTri(16, 16, 2); ASSERT_PIXEL_EQ(ABR2_B16_F16, 4, 4); )
217CESTER_TEST(abr2_tri_b16_f31, gpu_raster_phase12, drawAbrTri(16, 31, 2); ASSERT_PIXEL_EQ(ABR2_B16_F31, 4, 4); )
218CESTER_TEST(abr2_tri_b31_f00, gpu_raster_phase12, drawAbrTri(31, 0, 2); ASSERT_PIXEL_EQ(ABR2_B31_F00, 4, 4); )
219CESTER_TEST(abr2_tri_b31_f16, gpu_raster_phase12, drawAbrTri(31, 16, 2); ASSERT_PIXEL_EQ(ABR2_B31_F16, 4, 4); )
220CESTER_TEST(abr2_tri_b31_f31, gpu_raster_phase12, drawAbrTri(31, 31, 2); ASSERT_PIXEL_EQ(ABR2_B31_F31, 4, 4); )
221
222CESTER_TEST(abr3_tri_b00_f00, gpu_raster_phase12, drawAbrTri(0, 0, 3); ASSERT_PIXEL_EQ(ABR3_B00_F00, 4, 4); )
223CESTER_TEST(abr3_tri_b00_f16, gpu_raster_phase12, drawAbrTri(0, 16, 3); ASSERT_PIXEL_EQ(ABR3_B00_F16, 4, 4); )
224CESTER_TEST(abr3_tri_b00_f31, gpu_raster_phase12, drawAbrTri(0, 31, 3); ASSERT_PIXEL_EQ(ABR3_B00_F31, 4, 4); )
225CESTER_TEST(abr3_tri_b16_f00, gpu_raster_phase12, drawAbrTri(16, 0, 3); ASSERT_PIXEL_EQ(ABR3_B16_F00, 4, 4); )
226CESTER_TEST(abr3_tri_b16_f16, gpu_raster_phase12, drawAbrTri(16, 16, 3); ASSERT_PIXEL_EQ(ABR3_B16_F16, 4, 4); )
227CESTER_TEST(abr3_tri_b16_f31, gpu_raster_phase12, drawAbrTri(16, 31, 3); ASSERT_PIXEL_EQ(ABR3_B16_F31, 4, 4); )
228CESTER_TEST(abr3_tri_b31_f00, gpu_raster_phase12, drawAbrTri(31, 0, 3); ASSERT_PIXEL_EQ(ABR3_B31_F00, 4, 4); )
229CESTER_TEST(abr3_tri_b31_f16, gpu_raster_phase12, drawAbrTri(31, 16, 3); ASSERT_PIXEL_EQ(ABR3_B31_F16, 4, 4); )
230CESTER_TEST(abr3_tri_b31_f31, gpu_raster_phase12, drawAbrTri(31, 31, 3); ASSERT_PIXEL_EQ(ABR3_B31_F31, 4, 4); )
231
232// ============================================================================
233// ABR_PRIM: same blend math across other untextured primitive types.
234// Single representative (B=16, F=16) per ABR mode for each primitive.
235// Confirms primitives share blend math.
236// ============================================================================
237
238CESTER_TEST(abr0_quad_b16_f16, gpu_raster_phase12, drawAbrQuad(16, 16, 0); ASSERT_PIXEL_EQ(ABR0_PRIM_QUAD, 4, 4); )
239CESTER_TEST(abr1_quad_b16_f16, gpu_raster_phase12, drawAbrQuad(16, 16, 1); ASSERT_PIXEL_EQ(ABR1_PRIM_QUAD, 4, 4); )
240CESTER_TEST(abr2_quad_b16_f16, gpu_raster_phase12, drawAbrQuad(16, 16, 2); ASSERT_PIXEL_EQ(ABR2_PRIM_QUAD, 4, 4); )
241CESTER_TEST(abr3_quad_b16_f16, gpu_raster_phase12, drawAbrQuad(16, 16, 3); ASSERT_PIXEL_EQ(ABR3_PRIM_QUAD, 4, 4); )
242
243CESTER_TEST(abr0_rect_b16_f16, gpu_raster_phase12, drawAbrRect(16, 16, 0); ASSERT_PIXEL_EQ(ABR0_PRIM_RECT, 4, 4); )
244CESTER_TEST(abr1_rect_b16_f16, gpu_raster_phase12, drawAbrRect(16, 16, 1); ASSERT_PIXEL_EQ(ABR1_PRIM_RECT, 4, 4); )
245CESTER_TEST(abr2_rect_b16_f16, gpu_raster_phase12, drawAbrRect(16, 16, 2); ASSERT_PIXEL_EQ(ABR2_PRIM_RECT, 4, 4); )
246CESTER_TEST(abr3_rect_b16_f16, gpu_raster_phase12, drawAbrRect(16, 16, 3); ASSERT_PIXEL_EQ(ABR3_PRIM_RECT, 4, 4); )
247
248CESTER_TEST(abr0_line_b16_f16, gpu_raster_phase12, drawAbrLine(16, 16, 0); ASSERT_PIXEL_EQ(ABR0_PRIM_LINE, 5, 4); )
249CESTER_TEST(abr1_line_b16_f16, gpu_raster_phase12, drawAbrLine(16, 16, 1); ASSERT_PIXEL_EQ(ABR1_PRIM_LINE, 5, 4); )
250CESTER_TEST(abr2_line_b16_f16, gpu_raster_phase12, drawAbrLine(16, 16, 2); ASSERT_PIXEL_EQ(ABR2_PRIM_LINE, 5, 4); )
251CESTER_TEST(abr3_line_b16_f16, gpu_raster_phase12, drawAbrLine(16, 16, 3); ASSERT_PIXEL_EQ(ABR3_PRIM_LINE, 5, 4); )
252
253// ============================================================================
254// ABR_TEX_MASKED: textured semi-trans tri at 4-bit with masked CLUT.
255// CLUT entry [4] has bit-15 set so the semi-trans gate fires. Probe
256// (4, 2) which samples texel u=4, CLUT[4] = vram555(4, 27, 0)|0x8000.
257// Then blend formula applies. Capture for all 4 ABR modes.
258// ============================================================================
259
260CESTER_TEST(abr0_tex_masked_b16, gpu_raster_phase12, drawAbrTexTriMasked(16, 0); ASSERT_PIXEL_EQ(ABR0_TEX_MASKED, 4, 2); )
261CESTER_TEST(abr1_tex_masked_b16, gpu_raster_phase12, drawAbrTexTriMasked(16, 1); ASSERT_PIXEL_EQ(ABR1_TEX_MASKED, 4, 2); )
262CESTER_TEST(abr2_tex_masked_b16, gpu_raster_phase12, drawAbrTexTriMasked(16, 2); ASSERT_PIXEL_EQ(ABR2_TEX_MASKED, 4, 2); )
263CESTER_TEST(abr3_tex_masked_b16, gpu_raster_phase12, drawAbrTexTriMasked(16, 3); ASSERT_PIXEL_EQ(ABR3_TEX_MASKED, 4, 2); )
264
265// ============================================================================
266// ABR_MASKBIT: set-mask and check-mask interactions.
267// Set-mask: output should be blended value with bit-15 forced to 1.
268// Check-mask: pre-fill has bit-15 set, so writes are SKIPPED - read
269// returns the pre-fill value unchanged.
270// ============================================================================
271
272CESTER_TEST(abr0_setmask_b16_f16, gpu_raster_phase12, drawAbrTriSetMask(16, 16, 0); ASSERT_PIXEL_EQ(ABR0_SETMASK, 4, 4); )
273CESTER_TEST(abr1_setmask_b16_f16, gpu_raster_phase12, drawAbrTriSetMask(16, 16, 1); ASSERT_PIXEL_EQ(ABR1_SETMASK, 4, 4); )
274CESTER_TEST(abr2_setmask_b16_f16, gpu_raster_phase12, drawAbrTriSetMask(16, 16, 2); ASSERT_PIXEL_EQ(ABR2_SETMASK, 4, 4); )
275CESTER_TEST(abr3_setmask_b16_f16, gpu_raster_phase12, drawAbrTriSetMask(16, 16, 3); ASSERT_PIXEL_EQ(ABR3_SETMASK, 4, 4); )
276CESTER_TEST(abr1_setmask_b16_f0, gpu_raster_phase12, drawAbrTriSetMask(16, 0, 1); ASSERT_PIXEL_EQ(ABR1_SETMASK_F0, 4, 4); )
277CESTER_TEST(abr1_nomask_b16_f0, gpu_raster_phase12, drawAbrTri(16, 0, 1); ASSERT_PIXEL_EQ(ABR1_NOMASK_F0, 4, 4); )
278
279CESTER_TEST(abr0_checkmask_b16_f16, gpu_raster_phase12, drawAbrTriCheckMask(16, 16, 0); ASSERT_PIXEL_EQ(ABR0_CHECKMASK, 4, 4); )
280CESTER_TEST(abr1_checkmask_b16_f16, gpu_raster_phase12, drawAbrTriCheckMask(16, 16, 1); ASSERT_PIXEL_EQ(ABR1_CHECKMASK, 4, 4); )
281CESTER_TEST(abr2_checkmask_b16_f16, gpu_raster_phase12, drawAbrTriCheckMask(16, 16, 2); ASSERT_PIXEL_EQ(ABR2_CHECKMASK, 4, 4); )
282CESTER_TEST(abr3_checkmask_b16_f16, gpu_raster_phase12, drawAbrTriCheckMask(16, 16, 3); ASSERT_PIXEL_EQ(ABR3_CHECKMASK, 4, 4); )
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 GPU_DATA
Definition hwregs.h:52
volatile void * u0
Definition load-timings.c:875
volatile void * u1
Definition load-timings.c:876
#define ABR0_PRIM_LINE
Definition raster-expected-phase12.h:118
#define ABR3_B16_F31
Definition raster-expected-phase12.h:99
#define ABR1_B16_F16
Definition raster-expected-phase12.h:70
#define ABR2_TEX_MASKED
Definition raster-expected-phase12.h:153
#define ABR0_B16_F31
Definition raster-expected-phase12.h:57
#define ABR1_NOMASK_F0
Definition raster-expected-phase12.h:170
#define ABR3_SETMASK
Definition raster-expected-phase12.h:164
#define ABR1_B16_F00
Definition raster-expected-phase12.h:69
#define ABR3_PRIM_LINE
Definition raster-expected-phase12.h:121
#define ABR0_PRIM_QUAD
Definition raster-expected-phase12.h:108
#define ABR2_B00_F00
Definition raster-expected-phase12.h:80
#define ABR2_B00_F31
Definition raster-expected-phase12.h:82
#define ABR1_SETMASK
Definition raster-expected-phase12.h:162
#define ABR0_B00_F16
Definition raster-expected-phase12.h:53
#define ABR0_B16_F16
Definition raster-expected-phase12.h:56
#define ABR0_B31_F31
Definition raster-expected-phase12.h:60
#define ABR1_B16_F31
Definition raster-expected-phase12.h:71
#define ABR1_B00_F00
Definition raster-expected-phase12.h:66
#define ABR0_B16_F00
Definition raster-expected-phase12.h:55
#define ABR3_CHECKMASK
Definition raster-expected-phase12.h:180
#define ABR1_PRIM_LINE
Definition raster-expected-phase12.h:119
#define ABR2_PRIM_LINE
Definition raster-expected-phase12.h:120
#define ABR1_B31_F31
Definition raster-expected-phase12.h:74
#define ABR3_TEX_MASKED
Definition raster-expected-phase12.h:154
#define ABR0_B31_F16
Definition raster-expected-phase12.h:59
#define ABR3_B16_F16
Definition raster-expected-phase12.h:98
#define ABR2_B31_F16
Definition raster-expected-phase12.h:87
#define ABR0_PRIM_RECT
Definition raster-expected-phase12.h:113
#define ABR3_B00_F00
Definition raster-expected-phase12.h:94
#define ABR3_B31_F31
Definition raster-expected-phase12.h:102
#define ABR2_B16_F31
Definition raster-expected-phase12.h:85
#define ABR3_B00_F16
Definition raster-expected-phase12.h:95
#define ABR2_B31_F31
Definition raster-expected-phase12.h:88
#define ABR3_B31_F16
Definition raster-expected-phase12.h:101
#define ABR0_B00_F00
Definition raster-expected-phase12.h:52
#define ABR2_CHECKMASK
Definition raster-expected-phase12.h:179
#define ABR1_B00_F16
Definition raster-expected-phase12.h:67
#define ABR0_B00_F31
Definition raster-expected-phase12.h:54
#define ABR1_PRIM_QUAD
Definition raster-expected-phase12.h:109
#define ABR3_PRIM_RECT
Definition raster-expected-phase12.h:116
#define ABR0_CHECKMASK
Definition raster-expected-phase12.h:177
#define ABR2_B16_F00
Definition raster-expected-phase12.h:83
#define ABR2_B00_F16
Definition raster-expected-phase12.h:81
#define ABR2_B31_F00
Definition raster-expected-phase12.h:86
#define ABR2_B16_F16
Definition raster-expected-phase12.h:84
#define ABR3_B31_F00
Definition raster-expected-phase12.h:100
#define ABR3_B16_F00
Definition raster-expected-phase12.h:97
#define ABR1_B31_F16
Definition raster-expected-phase12.h:73
#define ABR1_CHECKMASK
Definition raster-expected-phase12.h:178
#define ABR1_B00_F31
Definition raster-expected-phase12.h:68
#define ABR2_PRIM_QUAD
Definition raster-expected-phase12.h:110
#define ABR0_B31_F00
Definition raster-expected-phase12.h:58
#define ABR0_SETMASK
Definition raster-expected-phase12.h:161
#define ABR2_SETMASK
Definition raster-expected-phase12.h:163
#define ABR1_SETMASK_F0
Definition raster-expected-phase12.h:169
#define ABR1_PRIM_RECT
Definition raster-expected-phase12.h:114
#define ABR3_PRIM_QUAD
Definition raster-expected-phase12.h:111
#define ABR3_B00_F31
Definition raster-expected-phase12.h:96
#define ABR1_TEX_MASKED
Definition raster-expected-phase12.h:152
#define ABR0_TEX_MASKED
Definition raster-expected-phase12.h:151
#define ABR2_PRIM_RECT
Definition raster-expected-phase12.h:115
#define ABR1_B31_F00
Definition raster-expected-phase12.h:72
#define ASSERT_PIXEL_EQ(expected, x_, y_)
Definition raster-helpers.h:473
#define CLUT4_FIELD
Definition texture-fixtures.h:83
#define TEX_MOD_NEUTRAL
Definition texture-fixtures.h:308
#define TEX4_TY
Definition texture-fixtures.h:56
#define TEX4_TX
Definition texture-fixtures.h:55
uint16_t v2
Definition timers.c:262
uint16_t v1
Definition timers.c:260