Nugget
Loading...
Searching...
No Matches
gte-rtps.c
Go to the documentation of this file.
1// RTPS/RTPT: perspective transformation (single and triple)
2// Also covers division table behavior and screen coordinate saturation.
3
4CESTER_TEST(rtps_identity_center, gte_tests,
6 gte_set_translation(0, 0, 1000);
7 gte_set_screen(160 << 16, 120 << 16, 200);
8 cop2_put(0, 0x00000000); // V0 = (0, 0)
9 cop2_put(1, 0); // VZ0 = 0
11 cop2_cmd(COP2_RTPS(1, 0));
13 cop2_get(19, sz3);
14 cop2_get(14, sxy2);
16 cester_assert_int_eq(160, (int16_t)(sxy2 & 0xffff));
17 cester_assert_int_eq(120, (int16_t)(sxy2 >> 16));
18)
19
20CESTER_TEST(rtps_offset_vertex, gte_tests,
23 gte_set_screen(160 << 16, 120 << 16, 200);
24 cop2_put(0, (50 << 16) | (100 & 0xffff));
25 cop2_put(1, 500);
31 // SX = 160 + 100*200/500 = 160 + 40 ~ 199 (division rounding)
32 // SY = 120 + 50*200/500 = 120 + 20 ~ 139
35 int16_t sx = (int16_t)(sxy2 & 0xffff);
36 int16_t sy = (int16_t)(sxy2 >> 16);
37 ramsyscall_printf("RTPS offset: SX=%d SY=%d\n", sx, sy);
41)
42
43// RTPS MAC output
44CESTER_TEST(rtps_mac_output, gte_tests,
46 gte_set_translation(100, 200, 300);
47 gte_set_screen(0, 0, 200);
48 cop2_put(0, (50 << 16) | 10); // V0 = (10, 50)
49 cop2_put(1, 500);
51 cop2_cmd(COP2_RTPS(1, 0));
52 int32_t mac1, mac2, mac3;
53 cop2_get(25, mac1);
54 cop2_get(26, mac2);
55 cop2_get(27, mac3);
56 // Identity rotation: MAC = V + TR
60)
61
62// RTPS with Z=0 (division overflow)
63CESTER_TEST(rtps_division_overflow, gte_tests,
65 gte_set_translation(0, 0, 0);
66 gte_set_screen(0, 0, 200);
67 cop2_put(0, (0 << 16) | 100);
68 cop2_put(1, 1); // VZ0 = 1, very small Z
70 cop2_cmd(COP2_RTPS(1, 0));
72 flag = gte_read_flag();
73 // H=200, SZ3=1 -> H >= SZ3*2 (200 >= 2) -> division overflow FLAG.17
74 ramsyscall_printf("RTPS div overflow: FLAG=0x%08x (bit17=%u)\n", flag, (flag >> 17) & 1);
75 uint32_t flag17 = (flag >> 17) & 1;
77)
78
79// RTPS screen coordinate saturation
80CESTER_TEST(rtps_screen_saturation, gte_tests,
82 gte_set_translation(0, 0, 0);
83 gte_set_screen(0, 0, 200);
84 // Large X, small Z -> SX will exceed -0x400..0x3FF range
85 cop2_put(0, (0 << 16) | 0x7fff); // VX0 = 32767
86 cop2_put(1, 100); // VZ0 = 100
88 cop2_cmd(COP2_RTPS(1, 0));
90 cop2_get(14, sxy2);
91 flag = gte_read_flag();
92 int16_t sx = (int16_t)(sxy2 & 0xffff);
93 ramsyscall_printf("RTPS sat: SX=%d FLAG=0x%08x (bit14=%u)\n", sx, flag, (flag >> 14) & 1);
94 // SX should be saturated to 0x3FF
96 uint32_t flag14 = (flag >> 14) & 1;
97 cester_assert_uint_eq(1, flag14); // FLAG.14 = SX2 saturated
98)
99
100// RTPS depth cue output (MAC0/IR0)
101CESTER_TEST(rtps_depth_cue, gte_tests,
103 gte_set_translation(0, 0, 0);
104 cop2_putc(24, 0);
105 cop2_putc(25, 0);
106 cop2_putc(26, 200);
107 cop2_putc(27, 0xfffff880); // DQA = -1920 (negative)
108 cop2_putc(28, 0x01000000); // DQB = 16777216
109 cop2_put(0, 0x00000000);
110 cop2_put(1, 1000);
112 cop2_cmd(COP2_RTPS(1, 0));
113 int32_t mac0;
117 ramsyscall_printf("RTPS depth: MAC0=%d IR0=0x%04x\n", mac0, ir0 & 0xffff);
118 // IR0 should be clamped to [0, 0x1000]
121)
122
123// RTPS with sf=0
126 gte_set_translation(0, 0, 0x1000);
127 gte_set_screen(0, 0, 200);
128 cop2_put(0, 0x00000000);
129 cop2_put(1, 0);
131 cop2_cmd(COP2_RTPS(0, 0));
132 int32_t mac3;
134 cop2_get(27, mac3);
135 cop2_get(11, ir3);
136 cop2_get(19, sz3);
137 flag = gte_read_flag();
138 ramsyscall_printf("RTPS sf=0: MAC3=%d IR3=0x%04x SZ3=%u FLAG=0x%08x\n",
139 mac3, ir3 & 0xffff, sz3, flag);
140 // sf=0: MAC3 = TRZ<<12 + rotation = 0x1000<<12 = 0x1000000 (no >>12 shift)
141 // IR3 uses Lm_B3_sf which checks MAC3>>12 for FLAG but clamps the unshifted value
142 cester_assert_int_eq(16777216, mac3);
143 cester_assert_uint_eq(0x7fff, ir3);
146)
147
148// RTPT: triple perspective transform
149CESTER_TEST(rtpt_three_vertices, gte_tests,
151 gte_set_translation(0, 0, 0);
152 gte_set_screen(160 << 16, 120 << 16, 200);
153 // V0 = (0, 0, 1000)
154 cop2_put(0, 0x00000000);
155 cop2_put(1, 1000);
156 // V1 = (100, 0, 1000)
157 cop2_put(2, (0 << 16) | 100);
158 cop2_put(3, 1000);
159 // V2 = (0, 100, 1000)
160 cop2_put(4, (100 << 16) | 0);
161 cop2_put(5, 1000);
167 cop2_get(14, sxy2);
168 // V0 at origin -> (160, 120)
169 cester_assert_int_eq(160, (int16_t)(sxy0 & 0xffff));
170 cester_assert_int_eq(120, (int16_t)(sxy0 >> 16));
171 // V1 at (100,0,1000) -> SX ~ 180
172 int16_t sx1 = (int16_t)(sxy1 & 0xffff);
173 int16_t sy1 = (int16_t)(sxy1 >> 16);
174 ramsyscall_printf("RTPT: V1=(%d,%d) V2=(%d,%d)\n", sx1, sy1,
175 (int16_t)(sxy2 & 0xffff), (int16_t)(sxy2 >> 16));
176 cester_assert_int_eq(120, sy1); // Y unchanged
177)
178
179// RTPT: FLAG accumulates across all three vertices
180CESTER_TEST(rtpt_flag_accumulates, gte_tests,
182 gte_set_translation(0, 0, 0);
183 gte_set_screen(0, 0, 200);
184 // V0: normal
185 cop2_put(0, 0x00000000);
186 cop2_put(1, 1000);
187 // V1: will cause SX saturation (large X, small Z)
188 cop2_put(2, (0 << 16) | 0x7fff);
189 cop2_put(3, 100);
190 // V2: normal
191 cop2_put(4, 0x00000000);
192 cop2_put(5, 1000);
194 cop2_cmd(COP2_RTPT(1, 0));
196 flag = gte_read_flag();
197 // FLAG should have SX2 saturation from V1, even though V2 was fine
198 ramsyscall_printf("RTPT flag accum: FLAG=0x%08x\n", flag);
199 // Division overflow from V1 (H=200, SZ3=100, 200 >= 200)
200 uint32_t flag17 = (flag >> 17) & 1;
202)
203
204// RTPT pushes SZ FIFO correctly
205CESTER_TEST(rtpt_sz_fifo, gte_tests,
207 gte_set_translation(0, 0, 0);
208 gte_set_screen(160 << 16, 120 << 16, 200);
209 cop2_put(0, 0x00000000);
210 cop2_put(1, 100);
211 cop2_put(2, 0x00000000);
212 cop2_put(3, 200);
213 cop2_put(4, 0x00000000);
214 cop2_put(5, 300);
216 cop2_cmd(COP2_RTPT(1, 0));
220 cop2_get(19, sz3);
224)
#define cop2_cmd(op)
Definition cop2.h:175
#define cop2_put(reg, val)
Definition cop2.h:182
#define COP2_RTPT(sf, lm)
Definition cop2.h:130
#define cop2_putc(reg, val)
Definition cop2.h:196
#define COP2_RTPS(sf, lm)
Definition cop2.h:129
#define cop2_get(reg, dest)
Definition cop2.h:189
int32_t mac1
Definition gte-depthcue.c:116
int32_t mac2
Definition gte-depthcue.c:116
int32_t mac3
Definition gte-depthcue.c:116
uint32_t ir3
Definition gte-precision.c:320
gte_set_identity_rotation()
uint32_t sz3
Definition gte-rtps.c:28
uint32_t sxy2
Definition gte-rtps.c:33
int16_t sy1
Definition gte-rtps.c:173
gte_tests
Definition gte-rtps.c:20
uint32_t flag
Definition gte-rtps.c:71
int16_t sx
Definition gte-rtps.c:35
uint32_t sxy0
Definition gte-rtps.c:164
uint32_t flag17
Definition gte-rtps.c:75
uint32_t sz1
Definition gte-rtps.c:217
gte_set_translation(0, 0, 0)
CESTER_TEST(rtps_identity_center, gte_tests, gte_set_identity_rotation();gte_set_translation(0, 0, 1000);gte_set_screen(160<< 16, 120<< 16, 200);cop2_put(0, 0x00000000);cop2_put(1, 0);gte_clear_flag();cop2_cmd(COP2_RTPS(1, 0));uint32_t sz3, sxy2;cop2_get(19, sz3);cop2_get(14, sxy2);cester_assert_uint_eq(1000, sz3);cester_assert_int_eq(160,(int16_t)(sxy2 &0xffff));cester_assert_int_eq(120,(int16_t)(sxy2 > > 16));) CESTER_TEST(rtps_offset_vertex
cester_assert_int_eq(199, sx)
uint32_t sz2
Definition gte-rtps.c:217
gte_set_screen(160<< 16, 120<< 16, 200)
uint32_t sxy1
Definition gte-rtps.c:164
gte_clear_flag()
uint32_t ir0
Definition gte-rtps.c:114
int16_t sy
Definition gte-rtps.c:36
int16_t sx1
Definition gte-rtps.c:172
ramsyscall_printf("RTPS offset: SX=%d SY=%d\n", sx, sy)
cester_assert_uint_eq(500, sz3)
int32_t mac0
Definition gte-rtps.c:113
void uint32_t(classId, spec)