cdrom: change pause timing again
[pcsx_rearmed.git] / plugins / gpu_unai / gpu_command.h
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 ///////////////////////////////////////////////////////////////////////////////
26 void gpuSetTexture(u16 tpage)
27 {
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];
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
43         tx += (gpu_unai.TextureWindow[0] >> (2 - tmode));
44         ty += gpu_unai.TextureWindow[1];
45         
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)];
49 }
50
51 ///////////////////////////////////////////////////////////////////////////////
52 INLINE void gpuSetCLUT(u16 clut)
53 {
54         gpu_unai.CBA = &gpu_unai.vram[(clut & 0x7FFF) << 4];
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)
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 }
153
154 void 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)
160         PtrUnion packet = { .ptr = (void*)&gpu_unai.PacketBuffer };
161
162         switch (PRIM)
163         {
164                 case 0x02: {
165                         NULL_GPU();
166                         gpuClearImage(packet);    //  prim handles updateLace && skip
167                         gpu_unai.fb_dirty = true;
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
175                         if (!gpu_unai.frameskip.skipGPU)
176                         {
177                                 NULL_GPU();
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));
186                         }
187                 } break;
188
189                 case 0x24:
190                 case 0x25:
191                 case 0x26:
192                 case 0x27: {          // Textured 3-pt poly
193                         if (!gpu_unai.frameskip.skipGPU)
194                         {
195                                 NULL_GPU();
196                                 gpuSetCLUT    (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
197                                 gpuSetTexture (le32_to_u32(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));
216                         }
217                 } break;
218
219                 case 0x28:
220                 case 0x29:
221                 case 0x2A:
222                 case 0x2B: {          // Monochrome 4-pt poly
223                         if (!gpu_unai.frameskip.skipGPU)
224                         {
225                                 NULL_GPU();
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));
234                         }
235                 } break;
236
237                 case 0x2C:
238                 case 0x2D:
239                 case 0x2E:
240                 case 0x2F: {          // Textured 4-pt poly
241                         if (!gpu_unai.frameskip.skipGPU)
242                         {
243                                 NULL_GPU();
244                                 gpuSetCLUT    (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
245                                 gpuSetTexture (le32_to_u32(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));
264                         }
265                 } break;
266
267                 case 0x30:
268                 case 0x31:
269                 case 0x32:
270                 case 0x33: {          // Gouraud-shaded 3-pt poly
271                         if (!gpu_unai.frameskip.skipGPU)
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[
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));
287                         }
288                 } break;
289
290                 case 0x34:
291                 case 0x35:
292                 case 0x36:
293                 case 0x37: {          // Gouraud-shaded, textured 3-pt poly
294                         if (!gpu_unai.frameskip.skipGPU)
295                         {
296                                 NULL_GPU();
297                                 gpuSetCLUT    (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
298                                 gpuSetTexture (le32_to_u32(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));
308                         }
309                 } break;
310
311                 case 0x38:
312                 case 0x39:
313                 case 0x3A:
314                 case 0x3B: {          // Gouraud-shaded 4-pt poly
315                         if (!gpu_unai.frameskip.skipGPU)
316                         {
317                                 NULL_GPU();
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));
328                         }
329                 } break;
330
331                 case 0x3C:
332                 case 0x3D:
333                 case 0x3E:
334                 case 0x3F: {          // Gouraud-shaded, textured 4-pt poly
335                         if (!gpu_unai.frameskip.skipGPU)
336                         {
337                                 NULL_GPU();
338                                 gpuSetCLUT    (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
339                                 gpuSetTexture (le32_to_u32(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));
349                         }
350                 } break;
351
352                 case 0x40:
353                 case 0x41:
354                 case 0x42:
355                 case 0x43: {          // Monochrome line
356                         if (!gpu_unai.frameskip.skipGPU)
357                         {
358                                 NULL_GPU();
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));
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
376                         if (!gpu_unai.frameskip.skipGPU)
377                         {
378                                 NULL_GPU();
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));
385                         }
386                         if ((le32_raw(gpu_unai.PacketBuffer.U4[3]) & HTOLE32(0xF000F000)) != HTOLE32(0x50005000))
387                         {
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;
392                         }
393                 } break;
394
395                 case 0x50:
396                 case 0x51:
397                 case 0x52:
398                 case 0x53: {          // Gouraud-shaded line
399                         if (!gpu_unai.frameskip.skipGPU)
400                         {
401                                 NULL_GPU();
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));
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
421                         if (!gpu_unai.frameskip.skipGPU)
422                         {
423                                 NULL_GPU();
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));
432                         }
433                         if ((le32_raw(gpu_unai.PacketBuffer.U4[4]) & HTOLE32(0xF000F000)) != HTOLE32(0x50005000))
434                         {
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;
441                         }
442                 } break;
443
444                 case 0x60:
445                 case 0x61:
446                 case 0x62:
447                 case 0x63: {          // Monochrome rectangle (variable size)
448                         if (!gpu_unai.frameskip.skipGPU)
449                         {
450                                 NULL_GPU();
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;
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)
462                         if (!gpu_unai.frameskip.skipGPU)
463                         {
464                                 NULL_GPU();
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);
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 ((le32_raw(gpu_unai.PacketBuffer.U4[0]) & HTOLE32(0xF8F8F8)) != HTOLE32(0x808080))
482                                         driver_idx |= Lighting;
483                                 PS driver = gpuSpriteSpanDrivers[driver_idx];
484                                 gpuDrawS(packet, driver);
485                                 gpu_unai.fb_dirty = true;
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)
494                         if (!gpu_unai.frameskip.skipGPU)
495                         {
496                                 NULL_GPU();
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];
499                                 gpuDrawT(packet, driver);
500                                 gpu_unai.fb_dirty = true;
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)
509                         if (!gpu_unai.frameskip.skipGPU)
510                         {
511                                 NULL_GPU();
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];
514                                 gpuDrawT(packet, driver);
515                                 gpu_unai.fb_dirty = true;
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)
524                         if (!gpu_unai.frameskip.skipGPU)
525                         {
526                                 NULL_GPU();
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);
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 ((le32_raw(gpu_unai.PacketBuffer.U4[0]) & HTOLE32(0xF8F8F8)) != HTOLE32(0x808080))
535                                         driver_idx |= Lighting;
536                                 PS driver = gpuSpriteSpanDrivers[driver_idx];
537                                 gpuDrawS(packet, driver);
538                                 gpu_unai.fb_dirty = true;
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)
547                         if (!gpu_unai.frameskip.skipGPU)
548                         {
549                                 NULL_GPU();
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];
552                                 gpuDrawT(packet, driver);
553                                 gpu_unai.fb_dirty = true;
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 */
562                         if ((!gpu_unai.frameskip.skipGPU) && (!(gpu_unai.GPU_GP1&0x180)) && (!(gpu_unai.Masking|gpu_unai.PixelMSB)))
563                         {
564                                 gpuSetCLUT    (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
565                                 gpuDrawS16(packet);
566                                 gpu_unai.fb_dirty = true;
567                                 break;
568                         }
569                         #endif
570                 case 0x7E:
571                 case 0x7F: {          // Textured rectangle (16x16)
572                         if (!gpu_unai.frameskip.skipGPU)
573                         {
574                                 NULL_GPU();
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);
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 ((le32_raw(gpu_unai.PacketBuffer.U4[0]) & HTOLE32(0xF8F8F8)) != HTOLE32(0x808080))
583                                         driver_idx |= Lighting;
584                                 PS driver = gpuSpriteSpanDrivers[driver_idx];
585                                 gpuDrawS(packet, driver);
586                                 gpu_unai.fb_dirty = true;
587                                 DO_LOG(("gpuDrawS(0x%x)\n",PRIM));
588                         }
589                 } break;
590
591                 case 0x80:          //  vid -> vid
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                         }
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
612                         gpuGP0Cmd_0xEx(gpu_unai, le32_to_u32(gpu_unai.PacketBuffer.U4[0]));
613                 } break;
614         }
615 }
616 #endif //!USE_GPULIB
617 ///////////////////////////////////////////////////////////////////////////////
618 // End of code specific to non-gpulib standalone version of gpu_unai
619 ///////////////////////////////////////////////////////////////////////////////
620
621 #endif /* __GPU_UNAI_GPU_COMMAND_H__ */