86aad47b |
1 | /*************************************************************************** |
2 | * Copyright (C) 2010 PCSX4ALL Team * |
3 | * Copyright (C) 2010 Unai * |
030d1121 |
4 | * Copyright (C) 2016 Senquack (dansilsby <AT> gmail <DOT> com) * |
86aad47b |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License, or * |
9 | * (at your option) any later version. * |
10 | * * |
11 | * This program is distributed in the hope that it will be useful, * |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
14 | * GNU General Public License for more details. * |
15 | * * |
16 | * You should have received a copy of the GNU General Public License * |
17 | * along with this program; if not, write to the * |
18 | * Free Software Foundation, Inc., * |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * |
20 | ***************************************************************************/ |
21 | |
908e426c |
22 | #ifndef __GPU_UNAI_GPU_COMMAND_H__ |
23 | #define __GPU_UNAI_GPU_COMMAND_H__ |
24 | |
86aad47b |
25 | /////////////////////////////////////////////////////////////////////////////// |
030d1121 |
26 | void gpuSetTexture(u16 tpage) |
86aad47b |
27 | { |
030d1121 |
28 | u32 tmode, tx, ty; |
29 | gpu_unai.GPU_GP1 = (gpu_unai.GPU_GP1 & ~0x1FF) | (tpage & 0x1FF); |
30 | gpu_unai.TextureWindow[0]&= ~gpu_unai.TextureWindow[2]; |
31 | gpu_unai.TextureWindow[1]&= ~gpu_unai.TextureWindow[3]; |
86aad47b |
32 | |
030d1121 |
33 | tmode = (tpage >> 7) & 3; // 16bpp, 8bpp, or 4bpp texture colors? |
34 | // 0: 4bpp 1: 8bpp 2/3: 16bpp |
35 | |
36 | // Nocash PSX docs state setting of 3 is same as setting of 2 (16bpp): |
37 | // Note: DrHell assumes 3 is same as 0.. TODO: verify which is correct? |
38 | if (tmode == 3) tmode = 2; |
86aad47b |
39 | |
86aad47b |
40 | tx = (tpage & 0x0F) << 6; |
41 | ty = (tpage & 0x10) << 4; |
42 | |
030d1121 |
43 | tx += (gpu_unai.TextureWindow[0] >> (2 - tmode)); |
44 | ty += gpu_unai.TextureWindow[1]; |
86aad47b |
45 | |
030d1121 |
46 | gpu_unai.BLEND_MODE = ((tpage>>5) & 3) << 3; |
47 | gpu_unai.TEXT_MODE = (tmode + 1) << 5; // gpu_unai.TEXT_MODE should be values 1..3, so add one |
48 | gpu_unai.TBA = &((u16*)gpu_unai.vram)[FRAME_OFFSET(tx, ty)]; |
86aad47b |
49 | } |
50 | |
51 | /////////////////////////////////////////////////////////////////////////////// |
52 | INLINE void gpuSetCLUT(u16 clut) |
53 | { |
030d1121 |
54 | gpu_unai.CBA = &((u16*)gpu_unai.vram)[(clut & 0x7FFF) << 4]; |
86aad47b |
55 | } |
56 | |
57 | #ifdef ENABLE_GPU_NULL_SUPPORT |
58 | #define NULL_GPU() break |
59 | #else |
60 | #define NULL_GPU() |
61 | #endif |
62 | |
63 | #ifdef ENABLE_GPU_LOG_SUPPORT |
64 | #define DO_LOG(expr) printf expr |
65 | #else |
66 | #define DO_LOG(expr) {} |
67 | #endif |
68 | |
030d1121 |
69 | #define Blending (((PRIM&0x2) && BlendingEnabled()) ? (PRIM&0x2) : 0) |
70 | #define Blending_Mode (((PRIM&0x2) && BlendingEnabled()) ? gpu_unai.BLEND_MODE : 0) |
71 | #define Lighting (((~PRIM)&0x1) && LightingEnabled()) |
72 | // Dithering applies only to Gouraud-shaded polys or texture-blended polys: |
73 | #define Dithering (((((~PRIM)&0x1) || (PRIM&0x10)) && DitheringEnabled()) ? \ |
74 | (ForcedDitheringEnabled() ? (1<<9) : (gpu_unai.GPU_GP1 & (1 << 9))) \ |
75 | : 0) |
76 | |
77 | /////////////////////////////////////////////////////////////////////////////// |
78 | //Now handled by Rearmed's gpulib and gpu_unai/gpulib_if.cpp: |
79 | /////////////////////////////////////////////////////////////////////////////// |
80 | #ifndef USE_GPULIB |
81 | |
82 | // Handles GP0 draw settings commands 0xE1...0xE6 |
83 | static void gpuGP0Cmd_0xEx(gpu_unai_t &gpu_unai, u32 cmd_word) |
84 | { |
85 | // Assume incoming GP0 command is 0xE1..0xE6, convert to 1..6 |
86 | u8 num = (cmd_word >> 24) & 7; |
87 | switch (num) { |
88 | case 1: { |
89 | // GP0(E1h) - Draw Mode setting (aka "Texpage") |
90 | DO_LOG(("GP0(0xE1) DrawMode TexPage(0x%x)\n", cmd_word)); |
91 | u32 cur_texpage = gpu_unai.GPU_GP1 & 0x7FF; |
92 | u32 new_texpage = cmd_word & 0x7FF; |
93 | if (cur_texpage != new_texpage) { |
94 | gpu_unai.GPU_GP1 = (gpu_unai.GPU_GP1 & ~0x7FF) | new_texpage; |
95 | gpuSetTexture(gpu_unai.GPU_GP1); |
96 | } |
97 | } break; |
98 | |
99 | case 2: { |
100 | // GP0(E2h) - Texture Window setting |
101 | DO_LOG(("GP0(0xE2) TextureWindow(0x%x)\n", cmd_word)); |
102 | if (cmd_word != gpu_unai.TextureWindowCur) { |
103 | static const u8 TextureMask[32] = { |
104 | 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7, |
105 | 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7 |
106 | }; |
107 | gpu_unai.TextureWindowCur = cmd_word; |
108 | gpu_unai.TextureWindow[0] = ((cmd_word >> 10) & 0x1F) << 3; |
109 | gpu_unai.TextureWindow[1] = ((cmd_word >> 15) & 0x1F) << 3; |
110 | gpu_unai.TextureWindow[2] = TextureMask[(cmd_word >> 0) & 0x1F]; |
111 | gpu_unai.TextureWindow[3] = TextureMask[(cmd_word >> 5) & 0x1F]; |
112 | gpu_unai.TextureWindow[0] &= ~gpu_unai.TextureWindow[2]; |
113 | gpu_unai.TextureWindow[1] &= ~gpu_unai.TextureWindow[3]; |
114 | |
115 | // Inner loop vars must be updated whenever texture window is changed: |
116 | const u32 fb = FIXED_BITS; // # of fractional fixed-pt bits of u4/v4 |
117 | gpu_unai.u_msk = (((u32)gpu_unai.TextureWindow[2]) << fb) | ((1 << fb) - 1); |
118 | gpu_unai.v_msk = (((u32)gpu_unai.TextureWindow[3]) << fb) | ((1 << fb) - 1); |
119 | |
120 | gpuSetTexture(gpu_unai.GPU_GP1); |
121 | } |
122 | } break; |
123 | |
124 | case 3: { |
125 | // GP0(E3h) - Set Drawing Area top left (X1,Y1) |
126 | DO_LOG(("GP0(0xE3) DrawingArea Pos(0x%x)\n", cmd_word)); |
127 | gpu_unai.DrawingArea[0] = cmd_word & 0x3FF; |
128 | gpu_unai.DrawingArea[1] = (cmd_word >> 10) & 0x3FF; |
129 | } break; |
130 | |
131 | case 4: { |
132 | // GP0(E4h) - Set Drawing Area bottom right (X2,Y2) |
133 | DO_LOG(("GP0(0xE4) DrawingArea Size(0x%x)\n", cmd_word)); |
134 | gpu_unai.DrawingArea[2] = (cmd_word & 0x3FF) + 1; |
135 | gpu_unai.DrawingArea[3] = ((cmd_word >> 10) & 0x3FF) + 1; |
136 | } break; |
137 | |
138 | case 5: { |
139 | // GP0(E5h) - Set Drawing Offset (X,Y) |
140 | DO_LOG(("GP0(0xE5) DrawingOffset(0x%x)\n", cmd_word)); |
141 | gpu_unai.DrawingOffset[0] = ((s32)cmd_word<<(32-11))>>(32-11); |
142 | gpu_unai.DrawingOffset[1] = ((s32)cmd_word<<(32-22))>>(32-11); |
143 | } break; |
144 | |
145 | case 6: { |
146 | // GP0(E6h) - Mask Bit Setting |
147 | DO_LOG(("GP0(0xE6) SetMask(0x%x)\n", cmd_word)); |
148 | gpu_unai.Masking = (cmd_word & 0x2) << 1; |
149 | gpu_unai.PixelMSB = (cmd_word & 0x1) << 8; |
150 | } break; |
151 | } |
152 | } |
86aad47b |
153 | |
154 | void gpuSendPacketFunction(const int PRIM) |
155 | { |
156 | //printf("0x%x\n",PRIM); |
157 | |
030d1121 |
158 | //senquack - TODO: optimize this (packet pointer union as prim draw parameter |
159 | // introduced as optimization for gpulib command-list processing) |
160 | PtrUnion packet = { .ptr = (void*)&gpu_unai.PacketBuffer }; |
161 | |
86aad47b |
162 | switch (PRIM) |
163 | { |
030d1121 |
164 | case 0x02: { |
86aad47b |
165 | NULL_GPU(); |
030d1121 |
166 | gpuClearImage(packet); // prim handles updateLace && skip |
167 | gpu_unai.fb_dirty = true; |
86aad47b |
168 | DO_LOG(("gpuClearImage(0x%x)\n",PRIM)); |
030d1121 |
169 | } break; |
170 | |
86aad47b |
171 | case 0x20: |
172 | case 0x21: |
173 | case 0x22: |
030d1121 |
174 | case 0x23: { // Monochrome 3-pt poly |
175 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
176 | { |
177 | NULL_GPU(); |
030d1121 |
178 | PP driver = gpuPolySpanDrivers[ |
179 | (gpu_unai.blit_mask?1024:0) | |
180 | Blending_Mode | |
181 | gpu_unai.Masking | Blending | gpu_unai.PixelMSB |
182 | ]; |
183 | gpuDrawPolyF(packet, driver, false); |
184 | gpu_unai.fb_dirty = true; |
185 | DO_LOG(("gpuDrawPolyF(0x%x)\n",PRIM)); |
86aad47b |
186 | } |
030d1121 |
187 | } break; |
188 | |
86aad47b |
189 | case 0x24: |
190 | case 0x25: |
191 | case 0x26: |
030d1121 |
192 | case 0x27: { // Textured 3-pt poly |
193 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
194 | { |
195 | NULL_GPU(); |
030d1121 |
196 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
197 | gpuSetTexture (gpu_unai.PacketBuffer.U4[4] >> 16); |
198 | |
199 | u32 driver_idx = |
200 | (gpu_unai.blit_mask?1024:0) | |
201 | Dithering | |
202 | Blending_Mode | gpu_unai.TEXT_MODE | |
203 | gpu_unai.Masking | Blending | gpu_unai.PixelMSB; |
204 | |
205 | if (!FastLightingEnabled()) { |
206 | driver_idx |= Lighting; |
207 | } else { |
208 | if (!((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))) |
209 | driver_idx |= Lighting; |
210 | } |
211 | |
212 | PP driver = gpuPolySpanDrivers[driver_idx]; |
213 | gpuDrawPolyFT(packet, driver, false); |
214 | gpu_unai.fb_dirty = true; |
215 | DO_LOG(("gpuDrawPolyFT(0x%x)\n",PRIM)); |
86aad47b |
216 | } |
030d1121 |
217 | } break; |
218 | |
86aad47b |
219 | case 0x28: |
220 | case 0x29: |
221 | case 0x2A: |
030d1121 |
222 | case 0x2B: { // Monochrome 4-pt poly |
223 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
224 | { |
225 | NULL_GPU(); |
030d1121 |
226 | PP driver = gpuPolySpanDrivers[ |
227 | (gpu_unai.blit_mask?1024:0) | |
228 | Blending_Mode | |
229 | gpu_unai.Masking | Blending | gpu_unai.PixelMSB |
230 | ]; |
231 | gpuDrawPolyF(packet, driver, true); // is_quad = true |
232 | gpu_unai.fb_dirty = true; |
233 | DO_LOG(("gpuDrawPolyF(0x%x) (4-pt QUAD)\n",PRIM)); |
86aad47b |
234 | } |
030d1121 |
235 | } break; |
236 | |
86aad47b |
237 | case 0x2C: |
238 | case 0x2D: |
239 | case 0x2E: |
030d1121 |
240 | case 0x2F: { // Textured 4-pt poly |
241 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
242 | { |
243 | NULL_GPU(); |
030d1121 |
244 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
245 | gpuSetTexture (gpu_unai.PacketBuffer.U4[4] >> 16); |
246 | |
247 | u32 driver_idx = |
248 | (gpu_unai.blit_mask?1024:0) | |
249 | Dithering | |
250 | Blending_Mode | gpu_unai.TEXT_MODE | |
251 | gpu_unai.Masking | Blending | gpu_unai.PixelMSB; |
252 | |
253 | if (!FastLightingEnabled()) { |
254 | driver_idx |= Lighting; |
255 | } else { |
256 | if (!((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))) |
257 | driver_idx |= Lighting; |
258 | } |
259 | |
260 | PP driver = gpuPolySpanDrivers[driver_idx]; |
261 | gpuDrawPolyFT(packet, driver, true); // is_quad = true |
262 | gpu_unai.fb_dirty = true; |
263 | DO_LOG(("gpuDrawPolyFT(0x%x) (4-pt QUAD)\n",PRIM)); |
86aad47b |
264 | } |
030d1121 |
265 | } break; |
266 | |
86aad47b |
267 | case 0x30: |
268 | case 0x31: |
269 | case 0x32: |
030d1121 |
270 | case 0x33: { // Gouraud-shaded 3-pt poly |
271 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
272 | { |
273 | NULL_GPU(); |
030d1121 |
274 | //NOTE: The '129' here is CF_GOURAUD | CF_LIGHT, however |
275 | // this is an untextured poly, so CF_LIGHT (texture blend) |
276 | // shouldn't apply. Until the original array of template |
277 | // instantiation ptrs is fixed, we're stuck with this. (TODO) |
278 | PP driver = gpuPolySpanDrivers[ |
279 | (gpu_unai.blit_mask?1024:0) | |
280 | Dithering | |
281 | Blending_Mode | |
282 | gpu_unai.Masking | Blending | 129 | gpu_unai.PixelMSB |
283 | ]; |
284 | gpuDrawPolyG(packet, driver, false); |
285 | gpu_unai.fb_dirty = true; |
286 | DO_LOG(("gpuDrawPolyG(0x%x)\n",PRIM)); |
86aad47b |
287 | } |
030d1121 |
288 | } break; |
289 | |
86aad47b |
290 | case 0x34: |
291 | case 0x35: |
292 | case 0x36: |
030d1121 |
293 | case 0x37: { // Gouraud-shaded, textured 3-pt poly |
294 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
295 | { |
296 | NULL_GPU(); |
030d1121 |
297 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
298 | gpuSetTexture (gpu_unai.PacketBuffer.U4[5] >> 16); |
299 | PP driver = gpuPolySpanDrivers[ |
300 | (gpu_unai.blit_mask?1024:0) | |
301 | Dithering | |
302 | Blending_Mode | gpu_unai.TEXT_MODE | |
303 | gpu_unai.Masking | Blending | ((Lighting)?129:0) | gpu_unai.PixelMSB |
304 | ]; |
305 | gpuDrawPolyGT(packet, driver, false); |
306 | gpu_unai.fb_dirty = true; |
307 | DO_LOG(("gpuDrawPolyGT(0x%x)\n",PRIM)); |
86aad47b |
308 | } |
030d1121 |
309 | } break; |
310 | |
86aad47b |
311 | case 0x38: |
312 | case 0x39: |
313 | case 0x3A: |
030d1121 |
314 | case 0x3B: { // Gouraud-shaded 4-pt poly |
315 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
316 | { |
317 | NULL_GPU(); |
030d1121 |
318 | // See notes regarding '129' for 0x30..0x33 further above -senquack |
319 | PP driver = gpuPolySpanDrivers[ |
320 | (gpu_unai.blit_mask?1024:0) | |
321 | Dithering | |
322 | Blending_Mode | |
323 | gpu_unai.Masking | Blending | 129 | gpu_unai.PixelMSB |
324 | ]; |
325 | gpuDrawPolyG(packet, driver, true); // is_quad = true |
326 | gpu_unai.fb_dirty = true; |
327 | DO_LOG(("gpuDrawPolyG(0x%x) (4-pt QUAD)\n",PRIM)); |
86aad47b |
328 | } |
030d1121 |
329 | } break; |
330 | |
86aad47b |
331 | case 0x3C: |
332 | case 0x3D: |
333 | case 0x3E: |
030d1121 |
334 | case 0x3F: { // Gouraud-shaded, textured 4-pt poly |
335 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
336 | { |
337 | NULL_GPU(); |
030d1121 |
338 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
339 | gpuSetTexture (gpu_unai.PacketBuffer.U4[5] >> 16); |
340 | PP driver = gpuPolySpanDrivers[ |
341 | (gpu_unai.blit_mask?1024:0) | |
342 | Dithering | |
343 | Blending_Mode | gpu_unai.TEXT_MODE | |
344 | gpu_unai.Masking | Blending | ((Lighting)?129:0) | gpu_unai.PixelMSB |
345 | ]; |
346 | gpuDrawPolyGT(packet, driver, true); // is_quad = true |
347 | gpu_unai.fb_dirty = true; |
348 | DO_LOG(("gpuDrawPolyGT(0x%x) (4-pt QUAD)\n",PRIM)); |
86aad47b |
349 | } |
030d1121 |
350 | } break; |
351 | |
86aad47b |
352 | case 0x40: |
353 | case 0x41: |
354 | case 0x42: |
030d1121 |
355 | case 0x43: { // Monochrome line |
356 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
357 | { |
358 | NULL_GPU(); |
030d1121 |
359 | // Shift index right by one, as untextured prims don't use lighting |
360 | u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1; |
361 | PSD driver = gpuPixelSpanDrivers[driver_idx]; |
362 | gpuDrawLineF(packet, driver); |
363 | gpu_unai.fb_dirty = true; |
364 | DO_LOG(("gpuDrawLineF(0x%x)\n",PRIM)); |
86aad47b |
365 | } |
030d1121 |
366 | } break; |
367 | |
86aad47b |
368 | case 0x48: |
369 | case 0x49: |
370 | case 0x4A: |
371 | case 0x4B: |
372 | case 0x4C: |
373 | case 0x4D: |
374 | case 0x4E: |
030d1121 |
375 | case 0x4F: { // Monochrome line strip |
376 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
377 | { |
378 | NULL_GPU(); |
030d1121 |
379 | // Shift index right by one, as untextured prims don't use lighting |
380 | u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1; |
381 | PSD driver = gpuPixelSpanDrivers[driver_idx]; |
382 | gpuDrawLineF(packet, driver); |
383 | gpu_unai.fb_dirty = true; |
384 | DO_LOG(("gpuDrawLineF(0x%x)\n",PRIM)); |
86aad47b |
385 | } |
030d1121 |
386 | if ((gpu_unai.PacketBuffer.U4[3] & 0xF000F000) != 0x50005000) |
86aad47b |
387 | { |
030d1121 |
388 | gpu_unai.PacketBuffer.U4[1] = gpu_unai.PacketBuffer.U4[2]; |
389 | gpu_unai.PacketBuffer.U4[2] = gpu_unai.PacketBuffer.U4[3]; |
390 | gpu_unai.PacketCount = 1; |
391 | gpu_unai.PacketIndex = 3; |
86aad47b |
392 | } |
030d1121 |
393 | } break; |
394 | |
86aad47b |
395 | case 0x50: |
396 | case 0x51: |
397 | case 0x52: |
030d1121 |
398 | case 0x53: { // Gouraud-shaded line |
399 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
400 | { |
401 | NULL_GPU(); |
030d1121 |
402 | // Shift index right by one, as untextured prims don't use lighting |
403 | u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1; |
404 | // Index MSB selects Gouraud-shaded PixelSpanDriver: |
405 | driver_idx |= (1 << 5); |
406 | PSD driver = gpuPixelSpanDrivers[driver_idx]; |
407 | gpuDrawLineG(packet, driver); |
408 | gpu_unai.fb_dirty = true; |
409 | DO_LOG(("gpuDrawLineG(0x%x)\n",PRIM)); |
86aad47b |
410 | } |
030d1121 |
411 | } break; |
412 | |
86aad47b |
413 | case 0x58: |
414 | case 0x59: |
415 | case 0x5A: |
416 | case 0x5B: |
417 | case 0x5C: |
418 | case 0x5D: |
419 | case 0x5E: |
030d1121 |
420 | case 0x5F: { // Gouraud-shaded line strip |
421 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
422 | { |
423 | NULL_GPU(); |
030d1121 |
424 | // Shift index right by one, as untextured prims don't use lighting |
425 | u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1; |
426 | // Index MSB selects Gouraud-shaded PixelSpanDriver: |
427 | driver_idx |= (1 << 5); |
428 | PSD driver = gpuPixelSpanDrivers[driver_idx]; |
429 | gpuDrawLineG(packet, driver); |
430 | gpu_unai.fb_dirty = true; |
431 | DO_LOG(("gpuDrawLineG(0x%x)\n",PRIM)); |
86aad47b |
432 | } |
030d1121 |
433 | if ((gpu_unai.PacketBuffer.U4[4] & 0xF000F000) != 0x50005000) |
86aad47b |
434 | { |
030d1121 |
435 | gpu_unai.PacketBuffer.U1[3 + (2 * 4)] = gpu_unai.PacketBuffer.U1[3 + (0 * 4)]; |
436 | gpu_unai.PacketBuffer.U4[0] = gpu_unai.PacketBuffer.U4[2]; |
437 | gpu_unai.PacketBuffer.U4[1] = gpu_unai.PacketBuffer.U4[3]; |
438 | gpu_unai.PacketBuffer.U4[2] = gpu_unai.PacketBuffer.U4[4]; |
439 | gpu_unai.PacketCount = 2; |
440 | gpu_unai.PacketIndex = 3; |
86aad47b |
441 | } |
030d1121 |
442 | } break; |
443 | |
86aad47b |
444 | case 0x60: |
445 | case 0x61: |
446 | case 0x62: |
030d1121 |
447 | case 0x63: { // Monochrome rectangle (variable size) |
448 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
449 | { |
450 | NULL_GPU(); |
030d1121 |
451 | PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1]; |
452 | gpuDrawT(packet, driver); |
453 | gpu_unai.fb_dirty = true; |
86aad47b |
454 | DO_LOG(("gpuDrawT(0x%x)\n",PRIM)); |
455 | } |
030d1121 |
456 | } break; |
457 | |
86aad47b |
458 | case 0x64: |
459 | case 0x65: |
460 | case 0x66: |
030d1121 |
461 | case 0x67: { // Textured rectangle (variable size) |
462 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
463 | { |
464 | NULL_GPU(); |
030d1121 |
465 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
466 | u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1); |
467 | |
468 | // This fixes Silent Hill running animation on loading screens: |
469 | // (On PSX, color values 0x00-0x7F darken the source texture's color, |
470 | // 0x81-FF lighten textures (ultimately clamped to 0x1F), |
471 | // 0x80 leaves source texture color unchanged, HOWEVER, |
472 | // gpu_unai uses a simple lighting LUT whereby only the upper |
473 | // 5 bits of an 8-bit color are used, so 0x80-0x87 all behave as |
474 | // 0x80. |
475 | // |
476 | // NOTE: I've changed all textured sprite draw commands here and |
477 | // elsewhere to use proper behavior, but left poly commands |
478 | // alone, I don't want to slow rendering down too much. (TODO) |
479 | //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)) |
480 | // Strip lower 3 bits of each color and determine if lighting should be used: |
481 | if ((gpu_unai.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080) |
482 | driver_idx |= Lighting; |
483 | PS driver = gpuSpriteSpanDrivers[driver_idx]; |
484 | gpuDrawS(packet, driver); |
485 | gpu_unai.fb_dirty = true; |
86aad47b |
486 | DO_LOG(("gpuDrawS(0x%x)\n",PRIM)); |
487 | } |
030d1121 |
488 | } break; |
489 | |
86aad47b |
490 | case 0x68: |
491 | case 0x69: |
492 | case 0x6A: |
030d1121 |
493 | case 0x6B: { // Monochrome rectangle (1x1 dot) |
494 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
495 | { |
496 | NULL_GPU(); |
030d1121 |
497 | gpu_unai.PacketBuffer.U4[2] = 0x00010001; |
498 | PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1]; |
499 | gpuDrawT(packet, driver); |
500 | gpu_unai.fb_dirty = true; |
86aad47b |
501 | DO_LOG(("gpuDrawT(0x%x)\n",PRIM)); |
502 | } |
030d1121 |
503 | } break; |
504 | |
86aad47b |
505 | case 0x70: |
506 | case 0x71: |
507 | case 0x72: |
030d1121 |
508 | case 0x73: { // Monochrome rectangle (8x8) |
509 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
510 | { |
511 | NULL_GPU(); |
030d1121 |
512 | gpu_unai.PacketBuffer.U4[2] = 0x00080008; |
513 | PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1]; |
514 | gpuDrawT(packet, driver); |
515 | gpu_unai.fb_dirty = true; |
86aad47b |
516 | DO_LOG(("gpuDrawT(0x%x)\n",PRIM)); |
517 | } |
030d1121 |
518 | } break; |
519 | |
86aad47b |
520 | case 0x74: |
521 | case 0x75: |
522 | case 0x76: |
030d1121 |
523 | case 0x77: { // Textured rectangle (8x8) |
524 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
525 | { |
526 | NULL_GPU(); |
030d1121 |
527 | gpu_unai.PacketBuffer.U4[3] = 0x00080008; |
528 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
529 | u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1); |
530 | |
531 | //senquack - Only color 808080h-878787h allows skipping lighting calculation: |
532 | //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)) |
533 | // Strip lower 3 bits of each color and determine if lighting should be used: |
534 | if ((gpu_unai.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080) |
535 | driver_idx |= Lighting; |
536 | PS driver = gpuSpriteSpanDrivers[driver_idx]; |
537 | gpuDrawS(packet, driver); |
538 | gpu_unai.fb_dirty = true; |
86aad47b |
539 | DO_LOG(("gpuDrawS(0x%x)\n",PRIM)); |
540 | } |
030d1121 |
541 | } break; |
542 | |
86aad47b |
543 | case 0x78: |
544 | case 0x79: |
545 | case 0x7A: |
030d1121 |
546 | case 0x7B: { // Monochrome rectangle (16x16) |
547 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
548 | { |
549 | NULL_GPU(); |
030d1121 |
550 | gpu_unai.PacketBuffer.U4[2] = 0x00100010; |
551 | PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1]; |
552 | gpuDrawT(packet, driver); |
553 | gpu_unai.fb_dirty = true; |
86aad47b |
554 | DO_LOG(("gpuDrawT(0x%x)\n",PRIM)); |
555 | } |
030d1121 |
556 | } break; |
557 | |
86aad47b |
558 | case 0x7C: |
559 | case 0x7D: |
030d1121 |
560 | #ifdef __arm__ |
561 | /* Notaz 4bit sprites optimization */ |
562 | if ((!gpu_unai.frameskip.skipGPU) && (!(gpu_unai.GPU_GP1&0x180)) && (!(gpu_unai.Masking|gpu_unai.PixelMSB))) |
b3db9409 |
563 | { |
030d1121 |
564 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
565 | gpuDrawS16(packet); |
566 | gpu_unai.fb_dirty = true; |
b3db9409 |
567 | break; |
568 | } |
030d1121 |
569 | #endif |
86aad47b |
570 | case 0x7E: |
030d1121 |
571 | case 0x7F: { // Textured rectangle (16x16) |
572 | if (!gpu_unai.frameskip.skipGPU) |
86aad47b |
573 | { |
574 | NULL_GPU(); |
030d1121 |
575 | gpu_unai.PacketBuffer.U4[3] = 0x00100010; |
576 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
577 | u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1); |
578 | |
579 | //senquack - Only color 808080h-878787h allows skipping lighting calculation: |
580 | //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)) |
581 | // Strip lower 3 bits of each color and determine if lighting should be used: |
582 | if ((gpu_unai.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080) |
583 | driver_idx |= Lighting; |
584 | PS driver = gpuSpriteSpanDrivers[driver_idx]; |
585 | gpuDrawS(packet, driver); |
586 | gpu_unai.fb_dirty = true; |
86aad47b |
587 | DO_LOG(("gpuDrawS(0x%x)\n",PRIM)); |
588 | } |
030d1121 |
589 | } break; |
590 | |
86aad47b |
591 | case 0x80: // vid -> vid |
030d1121 |
592 | gpuMoveImage(packet); // prim handles updateLace && skip |
593 | if ((!gpu_unai.frameskip.skipCount) && (gpu_unai.DisplayArea[3] == 480)) // Tekken 3 hack |
594 | { |
595 | if (!gpu_unai.frameskip.skipGPU) gpu_unai.fb_dirty = true; |
596 | } |
597 | else |
598 | { |
599 | gpu_unai.fb_dirty = true; |
600 | } |
86aad47b |
601 | DO_LOG(("gpuMoveImage(0x%x)\n",PRIM)); |
602 | break; |
603 | case 0xA0: // sys ->vid |
030d1121 |
604 | gpuLoadImage(packet); // prim handles updateLace && skip |
86aad47b |
605 | DO_LOG(("gpuLoadImage(0x%x)\n",PRIM)); |
606 | break; |
607 | case 0xC0: // vid -> sys |
030d1121 |
608 | gpuStoreImage(packet); // prim handles updateLace && skip |
86aad47b |
609 | DO_LOG(("gpuStoreImage(0x%x)\n",PRIM)); |
610 | break; |
030d1121 |
611 | case 0xE1 ... 0xE6: { // Draw settings |
612 | gpuGP0Cmd_0xEx(gpu_unai, gpu_unai.PacketBuffer.U4[0]); |
613 | } break; |
86aad47b |
614 | } |
615 | } |
030d1121 |
616 | #endif //!USE_GPULIB |
617 | /////////////////////////////////////////////////////////////////////////////// |
618 | // End of code specific to non-gpulib standalone version of gpu_unai |
619 | /////////////////////////////////////////////////////////////////////////////// |
908e426c |
620 | |
621 | #endif /* __GPU_UNAI_GPU_COMMAND_H__ */ |