Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
gte-mvmva.c
Go to the documentation of this file.
1// MVMVA: parameterized matrix-vector multiply and add
2
3// mx=RT, v=V0, cv=TR (standard transform)
4// clang-format off
5
6CESTER_TEST(mvmva_rt_v0_tr, gte_tests,
7 // 90-degree Z rotation
8 cop2_putc(0, 0xf0000000); // R11=0, R12=-0x1000
9 cop2_putc(1, 0x10000000); // R13=0, R21=0x1000
10 cop2_putc(2, 0x00000000);
11 cop2_putc(3, 0x00000000);
12 cop2_putc(4, 0x1000);
13 gte_set_translation(10, 20, 30);
14 cop2_put(0, (200 << 16) | 100);
15 cop2_put(1, 300);
17 cop2_cmd(COP2_MVMVA(1, 0, 0, 0, 0));
18 int32_t mac1, mac2, mac3;
19 cop2_get(25, mac1);
20 cop2_get(26, mac2);
21 cop2_get(27, mac3);
25)
26
27// mx=RT, v=V1, cv=Zero
28CESTER_TEST(mvmva_rt_v1_zero, gte_tests,
30 cop2_put(2, (40 << 16) | 30); // V1 = (30, 40)
31 cop2_put(3, 50); // V1.Z = 50
33 cop2_cmd(COP2_MVMVA(1, 0, 1, 3, 0));
34 int32_t mac1, mac2, mac3;
41)
42
43// mx=RT, v=V2, cv=BK
44CESTER_TEST(mvmva_rt_v2_bk, gte_tests,
46 cop2_putc(13, 1000); // RBK
47 cop2_putc(14, 2000); // GBK
48 cop2_putc(15, 3000); // BBK
49 cop2_put(4, (200 << 16) | 100); // V2
50 cop2_put(5, 300);
52 cop2_cmd(COP2_MVMVA(1, 0, 2, 1, 0));
53 int32_t mac1, mac2, mac3;
54 cop2_get(25, mac1);
55 cop2_get(26, mac2);
56 cop2_get(27, mac3);
60)
61
62// mx=RT, v=IR, cv=Zero
63CESTER_TEST(mvmva_rt_ir_zero, gte_tests,
65 cop2_put(9, 500);
66 cop2_put(10, 600);
67 cop2_put(11, 700);
69 cop2_cmd(COP2_MVMVA(1, 0, 3, 3, 0));
70 int32_t mac1, mac2, mac3;
71 cop2_get(25, mac1);
72 cop2_get(26, mac2);
73 cop2_get(27, mac3);
77)
78
79// mx=LL (light matrix), v=V0, cv=Zero
80CESTER_TEST(mvmva_ll_v0_zero, gte_tests,
81 gte_set_simple_light(); // L33=0x1000, rest zero
82 cop2_put(0, (200 << 16) | 100);
83 cop2_put(1, 0x1000);
85 cop2_cmd(COP2_MVMVA(1, 1, 0, 3, 0));
86 int32_t mac1, mac2, mac3;
87 cop2_get(25, mac1);
88 cop2_get(26, mac2);
89 cop2_get(27, mac3);
90 // Only L33 is non-zero, so MAC3 = L33*VZ0 >> 12 = 0x1000 * 0x1000 >> 12 = 0x1000
94)
95
96// mx=LC (light color), v=IR, cv=BK
97CESTER_TEST(mvmva_lc_ir_bk, gte_tests,
99 cop2_putc(13, 100); // RBK
100 cop2_putc(14, 200); // GBK
101 cop2_putc(15, 300); // BBK
102 cop2_put(9, 0x1000);
103 cop2_put(10, 0x1000);
104 cop2_put(11, 0x1000);
106 cop2_cmd(COP2_MVMVA(1, 2, 3, 1, 0));
107 int32_t mac1, mac2, mac3;
108 cop2_get(25, mac1);
109 cop2_get(26, mac2);
110 cop2_get(27, mac3);
111 // White LC identity: MAC = (BK<<12 + LR1*IR1) >> 12 = BK + IR
112 // BK = (100, 200, 300), IR = (0x1000, 0x1000, 0x1000) = (4096, 4096, 4096)
113 // MAC1 = 100 + 4096 = 4196, etc.
117)
118
119// cv=2 (far color) bug
120CESTER_TEST(mvmva_cv2_fc_bug, gte_tests,
122 gte_set_far_color(0x1000, 0x2000, 0x3000);
123 cop2_put(0, (0x200 << 16) | 0x100);
124 cop2_put(1, 0x300);
126 cop2_cmd(COP2_MVMVA(1, 0, 0, 2, 0));
127 int32_t mac1, mac2, mac3;
128 uint32_t flag;
129 cop2_get(25, mac1);
130 cop2_get(26, mac2);
131 cop2_get(27, mac3);
132 flag = gte_read_flag();
133 // Buggy: result is partial - only last column (R13*VZ, R23*VZ, R33*VZ)
134 // With identity: R13=0, R23=0, R33=0x1000
135 // MAC1 = R13*VZ >> 12 = 0
136 // MAC2 = R23*VZ >> 12 = 0 (but VY contribution leaks? Let's check)
137 // MAC3 = R33*VZ >> 12 = 0x300
138 ramsyscall_printf("MVMVA cv=2: MAC=(%d,%d,%d) FLAG=0x%08x\n", mac1, mac2, mac3, flag);
142 cester_assert_uint_eq(0x00000000, flag);
143)
144
145// mx=3 (garbage matrix)
146CESTER_TEST(mvmva_mx3_garbage, gte_tests,
147 cop2_putc(0, 0x20001000); // R11=0x1000, R12=0x2000
148 cop2_putc(1, 0x40003000); // R13=0x3000, R21=0x4000
149 cop2_putc(2, 0x60005000); // R22=0x5000, R23=0x6000
150 cop2_putc(3, 0x80007000); // R31=0x7000, R32=-0x8000
151 cop2_putc(4, 0x1000);
152 cop2_put(8, 0x0800); // IR0
153 cop2_put(0, (0x100 << 16) | 0x100);
154 cop2_put(1, 0x100);
156 cop2_cmd(COP2_MVMVA(1, 3, 0, 3, 0));
157 int32_t mac1, mac2, mac3;
158 uint32_t flag;
159 cop2_get(25, mac1);
160 cop2_get(26, mac2);
161 cop2_get(27, mac3);
162 flag = gte_read_flag();
163 ramsyscall_printf("MVMVA mx=3: MAC=(%d,%d,%d) FLAG=0x%08x\n", mac1, mac2, mac3, flag);
168)
169
170// MVMVA with lm=1
171CESTER_TEST(mvmva_lm1, gte_tests,
173 gte_set_translation(-500, -600, -700);
174 cop2_put(0, (100 << 16) | 100);
175 cop2_put(1, 100);
177 // sf=1, mx=RT, v=V0, cv=TR, lm=1
178 cop2_cmd(COP2_MVMVA(1, 0, 0, 0, 1));
179 int32_t mac1;
180 uint32_t ir1;
181 cop2_get(25, mac1);
182 cop2_get(9, ir1);
183 // MAC1 = 100 + (-500) = -400
185 // IR1 with lm=1: clamped to [0, 0x7fff], so -400 -> 0
187)
188
189// MVMVA sf=0 (no shift)
190CESTER_TEST(mvmva_sf0, gte_tests,
192 gte_set_translation(0, 0, 0);
193 cop2_put(0, (10 << 16) | 10);
194 cop2_put(1, 10);
196 cop2_cmd(COP2_MVMVA(0, 0, 0, 3, 0));
197 int32_t mac1, mac2, mac3;
198 cop2_get(25, mac1);
199 cop2_get(26, mac2);
200 cop2_get(27, mac3);
201 // sf=0: no >>12 shift. MAC = R * V = 0x1000 * 10 = 40960
205)
#define cop2_cmd(op)
Definition cop2.h:175
#define cop2_put(reg, val)
Definition cop2.h:191
#define cop2_putc(reg, val)
Definition cop2.h:205
#define COP2_MVMVA(sf, mx, v, cv, lm)
Definition cop2.h:145
#define cop2_get(reg, dest)
Definition cop2.h:198
gte_set_far_color(0xff00, 0xff00, 0xff00)
uint32_t ir1
Definition gte-edgecase.c:110
gte_set_translation(0, 0, 0)
gte_set_simple_light()
int32_t mac1
Definition gte-mvmva.c:34
gte_set_identity_rotation()
gte_set_white_light_color()
cester_assert_int_eq(30, mac1)
ramsyscall_printf("MVMVA mx=3: MAC=(%d,%d,%d) FLAG=0x%08x\n", mac1, mac2, mac3, flag)
gte_tests
Definition gte-mvmva.c:28
CESTER_TEST(mvmva_rt_v0_tr, gte_tests, cop2_putc(0, 0xf0000000);cop2_putc(1, 0x10000000);cop2_putc(2, 0x00000000);cop2_putc(3, 0x00000000);cop2_putc(4, 0x1000);gte_set_translation(10, 20, 30);cop2_put(0,(200<< 16)|100);cop2_put(1, 300);gte_clear_flag();cop2_cmd(COP2_MVMVA(1, 0, 0, 0, 0));int32_t mac1, mac2, mac3;cop2_get(25, mac1);cop2_get(26, mac2);cop2_get(27, mac3);cester_assert_int_eq(-190, mac1);cester_assert_int_eq(120, mac2);cester_assert_int_eq(330, mac3);) CESTER_TEST(mvmva_rt_v1_zero
uint32_t flag
Definition gte-mvmva.c:158
cester_assert_uint_eq(0x00000000, flag)
int32_t mac2
Definition gte-mvmva.c:34
gte_clear_flag()
int32_t mac3
Definition gte-mvmva.c:34