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