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) *
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. *
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. *
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 ***************************************************************************/
27 #include "../gpulib/gpu.h"
31 // GPU fixed point math
32 #include "gpu_fixedpoint.h"
34 // Inner loop driver instantiation file
35 #include "gpu_inner.h"
37 // GPU internal image drawing functions
38 #include "gpu_raster_image.h"
40 // GPU internal line drawing functions
41 #include "gpu_raster_line.h"
43 // GPU internal polygon drawing functions
44 #include "gpu_raster_polygon.h"
46 // GPU internal sprite drawing functions
47 #include "gpu_raster_sprite.h"
49 // GPU command buffer execution/store
50 #include "gpu_command.h"
52 /////////////////////////////////////////////////////////////////////////////
54 #define DOWNSCALE_VRAM_SIZE (1024 * 512 * 2 * 2 + 4096)
56 INLINE void scale_640_to_320(uint16_t *dest, const uint16_t *src, bool isRGB24) {
60 const uint8_t* src8 = (const uint8_t *)src;
61 uint8_t* dst8 = (uint8_t *)dest;
70 const uint16_t* src16 = src;
71 uint16_t* dst16 = dest;
80 INLINE void scale_512_to_320(uint16_t *dest, const uint16_t *src, bool isRGB24) {
84 const uint8_t* src8 = (const uint8_t *)src;
85 uint8_t* dst8 = (uint8_t *)dest;
108 const uint16_t* src16 = src;
109 uint16_t* dst16 = dest;
124 static uint16_t *get_downscale_buffer(int *x, int *y, int *w, int *h, int *vram_h)
126 uint16_t *dest = gpu_unai.downscale_vram;
127 const uint16_t *src = gpu_unai.vram;
128 bool isRGB24 = (gpu_unai.GPU_GP1 & 0x00200000 ? true : false);
129 int stride = 1024, dstride = 1024, lines = *h, orig_w = *w;
131 // PS1 fb read wraps around (fixes black screen in 'Tobal no. 1')
132 unsigned int fb_mask = 1024 * 512 - 1;
139 // Ensure start at a non-skipped line
140 while (*y & gpu_unai.ilace_mask) ++*y;
143 unsigned int fb_offset_src = (*y * dstride + *x) & fb_mask;
144 unsigned int fb_offset_dest = fb_offset_src;
146 if (*w == 512 || *w == 640) {
153 scale_640_to_320(dest + fb_offset_dest, src + fb_offset_src, isRGB24);
154 fb_offset_src = (fb_offset_src + stride) & fb_mask;
155 fb_offset_dest = (fb_offset_dest + dstride) & fb_mask;
161 scale_512_to_320(dest + fb_offset_dest, src + fb_offset_src, isRGB24);
162 fb_offset_src = (fb_offset_src + stride) & fb_mask;
163 fb_offset_dest = (fb_offset_dest + dstride) & fb_mask;
167 size_t size = isRGB24 ? *w * 3 : *w * 2;
170 memcpy(dest + fb_offset_dest, src + fb_offset_src, size);
171 fb_offset_src = (fb_offset_src + stride) & fb_mask;
172 fb_offset_dest = (fb_offset_dest + dstride) & fb_mask;
177 return gpu_unai.downscale_vram;
180 static void map_downscale_buffer(void)
182 if (gpu_unai.downscale_vram)
185 gpu_unai.downscale_vram = (uint16_t*)gpu.mmap(DOWNSCALE_VRAM_SIZE);
187 if (gpu_unai.downscale_vram == NULL) {
188 fprintf(stderr, "failed to map downscale buffer\n");
189 gpu.get_downscale_buffer = NULL;
192 gpu.get_downscale_buffer = get_downscale_buffer;
196 static void unmap_downscale_buffer(void)
198 if (gpu_unai.downscale_vram == NULL)
201 gpu.munmap(gpu_unai.downscale_vram, DOWNSCALE_VRAM_SIZE);
202 gpu_unai.downscale_vram = NULL;
203 gpu.get_downscale_buffer = NULL;
206 int renderer_init(void)
208 memset((void*)&gpu_unai, 0, sizeof(gpu_unai));
209 gpu_unai.vram = (u16*)gpu.vram;
211 // Original standalone gpu_unai initialized TextureWindow[]. I added the
212 // same behavior here, since it seems unsafe to leave [2],[3] unset when
213 // using HLE and Rearmed gpu_neon sets this similarly on init. -senquack
214 gpu_unai.TextureWindow[0] = 0;
215 gpu_unai.TextureWindow[1] = 0;
216 gpu_unai.TextureWindow[2] = 255;
217 gpu_unai.TextureWindow[3] = 255;
218 //senquack - new vars must be updated whenever texture window is changed:
219 // (used for polygon-drawing in gpu_inner.h, gpu_raster_polygon.h)
220 const u32 fb = FIXED_BITS; // # of fractional fixed-pt bits of u4/v4
221 gpu_unai.u_msk = (((u32)gpu_unai.TextureWindow[2]) << fb) | ((1 << fb) - 1);
222 gpu_unai.v_msk = (((u32)gpu_unai.TextureWindow[3]) << fb) | ((1 << fb) - 1);
224 // Configuration options
225 gpu_unai.config = gpu_unai_config_ext;
226 //senquack - disabled, not sure this is needed and would require modifying
227 // sprite-span functions, perhaps unnecessarily. No Abe Oddysey hack was
228 // present in latest PCSX4ALL sources we were using.
229 //gpu_unai.config.enableAbbeyHack = gpu_unai_config_ext.abe_hack;
230 gpu_unai.ilace_mask = gpu_unai.config.ilace_force;
232 #ifdef GPU_UNAI_USE_INT_DIV_MULTINV
234 for(int i=1;i<=(1<<TABLE_BITS);++i)
236 double v = 1.0 / double(i);
237 #ifdef GPU_TABLE_10_BITS
238 v *= double(0xffffffff>>1);
240 v *= double(0x80000000);
242 s_invTable[i-1]=s32(v);
247 SetupDitheringConstants();
249 if (gpu_unai.config.scale_hires) {
250 map_downscale_buffer();
256 void renderer_finish(void)
258 unmap_downscale_buffer();
261 void renderer_notify_res_change(void)
263 if (PixelSkipEnabled()) {
264 // Set blit_mask for high horizontal resolutions. This allows skipping
265 // rendering pixels that would never get displayed on low-resolution
266 // platforms that use simple pixel-dropping scaler.
268 switch (gpu.screen.hres)
270 case 512: gpu_unai.blit_mask = 0xa4; break; // GPU_BlitWWSWWSWS
271 case 640: gpu_unai.blit_mask = 0xaa; break; // GPU_BlitWS
272 default: gpu_unai.blit_mask = 0; break;
275 gpu_unai.blit_mask = 0;
278 if (LineSkipEnabled()) {
279 // Set rendering line-skip (only render every other line in high-res
280 // 480 vertical mode, or, optionally, force it for all video modes)
282 if (gpu.screen.vres == 480) {
283 if (gpu_unai.config.ilace_force) {
284 gpu_unai.ilace_mask = 3; // Only need 1/4 of lines
286 gpu_unai.ilace_mask = 1; // Only need 1/2 of lines
289 // Vert resolution changed from 480 to lower one
290 gpu_unai.ilace_mask = gpu_unai.config.ilace_force;
293 gpu_unai.ilace_mask = 0;
297 printf("res change hres: %d vres: %d depth: %d ilace_mask: %d\n",
298 gpu.screen.hres, gpu.screen.vres, gpu.status.rgb24 ? 24 : 15,
299 gpu_unai.ilace_mask);
304 // Handles GP0 draw settings commands 0xE1...0xE6
305 static void gpuGP0Cmd_0xEx(gpu_unai_t &gpu_unai, u32 cmd_word)
307 // Assume incoming GP0 command is 0xE1..0xE6, convert to 1..6
308 u8 num = (cmd_word >> 24) & 7;
309 gpu.ex_regs[num] = cmd_word; // Update gpulib register
312 // GP0(E1h) - Draw Mode setting (aka "Texpage")
313 u32 cur_texpage = gpu_unai.GPU_GP1 & 0x7FF;
314 u32 new_texpage = cmd_word & 0x7FF;
315 if (cur_texpage != new_texpage) {
316 gpu_unai.GPU_GP1 = (gpu_unai.GPU_GP1 & ~0x7FF) | new_texpage;
317 gpuSetTexture(gpu_unai.GPU_GP1);
322 // GP0(E2h) - Texture Window setting
323 if (cmd_word != gpu_unai.TextureWindowCur) {
324 static const u8 TextureMask[32] = {
325 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
326 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
328 gpu_unai.TextureWindowCur = cmd_word;
329 gpu_unai.TextureWindow[0] = ((cmd_word >> 10) & 0x1F) << 3;
330 gpu_unai.TextureWindow[1] = ((cmd_word >> 15) & 0x1F) << 3;
331 gpu_unai.TextureWindow[2] = TextureMask[(cmd_word >> 0) & 0x1F];
332 gpu_unai.TextureWindow[3] = TextureMask[(cmd_word >> 5) & 0x1F];
333 gpu_unai.TextureWindow[0] &= ~gpu_unai.TextureWindow[2];
334 gpu_unai.TextureWindow[1] &= ~gpu_unai.TextureWindow[3];
336 // Inner loop vars must be updated whenever texture window is changed:
337 const u32 fb = FIXED_BITS; // # of fractional fixed-pt bits of u4/v4
338 gpu_unai.u_msk = (((u32)gpu_unai.TextureWindow[2]) << fb) | ((1 << fb) - 1);
339 gpu_unai.v_msk = (((u32)gpu_unai.TextureWindow[3]) << fb) | ((1 << fb) - 1);
341 gpuSetTexture(gpu_unai.GPU_GP1);
346 // GP0(E3h) - Set Drawing Area top left (X1,Y1)
347 gpu_unai.DrawingArea[0] = cmd_word & 0x3FF;
348 gpu_unai.DrawingArea[1] = (cmd_word >> 10) & 0x3FF;
352 // GP0(E4h) - Set Drawing Area bottom right (X2,Y2)
353 gpu_unai.DrawingArea[2] = (cmd_word & 0x3FF) + 1;
354 gpu_unai.DrawingArea[3] = ((cmd_word >> 10) & 0x3FF) + 1;
358 // GP0(E5h) - Set Drawing Offset (X,Y)
359 gpu_unai.DrawingOffset[0] = ((s32)cmd_word<<(32-11))>>(32-11);
360 gpu_unai.DrawingOffset[1] = ((s32)cmd_word<<(32-22))>>(32-11);
364 // GP0(E6h) - Mask Bit Setting
365 gpu_unai.Masking = (cmd_word & 0x2) << 1;
366 gpu_unai.PixelMSB = (cmd_word & 0x1) << 8;
372 extern const unsigned char cmd_lengths[256];
374 int do_cmd_list(u32 *list, int list_len, int *last_cmd)
377 u32 *list_start = list;
378 u32 *list_end = list + list_len;
380 //TODO: set ilace_mask when resolution changes instead of every time,
381 // eliminate #ifdef below.
382 gpu_unai.ilace_mask = gpu_unai.config.ilace_force;
384 #ifdef HAVE_PRE_ARMV7 /* XXX */
385 gpu_unai.ilace_mask |= gpu.status.interlace;
387 if (gpu_unai.config.scale_hires) {
388 gpu_unai.ilace_mask |= gpu.status.interlace;
391 for (; list < list_end; list += 1 + len)
394 len = cmd_lengths[cmd];
395 if (list + 1 + len > list_end) {
401 gpu_unai.PacketBuffer.U4[0] = list[0];
402 for (i = 1; i <= len; i++)
403 gpu_unai.PacketBuffer.U4[i] = list[i];
405 PtrUnion packet = { .ptr = (void*)&gpu_unai.PacketBuffer };
410 gpuClearImage(packet);
416 case 0x23: { // Monochrome 3-pt poly
417 PP driver = gpuPolySpanDrivers[
418 (gpu_unai.blit_mask?1024:0) |
420 gpu_unai.Masking | Blending | gpu_unai.PixelMSB
422 gpuDrawPolyF(packet, driver, false);
428 case 0x27: { // Textured 3-pt poly
429 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
430 gpuSetTexture(gpu_unai.PacketBuffer.U4[4] >> 16);
433 (gpu_unai.blit_mask?1024:0) |
435 Blending_Mode | gpu_unai.TEXT_MODE |
436 gpu_unai.Masking | Blending | gpu_unai.PixelMSB;
438 if (!FastLightingEnabled()) {
439 driver_idx |= Lighting;
441 if (!((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)))
442 driver_idx |= Lighting;
445 PP driver = gpuPolySpanDrivers[driver_idx];
446 gpuDrawPolyFT(packet, driver, false);
452 case 0x2B: { // Monochrome 4-pt poly
453 PP driver = gpuPolySpanDrivers[
454 (gpu_unai.blit_mask?1024:0) |
456 gpu_unai.Masking | Blending | gpu_unai.PixelMSB
458 gpuDrawPolyF(packet, driver, true); // is_quad = true
464 case 0x2F: { // Textured 4-pt poly
465 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
466 gpuSetTexture(gpu_unai.PacketBuffer.U4[4] >> 16);
469 (gpu_unai.blit_mask?1024:0) |
471 Blending_Mode | gpu_unai.TEXT_MODE |
472 gpu_unai.Masking | Blending | gpu_unai.PixelMSB;
474 if (!FastLightingEnabled()) {
475 driver_idx |= Lighting;
477 if (!((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)))
478 driver_idx |= Lighting;
481 PP driver = gpuPolySpanDrivers[driver_idx];
482 gpuDrawPolyFT(packet, driver, true); // is_quad = true
488 case 0x33: { // Gouraud-shaded 3-pt poly
489 //NOTE: The '129' here is CF_GOURAUD | CF_LIGHT, however
490 // this is an untextured poly, so CF_LIGHT (texture blend)
491 // shouldn't apply. Until the original array of template
492 // instantiation ptrs is fixed, we're stuck with this. (TODO)
493 PP driver = gpuPolySpanDrivers[
494 (gpu_unai.blit_mask?1024:0) |
497 gpu_unai.Masking | Blending | 129 | gpu_unai.PixelMSB
499 gpuDrawPolyG(packet, driver, false);
505 case 0x37: { // Gouraud-shaded, textured 3-pt poly
506 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
507 gpuSetTexture (gpu_unai.PacketBuffer.U4[5] >> 16);
508 PP driver = gpuPolySpanDrivers[
509 (gpu_unai.blit_mask?1024:0) |
511 Blending_Mode | gpu_unai.TEXT_MODE |
512 gpu_unai.Masking | Blending | ((Lighting)?129:0) | gpu_unai.PixelMSB
514 gpuDrawPolyGT(packet, driver, false);
520 case 0x3B: { // Gouraud-shaded 4-pt poly
521 // See notes regarding '129' for 0x30..0x33 further above -senquack
522 PP driver = gpuPolySpanDrivers[
523 (gpu_unai.blit_mask?1024:0) |
526 gpu_unai.Masking | Blending | 129 | gpu_unai.PixelMSB
528 gpuDrawPolyG(packet, driver, true); // is_quad = true
534 case 0x3F: { // Gouraud-shaded, textured 4-pt poly
535 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
536 gpuSetTexture (gpu_unai.PacketBuffer.U4[5] >> 16);
537 PP driver = gpuPolySpanDrivers[
538 (gpu_unai.blit_mask?1024:0) |
540 Blending_Mode | gpu_unai.TEXT_MODE |
541 gpu_unai.Masking | Blending | ((Lighting)?129:0) | gpu_unai.PixelMSB
543 gpuDrawPolyGT(packet, driver, true); // is_quad = true
549 case 0x43: { // Monochrome line
550 // Shift index right by one, as untextured prims don't use lighting
551 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
552 PSD driver = gpuPixelSpanDrivers[driver_idx];
553 gpuDrawLineF(packet, driver);
556 case 0x48 ... 0x4F: { // Monochrome line strip
557 u32 num_vertexes = 1;
558 u32 *list_position = &(list[2]);
560 // Shift index right by one, as untextured prims don't use lighting
561 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
562 PSD driver = gpuPixelSpanDrivers[driver_idx];
563 gpuDrawLineF(packet, driver);
567 gpu_unai.PacketBuffer.U4[1] = gpu_unai.PacketBuffer.U4[2];
568 gpu_unai.PacketBuffer.U4[2] = *list_position++;
569 gpuDrawLineF(packet, driver);
572 if(list_position >= list_end) {
576 if((*list_position & 0xf000f000) == 0x50005000)
580 len += (num_vertexes - 2);
586 case 0x53: { // Gouraud-shaded line
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 // Index MSB selects Gouraud-shaded PixelSpanDriver:
590 driver_idx |= (1 << 5);
591 PSD driver = gpuPixelSpanDrivers[driver_idx];
592 gpuDrawLineG(packet, driver);
595 case 0x58 ... 0x5F: { // Gouraud-shaded line strip
596 u32 num_vertexes = 1;
597 u32 *list_position = &(list[2]);
599 // Shift index right by one, as untextured prims don't use lighting
600 u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1;
601 // Index MSB selects Gouraud-shaded PixelSpanDriver:
602 driver_idx |= (1 << 5);
603 PSD driver = gpuPixelSpanDrivers[driver_idx];
604 gpuDrawLineG(packet, driver);
608 gpu_unai.PacketBuffer.U4[0] = gpu_unai.PacketBuffer.U4[2];
609 gpu_unai.PacketBuffer.U4[1] = gpu_unai.PacketBuffer.U4[3];
610 gpu_unai.PacketBuffer.U4[2] = *list_position++;
611 gpu_unai.PacketBuffer.U4[3] = *list_position++;
612 gpuDrawLineG(packet, driver);
615 if(list_position >= list_end) {
619 if((*list_position & 0xf000f000) == 0x50005000)
623 len += (num_vertexes - 2) * 2;
629 case 0x63: { // Monochrome rectangle (variable size)
630 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
631 gpuDrawT(packet, driver);
637 case 0x67: { // Textured rectangle (variable size)
638 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
639 u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1);
641 //senquack - Only color 808080h-878787h allows skipping lighting calculation:
642 // This fixes Silent Hill running animation on loading screens:
643 // (On PSX, color values 0x00-0x7F darken the source texture's color,
644 // 0x81-FF lighten textures (ultimately clamped to 0x1F),
645 // 0x80 leaves source texture color unchanged, HOWEVER,
646 // gpu_unai uses a simple lighting LUT whereby only the upper
647 // 5 bits of an 8-bit color are used, so 0x80-0x87 all behave as
650 // NOTE: I've changed all textured sprite draw commands here and
651 // elsewhere to use proper behavior, but left poly commands
652 // alone, I don't want to slow rendering down too much. (TODO)
653 //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))
654 // Strip lower 3 bits of each color and determine if lighting should be used:
655 if ((gpu_unai.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080)
656 driver_idx |= Lighting;
657 PS driver = gpuSpriteSpanDrivers[driver_idx];
658 gpuDrawS(packet, driver);
664 case 0x6B: { // Monochrome rectangle (1x1 dot)
665 gpu_unai.PacketBuffer.U4[2] = 0x00010001;
666 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
667 gpuDrawT(packet, driver);
673 case 0x73: { // Monochrome rectangle (8x8)
674 gpu_unai.PacketBuffer.U4[2] = 0x00080008;
675 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
676 gpuDrawT(packet, driver);
682 case 0x77: { // Textured rectangle (8x8)
683 gpu_unai.PacketBuffer.U4[3] = 0x00080008;
684 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
685 u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1);
687 //senquack - Only color 808080h-878787h allows skipping lighting calculation:
688 //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))
689 // Strip lower 3 bits of each color and determine if lighting should be used:
690 if ((gpu_unai.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080)
691 driver_idx |= Lighting;
692 PS driver = gpuSpriteSpanDrivers[driver_idx];
693 gpuDrawS(packet, driver);
699 case 0x7B: { // Monochrome rectangle (16x16)
700 gpu_unai.PacketBuffer.U4[2] = 0x00100010;
701 PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1];
702 gpuDrawT(packet, driver);
708 if ((gpu_unai.GPU_GP1 & 0x180) == 0 && (gpu_unai.Masking | gpu_unai.PixelMSB) == 0)
710 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
717 case 0x7F: { // Textured rectangle (16x16)
718 gpu_unai.PacketBuffer.U4[3] = 0x00100010;
719 gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16);
720 u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1);
721 //senquack - Only color 808080h-878787h allows skipping lighting calculation:
722 //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))
723 // Strip lower 3 bits of each color and determine if lighting should be used:
724 if ((gpu_unai.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080)
725 driver_idx |= Lighting;
726 PS driver = gpuSpriteSpanDrivers[driver_idx];
727 gpuDrawS(packet, driver);
730 case 0x80: // vid -> vid
731 gpuMoveImage(packet);
735 case 0xA0: // sys -> vid
737 u32 load_width = list[2] & 0xffff;
738 u32 load_height = list[2] >> 16;
739 u32 load_size = load_width * load_height;
741 len += load_size / 2;
747 case 0xA0: // sys ->vid
748 case 0xC0: // vid -> sys
752 case 0xE1 ... 0xE6: { // Draw settings
753 gpuGP0Cmd_0xEx(gpu_unai, gpu_unai.PacketBuffer.U4[0]);
759 gpu.ex_regs[1] &= ~0x1ff;
760 gpu.ex_regs[1] |= gpu_unai.GPU_GP1 & 0x1ff;
763 return list - list_start;
766 void renderer_sync_ecmds(uint32_t *ecmds)
769 do_cmd_list(&ecmds[1], 6, &dummy);
772 void renderer_update_caches(int x, int y, int w, int h)
776 void renderer_flush_queues(void)
780 void renderer_set_interlace(int enable, int is_odd)
784 #include "../../frontend/plugin_lib.h"
785 // Handle any gpulib settings applicable to gpu_unai:
786 void renderer_set_config(const struct rearmed_cbs *cbs)
788 gpu_unai.vram = (u16*)gpu.vram;
789 gpu_unai.config.ilace_force = cbs->gpu_unai.ilace_force;
790 gpu_unai.config.pixel_skip = cbs->gpu_unai.pixel_skip;
791 gpu_unai.config.lighting = cbs->gpu_unai.lighting;
792 gpu_unai.config.fast_lighting = cbs->gpu_unai.fast_lighting;
793 gpu_unai.config.blending = cbs->gpu_unai.blending;
794 gpu_unai.config.dithering = cbs->gpu_unai.dithering;
795 gpu_unai.config.scale_hires = cbs->gpu_unai.scale_hires;
797 gpu.state.downscale_enable = gpu_unai.config.scale_hires;
798 if (gpu_unai.config.scale_hires) {
799 map_downscale_buffer();
801 unmap_downscale_buffer();
805 // vim:shiftwidth=2:expandtab