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_change(int x, int y)
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]);
442 case 0x80: // vid -> vid
443 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 0x80 ... 0x9F: // vid -> vid
458 case 0xA0 ... 0xBF: // sys -> vid
459 case 0xC0 ... 0xDF: // vid -> sys
464 const u32 temp = PacketBuffer.U4[0];
465 GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
467 gpu.ex_regs[1] = temp;
471 static const u8 TextureMask[32] = {
472 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
473 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
475 const u32 temp = PacketBuffer.U4[0];
476 TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
477 TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
478 TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
479 TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
480 gpuSetTexture(GPU_GP1);
481 gpu.ex_regs[2] = temp;
485 const u32 temp = PacketBuffer.U4[0];
486 DrawingArea[0] = temp & 0x3FF;
487 DrawingArea[1] = (temp >> 10) & 0x3FF;
488 gpu.ex_regs[3] = temp;
492 const u32 temp = PacketBuffer.U4[0];
493 DrawingArea[2] = (temp & 0x3FF) + 1;
494 DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
495 gpu.ex_regs[4] = temp;
499 const u32 temp = PacketBuffer.U4[0];
500 DrawingOffset[0] = ((s32)temp<<(32-11))>>(32-11);
501 DrawingOffset[1] = ((s32)temp<<(32-22))>>(32-11);
502 gpu.ex_regs[5] = temp;
506 const u32 temp = PacketBuffer.U4[0];
507 Masking = (temp & 0x2) << 1;
508 PixelMSB =(temp & 0x1) << 8;
509 gpu.ex_regs[6] = temp;
516 gpu.ex_regs[1] &= ~0x1ff;
517 gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
520 return list - list_start;
523 void renderer_sync_ecmds(uint32_t *ecmds)
526 do_cmd_list(&ecmds[1], 6, &dummy);
529 void renderer_update_caches(int x, int y, int w, int h, int state_changed)
533 void renderer_flush_queues(void)
537 void renderer_set_interlace(int enable, int is_odd)
543 #include "../../frontend/plugin_lib.h"
545 void renderer_set_config(const struct rearmed_cbs *cbs)
547 force_interlace = cbs->gpu_unai.lineskip;
548 enableAbbeyHack = cbs->gpu_unai.abe_hack;
549 light = !cbs->gpu_unai.no_light;
550 blend = !cbs->gpu_unai.no_blend;
552 GPU_FrameBuffer = (u16 *)gpu.vram;
557 // vim:shiftwidth=2:expandtab