1 /***************************************************************************
2 * Copyright (C) 2010 PCSX4ALL Team *
3 * Copyright (C) 2010 Unai *
4 * Copyright (C) 2011 notaz *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
20 ***************************************************************************/
25 #include "../gpulib/gpu.h"
37 #define FRAME_BUFFER_SIZE (1024*512*2)
38 #define FRAME_WIDTH 1024
39 #define FRAME_HEIGHT 512
40 #define FRAME_OFFSET(x,y) (((y)<<10)+(x))
42 #define isSkip 0 /* skip frame (info coming from GPU) */
44 static int linesInterlace; /* internal lines interlace */
45 static int force_interlace;
47 static bool light = true; /* lighting */
48 static bool blend = true; /* blending */
49 static bool FrameToRead = false; /* load image in progress */
50 static bool FrameToWrite = false; /* store image in progress */
52 static bool enableAbbeyHack = false; /* Abe's Odyssey hack */
61 ///////////////////////////////////////////////////////////////////////////////
63 ///////////////////////////////////////////////////////////////////////////////
67 static s32 x_end,y_end;
70 static s32 PacketCount;
71 static s32 PacketIndex;
74 static u32 TextureWindow [4];
75 static u32 DrawingArea [4];
76 static u32 DrawingOffset [2];
88 static u32 tInc, tMsk;
100 static GPUPacket PacketBuffer;
101 static u16 *GPU_FrameBuffer;
104 ///////////////////////////////////////////////////////////////////////////////
106 #include "../gpu_unai/gpu_fixedpoint.h"
108 // Inner loop driver instanciation file
109 #include "../gpu_unai/gpu_inner.h"
112 #define GPU_RGB16(rgb) ((((rgb)&0xF80000)>>9)|(((rgb)&0xF800)>>6)|(((rgb)&0xF8)>>3))
114 #define GPU_EXPANDSIGN(x) (((s32)(x)<<21)>>21)
116 #define CHKMAX_X 1024
119 #define GPU_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);}
121 // GPU internal image drawing functions
122 #include "../gpu_unai/gpu_raster_image.h"
124 // GPU internal line drawing functions
125 #include "../gpu_unai/gpu_raster_line.h"
127 // GPU internal polygon drawing functions
128 #include "../gpu_unai/gpu_raster_polygon.h"
130 // GPU internal sprite drawing functions
131 #include "../gpu_unai/gpu_raster_sprite.h"
133 // GPU command buffer execution/store
134 #include "../gpu_unai/gpu_command.h"
136 /////////////////////////////////////////////////////////////////////////////
138 int renderer_init(void)
140 GPU_FrameBuffer = (u16 *)gpu.vram;
143 for(int i=1;i<=(1<<TABLE_BITS);++i)
145 double v = 1.0 / double(i);
146 #ifdef GPU_TABLE_10_BITS
147 v *= double(0xffffffff>>1);
149 v *= double(0x80000000);
151 s_invTable[i-1]=s32(v);
157 void renderer_finish(void)
161 void renderer_notify_res_change(void)
165 extern const unsigned char cmd_lengths[256];
167 int do_cmd_list(unsigned int *list, int list_len, int *last_cmd)
169 unsigned int cmd = 0, len, i;
170 unsigned int *list_start = list;
171 unsigned int *list_end = list + list_len;
173 linesInterlace = force_interlace;
174 #ifndef __ARM_ARCH_7A__ /* XXX */
175 linesInterlace |= gpu.status.interlace;
178 for (; list < list_end; list += 1 + len)
181 len = cmd_lengths[cmd];
182 if (list + 1 + len > list_end) {
188 PacketBuffer.U4[0] = list[0];
189 for (i = 1; i <= len; i++)
190 PacketBuffer.U4[i] = list[i];
202 gpuDrawF3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB]);
209 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
210 gpuSetTexture(PacketBuffer.U4[4] >> 16);
211 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
212 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB]);
214 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB]);
221 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB];
222 gpuDrawF3(gpuPolySpanDriver);
223 PacketBuffer.U4[1] = PacketBuffer.U4[4];
224 gpuDrawF3(gpuPolySpanDriver);
232 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
233 gpuSetTexture(PacketBuffer.U4[4] >> 16);
234 PP gpuPolySpanDriver;
235 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
236 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB];
238 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB];
239 gpuDrawFT3(gpuPolySpanDriver);
240 PacketBuffer.U4[1] = PacketBuffer.U4[7];
241 PacketBuffer.U4[2] = PacketBuffer.U4[8];
242 gpuDrawFT3(gpuPolySpanDriver);
250 gpuDrawG3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB]);
257 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
258 gpuSetTexture (PacketBuffer.U4[5] >> 16);
259 gpuDrawGT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB]);
266 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB];
267 gpuDrawG3(gpuPolySpanDriver);
268 PacketBuffer.U4[0] = PacketBuffer.U4[6];
269 PacketBuffer.U4[1] = PacketBuffer.U4[7];
270 gpuDrawG3(gpuPolySpanDriver);
278 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
279 gpuSetTexture (PacketBuffer.U4[5] >> 16);
280 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB];
281 gpuDrawGT3(gpuPolySpanDriver);
282 PacketBuffer.U4[0] = PacketBuffer.U4[9];
283 PacketBuffer.U4[1] = PacketBuffer.U4[10];
284 PacketBuffer.U4[2] = PacketBuffer.U4[11];
285 gpuDrawGT3(gpuPolySpanDriver);
293 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
298 u32 num_vertexes = 1;
299 u32 *list_position = &(list[2]);
301 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
305 PacketBuffer.U4[1] = PacketBuffer.U4[2];
306 PacketBuffer.U4[2] = *list_position++;
307 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
310 if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
314 len += (num_vertexes - 2);
322 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
327 u32 num_vertexes = 1;
328 u32 *list_position = &(list[2]);
330 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
334 PacketBuffer.U4[0] = PacketBuffer.U4[2];
335 PacketBuffer.U4[1] = PacketBuffer.U4[3];
336 PacketBuffer.U4[2] = *list_position++;
337 PacketBuffer.U4[3] = *list_position++;
338 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
341 if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
345 len += (num_vertexes - 2) * 2;
353 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
360 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
361 gpuSetTexture (GPU_GP1);
362 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
363 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
365 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
372 PacketBuffer.U4[2] = 0x00010001;
373 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
380 PacketBuffer.U4[2] = 0x00080008;
381 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
388 PacketBuffer.U4[3] = 0x00080008;
389 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
390 gpuSetTexture (GPU_GP1);
391 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
392 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
394 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
401 PacketBuffer.U4[2] = 0x00100010;
402 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
408 if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
410 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
411 gpuSetTexture (GPU_GP1);
419 PacketBuffer.U4[3] = 0x00100010;
420 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
421 gpuSetTexture (GPU_GP1);
422 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
423 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
425 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
428 case 0x80: // vid -> vid
429 gpuMoveImage(); // prim handles updateLace && skip
432 case 0xA0: // sys -> vid
434 u32 load_width = list[2] & 0xffff;
435 u32 load_height = list[2] >> 16;
436 u32 load_size = load_width * load_height;
438 len += load_size / 2;
444 case 0xA0: // sys ->vid
445 case 0xC0: // vid -> sys
449 const u32 temp = PacketBuffer.U4[0];
450 GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
452 gpu.ex_regs[1] = temp;
456 static const u8 TextureMask[32] = {
457 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
458 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
460 const u32 temp = PacketBuffer.U4[0];
461 TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
462 TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
463 TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
464 TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
465 gpuSetTexture(GPU_GP1);
466 gpu.ex_regs[2] = temp;
470 const u32 temp = PacketBuffer.U4[0];
471 DrawingArea[0] = temp & 0x3FF;
472 DrawingArea[1] = (temp >> 10) & 0x3FF;
473 gpu.ex_regs[3] = temp;
477 const u32 temp = PacketBuffer.U4[0];
478 DrawingArea[2] = (temp & 0x3FF) + 1;
479 DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
480 gpu.ex_regs[4] = temp;
484 const u32 temp = PacketBuffer.U4[0];
485 DrawingOffset[0] = ((long)temp<<(32-11))>>(32-11);
486 DrawingOffset[1] = ((long)temp<<(32-22))>>(32-11);
487 gpu.ex_regs[5] = temp;
491 const u32 temp = PacketBuffer.U4[0];
492 Masking = (temp & 0x2) << 1;
493 PixelMSB =(temp & 0x1) << 8;
494 gpu.ex_regs[6] = temp;
501 gpu.ex_regs[1] &= ~0x1ff;
502 gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
505 return list - list_start;
508 void renderer_sync_ecmds(uint32_t *ecmds)
511 do_cmd_list(&ecmds[1], 6, &dummy);
514 void renderer_update_caches(int x, int y, int w, int h)
518 void renderer_flush_queues(void)
522 void renderer_set_interlace(int enable, int is_odd)
528 #include "../../frontend/plugin_lib.h"
530 void renderer_set_config(const struct rearmed_cbs *cbs)
532 force_interlace = cbs->gpu_unai.lineskip;
533 enableAbbeyHack = cbs->gpu_unai.abe_hack;
534 light = !cbs->gpu_unai.no_light;
535 blend = !cbs->gpu_unai.no_blend;
540 // vim:shiftwidth=2:expandtab