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"
26 #include "arm_features.h"
38 #define FRAME_BUFFER_SIZE (1024*512*2)
39 #define FRAME_WIDTH 1024
40 #define FRAME_HEIGHT 512
41 #define FRAME_OFFSET(x,y) (((y)<<10)+(x))
43 #define isSkip 0 /* skip frame (info coming from GPU) */
45 static int linesInterlace; /* internal lines interlace */
46 static int force_interlace;
48 static bool light = true; /* lighting */
49 static bool blend = true; /* blending */
50 static bool FrameToRead = false; /* load image in progress */
51 static bool FrameToWrite = false; /* store image in progress */
53 static bool enableAbbeyHack = false; /* Abe's Odyssey hack */
62 ///////////////////////////////////////////////////////////////////////////////
64 ///////////////////////////////////////////////////////////////////////////////
68 static s32 x_end,y_end;
71 static s32 PacketCount;
72 static s32 PacketIndex;
75 static u32 TextureWindow [4];
76 static u32 DrawingArea [4];
77 static u32 DrawingOffset [2];
89 static u32 tInc, tMsk;
101 static GPUPacket PacketBuffer;
102 static u16 *GPU_FrameBuffer;
105 ///////////////////////////////////////////////////////////////////////////////
107 #include "../gpu_unai/gpu_fixedpoint.h"
109 // Inner loop driver instanciation file
110 #include "../gpu_unai/gpu_inner.h"
113 #define GPU_RGB16(rgb) ((((rgb)&0xF80000)>>9)|(((rgb)&0xF800)>>6)|(((rgb)&0xF8)>>3))
115 #define GPU_EXPANDSIGN(x) (((s32)(x)<<21)>>21)
117 #define CHKMAX_X 1024
120 #define GPU_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);}
122 // GPU internal image drawing functions
123 #include "../gpu_unai/gpu_raster_image.h"
125 // GPU internal line drawing functions
126 #include "../gpu_unai/gpu_raster_line.h"
128 // GPU internal polygon drawing functions
129 #include "../gpu_unai/gpu_raster_polygon.h"
131 // GPU internal sprite drawing functions
132 #include "../gpu_unai/gpu_raster_sprite.h"
134 // GPU command buffer execution/store
135 #include "../gpu_unai/gpu_command.h"
137 /////////////////////////////////////////////////////////////////////////////
139 int renderer_init(void)
141 GPU_FrameBuffer = (u16 *)gpu.vram;
144 for(int i=1;i<=(1<<TABLE_BITS);++i)
146 double v = 1.0 / double(i);
147 #ifdef GPU_TABLE_10_BITS
148 v *= double(0xffffffff>>1);
150 v *= double(0x80000000);
152 s_invTable[i-1]=s32(v);
158 void renderer_finish(void)
162 void renderer_notify_res_change(void)
166 extern const unsigned char cmd_lengths[256];
168 int do_cmd_list(unsigned int *list, int list_len, int *last_cmd)
170 unsigned int cmd = 0, len, i;
171 unsigned int *list_start = list;
172 unsigned int *list_end = list + list_len;
174 linesInterlace = force_interlace;
175 #ifdef HAVE_PRE_ARMV7 /* XXX */
176 linesInterlace |= !!(gpu.status & PSX_GPU_STATUS_INTERLACE);
179 for (; list < list_end; list += 1 + len)
182 len = cmd_lengths[cmd];
183 if (list + 1 + len > list_end) {
189 PacketBuffer.U4[0] = list[0];
190 for (i = 1; i <= len; i++)
191 PacketBuffer.U4[i] = list[i];
203 gpuDrawF3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB]);
210 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
211 gpuSetTexture(PacketBuffer.U4[4] >> 16);
212 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
213 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB]);
215 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB]);
222 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB];
223 gpuDrawF3(gpuPolySpanDriver);
224 PacketBuffer.U4[1] = PacketBuffer.U4[4];
225 gpuDrawF3(gpuPolySpanDriver);
233 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
234 gpuSetTexture(PacketBuffer.U4[4] >> 16);
235 PP gpuPolySpanDriver;
236 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
237 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB];
239 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB];
240 gpuDrawFT3(gpuPolySpanDriver);
241 PacketBuffer.U4[1] = PacketBuffer.U4[7];
242 PacketBuffer.U4[2] = PacketBuffer.U4[8];
243 gpuDrawFT3(gpuPolySpanDriver);
251 gpuDrawG3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB]);
258 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
259 gpuSetTexture (PacketBuffer.U4[5] >> 16);
260 gpuDrawGT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB]);
267 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB];
268 gpuDrawG3(gpuPolySpanDriver);
269 PacketBuffer.U4[0] = PacketBuffer.U4[6];
270 PacketBuffer.U4[1] = PacketBuffer.U4[7];
271 gpuDrawG3(gpuPolySpanDriver);
279 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
280 gpuSetTexture (PacketBuffer.U4[5] >> 16);
281 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB];
282 gpuDrawGT3(gpuPolySpanDriver);
283 PacketBuffer.U4[0] = PacketBuffer.U4[9];
284 PacketBuffer.U4[1] = PacketBuffer.U4[10];
285 PacketBuffer.U4[2] = PacketBuffer.U4[11];
286 gpuDrawGT3(gpuPolySpanDriver);
294 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
299 u32 num_vertexes = 1;
300 u32 *list_position = &(list[2]);
302 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
306 PacketBuffer.U4[1] = PacketBuffer.U4[2];
307 PacketBuffer.U4[2] = *list_position++;
308 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
311 if(list_position >= list_end) {
315 if((*list_position & 0xf000f000) == 0x50005000)
319 len += (num_vertexes - 2);
327 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
332 u32 num_vertexes = 1;
333 u32 *list_position = &(list[2]);
335 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
339 PacketBuffer.U4[0] = PacketBuffer.U4[2];
340 PacketBuffer.U4[1] = PacketBuffer.U4[3];
341 PacketBuffer.U4[2] = *list_position++;
342 PacketBuffer.U4[3] = *list_position++;
343 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
346 if(list_position >= list_end) {
350 if((*list_position & 0xf000f000) == 0x50005000)
354 len += (num_vertexes - 2) * 2;
362 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
369 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
370 gpuSetTexture (GPU_GP1);
371 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
372 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
374 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
381 PacketBuffer.U4[2] = 0x00010001;
382 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
389 PacketBuffer.U4[2] = 0x00080008;
390 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
397 PacketBuffer.U4[3] = 0x00080008;
398 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
399 gpuSetTexture (GPU_GP1);
400 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
401 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
403 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
410 PacketBuffer.U4[2] = 0x00100010;
411 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
417 if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
419 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
420 gpuSetTexture (GPU_GP1);
428 PacketBuffer.U4[3] = 0x00100010;
429 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
430 gpuSetTexture (GPU_GP1);
431 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
432 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
434 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
437 case 0x80: // vid -> vid
438 gpuMoveImage(); // prim handles updateLace && skip
441 case 0xA0: // sys -> vid
443 u32 load_width = list[2] & 0xffff;
444 u32 load_height = list[2] >> 16;
445 u32 load_size = load_width * load_height;
447 len += load_size / 2;
453 case 0xA0: // sys ->vid
454 case 0xC0: // vid -> sys
458 const u32 temp = PacketBuffer.U4[0];
459 GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
461 gpu.ex_regs[1] = temp;
465 static const u8 TextureMask[32] = {
466 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
467 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
469 const u32 temp = PacketBuffer.U4[0];
470 TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
471 TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
472 TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
473 TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
474 gpuSetTexture(GPU_GP1);
475 gpu.ex_regs[2] = temp;
479 const u32 temp = PacketBuffer.U4[0];
480 DrawingArea[0] = temp & 0x3FF;
481 DrawingArea[1] = (temp >> 10) & 0x3FF;
482 gpu.ex_regs[3] = temp;
486 const u32 temp = PacketBuffer.U4[0];
487 DrawingArea[2] = (temp & 0x3FF) + 1;
488 DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
489 gpu.ex_regs[4] = temp;
493 const u32 temp = PacketBuffer.U4[0];
494 DrawingOffset[0] = ((s32)temp<<(32-11))>>(32-11);
495 DrawingOffset[1] = ((s32)temp<<(32-22))>>(32-11);
496 gpu.ex_regs[5] = temp;
500 const u32 temp = PacketBuffer.U4[0];
501 Masking = (temp & 0x2) << 1;
502 PixelMSB =(temp & 0x1) << 8;
503 gpu.ex_regs[6] = temp;
510 gpu.ex_regs[1] &= ~0x1ff;
511 gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
514 return list - list_start;
517 void renderer_sync_ecmds(uint32_t *ecmds)
520 do_cmd_list(&ecmds[1], 6, &dummy);
523 void renderer_update_caches(int x, int y, int w, int h)
527 void renderer_flush_queues(void)
531 void renderer_set_interlace(int enable, int is_odd)
537 #include "../../frontend/plugin_lib.h"
539 void renderer_set_config(const struct rearmed_cbs *cbs)
541 force_interlace = cbs->gpu_unai.lineskip;
542 enableAbbeyHack = cbs->gpu_unai.abe_hack;
543 light = !cbs->gpu_unai.no_light;
544 blend = !cbs->gpu_unai.no_blend;
546 GPU_FrameBuffer = (u16 *)gpu.vram;
551 // vim:shiftwidth=2:expandtab