cdrom: change pause timing again
[pcsx_rearmed.git] / plugins / gpu_unai / gpu_command.h
CommitLineData
0bfe8d59 1/***************************************************************************
2* Copyright (C) 2010 PCSX4ALL Team *
3* Copyright (C) 2010 Unai *
4* Copyright (C) 2016 Senquack (dansilsby <AT> gmail <DOT> com) *
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#ifndef __GPU_UNAI_GPU_COMMAND_H__
23#define __GPU_UNAI_GPU_COMMAND_H__
24
25///////////////////////////////////////////////////////////////////////////////
26void gpuSetTexture(u16 tpage)
27{
28 u32 tmode, tx, ty;
e223fa15 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];
0bfe8d59 32
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;
39
40 tx = (tpage & 0x0F) << 6;
41 ty = (tpage & 0x10) << 4;
42
e223fa15 43 tx += (gpu_unai.TextureWindow[0] >> (2 - tmode));
44 ty += gpu_unai.TextureWindow[1];
0bfe8d59 45
e223fa15 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 = &gpu_unai.vram[FRAME_OFFSET(tx, ty)];
0bfe8d59 49}
50
51///////////////////////////////////////////////////////////////////////////////
52INLINE void gpuSetCLUT(u16 clut)
53{
e223fa15 54 gpu_unai.CBA = &gpu_unai.vram[(clut & 0x7FFF) << 4];
0bfe8d59 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
69#define Blending (((PRIM&0x2) && BlendingEnabled()) ? (PRIM&0x2) : 0)
e223fa15 70#define Blending_Mode (((PRIM&0x2) && BlendingEnabled()) ? gpu_unai.BLEND_MODE : 0)
0bfe8d59 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()) ? \
e223fa15 74 (ForcedDitheringEnabled() ? (1<<9) : (gpu_unai.GPU_GP1 & (1 << 9))) \
0bfe8d59 75 : 0)
76
77///////////////////////////////////////////////////////////////////////////////
e223fa15 78//Now handled by Rearmed's gpulib and gpu_unai/gpulib_if.cpp:
0bfe8d59 79///////////////////////////////////////////////////////////////////////////////
80#ifndef USE_GPULIB
81
82// Handles GP0 draw settings commands 0xE1...0xE6
e223fa15 83static void gpuGP0Cmd_0xEx(gpu_unai_t &gpu_unai, u32 cmd_word)
0bfe8d59 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));
e223fa15 91 u32 cur_texpage = gpu_unai.GPU_GP1 & 0x7FF;
0bfe8d59 92 u32 new_texpage = cmd_word & 0x7FF;
93 if (cur_texpage != new_texpage) {
e223fa15 94 gpu_unai.GPU_GP1 = (gpu_unai.GPU_GP1 & ~0x7FF) | new_texpage;
95 gpuSetTexture(gpu_unai.GPU_GP1);
0bfe8d59 96 }
97 } break;
98
99 case 2: {
100 // GP0(E2h) - Texture Window setting
101 DO_LOG(("GP0(0xE2) TextureWindow(0x%x)\n", cmd_word));
e223fa15 102 if (cmd_word != gpu_unai.TextureWindowCur) {
0bfe8d59 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 };
e223fa15 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];
0bfe8d59 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
e223fa15 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);
0bfe8d59 119
e223fa15 120 gpuSetTexture(gpu_unai.GPU_GP1);
0bfe8d59 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));
e223fa15 127 gpu_unai.DrawingArea[0] = cmd_word & 0x3FF;
128 gpu_unai.DrawingArea[1] = (cmd_word >> 10) & 0x3FF;
0bfe8d59 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));
e223fa15 134 gpu_unai.DrawingArea[2] = (cmd_word & 0x3FF) + 1;
135 gpu_unai.DrawingArea[3] = ((cmd_word >> 10) & 0x3FF) + 1;
0bfe8d59 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));
e223fa15 141 gpu_unai.DrawingOffset[0] = ((s32)cmd_word<<(32-11))>>(32-11);
142 gpu_unai.DrawingOffset[1] = ((s32)cmd_word<<(32-22))>>(32-11);
0bfe8d59 143 } break;
144
145 case 6: {
146 // GP0(E6h) - Mask Bit Setting
147 DO_LOG(("GP0(0xE6) SetMask(0x%x)\n", cmd_word));
e223fa15 148 gpu_unai.Masking = (cmd_word & 0x2) << 1;
149 gpu_unai.PixelMSB = (cmd_word & 0x1) << 8;
0bfe8d59 150 } break;
151 }
152}
153
154void gpuSendPacketFunction(const int PRIM)
155{
156 //printf("0x%x\n",PRIM);
157
158 //senquack - TODO: optimize this (packet pointer union as prim draw parameter
159 // introduced as optimization for gpulib command-list processing)
e223fa15 160 PtrUnion packet = { .ptr = (void*)&gpu_unai.PacketBuffer };
0bfe8d59 161
162 switch (PRIM)
163 {
164 case 0x02: {
165 NULL_GPU();
166 gpuClearImage(packet); // prim handles updateLace && skip
e223fa15 167 gpu_unai.fb_dirty = true;
0bfe8d59 168 DO_LOG(("gpuClearImage(0x%x)\n",PRIM));
169 } break;
170
171 case 0x20:
172 case 0x21:
173 case 0x22:
174 case 0x23: { // Monochrome 3-pt poly
e223fa15 175 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 176 {
177 NULL_GPU();
178 PP driver = gpuPolySpanDrivers[
e223fa15 179 (gpu_unai.blit_mask?1024:0) |
0bfe8d59 180 Blending_Mode |
e223fa15 181 gpu_unai.Masking | Blending | gpu_unai.PixelMSB
0bfe8d59 182 ];
183 gpuDrawPolyF(packet, driver, false);
e223fa15 184 gpu_unai.fb_dirty = true;
0bfe8d59 185 DO_LOG(("gpuDrawPolyF(0x%x)\n",PRIM));
186 }
187 } break;
188
189 case 0x24:
190 case 0x25:
191 case 0x26:
192 case 0x27: { // Textured 3-pt poly
e223fa15 193 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 194 {
195 NULL_GPU();
e223fa15 196 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
197 gpuSetTexture (le32_to_u32(gpu_unai.PacketBuffer.U4[4]) >> 16);
0bfe8d59 198
199 u32 driver_idx =
e223fa15 200 (gpu_unai.blit_mask?1024:0) |
0bfe8d59 201 Dithering |
e223fa15 202 Blending_Mode | gpu_unai.TEXT_MODE |
203 gpu_unai.Masking | Blending | gpu_unai.PixelMSB;
0bfe8d59 204
205 if (!FastLightingEnabled()) {
206 driver_idx |= Lighting;
207 } else {
e223fa15 208 if (!((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)))
0bfe8d59 209 driver_idx |= Lighting;
210 }
211
212 PP driver = gpuPolySpanDrivers[driver_idx];
213 gpuDrawPolyFT(packet, driver, false);
e223fa15 214 gpu_unai.fb_dirty = true;
0bfe8d59 215 DO_LOG(("gpuDrawPolyFT(0x%x)\n",PRIM));
216 }
217 } break;
218
219 case 0x28:
220 case 0x29:
221 case 0x2A:
222 case 0x2B: { // Monochrome 4-pt poly
e223fa15 223 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 224 {
225 NULL_GPU();
226 PP driver = gpuPolySpanDrivers[
e223fa15 227 (gpu_unai.blit_mask?1024:0) |
0bfe8d59 228 Blending_Mode |
e223fa15 229 gpu_unai.Masking | Blending | gpu_unai.PixelMSB
0bfe8d59 230 ];
231 gpuDrawPolyF(packet, driver, true); // is_quad = true
e223fa15 232 gpu_unai.fb_dirty = true;
0bfe8d59 233 DO_LOG(("gpuDrawPolyF(0x%x) (4-pt QUAD)\n",PRIM));
234 }
235 } break;
236
237 case 0x2C:
238 case 0x2D:
239 case 0x2E:
240 case 0x2F: { // Textured 4-pt poly
e223fa15 241 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 242 {
243 NULL_GPU();
e223fa15 244 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
245 gpuSetTexture (le32_to_u32(gpu_unai.PacketBuffer.U4[4]) >> 16);
0bfe8d59 246
247 u32 driver_idx =
e223fa15 248 (gpu_unai.blit_mask?1024:0) |
0bfe8d59 249 Dithering |
e223fa15 250 Blending_Mode | gpu_unai.TEXT_MODE |
251 gpu_unai.Masking | Blending | gpu_unai.PixelMSB;
0bfe8d59 252
253 if (!FastLightingEnabled()) {
254 driver_idx |= Lighting;
255 } else {
e223fa15 256 if (!((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)))
0bfe8d59 257 driver_idx |= Lighting;
258 }
259
260 PP driver = gpuPolySpanDrivers[driver_idx];
261 gpuDrawPolyFT(packet, driver, true); // is_quad = true
e223fa15 262 gpu_unai.fb_dirty = true;
0bfe8d59 263 DO_LOG(("gpuDrawPolyFT(0x%x) (4-pt QUAD)\n",PRIM));
264 }
265 } break;
266
267 case 0x30:
268 case 0x31:
269 case 0x32:
270 case 0x33: { // Gouraud-shaded 3-pt poly
e223fa15 271 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 272 {
273 NULL_GPU();
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[
e223fa15 279 (gpu_unai.blit_mask?1024:0) |
0bfe8d59 280 Dithering |
281 Blending_Mode |
e223fa15 282 gpu_unai.Masking | Blending | 129 | gpu_unai.PixelMSB
0bfe8d59 283 ];
284 gpuDrawPolyG(packet, driver, false);
e223fa15 285 gpu_unai.fb_dirty = true;
0bfe8d59 286 DO_LOG(("gpuDrawPolyG(0x%x)\n",PRIM));
287 }
288 } break;
289
290 case 0x34:
291 case 0x35:
292 case 0x36:
293 case 0x37: { // Gouraud-shaded, textured 3-pt poly
e223fa15 294 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 295 {
296 NULL_GPU();
e223fa15 297 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
298 gpuSetTexture (le32_to_u32(gpu_unai.PacketBuffer.U4[5]) >> 16);
0bfe8d59 299 PP driver = gpuPolySpanDrivers[
e223fa15 300 (gpu_unai.blit_mask?1024:0) |
0bfe8d59 301 Dithering |
e223fa15 302 Blending_Mode | gpu_unai.TEXT_MODE |
303 gpu_unai.Masking | Blending | ((Lighting)?129:0) | gpu_unai.PixelMSB
0bfe8d59 304 ];
305 gpuDrawPolyGT(packet, driver, false);
e223fa15 306 gpu_unai.fb_dirty = true;
0bfe8d59 307 DO_LOG(("gpuDrawPolyGT(0x%x)\n",PRIM));
308 }
309 } break;
310
311 case 0x38:
312 case 0x39:
313 case 0x3A:
314 case 0x3B: { // Gouraud-shaded 4-pt poly
e223fa15 315 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 316 {
317 NULL_GPU();
318 // See notes regarding '129' for 0x30..0x33 further above -senquack
319 PP driver = gpuPolySpanDrivers[
e223fa15 320 (gpu_unai.blit_mask?1024:0) |
0bfe8d59 321 Dithering |
322 Blending_Mode |
e223fa15 323 gpu_unai.Masking | Blending | 129 | gpu_unai.PixelMSB
0bfe8d59 324 ];
325 gpuDrawPolyG(packet, driver, true); // is_quad = true
e223fa15 326 gpu_unai.fb_dirty = true;
0bfe8d59 327 DO_LOG(("gpuDrawPolyG(0x%x) (4-pt QUAD)\n",PRIM));
328 }
329 } break;
330
331 case 0x3C:
332 case 0x3D:
333 case 0x3E:
334 case 0x3F: { // Gouraud-shaded, textured 4-pt poly
e223fa15 335 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 336 {
337 NULL_GPU();
e223fa15 338 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
339 gpuSetTexture (le32_to_u32(gpu_unai.PacketBuffer.U4[5]) >> 16);
0bfe8d59 340 PP driver = gpuPolySpanDrivers[
e223fa15 341 (gpu_unai.blit_mask?1024:0) |
0bfe8d59 342 Dithering |
e223fa15 343 Blending_Mode | gpu_unai.TEXT_MODE |
344 gpu_unai.Masking | Blending | ((Lighting)?129:0) | gpu_unai.PixelMSB
0bfe8d59 345 ];
346 gpuDrawPolyGT(packet, driver, true); // is_quad = true
e223fa15 347 gpu_unai.fb_dirty = true;
0bfe8d59 348 DO_LOG(("gpuDrawPolyGT(0x%x) (4-pt QUAD)\n",PRIM));
349 }
350 } break;
351
352 case 0x40:
353 case 0x41:
354 case 0x42:
355 case 0x43: { // Monochrome line
e223fa15 356 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 357 {
358 NULL_GPU();
359 // Shift index right by one, as untextured prims don't use lighting
e223fa15 360 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
0bfe8d59 361 PSD driver = gpuPixelSpanDrivers[driver_idx];
362 gpuDrawLineF(packet, driver);
e223fa15 363 gpu_unai.fb_dirty = true;
0bfe8d59 364 DO_LOG(("gpuDrawLineF(0x%x)\n",PRIM));
365 }
366 } break;
367
368 case 0x48:
369 case 0x49:
370 case 0x4A:
371 case 0x4B:
372 case 0x4C:
373 case 0x4D:
374 case 0x4E:
375 case 0x4F: { // Monochrome line strip
e223fa15 376 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 377 {
378 NULL_GPU();
379 // Shift index right by one, as untextured prims don't use lighting
e223fa15 380 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
0bfe8d59 381 PSD driver = gpuPixelSpanDrivers[driver_idx];
382 gpuDrawLineF(packet, driver);
e223fa15 383 gpu_unai.fb_dirty = true;
0bfe8d59 384 DO_LOG(("gpuDrawLineF(0x%x)\n",PRIM));
385 }
e223fa15 386 if ((le32_raw(gpu_unai.PacketBuffer.U4[3]) & HTOLE32(0xF000F000)) != HTOLE32(0x50005000))
0bfe8d59 387 {
e223fa15 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;
0bfe8d59 392 }
393 } break;
394
395 case 0x50:
396 case 0x51:
397 case 0x52:
398 case 0x53: { // Gouraud-shaded line
e223fa15 399 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 400 {
401 NULL_GPU();
402 // Shift index right by one, as untextured prims don't use lighting
e223fa15 403 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
0bfe8d59 404 // Index MSB selects Gouraud-shaded PixelSpanDriver:
405 driver_idx |= (1 << 5);
406 PSD driver = gpuPixelSpanDrivers[driver_idx];
407 gpuDrawLineG(packet, driver);
e223fa15 408 gpu_unai.fb_dirty = true;
0bfe8d59 409 DO_LOG(("gpuDrawLineG(0x%x)\n",PRIM));
410 }
411 } break;
412
413 case 0x58:
414 case 0x59:
415 case 0x5A:
416 case 0x5B:
417 case 0x5C:
418 case 0x5D:
419 case 0x5E:
420 case 0x5F: { // Gouraud-shaded line strip
e223fa15 421 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 422 {
423 NULL_GPU();
424 // Shift index right by one, as untextured prims don't use lighting
e223fa15 425 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
0bfe8d59 426 // Index MSB selects Gouraud-shaded PixelSpanDriver:
427 driver_idx |= (1 << 5);
428 PSD driver = gpuPixelSpanDrivers[driver_idx];
429 gpuDrawLineG(packet, driver);
e223fa15 430 gpu_unai.fb_dirty = true;
0bfe8d59 431 DO_LOG(("gpuDrawLineG(0x%x)\n",PRIM));
432 }
e223fa15 433 if ((le32_raw(gpu_unai.PacketBuffer.U4[4]) & HTOLE32(0xF000F000)) != HTOLE32(0x50005000))
0bfe8d59 434 {
e223fa15 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;
0bfe8d59 441 }
442 } break;
443
444 case 0x60:
445 case 0x61:
446 case 0x62:
447 case 0x63: { // Monochrome rectangle (variable size)
e223fa15 448 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 449 {
450 NULL_GPU();
e223fa15 451 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
0bfe8d59 452 gpuDrawT(packet, driver);
e223fa15 453 gpu_unai.fb_dirty = true;
0bfe8d59 454 DO_LOG(("gpuDrawT(0x%x)\n",PRIM));
455 }
456 } break;
457
458 case 0x64:
459 case 0x65:
460 case 0x66:
461 case 0x67: { // Textured rectangle (variable size)
e223fa15 462 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 463 {
464 NULL_GPU();
e223fa15 465 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
466 u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1);
0bfe8d59 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,
e223fa15 472 // gpu_unai uses a simple lighting LUT whereby only the upper
0bfe8d59 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)
e223fa15 479 //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))
0bfe8d59 480 // Strip lower 3 bits of each color and determine if lighting should be used:
e223fa15 481 if ((le32_raw(gpu_unai.PacketBuffer.U4[0]) & HTOLE32(0xF8F8F8)) != HTOLE32(0x808080))
0bfe8d59 482 driver_idx |= Lighting;
483 PS driver = gpuSpriteSpanDrivers[driver_idx];
484 gpuDrawS(packet, driver);
e223fa15 485 gpu_unai.fb_dirty = true;
0bfe8d59 486 DO_LOG(("gpuDrawS(0x%x)\n",PRIM));
487 }
488 } break;
489
490 case 0x68:
491 case 0x69:
492 case 0x6A:
493 case 0x6B: { // Monochrome rectangle (1x1 dot)
e223fa15 494 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 495 {
496 NULL_GPU();
e223fa15 497 gpu_unai.PacketBuffer.U4[2] = u32_to_le32(0x00010001);
498 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
0bfe8d59 499 gpuDrawT(packet, driver);
e223fa15 500 gpu_unai.fb_dirty = true;
0bfe8d59 501 DO_LOG(("gpuDrawT(0x%x)\n",PRIM));
502 }
503 } break;
504
505 case 0x70:
506 case 0x71:
507 case 0x72:
508 case 0x73: { // Monochrome rectangle (8x8)
e223fa15 509 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 510 {
511 NULL_GPU();
e223fa15 512 gpu_unai.PacketBuffer.U4[2] = u32_to_le32(0x00080008);
513 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
0bfe8d59 514 gpuDrawT(packet, driver);
e223fa15 515 gpu_unai.fb_dirty = true;
0bfe8d59 516 DO_LOG(("gpuDrawT(0x%x)\n",PRIM));
517 }
518 } break;
519
520 case 0x74:
521 case 0x75:
522 case 0x76:
523 case 0x77: { // Textured rectangle (8x8)
e223fa15 524 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 525 {
526 NULL_GPU();
e223fa15 527 gpu_unai.PacketBuffer.U4[3] = u32_to_le32(0x00080008);
528 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
529 u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1);
0bfe8d59 530
531 //senquack - Only color 808080h-878787h allows skipping lighting calculation:
e223fa15 532 //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))
0bfe8d59 533 // Strip lower 3 bits of each color and determine if lighting should be used:
e223fa15 534 if ((le32_raw(gpu_unai.PacketBuffer.U4[0]) & HTOLE32(0xF8F8F8)) != HTOLE32(0x808080))
0bfe8d59 535 driver_idx |= Lighting;
536 PS driver = gpuSpriteSpanDrivers[driver_idx];
537 gpuDrawS(packet, driver);
e223fa15 538 gpu_unai.fb_dirty = true;
0bfe8d59 539 DO_LOG(("gpuDrawS(0x%x)\n",PRIM));
540 }
541 } break;
542
543 case 0x78:
544 case 0x79:
545 case 0x7A:
546 case 0x7B: { // Monochrome rectangle (16x16)
e223fa15 547 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 548 {
549 NULL_GPU();
e223fa15 550 gpu_unai.PacketBuffer.U4[2] = u32_to_le32(0x00100010);
551 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
0bfe8d59 552 gpuDrawT(packet, driver);
e223fa15 553 gpu_unai.fb_dirty = true;
0bfe8d59 554 DO_LOG(("gpuDrawT(0x%x)\n",PRIM));
555 }
556 } break;
557
558 case 0x7C:
559 case 0x7D:
560 #ifdef __arm__
561 /* Notaz 4bit sprites optimization */
e223fa15 562 if ((!gpu_unai.frameskip.skipGPU) && (!(gpu_unai.GPU_GP1&0x180)) && (!(gpu_unai.Masking|gpu_unai.PixelMSB)))
0bfe8d59 563 {
e223fa15 564 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
0bfe8d59 565 gpuDrawS16(packet);
e223fa15 566 gpu_unai.fb_dirty = true;
0bfe8d59 567 break;
568 }
569 #endif
570 case 0x7E:
571 case 0x7F: { // Textured rectangle (16x16)
e223fa15 572 if (!gpu_unai.frameskip.skipGPU)
0bfe8d59 573 {
574 NULL_GPU();
e223fa15 575 gpu_unai.PacketBuffer.U4[3] = u32_to_le32(0x00100010);
576 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
577 u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1);
0bfe8d59 578
579 //senquack - Only color 808080h-878787h allows skipping lighting calculation:
e223fa15 580 //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))
0bfe8d59 581 // Strip lower 3 bits of each color and determine if lighting should be used:
e223fa15 582 if ((le32_raw(gpu_unai.PacketBuffer.U4[0]) & HTOLE32(0xF8F8F8)) != HTOLE32(0x808080))
0bfe8d59 583 driver_idx |= Lighting;
584 PS driver = gpuSpriteSpanDrivers[driver_idx];
585 gpuDrawS(packet, driver);
e223fa15 586 gpu_unai.fb_dirty = true;
0bfe8d59 587 DO_LOG(("gpuDrawS(0x%x)\n",PRIM));
588 }
589 } break;
590
591 case 0x80: // vid -> vid
592 gpuMoveImage(packet); // prim handles updateLace && skip
e223fa15 593 if ((!gpu_unai.frameskip.skipCount) && (gpu_unai.DisplayArea[3] == 480)) // Tekken 3 hack
0bfe8d59 594 {
e223fa15 595 if (!gpu_unai.frameskip.skipGPU) gpu_unai.fb_dirty = true;
0bfe8d59 596 }
597 else
598 {
e223fa15 599 gpu_unai.fb_dirty = true;
0bfe8d59 600 }
601 DO_LOG(("gpuMoveImage(0x%x)\n",PRIM));
602 break;
603 case 0xA0: // sys ->vid
604 gpuLoadImage(packet); // prim handles updateLace && skip
605 DO_LOG(("gpuLoadImage(0x%x)\n",PRIM));
606 break;
607 case 0xC0: // vid -> sys
608 gpuStoreImage(packet); // prim handles updateLace && skip
609 DO_LOG(("gpuStoreImage(0x%x)\n",PRIM));
610 break;
611 case 0xE1 ... 0xE6: { // Draw settings
e223fa15 612 gpuGP0Cmd_0xEx(gpu_unai, le32_to_u32(gpu_unai.PacketBuffer.U4[0]));
0bfe8d59 613 } break;
614 }
615}
616#endif //!USE_GPULIB
617///////////////////////////////////////////////////////////////////////////////
e223fa15 618// End of code specific to non-gpulib standalone version of gpu_unai
0bfe8d59 619///////////////////////////////////////////////////////////////////////////////
620
621#endif /* __GPU_UNAI_GPU_COMMAND_H__ */