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 extern const unsigned char cmd_lengths[256];
159 int do_cmd_list(unsigned int *list, int list_len, int *last_cmd)
161 unsigned int cmd = 0, len, i;
162 unsigned int *list_start = list;
163 unsigned int *list_end = list + list_len;
165 linesInterlace = force_interlace;
166 #ifndef __ARM_ARCH_7A__ /* XXX */
167 linesInterlace |= gpu.status.interlace;
170 for (; list < list_end; list += 1 + len)
173 len = cmd_lengths[cmd];
174 if (list + 1 + len > list_end) {
180 PacketBuffer.U4[0] = list[0];
181 for (i = 1; i <= len; i++)
182 PacketBuffer.U4[i] = list[i];
194 gpuDrawF3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB]);
201 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
202 gpuSetTexture(PacketBuffer.U4[4] >> 16);
203 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
204 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB]);
206 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB]);
213 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB];
214 gpuDrawF3(gpuPolySpanDriver);
215 PacketBuffer.U4[1] = PacketBuffer.U4[4];
216 gpuDrawF3(gpuPolySpanDriver);
224 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
225 gpuSetTexture(PacketBuffer.U4[4] >> 16);
226 PP gpuPolySpanDriver;
227 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
228 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB];
230 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB];
231 gpuDrawFT3(gpuPolySpanDriver);
232 PacketBuffer.U4[1] = PacketBuffer.U4[7];
233 PacketBuffer.U4[2] = PacketBuffer.U4[8];
234 gpuDrawFT3(gpuPolySpanDriver);
242 gpuDrawG3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB]);
249 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
250 gpuSetTexture (PacketBuffer.U4[5] >> 16);
251 gpuDrawGT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB]);
258 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB];
259 gpuDrawG3(gpuPolySpanDriver);
260 PacketBuffer.U4[0] = PacketBuffer.U4[6];
261 PacketBuffer.U4[1] = PacketBuffer.U4[7];
262 gpuDrawG3(gpuPolySpanDriver);
270 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
271 gpuSetTexture (PacketBuffer.U4[5] >> 16);
272 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB];
273 gpuDrawGT3(gpuPolySpanDriver);
274 PacketBuffer.U4[0] = PacketBuffer.U4[9];
275 PacketBuffer.U4[1] = PacketBuffer.U4[10];
276 PacketBuffer.U4[2] = PacketBuffer.U4[11];
277 gpuDrawGT3(gpuPolySpanDriver);
285 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
290 u32 num_vertexes = 1;
291 u32 *list_position = &(list[2]);
293 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
297 PacketBuffer.U4[1] = PacketBuffer.U4[2];
298 PacketBuffer.U4[2] = *list_position++;
299 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
302 if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
306 len += (num_vertexes - 2);
314 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
319 u32 num_vertexes = 1;
320 u32 *list_position = &(list[2]);
322 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
326 PacketBuffer.U4[0] = PacketBuffer.U4[2];
327 PacketBuffer.U4[1] = PacketBuffer.U4[3];
328 PacketBuffer.U4[2] = *list_position++;
329 PacketBuffer.U4[3] = *list_position++;
330 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
333 if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
337 len += (num_vertexes - 2) * 2;
345 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
352 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
353 gpuSetTexture (GPU_GP1);
354 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
355 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
357 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
364 PacketBuffer.U4[2] = 0x00010001;
365 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
372 PacketBuffer.U4[2] = 0x00080008;
373 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
380 PacketBuffer.U4[3] = 0x00080008;
381 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
382 gpuSetTexture (GPU_GP1);
383 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
384 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
386 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
393 PacketBuffer.U4[2] = 0x00100010;
394 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
400 if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
402 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
403 gpuSetTexture (GPU_GP1);
411 PacketBuffer.U4[3] = 0x00100010;
412 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
413 gpuSetTexture (GPU_GP1);
414 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
415 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
417 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
420 case 0x80: // vid -> vid
421 gpuMoveImage(); // prim handles updateLace && skip
424 case 0xA0: // sys -> vid
426 u32 load_width = list[2] & 0xffff;
427 u32 load_height = list[2] >> 16;
428 u32 load_size = load_width * load_height;
430 len += load_size / 2;
436 case 0xA0: // sys ->vid
437 case 0xC0: // vid -> sys
441 const u32 temp = PacketBuffer.U4[0];
442 GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
444 gpu.ex_regs[1] = temp;
448 static const u8 TextureMask[32] = {
449 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
450 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
452 const u32 temp = PacketBuffer.U4[0];
453 TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
454 TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
455 TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
456 TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
457 gpuSetTexture(GPU_GP1);
458 gpu.ex_regs[2] = temp;
462 const u32 temp = PacketBuffer.U4[0];
463 DrawingArea[0] = temp & 0x3FF;
464 DrawingArea[1] = (temp >> 10) & 0x3FF;
465 gpu.ex_regs[3] = temp;
469 const u32 temp = PacketBuffer.U4[0];
470 DrawingArea[2] = (temp & 0x3FF) + 1;
471 DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
472 gpu.ex_regs[4] = temp;
476 const u32 temp = PacketBuffer.U4[0];
477 DrawingOffset[0] = ((long)temp<<(32-11))>>(32-11);
478 DrawingOffset[1] = ((long)temp<<(32-22))>>(32-11);
479 gpu.ex_regs[5] = temp;
483 const u32 temp = PacketBuffer.U4[0];
484 Masking = (temp & 0x2) << 1;
485 PixelMSB =(temp & 0x1) << 8;
486 gpu.ex_regs[6] = temp;
493 gpu.ex_regs[1] &= ~0x1ff;
494 gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
497 return list - list_start;
500 void renderer_sync_ecmds(uint32_t *ecmds)
503 do_cmd_list(&ecmds[1], 6, &dummy);
506 void renderer_update_caches(int x, int y, int w, int h)
510 void renderer_flush_queues(void)
514 void renderer_set_interlace(int enable, int is_odd)
520 #include "../../frontend/plugin_lib.h"
522 void renderer_set_config(const struct rearmed_cbs *cbs)
524 force_interlace = cbs->gpu_unai.lineskip;
525 enableAbbeyHack = cbs->gpu_unai.abe_hack;
526 light = !cbs->gpu_unai.no_light;
527 blend = !cbs->gpu_unai.no_blend;
532 // vim:shiftwidth=2:expandtab