Backport GPU Unai plugin from PCSX4ALL
[pcsx_rearmed.git] / plugins / gpu_unai / gpu_command.h
CommitLineData
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 23void 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///////////////////////////////////////////////////////////////////////////////
49INLINE 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
80static 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
151void 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///////////////////////////////////////////////////////////////////////////////