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_POLY(x) (((s32)(x)<<20)>>20)
115 //#define GPU_EXPANDSIGN_POLY(x) (((s32)(x)<<21)>>21)
116 #define GPU_EXPANDSIGN_SPRT(x) (((s32)(x)<<21)>>21)
118 //#define GPU_TESTRANGE(x) { if((u32)(x+1024) > 2047) return; }
119 #define GPU_TESTRANGE(x) { if ((x<-1023) || (x>1023)) return; }
121 #define GPU_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);}
123 // GPU internal image drawing functions
124 #include "../gpu_unai/gpu_raster_image.h"
126 // GPU internal line drawing functions
127 #include "../gpu_unai/gpu_raster_line.h"
129 // GPU internal polygon drawing functions
130 #include "../gpu_unai/gpu_raster_polygon.h"
132 // GPU internal sprite drawing functions
133 #include "../gpu_unai/gpu_raster_sprite.h"
135 // GPU command buffer execution/store
136 #include "../gpu_unai/gpu_command.h"
138 /////////////////////////////////////////////////////////////////////////////
140 int renderer_init(void)
142 GPU_FrameBuffer = (u16 *)gpu.vram;
145 for(int i=1;i<=(1<<TABLE_BITS);++i)
147 double v = 1.0 / double(i);
148 #ifdef GPU_TABLE_10_BITS
149 v *= double(0xffffffff>>1);
151 v *= double(0x80000000);
153 s_invTable[i-1]=s32(v);
159 extern const unsigned char cmd_lengths[256];
161 int do_cmd_list(unsigned int *list, int list_len, int *last_cmd)
163 unsigned int cmd = 0, len, i;
164 unsigned int *list_start = list;
165 unsigned int *list_end = list + list_len;
167 linesInterlace = force_interlace;
168 #ifndef __ARM_ARCH_7A__ /* XXX */
169 linesInterlace |= gpu.status.interlace;
172 for (; list < list_end; list += 1 + len)
175 len = cmd_lengths[cmd];
176 if (list + 1 + len > list_end) {
182 PacketBuffer.U4[0] = list[0];
183 for (i = 1; i <= len; i++)
184 PacketBuffer.U4[i] = list[i];
196 gpuDrawF3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB]);
203 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
204 gpuSetTexture(PacketBuffer.U4[4] >> 16);
205 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
206 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB]);
208 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB]);
215 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB];
216 gpuDrawF3(gpuPolySpanDriver);
217 PacketBuffer.U4[1] = PacketBuffer.U4[4];
218 gpuDrawF3(gpuPolySpanDriver);
226 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
227 gpuSetTexture(PacketBuffer.U4[4] >> 16);
228 PP gpuPolySpanDriver;
229 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
230 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB];
232 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB];
233 gpuDrawFT3(gpuPolySpanDriver);
234 PacketBuffer.U4[1] = PacketBuffer.U4[7];
235 PacketBuffer.U4[2] = PacketBuffer.U4[8];
236 gpuDrawFT3(gpuPolySpanDriver);
244 gpuDrawG3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB]);
251 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
252 gpuSetTexture (PacketBuffer.U4[5] >> 16);
253 gpuDrawGT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB]);
260 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB];
261 gpuDrawG3(gpuPolySpanDriver);
262 PacketBuffer.U4[0] = PacketBuffer.U4[6];
263 PacketBuffer.U4[1] = PacketBuffer.U4[7];
264 gpuDrawG3(gpuPolySpanDriver);
272 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
273 gpuSetTexture (PacketBuffer.U4[5] >> 16);
274 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB];
275 gpuDrawGT3(gpuPolySpanDriver);
276 PacketBuffer.U4[0] = PacketBuffer.U4[9];
277 PacketBuffer.U4[1] = PacketBuffer.U4[10];
278 PacketBuffer.U4[2] = PacketBuffer.U4[11];
279 gpuDrawGT3(gpuPolySpanDriver);
287 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
292 u32 num_vertexes = 1;
293 u32 *list_position = &(list[2]);
295 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
299 PacketBuffer.U4[1] = PacketBuffer.U4[2];
300 PacketBuffer.U4[2] = *list_position++;
301 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
304 if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
308 len += (num_vertexes - 2);
316 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
321 u32 num_vertexes = 1;
322 u32 *list_position = &(list[2]);
324 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
328 PacketBuffer.U4[0] = PacketBuffer.U4[2];
329 PacketBuffer.U4[1] = PacketBuffer.U4[3];
330 PacketBuffer.U4[2] = *list_position++;
331 PacketBuffer.U4[3] = *list_position++;
332 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
335 if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
339 len += (num_vertexes - 2) * 2;
347 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
354 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
355 gpuSetTexture (GPU_GP1);
356 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
357 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
359 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
366 PacketBuffer.U4[2] = 0x00010001;
367 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
374 PacketBuffer.U4[2] = 0x00080008;
375 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
382 PacketBuffer.U4[3] = 0x00080008;
383 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
384 gpuSetTexture (GPU_GP1);
385 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
386 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
388 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
395 PacketBuffer.U4[2] = 0x00100010;
396 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
402 if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
404 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
405 gpuSetTexture (GPU_GP1);
413 PacketBuffer.U4[3] = 0x00100010;
414 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
415 gpuSetTexture (GPU_GP1);
416 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
417 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
419 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
422 case 0x80: // vid -> vid
423 gpuMoveImage(); // prim handles updateLace && skip
426 case 0xA0: // sys -> vid
428 u32 load_width = list[2] & 0xffff;
429 u32 load_height = list[2] >> 16;
430 u32 load_size = load_width * load_height;
432 len += load_size / 2;
438 case 0xA0: // sys ->vid
439 case 0xC0: // vid -> sys
443 const u32 temp = PacketBuffer.U4[0];
444 GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
446 gpu.ex_regs[1] = temp;
450 static const u8 TextureMask[32] = {
451 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
452 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
454 const u32 temp = PacketBuffer.U4[0];
455 TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
456 TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
457 TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
458 TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
459 gpuSetTexture(GPU_GP1);
460 gpu.ex_regs[2] = temp;
464 const u32 temp = PacketBuffer.U4[0];
465 DrawingArea[0] = temp & 0x3FF;
466 DrawingArea[1] = (temp >> 10) & 0x3FF;
467 gpu.ex_regs[3] = temp;
471 const u32 temp = PacketBuffer.U4[0];
472 DrawingArea[2] = (temp & 0x3FF) + 1;
473 DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
474 gpu.ex_regs[4] = temp;
478 const u32 temp = PacketBuffer.U4[0];
479 DrawingOffset[0] = ((long)temp<<(32-11))>>(32-11);
480 DrawingOffset[1] = ((long)temp<<(32-22))>>(32-11);
481 gpu.ex_regs[5] = temp;
485 const u32 temp = PacketBuffer.U4[0];
486 Masking = (temp & 0x2) << 1;
487 PixelMSB =(temp & 0x1) << 8;
488 gpu.ex_regs[6] = temp;
495 gpu.ex_regs[1] &= ~0x1ff;
496 gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
499 return list - list_start;
502 void renderer_sync_ecmds(uint32_t *ecmds)
505 do_cmd_list(&ecmds[1], 6, &dummy);
508 void renderer_update_caches(int x, int y, int w, int h)
512 void renderer_flush_queues(void)
516 void renderer_set_interlace(int enable, int is_odd)
522 #include "../../frontend/plugin_lib.h"
524 void renderer_set_config(const struct rearmed_cbs *cbs)
526 force_interlace = cbs->gpu_unai.lineskip;
527 enableAbbeyHack = cbs->gpu_unai.abe_hack;
528 light = !cbs->gpu_unai.no_light;
529 blend = !cbs->gpu_unai.no_blend;
534 // vim:shiftwidth=2:expandtab