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 void renderer_notify_scanout_x_change(int x, int w)
170 extern const unsigned char cmd_lengths[256];
172 int do_cmd_list(unsigned int *list, int list_len, int *last_cmd)
174 unsigned int cmd = 0, len, i;
175 unsigned int *list_start = list;
176 unsigned int *list_end = list + list_len;
178 linesInterlace = force_interlace;
179 #ifdef HAVE_PRE_ARMV7 /* XXX */
180 linesInterlace |= !!(gpu.status & PSX_GPU_STATUS_INTERLACE);
183 for (; list < list_end; list += 1 + len)
186 len = cmd_lengths[cmd];
187 if (list + 1 + len > list_end) {
193 PacketBuffer.U4[0] = list[0];
194 for (i = 1; i <= len; i++)
195 PacketBuffer.U4[i] = list[i];
207 gpuDrawF3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB]);
214 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
215 gpuSetTexture(PacketBuffer.U4[4] >> 16);
216 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
217 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB]);
219 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB]);
226 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB];
227 gpuDrawF3(gpuPolySpanDriver);
228 PacketBuffer.U4[1] = PacketBuffer.U4[4];
229 gpuDrawF3(gpuPolySpanDriver);
237 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
238 gpuSetTexture(PacketBuffer.U4[4] >> 16);
239 PP gpuPolySpanDriver;
240 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
241 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB];
243 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB];
244 gpuDrawFT3(gpuPolySpanDriver);
245 PacketBuffer.U4[1] = PacketBuffer.U4[7];
246 PacketBuffer.U4[2] = PacketBuffer.U4[8];
247 gpuDrawFT3(gpuPolySpanDriver);
255 gpuDrawG3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB]);
262 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
263 gpuSetTexture (PacketBuffer.U4[5] >> 16);
264 gpuDrawGT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB]);
271 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB];
272 gpuDrawG3(gpuPolySpanDriver);
273 PacketBuffer.U4[0] = PacketBuffer.U4[6];
274 PacketBuffer.U4[1] = PacketBuffer.U4[7];
275 gpuDrawG3(gpuPolySpanDriver);
283 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
284 gpuSetTexture (PacketBuffer.U4[5] >> 16);
285 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB];
286 gpuDrawGT3(gpuPolySpanDriver);
287 PacketBuffer.U4[0] = PacketBuffer.U4[9];
288 PacketBuffer.U4[1] = PacketBuffer.U4[10];
289 PacketBuffer.U4[2] = PacketBuffer.U4[11];
290 gpuDrawGT3(gpuPolySpanDriver);
298 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
303 u32 num_vertexes = 1;
304 u32 *list_position = &(list[2]);
306 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
310 PacketBuffer.U4[1] = PacketBuffer.U4[2];
311 PacketBuffer.U4[2] = *list_position++;
312 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
315 if(list_position >= list_end) {
319 if((*list_position & 0xf000f000) == 0x50005000)
323 len += (num_vertexes - 2);
331 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
336 u32 num_vertexes = 1;
337 u32 *list_position = &(list[2]);
339 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
343 PacketBuffer.U4[0] = PacketBuffer.U4[2];
344 PacketBuffer.U4[1] = PacketBuffer.U4[3];
345 PacketBuffer.U4[2] = *list_position++;
346 PacketBuffer.U4[3] = *list_position++;
347 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
350 if(list_position >= list_end) {
354 if((*list_position & 0xf000f000) == 0x50005000)
358 len += (num_vertexes - 2) * 2;
366 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
373 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
374 gpuSetTexture (GPU_GP1);
375 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
376 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
378 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
385 PacketBuffer.U4[2] = 0x00010001;
386 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
393 PacketBuffer.U4[2] = 0x00080008;
394 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
401 PacketBuffer.U4[3] = 0x00080008;
402 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
403 gpuSetTexture (GPU_GP1);
404 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
405 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
407 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
414 PacketBuffer.U4[2] = 0x00100010;
415 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
421 if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
423 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
424 gpuSetTexture (GPU_GP1);
432 PacketBuffer.U4[3] = 0x00100010;
433 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
434 gpuSetTexture (GPU_GP1);
435 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
436 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
438 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
441 case 0x80: // vid -> vid
442 gpuMoveImage(); // prim handles updateLace && skip
445 case 0xA0: // sys -> vid
447 u32 load_width = list[2] & 0xffff;
448 u32 load_height = list[2] >> 16;
449 u32 load_size = load_width * load_height;
451 len += load_size / 2;
457 case 0xA0: // sys ->vid
458 case 0xC0: // vid -> sys
462 const u32 temp = PacketBuffer.U4[0];
463 GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
465 gpu.ex_regs[1] = temp;
469 static const u8 TextureMask[32] = {
470 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
471 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
473 const u32 temp = PacketBuffer.U4[0];
474 TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
475 TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
476 TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
477 TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
478 gpuSetTexture(GPU_GP1);
479 gpu.ex_regs[2] = temp;
483 const u32 temp = PacketBuffer.U4[0];
484 DrawingArea[0] = temp & 0x3FF;
485 DrawingArea[1] = (temp >> 10) & 0x3FF;
486 gpu.ex_regs[3] = temp;
490 const u32 temp = PacketBuffer.U4[0];
491 DrawingArea[2] = (temp & 0x3FF) + 1;
492 DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
493 gpu.ex_regs[4] = temp;
497 const u32 temp = PacketBuffer.U4[0];
498 DrawingOffset[0] = ((s32)temp<<(32-11))>>(32-11);
499 DrawingOffset[1] = ((s32)temp<<(32-22))>>(32-11);
500 gpu.ex_regs[5] = temp;
504 const u32 temp = PacketBuffer.U4[0];
505 Masking = (temp & 0x2) << 1;
506 PixelMSB =(temp & 0x1) << 8;
507 gpu.ex_regs[6] = temp;
514 gpu.ex_regs[1] &= ~0x1ff;
515 gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
518 return list - list_start;
521 void renderer_sync_ecmds(uint32_t *ecmds)
524 do_cmd_list(&ecmds[1], 6, &dummy);
527 void renderer_update_caches(int x, int y, int w, int h, int state_changed)
531 void renderer_flush_queues(void)
535 void renderer_set_interlace(int enable, int is_odd)
541 #include "../../frontend/plugin_lib.h"
543 void renderer_set_config(const struct rearmed_cbs *cbs)
545 force_interlace = cbs->gpu_unai.lineskip;
546 enableAbbeyHack = cbs->gpu_unai.abe_hack;
547 light = !cbs->gpu_unai.no_light;
548 blend = !cbs->gpu_unai.no_blend;
550 GPU_FrameBuffer = (u16 *)gpu.vram;
555 // vim:shiftwidth=2:expandtab