some lightgun selection mechanism
[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"
c765eb86
JW
28
29#ifdef THREAD_RENDERING
30#include "../gpulib/gpulib_thread_if.h"
31#define do_cmd_list real_do_cmd_list
32#define renderer_init real_renderer_init
33#define renderer_finish real_renderer_finish
34#define renderer_sync_ecmds real_renderer_sync_ecmds
35#define renderer_update_caches real_renderer_update_caches
36#define renderer_flush_queues real_renderer_flush_queues
37#define renderer_set_interlace real_renderer_set_interlace
38#define renderer_set_config real_renderer_set_config
39#define renderer_notify_res_change real_renderer_notify_res_change
40#define renderer_notify_update_lace real_renderer_notify_update_lace
41#define renderer_sync real_renderer_sync
42#define ex_regs scratch_ex_regs
43#endif
44
030d1121 45//#include "port.h"
46#include "gpu_unai.h"
6f2ee2be 47
030d1121 48// GPU fixed point math
49#include "gpu_fixedpoint.h"
6f2ee2be 50
030d1121 51// Inner loop driver instantiation file
52#include "gpu_inner.h"
6f2ee2be 53
54// GPU internal image drawing functions
030d1121 55#include "gpu_raster_image.h"
6f2ee2be 56
57// GPU internal line drawing functions
030d1121 58#include "gpu_raster_line.h"
6f2ee2be 59
60// GPU internal polygon drawing functions
030d1121 61#include "gpu_raster_polygon.h"
6f2ee2be 62
63// GPU internal sprite drawing functions
030d1121 64#include "gpu_raster_sprite.h"
6f2ee2be 65
66// GPU command buffer execution/store
030d1121 67#include "gpu_command.h"
6f2ee2be 68
6f2ee2be 69/////////////////////////////////////////////////////////////////////////////
70
43047988
JW
71#define DOWNSCALE_VRAM_SIZE (1024 * 512 * 2 * 2 + 4096)
72
4949d4ff 73INLINE void scale_640_to_320(uint16_t *dest, const le16_t *src, bool isRGB24) {
43047988
JW
74 size_t uCount = 320;
75
76 if(isRGB24) {
77 const uint8_t* src8 = (const uint8_t *)src;
78 uint8_t* dst8 = (uint8_t *)dest;
79
80 do {
81 *dst8++ = *src8++;
82 *dst8++ = *src8++;
83 *dst8++ = *src8;
84 src8 += 4;
85 } while(--uCount);
86 } else {
4949d4ff 87 const le16_t *src16 = src;
43047988
JW
88 uint16_t* dst16 = dest;
89
90 do {
4949d4ff 91 *dst16++ = le16_to_u16(*src16);
43047988
JW
92 src16 += 2;
93 } while(--uCount);
94 }
95}
96
4949d4ff 97INLINE void scale_512_to_320(uint16_t *dest, const le16_t *src, bool isRGB24) {
43047988
JW
98 size_t uCount = 64;
99
100 if(isRGB24) {
101 const uint8_t* src8 = (const uint8_t *)src;
102 uint8_t* dst8 = (uint8_t *)dest;
103
104 do {
105 *dst8++ = *src8++;
106 *dst8++ = *src8++;
107 *dst8++ = *src8++;
108 *dst8++ = *src8++;
109 *dst8++ = *src8++;
110 *dst8++ = *src8;
111 src8 += 4;
112 *dst8++ = *src8++;
113 *dst8++ = *src8++;
114 *dst8++ = *src8++;
115 *dst8++ = *src8++;
116 *dst8++ = *src8++;
117 *dst8++ = *src8;
118 src8 += 4;
119 *dst8++ = *src8++;
120 *dst8++ = *src8++;
121 *dst8++ = *src8;
122 src8 += 4;
123 } while(--uCount);
124 } else {
4949d4ff 125 const le16_t* src16 = src;
43047988
JW
126 uint16_t* dst16 = dest;
127
128 do {
4949d4ff
PC
129 *dst16++ = le16_to_u16(*src16++);
130 *dst16++ = le16_to_u16(*src16);
43047988 131 src16 += 2;
4949d4ff
PC
132 *dst16++ = le16_to_u16(*src16++);
133 *dst16++ = le16_to_u16(*src16);
43047988 134 src16 += 2;
4949d4ff 135 *dst16++ = le16_to_u16(*src16);
43047988
JW
136 src16 += 2;
137 } while(--uCount);
138 }
139}
140
141static uint16_t *get_downscale_buffer(int *x, int *y, int *w, int *h, int *vram_h)
142{
143 uint16_t *dest = gpu_unai.downscale_vram;
4949d4ff 144 const le16_t *src = gpu_unai.vram;
43047988
JW
145 bool isRGB24 = (gpu_unai.GPU_GP1 & 0x00200000 ? true : false);
146 int stride = 1024, dstride = 1024, lines = *h, orig_w = *w;
147
148 // PS1 fb read wraps around (fixes black screen in 'Tobal no. 1')
149 unsigned int fb_mask = 1024 * 512 - 1;
150
151 if (*h > 240) {
152 *h /= 2;
153 stride *= 2;
154 lines = *h;
155
156 // Ensure start at a non-skipped line
157 while (*y & gpu_unai.ilace_mask) ++*y;
158 }
159
160 unsigned int fb_offset_src = (*y * dstride + *x) & fb_mask;
161 unsigned int fb_offset_dest = fb_offset_src;
162
163 if (*w == 512 || *w == 640) {
164 *w = 320;
165 }
166
167 switch(orig_w) {
168 case 640:
169 do {
170 scale_640_to_320(dest + fb_offset_dest, src + fb_offset_src, isRGB24);
171 fb_offset_src = (fb_offset_src + stride) & fb_mask;
172 fb_offset_dest = (fb_offset_dest + dstride) & fb_mask;
173 } while(--lines);
174
175 break;
176 case 512:
177 do {
178 scale_512_to_320(dest + fb_offset_dest, src + fb_offset_src, isRGB24);
179 fb_offset_src = (fb_offset_src + stride) & fb_mask;
180 fb_offset_dest = (fb_offset_dest + dstride) & fb_mask;
181 } while(--lines);
182 break;
183 default:
184 size_t size = isRGB24 ? *w * 3 : *w * 2;
185
186 do {
4949d4ff
PC
187#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
188 for (unsigned int i; i < size; i += 2)
189 dest[fb_offset_dest + i] = le16_to_u16(src[fb_offset_src + i]);
190#else
191 memcpy(dest + fb_offset_dest, (u16 *)src + fb_offset_src, size);
192#endif
43047988
JW
193 fb_offset_src = (fb_offset_src + stride) & fb_mask;
194 fb_offset_dest = (fb_offset_dest + dstride) & fb_mask;
195 } while(--lines);
196 break;
197 }
198
199 return gpu_unai.downscale_vram;
200}
201
202static void map_downscale_buffer(void)
203{
204 if (gpu_unai.downscale_vram)
205 return;
206
207 gpu_unai.downscale_vram = (uint16_t*)gpu.mmap(DOWNSCALE_VRAM_SIZE);
208
209 if (gpu_unai.downscale_vram == NULL) {
210 fprintf(stderr, "failed to map downscale buffer\n");
211 gpu.get_downscale_buffer = NULL;
212 }
213 else {
214 gpu.get_downscale_buffer = get_downscale_buffer;
215 }
216}
217
218static void unmap_downscale_buffer(void)
219{
220 if (gpu_unai.downscale_vram == NULL)
221 return;
222
223 gpu.munmap(gpu_unai.downscale_vram, DOWNSCALE_VRAM_SIZE);
224 gpu_unai.downscale_vram = NULL;
225 gpu.get_downscale_buffer = NULL;
226}
227
6f2ee2be 228int renderer_init(void)
229{
030d1121 230 memset((void*)&gpu_unai, 0, sizeof(gpu_unai));
4949d4ff 231 gpu_unai.vram = (le16_t *)gpu.vram;
030d1121 232
233 // Original standalone gpu_unai initialized TextureWindow[]. I added the
234 // same behavior here, since it seems unsafe to leave [2],[3] unset when
235 // using HLE and Rearmed gpu_neon sets this similarly on init. -senquack
236 gpu_unai.TextureWindow[0] = 0;
237 gpu_unai.TextureWindow[1] = 0;
238 gpu_unai.TextureWindow[2] = 255;
239 gpu_unai.TextureWindow[3] = 255;
240 //senquack - new vars must be updated whenever texture window is changed:
241 // (used for polygon-drawing in gpu_inner.h, gpu_raster_polygon.h)
242 const u32 fb = FIXED_BITS; // # of fractional fixed-pt bits of u4/v4
243 gpu_unai.u_msk = (((u32)gpu_unai.TextureWindow[2]) << fb) | ((1 << fb) - 1);
244 gpu_unai.v_msk = (((u32)gpu_unai.TextureWindow[3]) << fb) | ((1 << fb) - 1);
245
246 // Configuration options
247 gpu_unai.config = gpu_unai_config_ext;
248 //senquack - disabled, not sure this is needed and would require modifying
249 // sprite-span functions, perhaps unnecessarily. No Abe Oddysey hack was
250 // present in latest PCSX4ALL sources we were using.
251 //gpu_unai.config.enableAbbeyHack = gpu_unai_config_ext.abe_hack;
252 gpu_unai.ilace_mask = gpu_unai.config.ilace_force;
253
254#ifdef GPU_UNAI_USE_INT_DIV_MULTINV
255 // s_invTable
256 for(int i=1;i<=(1<<TABLE_BITS);++i)
257 {
258 double v = 1.0 / double(i);
259#ifdef GPU_TABLE_10_BITS
260 v *= double(0xffffffff>>1);
261#else
262 v *= double(0x80000000);
263#endif
264 s_invTable[i-1]=s32(v);
265 }
266#endif
267
268 SetupLightLUT();
269 SetupDitheringConstants();
270
43047988
JW
271 if (gpu_unai.config.scale_hires) {
272 map_downscale_buffer();
273 }
274
030d1121 275 return 0;
6f2ee2be 276}
277
e929dec5 278void renderer_finish(void)
279{
43047988 280 unmap_downscale_buffer();
e929dec5 281}
282
283void renderer_notify_res_change(void)
284{
030d1121 285 if (PixelSkipEnabled()) {
286 // Set blit_mask for high horizontal resolutions. This allows skipping
287 // rendering pixels that would never get displayed on low-resolution
288 // platforms that use simple pixel-dropping scaler.
289
290 switch (gpu.screen.hres)
291 {
292 case 512: gpu_unai.blit_mask = 0xa4; break; // GPU_BlitWWSWWSWS
293 case 640: gpu_unai.blit_mask = 0xaa; break; // GPU_BlitWS
294 default: gpu_unai.blit_mask = 0; break;
295 }
296 } else {
297 gpu_unai.blit_mask = 0;
298 }
299
300 if (LineSkipEnabled()) {
301 // Set rendering line-skip (only render every other line in high-res
302 // 480 vertical mode, or, optionally, force it for all video modes)
303
304 if (gpu.screen.vres == 480) {
305 if (gpu_unai.config.ilace_force) {
306 gpu_unai.ilace_mask = 3; // Only need 1/4 of lines
307 } else {
308 gpu_unai.ilace_mask = 1; // Only need 1/2 of lines
309 }
310 } else {
311 // Vert resolution changed from 480 to lower one
312 gpu_unai.ilace_mask = gpu_unai.config.ilace_force;
313 }
314 } else {
315 gpu_unai.ilace_mask = 0;
316 }
317
318 /*
319 printf("res change hres: %d vres: %d depth: %d ilace_mask: %d\n",
b9db55a9 320 gpu.screen.hres, gpu.screen.vres, (gpu.status & PSX_GPU_STATUS_RGB24) ? 24 : 15,
030d1121 321 gpu_unai.ilace_mask);
322 */
323}
324
3b7b0065 325void renderer_notify_scanout_x_change(int x, int w)
326{
327}
328
12367ad0 329#ifdef USE_GPULIB
030d1121 330// Handles GP0 draw settings commands 0xE1...0xE6
331static void gpuGP0Cmd_0xEx(gpu_unai_t &gpu_unai, u32 cmd_word)
332{
333 // Assume incoming GP0 command is 0xE1..0xE6, convert to 1..6
334 u8 num = (cmd_word >> 24) & 7;
335 gpu.ex_regs[num] = cmd_word; // Update gpulib register
336 switch (num) {
337 case 1: {
338 // GP0(E1h) - Draw Mode setting (aka "Texpage")
339 u32 cur_texpage = gpu_unai.GPU_GP1 & 0x7FF;
340 u32 new_texpage = cmd_word & 0x7FF;
341 if (cur_texpage != new_texpage) {
342 gpu_unai.GPU_GP1 = (gpu_unai.GPU_GP1 & ~0x7FF) | new_texpage;
343 gpuSetTexture(gpu_unai.GPU_GP1);
344 }
345 } break;
346
347 case 2: {
348 // GP0(E2h) - Texture Window setting
349 if (cmd_word != gpu_unai.TextureWindowCur) {
350 static const u8 TextureMask[32] = {
351 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
352 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
353 };
354 gpu_unai.TextureWindowCur = cmd_word;
355 gpu_unai.TextureWindow[0] = ((cmd_word >> 10) & 0x1F) << 3;
356 gpu_unai.TextureWindow[1] = ((cmd_word >> 15) & 0x1F) << 3;
357 gpu_unai.TextureWindow[2] = TextureMask[(cmd_word >> 0) & 0x1F];
358 gpu_unai.TextureWindow[3] = TextureMask[(cmd_word >> 5) & 0x1F];
359 gpu_unai.TextureWindow[0] &= ~gpu_unai.TextureWindow[2];
360 gpu_unai.TextureWindow[1] &= ~gpu_unai.TextureWindow[3];
361
362 // Inner loop vars must be updated whenever texture window is changed:
363 const u32 fb = FIXED_BITS; // # of fractional fixed-pt bits of u4/v4
364 gpu_unai.u_msk = (((u32)gpu_unai.TextureWindow[2]) << fb) | ((1 << fb) - 1);
365 gpu_unai.v_msk = (((u32)gpu_unai.TextureWindow[3]) << fb) | ((1 << fb) - 1);
366
367 gpuSetTexture(gpu_unai.GPU_GP1);
368 }
369 } break;
370
371 case 3: {
372 // GP0(E3h) - Set Drawing Area top left (X1,Y1)
373 gpu_unai.DrawingArea[0] = cmd_word & 0x3FF;
374 gpu_unai.DrawingArea[1] = (cmd_word >> 10) & 0x3FF;
375 } break;
376
377 case 4: {
378 // GP0(E4h) - Set Drawing Area bottom right (X2,Y2)
379 gpu_unai.DrawingArea[2] = (cmd_word & 0x3FF) + 1;
380 gpu_unai.DrawingArea[3] = ((cmd_word >> 10) & 0x3FF) + 1;
381 } break;
382
383 case 5: {
384 // GP0(E5h) - Set Drawing Offset (X,Y)
385 gpu_unai.DrawingOffset[0] = ((s32)cmd_word<<(32-11))>>(32-11);
386 gpu_unai.DrawingOffset[1] = ((s32)cmd_word<<(32-22))>>(32-11);
387 } break;
388
389 case 6: {
390 // GP0(E6h) - Mask Bit Setting
391 gpu_unai.Masking = (cmd_word & 0x2) << 1;
392 gpu_unai.PixelMSB = (cmd_word & 0x1) << 8;
393 } break;
394 }
e929dec5 395}
12367ad0 396#endif
e929dec5 397
6f2ee2be 398extern const unsigned char cmd_lengths[256];
399
4949d4ff 400int do_cmd_list(u32 *_list, int list_len, int *last_cmd)
6f2ee2be 401{
5f315a8f 402 u32 cmd = 0, len, i;
4949d4ff
PC
403 le32_t *list = (le32_t *)_list;
404 le32_t *list_start = list;
405 le32_t *list_end = list + list_len;
6f2ee2be 406
030d1121 407 //TODO: set ilace_mask when resolution changes instead of every time,
408 // eliminate #ifdef below.
409 gpu_unai.ilace_mask = gpu_unai.config.ilace_force;
410
8f2bb0cb 411#ifdef HAVE_PRE_ARMV7 /* XXX */
b9db55a9 412 gpu_unai.ilace_mask |= !!(gpu.status & PSX_GPU_STATUS_INTERLACE);
89c0de42 413#endif
43047988 414 if (gpu_unai.config.scale_hires) {
b9db55a9 415 gpu_unai.ilace_mask |= !!(gpu.status & PSX_GPU_STATUS_INTERLACE);
43047988 416 }
89c0de42 417
6f2ee2be 418 for (; list < list_end; list += 1 + len)
419 {
4949d4ff 420 cmd = le32_to_u32(*list) >> 24;
6f2ee2be 421 len = cmd_lengths[cmd];
b243416b 422 if (list + 1 + len > list_end) {
423 cmd = -1;
424 break;
425 }
426
42a261f1 427 #define PRIM cmd
030d1121 428 gpu_unai.PacketBuffer.U4[0] = list[0];
42a261f1 429 for (i = 1; i <= len; i++)
030d1121 430 gpu_unai.PacketBuffer.U4[i] = list[i];
431
432 PtrUnion packet = { .ptr = (void*)&gpu_unai.PacketBuffer };
6f2ee2be 433
42a261f1 434 switch (cmd)
6f2ee2be 435 {
42a261f1 436 case 0x02:
030d1121 437 gpuClearImage(packet);
42a261f1 438 break;
439
440 case 0x20:
441 case 0x21:
442 case 0x22:
030d1121 443 case 0x23: { // Monochrome 3-pt poly
444 PP driver = gpuPolySpanDrivers[
445 (gpu_unai.blit_mask?1024:0) |
446 Blending_Mode |
447 gpu_unai.Masking | Blending | gpu_unai.PixelMSB
448 ];
449 gpuDrawPolyF(packet, driver, false);
450 } break;
42a261f1 451
452 case 0x24:
453 case 0x25:
454 case 0x26:
030d1121 455 case 0x27: { // Textured 3-pt poly
4949d4ff
PC
456 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
457 gpuSetTexture(le32_to_u32(gpu_unai.PacketBuffer.U4[4]) >> 16);
030d1121 458
459 u32 driver_idx =
460 (gpu_unai.blit_mask?1024:0) |
461 Dithering |
462 Blending_Mode | gpu_unai.TEXT_MODE |
463 gpu_unai.Masking | Blending | gpu_unai.PixelMSB;
464
465 if (!FastLightingEnabled()) {
466 driver_idx |= Lighting;
467 } else {
468 if (!((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)))
469 driver_idx |= Lighting;
470 }
471
472 PP driver = gpuPolySpanDrivers[driver_idx];
473 gpuDrawPolyFT(packet, driver, false);
474 } break;
42a261f1 475
476 case 0x28:
477 case 0x29:
478 case 0x2A:
030d1121 479 case 0x2B: { // Monochrome 4-pt poly
480 PP driver = gpuPolySpanDrivers[
481 (gpu_unai.blit_mask?1024:0) |
482 Blending_Mode |
483 gpu_unai.Masking | Blending | gpu_unai.PixelMSB
484 ];
485 gpuDrawPolyF(packet, driver, true); // is_quad = true
486 } break;
42a261f1 487
488 case 0x2C:
489 case 0x2D:
490 case 0x2E:
030d1121 491 case 0x2F: { // Textured 4-pt poly
4949d4ff
PC
492 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
493 gpuSetTexture(le32_to_u32(gpu_unai.PacketBuffer.U4[4]) >> 16);
030d1121 494
495 u32 driver_idx =
496 (gpu_unai.blit_mask?1024:0) |
497 Dithering |
498 Blending_Mode | gpu_unai.TEXT_MODE |
499 gpu_unai.Masking | Blending | gpu_unai.PixelMSB;
500
501 if (!FastLightingEnabled()) {
502 driver_idx |= Lighting;
503 } else {
504 if (!((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)))
505 driver_idx |= Lighting;
506 }
507
508 PP driver = gpuPolySpanDrivers[driver_idx];
509 gpuDrawPolyFT(packet, driver, true); // is_quad = true
510 } break;
42a261f1 511
512 case 0x30:
513 case 0x31:
514 case 0x32:
030d1121 515 case 0x33: { // Gouraud-shaded 3-pt poly
516 //NOTE: The '129' here is CF_GOURAUD | CF_LIGHT, however
517 // this is an untextured poly, so CF_LIGHT (texture blend)
518 // shouldn't apply. Until the original array of template
519 // instantiation ptrs is fixed, we're stuck with this. (TODO)
520 PP driver = gpuPolySpanDrivers[
521 (gpu_unai.blit_mask?1024:0) |
522 Dithering |
523 Blending_Mode |
524 gpu_unai.Masking | Blending | 129 | gpu_unai.PixelMSB
525 ];
526 gpuDrawPolyG(packet, driver, false);
527 } break;
42a261f1 528
529 case 0x34:
530 case 0x35:
531 case 0x36:
030d1121 532 case 0x37: { // Gouraud-shaded, textured 3-pt poly
4949d4ff
PC
533 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
534 gpuSetTexture (le32_to_u32(gpu_unai.PacketBuffer.U4[5]) >> 16);
030d1121 535 PP driver = gpuPolySpanDrivers[
536 (gpu_unai.blit_mask?1024:0) |
537 Dithering |
538 Blending_Mode | gpu_unai.TEXT_MODE |
539 gpu_unai.Masking | Blending | ((Lighting)?129:0) | gpu_unai.PixelMSB
540 ];
541 gpuDrawPolyGT(packet, driver, false);
542 } break;
42a261f1 543
544 case 0x38:
545 case 0x39:
546 case 0x3A:
030d1121 547 case 0x3B: { // Gouraud-shaded 4-pt poly
548 // See notes regarding '129' for 0x30..0x33 further above -senquack
549 PP driver = gpuPolySpanDrivers[
550 (gpu_unai.blit_mask?1024:0) |
551 Dithering |
552 Blending_Mode |
553 gpu_unai.Masking | Blending | 129 | gpu_unai.PixelMSB
554 ];
555 gpuDrawPolyG(packet, driver, true); // is_quad = true
556 } break;
42a261f1 557
558 case 0x3C:
559 case 0x3D:
560 case 0x3E:
030d1121 561 case 0x3F: { // Gouraud-shaded, textured 4-pt poly
4949d4ff
PC
562 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
563 gpuSetTexture (le32_to_u32(gpu_unai.PacketBuffer.U4[5]) >> 16);
030d1121 564 PP driver = gpuPolySpanDrivers[
565 (gpu_unai.blit_mask?1024:0) |
566 Dithering |
567 Blending_Mode | gpu_unai.TEXT_MODE |
568 gpu_unai.Masking | Blending | ((Lighting)?129:0) | gpu_unai.PixelMSB
569 ];
570 gpuDrawPolyGT(packet, driver, true); // is_quad = true
571 } break;
42a261f1 572
573 case 0x40:
574 case 0x41:
575 case 0x42:
030d1121 576 case 0x43: { // Monochrome line
577 // Shift index right by one, as untextured prims don't use lighting
578 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
579 PSD driver = gpuPixelSpanDrivers[driver_idx];
580 gpuDrawLineF(packet, driver);
581 } break;
582
583 case 0x48 ... 0x4F: { // Monochrome line strip
6f2ee2be 584 u32 num_vertexes = 1;
4949d4ff 585 le32_t *list_position = &list[2];
8aea5f5a 586
030d1121 587 // Shift index right by one, as untextured prims don't use lighting
588 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
589 PSD driver = gpuPixelSpanDrivers[driver_idx];
590 gpuDrawLineF(packet, driver);
6f2ee2be 591
592 while(1)
593 {
030d1121 594 gpu_unai.PacketBuffer.U4[1] = gpu_unai.PacketBuffer.U4[2];
595 gpu_unai.PacketBuffer.U4[2] = *list_position++;
596 gpuDrawLineF(packet, driver);
8aea5f5a 597
6f2ee2be 598 num_vertexes++;
5f315a8f 599 if(list_position >= list_end) {
804789d7 600 cmd = -1;
601 goto breakloop;
602 }
4949d4ff 603 if((le32_raw(*list_position) & HTOLE32(0xf000f000)) == HTOLE32(0x50005000))
b243416b 604 break;
6f2ee2be 605 }
606
b243416b 607 len += (num_vertexes - 2);
030d1121 608 } break;
6f2ee2be 609
42a261f1 610 case 0x50:
611 case 0x51:
612 case 0x52:
030d1121 613 case 0x53: { // Gouraud-shaded line
614 // Shift index right by one, as untextured prims don't use lighting
615 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
616 // Index MSB selects Gouraud-shaded PixelSpanDriver:
617 driver_idx |= (1 << 5);
618 PSD driver = gpuPixelSpanDrivers[driver_idx];
619 gpuDrawLineG(packet, driver);
620 } break;
621
622 case 0x58 ... 0x5F: { // Gouraud-shaded line strip
6f2ee2be 623 u32 num_vertexes = 1;
4949d4ff 624 le32_t *list_position = &list[2];
8aea5f5a 625
030d1121 626 // Shift index right by one, as untextured prims don't use lighting
627 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
628 // Index MSB selects Gouraud-shaded PixelSpanDriver:
629 driver_idx |= (1 << 5);
630 PSD driver = gpuPixelSpanDrivers[driver_idx];
631 gpuDrawLineG(packet, driver);
6f2ee2be 632
633 while(1)
634 {
030d1121 635 gpu_unai.PacketBuffer.U4[0] = gpu_unai.PacketBuffer.U4[2];
636 gpu_unai.PacketBuffer.U4[1] = gpu_unai.PacketBuffer.U4[3];
637 gpu_unai.PacketBuffer.U4[2] = *list_position++;
638 gpu_unai.PacketBuffer.U4[3] = *list_position++;
639 gpuDrawLineG(packet, driver);
8aea5f5a 640
6f2ee2be 641 num_vertexes++;
5f315a8f 642 if(list_position >= list_end) {
804789d7 643 cmd = -1;
644 goto breakloop;
645 }
4949d4ff 646 if((le32_raw(*list_position) & HTOLE32(0xf000f000)) == HTOLE32(0x50005000))
b243416b 647 break;
6f2ee2be 648 }
649
b243416b 650 len += (num_vertexes - 2) * 2;
030d1121 651 } break;
6f2ee2be 652
42a261f1 653 case 0x60:
654 case 0x61:
655 case 0x62:
030d1121 656 case 0x63: { // Monochrome rectangle (variable size)
657 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
658 gpuDrawT(packet, driver);
659 } break;
42a261f1 660
661 case 0x64:
662 case 0x65:
663 case 0x66:
030d1121 664 case 0x67: { // Textured rectangle (variable size)
4949d4ff 665 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
030d1121 666 u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1);
667
668 //senquack - Only color 808080h-878787h allows skipping lighting calculation:
669 // This fixes Silent Hill running animation on loading screens:
670 // (On PSX, color values 0x00-0x7F darken the source texture's color,
671 // 0x81-FF lighten textures (ultimately clamped to 0x1F),
672 // 0x80 leaves source texture color unchanged, HOWEVER,
673 // gpu_unai uses a simple lighting LUT whereby only the upper
674 // 5 bits of an 8-bit color are used, so 0x80-0x87 all behave as
675 // 0x80.
676 //
677 // NOTE: I've changed all textured sprite draw commands here and
678 // elsewhere to use proper behavior, but left poly commands
679 // alone, I don't want to slow rendering down too much. (TODO)
680 //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))
681 // Strip lower 3 bits of each color and determine if lighting should be used:
4949d4ff 682 if ((le32_raw(gpu_unai.PacketBuffer.U4[0]) & HTOLE32(0xF8F8F8)) != HTOLE32(0x808080))
030d1121 683 driver_idx |= Lighting;
684 PS driver = gpuSpriteSpanDrivers[driver_idx];
685 gpuDrawS(packet, driver);
686 } break;
42a261f1 687
688 case 0x68:
689 case 0x69:
690 case 0x6A:
030d1121 691 case 0x6B: { // Monochrome rectangle (1x1 dot)
4949d4ff 692 gpu_unai.PacketBuffer.U4[2] = u32_to_le32(0x00010001);
030d1121 693 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
694 gpuDrawT(packet, driver);
695 } break;
42a261f1 696
697 case 0x70:
698 case 0x71:
699 case 0x72:
030d1121 700 case 0x73: { // Monochrome rectangle (8x8)
4949d4ff 701 gpu_unai.PacketBuffer.U4[2] = u32_to_le32(0x00080008);
030d1121 702 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
703 gpuDrawT(packet, driver);
704 } break;
42a261f1 705
706 case 0x74:
707 case 0x75:
708 case 0x76:
030d1121 709 case 0x77: { // Textured rectangle (8x8)
4949d4ff
PC
710 gpu_unai.PacketBuffer.U4[3] = u32_to_le32(0x00080008);
711 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
030d1121 712 u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1);
713
714 //senquack - Only color 808080h-878787h allows skipping lighting calculation:
715 //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))
716 // Strip lower 3 bits of each color and determine if lighting should be used:
4949d4ff 717 if ((le32_raw(gpu_unai.PacketBuffer.U4[0]) & HTOLE32(0xF8F8F8)) != HTOLE32(0x808080))
030d1121 718 driver_idx |= Lighting;
719 PS driver = gpuSpriteSpanDrivers[driver_idx];
720 gpuDrawS(packet, driver);
721 } break;
42a261f1 722
723 case 0x78:
724 case 0x79:
725 case 0x7A:
030d1121 726 case 0x7B: { // Monochrome rectangle (16x16)
4949d4ff 727 gpu_unai.PacketBuffer.U4[2] = u32_to_le32(0x00100010);
030d1121 728 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
729 gpuDrawT(packet, driver);
730 } break;
42a261f1 731
732 case 0x7C:
733 case 0x7D:
734#ifdef __arm__
030d1121 735 if ((gpu_unai.GPU_GP1 & 0x180) == 0 && (gpu_unai.Masking | gpu_unai.PixelMSB) == 0)
42a261f1 736 {
4949d4ff 737 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
030d1121 738 gpuDrawS16(packet);
42a261f1 739 break;
740 }
741 // fallthrough
742#endif
743 case 0x7E:
030d1121 744 case 0x7F: { // Textured rectangle (16x16)
4949d4ff
PC
745 gpu_unai.PacketBuffer.U4[3] = u32_to_le32(0x00100010);
746 gpuSetCLUT (le32_to_u32(gpu_unai.PacketBuffer.U4[2]) >> 16);
030d1121 747 u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1);
748 //senquack - Only color 808080h-878787h allows skipping lighting calculation:
749 //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))
750 // Strip lower 3 bits of each color and determine if lighting should be used:
4949d4ff 751 if ((le32_raw(gpu_unai.PacketBuffer.U4[0]) & HTOLE32(0xF8F8F8)) != HTOLE32(0x808080))
030d1121 752 driver_idx |= Lighting;
753 PS driver = gpuSpriteSpanDrivers[driver_idx];
754 gpuDrawS(packet, driver);
755 } break;
42a261f1 756
757 case 0x80: // vid -> vid
030d1121 758 gpuMoveImage(packet);
42a261f1 759 break;
030d1121 760
9a6e7816 761#ifdef TEST
762 case 0xA0: // sys -> vid
763 {
764 u32 load_width = list[2] & 0xffff;
765 u32 load_height = list[2] >> 16;
766 u32 load_size = load_width * load_height;
767
768 len += load_size / 2;
030d1121 769 } break;
770
42a261f1 771 case 0xC0:
772 break;
773#else
774 case 0xA0: // sys ->vid
775 case 0xC0: // vid -> sys
030d1121 776 // Handled by gpulib
42a261f1 777 goto breakloop;
9a6e7816 778#endif
030d1121 779 case 0xE1 ... 0xE6: { // Draw settings
4949d4ff 780 gpuGP0Cmd_0xEx(gpu_unai, le32_to_u32(gpu_unai.PacketBuffer.U4[0]));
030d1121 781 } break;
6f2ee2be 782 }
783 }
b243416b 784
42a261f1 785breakloop:
b243416b 786 gpu.ex_regs[1] &= ~0x1ff;
030d1121 787 gpu.ex_regs[1] |= gpu_unai.GPU_GP1 & 0x1ff;
b243416b 788
789 *last_cmd = cmd;
790 return list - list_start;
6f2ee2be 791}
792
4949d4ff 793void renderer_sync_ecmds(u32 *ecmds)
6f2ee2be 794{
42a261f1 795 int dummy;
796 do_cmd_list(&ecmds[1], 6, &dummy);
6f2ee2be 797}
798
3b7b0065 799void renderer_update_caches(int x, int y, int w, int h, int state_changed)
6f2ee2be 800{
801}
802
803void renderer_flush_queues(void)
804{
805}
914455e6 806
5440b88e 807void renderer_set_interlace(int enable, int is_odd)
808{
809}
810
914455e6 811#include "../../frontend/plugin_lib.h"
030d1121 812// Handle any gpulib settings applicable to gpu_unai:
914455e6 813void renderer_set_config(const struct rearmed_cbs *cbs)
814{
4949d4ff 815 gpu_unai.vram = (le16_t *)gpu.vram;
030d1121 816 gpu_unai.config.ilace_force = cbs->gpu_unai.ilace_force;
817 gpu_unai.config.pixel_skip = cbs->gpu_unai.pixel_skip;
818 gpu_unai.config.lighting = cbs->gpu_unai.lighting;
819 gpu_unai.config.fast_lighting = cbs->gpu_unai.fast_lighting;
820 gpu_unai.config.blending = cbs->gpu_unai.blending;
821 gpu_unai.config.dithering = cbs->gpu_unai.dithering;
43047988
JW
822 gpu_unai.config.scale_hires = cbs->gpu_unai.scale_hires;
823
824 gpu.state.downscale_enable = gpu_unai.config.scale_hires;
825 if (gpu_unai.config.scale_hires) {
826 map_downscale_buffer();
827 } else {
828 unmap_downscale_buffer();
829 }
914455e6 830}
9a6e7816 831
c765eb86
JW
832void renderer_sync(void)
833{
834}
835
836void renderer_notify_update_lace(int updated)
837{
838}
839
42a261f1 840// vim:shiftwidth=2:expandtab