Merge pull request #436 from negativeExponent/patch-1
[pcsx_rearmed.git] / plugins / gpu_unai / gpulib_if.cpp
CommitLineData
6f2ee2be 1/***************************************************************************
2* Copyright (C) 2010 PCSX4ALL Team *
3* Copyright (C) 2010 Unai *
4* Copyright (C) 2011 notaz *
030d1121 5* Copyright (C) 2016 Senquack (dansilsby <AT> gmail <DOT> com) *
6f2ee2be 6* *
7* This program is free software; you can redistribute it and/or modify *
8* it under the terms of the GNU General Public License as published by *
9* the Free Software Foundation; either version 2 of the License, or *
10* (at your option) any later version. *
11* *
12* This program is distributed in the hope that it will be useful, *
13* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15* GNU General Public License for more details. *
16* *
17* You should have received a copy of the GNU General Public License *
18* along with this program; if not, write to the *
19* Free Software Foundation, Inc., *
20* 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
21***************************************************************************/
22
030d1121 23#include <stddef.h>
6f2ee2be 24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
62d7fa95 27#include "../gpulib/gpu.h"
030d1121 28//#include "port.h"
29#include "gpu_unai.h"
6f2ee2be 30
030d1121 31// GPU fixed point math
32#include "gpu_fixedpoint.h"
6f2ee2be 33
030d1121 34// Inner loop driver instantiation file
35#include "gpu_inner.h"
6f2ee2be 36
37// GPU internal image drawing functions
030d1121 38#include "gpu_raster_image.h"
6f2ee2be 39
40// GPU internal line drawing functions
030d1121 41#include "gpu_raster_line.h"
6f2ee2be 42
43// GPU internal polygon drawing functions
030d1121 44#include "gpu_raster_polygon.h"
6f2ee2be 45
46// GPU internal sprite drawing functions
030d1121 47#include "gpu_raster_sprite.h"
6f2ee2be 48
49// GPU command buffer execution/store
030d1121 50#include "gpu_command.h"
6f2ee2be 51
6f2ee2be 52/////////////////////////////////////////////////////////////////////////////
53
54int renderer_init(void)
55{
030d1121 56 memset((void*)&gpu_unai, 0, sizeof(gpu_unai));
57 gpu_unai.vram = (u16*)gpu.vram;
58
59 // Original standalone gpu_unai initialized TextureWindow[]. I added the
60 // same behavior here, since it seems unsafe to leave [2],[3] unset when
61 // using HLE and Rearmed gpu_neon sets this similarly on init. -senquack
62 gpu_unai.TextureWindow[0] = 0;
63 gpu_unai.TextureWindow[1] = 0;
64 gpu_unai.TextureWindow[2] = 255;
65 gpu_unai.TextureWindow[3] = 255;
66 //senquack - new vars must be updated whenever texture window is changed:
67 // (used for polygon-drawing in gpu_inner.h, gpu_raster_polygon.h)
68 const u32 fb = FIXED_BITS; // # of fractional fixed-pt bits of u4/v4
69 gpu_unai.u_msk = (((u32)gpu_unai.TextureWindow[2]) << fb) | ((1 << fb) - 1);
70 gpu_unai.v_msk = (((u32)gpu_unai.TextureWindow[3]) << fb) | ((1 << fb) - 1);
71
72 // Configuration options
73 gpu_unai.config = gpu_unai_config_ext;
74 //senquack - disabled, not sure this is needed and would require modifying
75 // sprite-span functions, perhaps unnecessarily. No Abe Oddysey hack was
76 // present in latest PCSX4ALL sources we were using.
77 //gpu_unai.config.enableAbbeyHack = gpu_unai_config_ext.abe_hack;
78 gpu_unai.ilace_mask = gpu_unai.config.ilace_force;
79
80#ifdef GPU_UNAI_USE_INT_DIV_MULTINV
81 // s_invTable
82 for(int i=1;i<=(1<<TABLE_BITS);++i)
83 {
84 double v = 1.0 / double(i);
85#ifdef GPU_TABLE_10_BITS
86 v *= double(0xffffffff>>1);
87#else
88 v *= double(0x80000000);
89#endif
90 s_invTable[i-1]=s32(v);
91 }
92#endif
93
94 SetupLightLUT();
95 SetupDitheringConstants();
96
97 return 0;
6f2ee2be 98}
99
e929dec5 100void renderer_finish(void)
101{
102}
103
104void renderer_notify_res_change(void)
105{
030d1121 106 if (PixelSkipEnabled()) {
107 // Set blit_mask for high horizontal resolutions. This allows skipping
108 // rendering pixels that would never get displayed on low-resolution
109 // platforms that use simple pixel-dropping scaler.
110
111 switch (gpu.screen.hres)
112 {
113 case 512: gpu_unai.blit_mask = 0xa4; break; // GPU_BlitWWSWWSWS
114 case 640: gpu_unai.blit_mask = 0xaa; break; // GPU_BlitWS
115 default: gpu_unai.blit_mask = 0; break;
116 }
117 } else {
118 gpu_unai.blit_mask = 0;
119 }
120
121 if (LineSkipEnabled()) {
122 // Set rendering line-skip (only render every other line in high-res
123 // 480 vertical mode, or, optionally, force it for all video modes)
124
125 if (gpu.screen.vres == 480) {
126 if (gpu_unai.config.ilace_force) {
127 gpu_unai.ilace_mask = 3; // Only need 1/4 of lines
128 } else {
129 gpu_unai.ilace_mask = 1; // Only need 1/2 of lines
130 }
131 } else {
132 // Vert resolution changed from 480 to lower one
133 gpu_unai.ilace_mask = gpu_unai.config.ilace_force;
134 }
135 } else {
136 gpu_unai.ilace_mask = 0;
137 }
138
139 /*
140 printf("res change hres: %d vres: %d depth: %d ilace_mask: %d\n",
141 gpu.screen.hres, gpu.screen.vres, gpu.status.rgb24 ? 24 : 15,
142 gpu_unai.ilace_mask);
143 */
144}
145
12367ad0 146#ifdef USE_GPULIB
030d1121 147// Handles GP0 draw settings commands 0xE1...0xE6
148static void gpuGP0Cmd_0xEx(gpu_unai_t &gpu_unai, u32 cmd_word)
149{
150 // Assume incoming GP0 command is 0xE1..0xE6, convert to 1..6
151 u8 num = (cmd_word >> 24) & 7;
152 gpu.ex_regs[num] = cmd_word; // Update gpulib register
153 switch (num) {
154 case 1: {
155 // GP0(E1h) - Draw Mode setting (aka "Texpage")
156 u32 cur_texpage = gpu_unai.GPU_GP1 & 0x7FF;
157 u32 new_texpage = cmd_word & 0x7FF;
158 if (cur_texpage != new_texpage) {
159 gpu_unai.GPU_GP1 = (gpu_unai.GPU_GP1 & ~0x7FF) | new_texpage;
160 gpuSetTexture(gpu_unai.GPU_GP1);
161 }
162 } break;
163
164 case 2: {
165 // GP0(E2h) - Texture Window setting
166 if (cmd_word != gpu_unai.TextureWindowCur) {
167 static const u8 TextureMask[32] = {
168 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
169 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
170 };
171 gpu_unai.TextureWindowCur = cmd_word;
172 gpu_unai.TextureWindow[0] = ((cmd_word >> 10) & 0x1F) << 3;
173 gpu_unai.TextureWindow[1] = ((cmd_word >> 15) & 0x1F) << 3;
174 gpu_unai.TextureWindow[2] = TextureMask[(cmd_word >> 0) & 0x1F];
175 gpu_unai.TextureWindow[3] = TextureMask[(cmd_word >> 5) & 0x1F];
176 gpu_unai.TextureWindow[0] &= ~gpu_unai.TextureWindow[2];
177 gpu_unai.TextureWindow[1] &= ~gpu_unai.TextureWindow[3];
178
179 // Inner loop vars must be updated whenever texture window is changed:
180 const u32 fb = FIXED_BITS; // # of fractional fixed-pt bits of u4/v4
181 gpu_unai.u_msk = (((u32)gpu_unai.TextureWindow[2]) << fb) | ((1 << fb) - 1);
182 gpu_unai.v_msk = (((u32)gpu_unai.TextureWindow[3]) << fb) | ((1 << fb) - 1);
183
184 gpuSetTexture(gpu_unai.GPU_GP1);
185 }
186 } break;
187
188 case 3: {
189 // GP0(E3h) - Set Drawing Area top left (X1,Y1)
190 gpu_unai.DrawingArea[0] = cmd_word & 0x3FF;
191 gpu_unai.DrawingArea[1] = (cmd_word >> 10) & 0x3FF;
192 } break;
193
194 case 4: {
195 // GP0(E4h) - Set Drawing Area bottom right (X2,Y2)
196 gpu_unai.DrawingArea[2] = (cmd_word & 0x3FF) + 1;
197 gpu_unai.DrawingArea[3] = ((cmd_word >> 10) & 0x3FF) + 1;
198 } break;
199
200 case 5: {
201 // GP0(E5h) - Set Drawing Offset (X,Y)
202 gpu_unai.DrawingOffset[0] = ((s32)cmd_word<<(32-11))>>(32-11);
203 gpu_unai.DrawingOffset[1] = ((s32)cmd_word<<(32-22))>>(32-11);
204 } break;
205
206 case 6: {
207 // GP0(E6h) - Mask Bit Setting
208 gpu_unai.Masking = (cmd_word & 0x2) << 1;
209 gpu_unai.PixelMSB = (cmd_word & 0x1) << 8;
210 } break;
211 }
e929dec5 212}
12367ad0 213#endif
e929dec5 214
6f2ee2be 215extern const unsigned char cmd_lengths[256];
216
5f315a8f 217int do_cmd_list(u32 *list, int list_len, int *last_cmd)
6f2ee2be 218{
5f315a8f 219 u32 cmd = 0, len, i;
220 u32 *list_start = list;
221 u32 *list_end = list + list_len;
6f2ee2be 222
030d1121 223 //TODO: set ilace_mask when resolution changes instead of every time,
224 // eliminate #ifdef below.
225 gpu_unai.ilace_mask = gpu_unai.config.ilace_force;
226
8f2bb0cb 227#ifdef HAVE_PRE_ARMV7 /* XXX */
030d1121 228 gpu_unai.ilace_mask |= gpu.status.interlace;
89c0de42 229#endif
230
6f2ee2be 231 for (; list < list_end; list += 1 + len)
232 {
6f2ee2be 233 cmd = *list >> 24;
234 len = cmd_lengths[cmd];
b243416b 235 if (list + 1 + len > list_end) {
236 cmd = -1;
237 break;
238 }
239
42a261f1 240 #define PRIM cmd
030d1121 241 gpu_unai.PacketBuffer.U4[0] = list[0];
42a261f1 242 for (i = 1; i <= len; i++)
030d1121 243 gpu_unai.PacketBuffer.U4[i] = list[i];
244
245 PtrUnion packet = { .ptr = (void*)&gpu_unai.PacketBuffer };
6f2ee2be 246
42a261f1 247 switch (cmd)
6f2ee2be 248 {
42a261f1 249 case 0x02:
030d1121 250 gpuClearImage(packet);
42a261f1 251 break;
252
253 case 0x20:
254 case 0x21:
255 case 0x22:
030d1121 256 case 0x23: { // Monochrome 3-pt poly
257 PP driver = gpuPolySpanDrivers[
258 (gpu_unai.blit_mask?1024:0) |
259 Blending_Mode |
260 gpu_unai.Masking | Blending | gpu_unai.PixelMSB
261 ];
262 gpuDrawPolyF(packet, driver, false);
263 } break;
42a261f1 264
265 case 0x24:
266 case 0x25:
267 case 0x26:
030d1121 268 case 0x27: { // Textured 3-pt poly
269 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
270 gpuSetTexture(gpu_unai.PacketBuffer.U4[4] >> 16);
271
272 u32 driver_idx =
273 (gpu_unai.blit_mask?1024:0) |
274 Dithering |
275 Blending_Mode | gpu_unai.TEXT_MODE |
276 gpu_unai.Masking | Blending | gpu_unai.PixelMSB;
277
278 if (!FastLightingEnabled()) {
279 driver_idx |= Lighting;
280 } else {
281 if (!((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)))
282 driver_idx |= Lighting;
283 }
284
285 PP driver = gpuPolySpanDrivers[driver_idx];
286 gpuDrawPolyFT(packet, driver, false);
287 } break;
42a261f1 288
289 case 0x28:
290 case 0x29:
291 case 0x2A:
030d1121 292 case 0x2B: { // Monochrome 4-pt poly
293 PP driver = gpuPolySpanDrivers[
294 (gpu_unai.blit_mask?1024:0) |
295 Blending_Mode |
296 gpu_unai.Masking | Blending | gpu_unai.PixelMSB
297 ];
298 gpuDrawPolyF(packet, driver, true); // is_quad = true
299 } break;
42a261f1 300
301 case 0x2C:
302 case 0x2D:
303 case 0x2E:
030d1121 304 case 0x2F: { // Textured 4-pt poly
305 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
306 gpuSetTexture(gpu_unai.PacketBuffer.U4[4] >> 16);
307
308 u32 driver_idx =
309 (gpu_unai.blit_mask?1024:0) |
310 Dithering |
311 Blending_Mode | gpu_unai.TEXT_MODE |
312 gpu_unai.Masking | Blending | gpu_unai.PixelMSB;
313
314 if (!FastLightingEnabled()) {
315 driver_idx |= Lighting;
316 } else {
317 if (!((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)))
318 driver_idx |= Lighting;
319 }
320
321 PP driver = gpuPolySpanDrivers[driver_idx];
322 gpuDrawPolyFT(packet, driver, true); // is_quad = true
323 } break;
42a261f1 324
325 case 0x30:
326 case 0x31:
327 case 0x32:
030d1121 328 case 0x33: { // Gouraud-shaded 3-pt poly
329 //NOTE: The '129' here is CF_GOURAUD | CF_LIGHT, however
330 // this is an untextured poly, so CF_LIGHT (texture blend)
331 // shouldn't apply. Until the original array of template
332 // instantiation ptrs is fixed, we're stuck with this. (TODO)
333 PP driver = gpuPolySpanDrivers[
334 (gpu_unai.blit_mask?1024:0) |
335 Dithering |
336 Blending_Mode |
337 gpu_unai.Masking | Blending | 129 | gpu_unai.PixelMSB
338 ];
339 gpuDrawPolyG(packet, driver, false);
340 } break;
42a261f1 341
342 case 0x34:
343 case 0x35:
344 case 0x36:
030d1121 345 case 0x37: { // Gouraud-shaded, textured 3-pt poly
346 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
347 gpuSetTexture (gpu_unai.PacketBuffer.U4[5] >> 16);
348 PP driver = gpuPolySpanDrivers[
349 (gpu_unai.blit_mask?1024:0) |
350 Dithering |
351 Blending_Mode | gpu_unai.TEXT_MODE |
352 gpu_unai.Masking | Blending | ((Lighting)?129:0) | gpu_unai.PixelMSB
353 ];
354 gpuDrawPolyGT(packet, driver, false);
355 } break;
42a261f1 356
357 case 0x38:
358 case 0x39:
359 case 0x3A:
030d1121 360 case 0x3B: { // Gouraud-shaded 4-pt poly
361 // See notes regarding '129' for 0x30..0x33 further above -senquack
362 PP driver = gpuPolySpanDrivers[
363 (gpu_unai.blit_mask?1024:0) |
364 Dithering |
365 Blending_Mode |
366 gpu_unai.Masking | Blending | 129 | gpu_unai.PixelMSB
367 ];
368 gpuDrawPolyG(packet, driver, true); // is_quad = true
369 } break;
42a261f1 370
371 case 0x3C:
372 case 0x3D:
373 case 0x3E:
030d1121 374 case 0x3F: { // Gouraud-shaded, textured 4-pt poly
375 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
376 gpuSetTexture (gpu_unai.PacketBuffer.U4[5] >> 16);
377 PP driver = gpuPolySpanDrivers[
378 (gpu_unai.blit_mask?1024:0) |
379 Dithering |
380 Blending_Mode | gpu_unai.TEXT_MODE |
381 gpu_unai.Masking | Blending | ((Lighting)?129:0) | gpu_unai.PixelMSB
382 ];
383 gpuDrawPolyGT(packet, driver, true); // is_quad = true
384 } break;
42a261f1 385
386 case 0x40:
387 case 0x41:
388 case 0x42:
030d1121 389 case 0x43: { // Monochrome line
390 // Shift index right by one, as untextured prims don't use lighting
391 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
392 PSD driver = gpuPixelSpanDrivers[driver_idx];
393 gpuDrawLineF(packet, driver);
394 } break;
395
396 case 0x48 ... 0x4F: { // Monochrome line strip
6f2ee2be 397 u32 num_vertexes = 1;
5f315a8f 398 u32 *list_position = &(list[2]);
8aea5f5a 399
030d1121 400 // Shift index right by one, as untextured prims don't use lighting
401 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
402 PSD driver = gpuPixelSpanDrivers[driver_idx];
403 gpuDrawLineF(packet, driver);
6f2ee2be 404
405 while(1)
406 {
030d1121 407 gpu_unai.PacketBuffer.U4[1] = gpu_unai.PacketBuffer.U4[2];
408 gpu_unai.PacketBuffer.U4[2] = *list_position++;
409 gpuDrawLineF(packet, driver);
8aea5f5a 410
6f2ee2be 411 num_vertexes++;
5f315a8f 412 if(list_position >= list_end) {
804789d7 413 cmd = -1;
414 goto breakloop;
415 }
416 if((*list_position & 0xf000f000) == 0x50005000)
b243416b 417 break;
6f2ee2be 418 }
419
b243416b 420 len += (num_vertexes - 2);
030d1121 421 } break;
6f2ee2be 422
42a261f1 423 case 0x50:
424 case 0x51:
425 case 0x52:
030d1121 426 case 0x53: { // Gouraud-shaded line
427 // Shift index right by one, as untextured prims don't use lighting
428 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
429 // Index MSB selects Gouraud-shaded PixelSpanDriver:
430 driver_idx |= (1 << 5);
431 PSD driver = gpuPixelSpanDrivers[driver_idx];
432 gpuDrawLineG(packet, driver);
433 } break;
434
435 case 0x58 ... 0x5F: { // Gouraud-shaded line strip
6f2ee2be 436 u32 num_vertexes = 1;
5f315a8f 437 u32 *list_position = &(list[2]);
8aea5f5a 438
030d1121 439 // Shift index right by one, as untextured prims don't use lighting
440 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
441 // Index MSB selects Gouraud-shaded PixelSpanDriver:
442 driver_idx |= (1 << 5);
443 PSD driver = gpuPixelSpanDrivers[driver_idx];
444 gpuDrawLineG(packet, driver);
6f2ee2be 445
446 while(1)
447 {
030d1121 448 gpu_unai.PacketBuffer.U4[0] = gpu_unai.PacketBuffer.U4[2];
449 gpu_unai.PacketBuffer.U4[1] = gpu_unai.PacketBuffer.U4[3];
450 gpu_unai.PacketBuffer.U4[2] = *list_position++;
451 gpu_unai.PacketBuffer.U4[3] = *list_position++;
452 gpuDrawLineG(packet, driver);
8aea5f5a 453
6f2ee2be 454 num_vertexes++;
5f315a8f 455 if(list_position >= list_end) {
804789d7 456 cmd = -1;
457 goto breakloop;
458 }
459 if((*list_position & 0xf000f000) == 0x50005000)
b243416b 460 break;
6f2ee2be 461 }
462
b243416b 463 len += (num_vertexes - 2) * 2;
030d1121 464 } break;
6f2ee2be 465
42a261f1 466 case 0x60:
467 case 0x61:
468 case 0x62:
030d1121 469 case 0x63: { // Monochrome rectangle (variable size)
470 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
471 gpuDrawT(packet, driver);
472 } break;
42a261f1 473
474 case 0x64:
475 case 0x65:
476 case 0x66:
030d1121 477 case 0x67: { // Textured rectangle (variable size)
478 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
479 u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1);
480
481 //senquack - Only color 808080h-878787h allows skipping lighting calculation:
482 // This fixes Silent Hill running animation on loading screens:
483 // (On PSX, color values 0x00-0x7F darken the source texture's color,
484 // 0x81-FF lighten textures (ultimately clamped to 0x1F),
485 // 0x80 leaves source texture color unchanged, HOWEVER,
486 // gpu_unai uses a simple lighting LUT whereby only the upper
487 // 5 bits of an 8-bit color are used, so 0x80-0x87 all behave as
488 // 0x80.
489 //
490 // NOTE: I've changed all textured sprite draw commands here and
491 // elsewhere to use proper behavior, but left poly commands
492 // alone, I don't want to slow rendering down too much. (TODO)
493 //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))
494 // Strip lower 3 bits of each color and determine if lighting should be used:
495 if ((gpu_unai.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080)
496 driver_idx |= Lighting;
497 PS driver = gpuSpriteSpanDrivers[driver_idx];
498 gpuDrawS(packet, driver);
499 } break;
42a261f1 500
501 case 0x68:
502 case 0x69:
503 case 0x6A:
030d1121 504 case 0x6B: { // Monochrome rectangle (1x1 dot)
505 gpu_unai.PacketBuffer.U4[2] = 0x00010001;
506 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
507 gpuDrawT(packet, driver);
508 } break;
42a261f1 509
510 case 0x70:
511 case 0x71:
512 case 0x72:
030d1121 513 case 0x73: { // Monochrome rectangle (8x8)
514 gpu_unai.PacketBuffer.U4[2] = 0x00080008;
515 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
516 gpuDrawT(packet, driver);
517 } break;
42a261f1 518
519 case 0x74:
520 case 0x75:
521 case 0x76:
030d1121 522 case 0x77: { // Textured rectangle (8x8)
523 gpu_unai.PacketBuffer.U4[3] = 0x00080008;
524 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
525 u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1);
526
527 //senquack - Only color 808080h-878787h allows skipping lighting calculation:
528 //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))
529 // Strip lower 3 bits of each color and determine if lighting should be used:
530 if ((gpu_unai.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080)
531 driver_idx |= Lighting;
532 PS driver = gpuSpriteSpanDrivers[driver_idx];
533 gpuDrawS(packet, driver);
534 } break;
42a261f1 535
536 case 0x78:
537 case 0x79:
538 case 0x7A:
030d1121 539 case 0x7B: { // Monochrome rectangle (16x16)
540 gpu_unai.PacketBuffer.U4[2] = 0x00100010;
541 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
542 gpuDrawT(packet, driver);
543 } break;
42a261f1 544
545 case 0x7C:
546 case 0x7D:
547#ifdef __arm__
030d1121 548 if ((gpu_unai.GPU_GP1 & 0x180) == 0 && (gpu_unai.Masking | gpu_unai.PixelMSB) == 0)
42a261f1 549 {
030d1121 550 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
551 gpuDrawS16(packet);
42a261f1 552 break;
553 }
554 // fallthrough
555#endif
556 case 0x7E:
030d1121 557 case 0x7F: { // Textured rectangle (16x16)
558 gpu_unai.PacketBuffer.U4[3] = 0x00100010;
559 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
560 u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1);
561 //senquack - Only color 808080h-878787h allows skipping lighting calculation:
562 //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))
563 // Strip lower 3 bits of each color and determine if lighting should be used:
564 if ((gpu_unai.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080)
565 driver_idx |= Lighting;
566 PS driver = gpuSpriteSpanDrivers[driver_idx];
567 gpuDrawS(packet, driver);
568 } break;
42a261f1 569
570 case 0x80: // vid -> vid
030d1121 571 gpuMoveImage(packet);
42a261f1 572 break;
030d1121 573
9a6e7816 574#ifdef TEST
575 case 0xA0: // sys -> vid
576 {
577 u32 load_width = list[2] & 0xffff;
578 u32 load_height = list[2] >> 16;
579 u32 load_size = load_width * load_height;
580
581 len += load_size / 2;
030d1121 582 } break;
583
42a261f1 584 case 0xC0:
585 break;
586#else
587 case 0xA0: // sys ->vid
588 case 0xC0: // vid -> sys
030d1121 589 // Handled by gpulib
42a261f1 590 goto breakloop;
9a6e7816 591#endif
030d1121 592 case 0xE1 ... 0xE6: { // Draw settings
593 gpuGP0Cmd_0xEx(gpu_unai, gpu_unai.PacketBuffer.U4[0]);
594 } break;
6f2ee2be 595 }
596 }
b243416b 597
42a261f1 598breakloop:
b243416b 599 gpu.ex_regs[1] &= ~0x1ff;
030d1121 600 gpu.ex_regs[1] |= gpu_unai.GPU_GP1 & 0x1ff;
b243416b 601
602 *last_cmd = cmd;
603 return list - list_start;
6f2ee2be 604}
605
606void renderer_sync_ecmds(uint32_t *ecmds)
607{
42a261f1 608 int dummy;
609 do_cmd_list(&ecmds[1], 6, &dummy);
6f2ee2be 610}
611
05740673 612void renderer_update_caches(int x, int y, int w, int h)
6f2ee2be 613{
614}
615
616void renderer_flush_queues(void)
617{
618}
914455e6 619
5440b88e 620void renderer_set_interlace(int enable, int is_odd)
621{
622}
623
914455e6 624#include "../../frontend/plugin_lib.h"
030d1121 625// Handle any gpulib settings applicable to gpu_unai:
914455e6 626void renderer_set_config(const struct rearmed_cbs *cbs)
627{
030d1121 628 gpu_unai.vram = (u16*)gpu.vram;
629 gpu_unai.config.ilace_force = cbs->gpu_unai.ilace_force;
630 gpu_unai.config.pixel_skip = cbs->gpu_unai.pixel_skip;
631 gpu_unai.config.lighting = cbs->gpu_unai.lighting;
632 gpu_unai.config.fast_lighting = cbs->gpu_unai.fast_lighting;
633 gpu_unai.config.blending = cbs->gpu_unai.blending;
634 gpu_unai.config.dithering = cbs->gpu_unai.dithering;
914455e6 635}
9a6e7816 636
42a261f1 637// vim:shiftwidth=2:expandtab