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