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