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_fixedpoint.h"
109 // Inner loop driver instanciation file
110 #include "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_raster_image.h"
125 // GPU internal line drawing functions
126 #include "gpu_raster_line.h"
128 // GPU internal polygon drawing functions
129 #include "gpu_raster_polygon.h"
131 // GPU internal sprite drawing functions
132 #include "gpu_raster_sprite.h"
134 // GPU command buffer execution/store
135 #include "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(uint32_t *list, int list_len,
173 int *cycles_sum_out, int *cycles_last, int *last_cmd)
175 unsigned int cmd = 0, len, i;
176 unsigned int *list_start = list;
177 unsigned int *list_end = list + list_len;
179 linesInterlace = force_interlace;
180 #ifdef HAVE_PRE_ARMV7 /* XXX */
181 linesInterlace |= !!(gpu.status & PSX_GPU_STATUS_INTERLACE);
184 for (; list < list_end; list += 1 + len)
187 len = cmd_lengths[cmd];
188 if (list + 1 + len > list_end) {
194 PacketBuffer.U4[0] = list[0];
195 for (i = 1; i <= len; i++)
196 PacketBuffer.U4[i] = list[i];
208 gpuDrawF3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB]);
215 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
216 gpuSetTexture(PacketBuffer.U4[4] >> 16);
217 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
218 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB]);
220 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB]);
227 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB];
228 gpuDrawF3(gpuPolySpanDriver);
229 PacketBuffer.U4[1] = PacketBuffer.U4[4];
230 gpuDrawF3(gpuPolySpanDriver);
238 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
239 gpuSetTexture(PacketBuffer.U4[4] >> 16);
240 PP gpuPolySpanDriver;
241 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
242 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB];
244 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB];
245 gpuDrawFT3(gpuPolySpanDriver);
246 PacketBuffer.U4[1] = PacketBuffer.U4[7];
247 PacketBuffer.U4[2] = PacketBuffer.U4[8];
248 gpuDrawFT3(gpuPolySpanDriver);
256 gpuDrawG3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB]);
263 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
264 gpuSetTexture (PacketBuffer.U4[5] >> 16);
265 gpuDrawGT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB]);
272 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB];
273 gpuDrawG3(gpuPolySpanDriver);
274 PacketBuffer.U4[0] = PacketBuffer.U4[6];
275 PacketBuffer.U4[1] = PacketBuffer.U4[7];
276 gpuDrawG3(gpuPolySpanDriver);
284 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
285 gpuSetTexture (PacketBuffer.U4[5] >> 16);
286 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB];
287 gpuDrawGT3(gpuPolySpanDriver);
288 PacketBuffer.U4[0] = PacketBuffer.U4[9];
289 PacketBuffer.U4[1] = PacketBuffer.U4[10];
290 PacketBuffer.U4[2] = PacketBuffer.U4[11];
291 gpuDrawGT3(gpuPolySpanDriver);
299 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
304 u32 num_vertexes = 1;
305 u32 *list_position = &(list[2]);
307 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
311 PacketBuffer.U4[1] = PacketBuffer.U4[2];
312 PacketBuffer.U4[2] = *list_position++;
313 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
316 if(list_position >= list_end) {
320 if((*list_position & 0xf000f000) == 0x50005000)
324 len += (num_vertexes - 2);
332 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
337 u32 num_vertexes = 1;
338 u32 *list_position = &(list[2]);
340 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
344 PacketBuffer.U4[0] = PacketBuffer.U4[2];
345 PacketBuffer.U4[1] = PacketBuffer.U4[3];
346 PacketBuffer.U4[2] = *list_position++;
347 PacketBuffer.U4[3] = *list_position++;
348 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
351 if(list_position >= list_end) {
355 if((*list_position & 0xf000f000) == 0x50005000)
359 len += (num_vertexes - 2) * 2;
367 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
374 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
375 gpuSetTexture (GPU_GP1);
376 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
377 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
379 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
386 PacketBuffer.U4[2] = 0x00010001;
387 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
394 PacketBuffer.U4[2] = 0x00080008;
395 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
402 PacketBuffer.U4[3] = 0x00080008;
403 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
404 gpuSetTexture (GPU_GP1);
405 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
406 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
408 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
415 PacketBuffer.U4[2] = 0x00100010;
416 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
422 if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
424 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
425 gpuSetTexture (GPU_GP1);
433 PacketBuffer.U4[3] = 0x00100010;
434 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
435 gpuSetTexture (GPU_GP1);
436 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
437 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
439 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
443 case 0x80: // vid -> vid
444 gpuMoveImage(); // prim handles updateLace && skip
446 case 0xA0: // sys -> vid
448 u32 load_width = list[2] & 0xffff;
449 u32 load_height = list[2] >> 16;
450 u32 load_size = load_width * load_height;
452 len += load_size / 2;
458 case 0x80 ... 0x9F: // vid -> vid
459 case 0xA0 ... 0xBF: // sys -> vid
460 case 0xC0 ... 0xDF: // vid -> sys
465 const u32 temp = PacketBuffer.U4[0];
466 GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
468 gpu.ex_regs[1] = temp;
472 static const u8 TextureMask[32] = {
473 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
474 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
476 const u32 temp = PacketBuffer.U4[0];
477 TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
478 TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
479 TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
480 TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
481 gpuSetTexture(GPU_GP1);
482 gpu.ex_regs[2] = temp;
486 const u32 temp = PacketBuffer.U4[0];
487 DrawingArea[0] = temp & 0x3FF;
488 DrawingArea[1] = (temp >> 10) & 0x3FF;
489 gpu.ex_regs[3] = temp;
493 const u32 temp = PacketBuffer.U4[0];
494 DrawingArea[2] = (temp & 0x3FF) + 1;
495 DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
496 gpu.ex_regs[4] = temp;
500 const u32 temp = PacketBuffer.U4[0];
501 DrawingOffset[0] = ((s32)temp<<(32-11))>>(32-11);
502 DrawingOffset[1] = ((s32)temp<<(32-22))>>(32-11);
503 gpu.ex_regs[5] = temp;
507 const u32 temp = PacketBuffer.U4[0];
508 Masking = (temp & 0x2) << 1;
509 PixelMSB =(temp & 0x1) << 8;
510 gpu.ex_regs[6] = temp;
517 gpu.ex_regs[1] &= ~0x1ff;
518 gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
521 return list - list_start;
524 void renderer_sync_ecmds(uint32_t *ecmds)
527 do_cmd_list(&ecmds[1], 6, &dummy, &dummy, &dummy);
530 void renderer_update_caches(int x, int y, int w, int h, int state_changed)
534 void renderer_flush_queues(void)
538 void renderer_set_interlace(int enable, int is_odd)
544 #include "../../frontend/plugin_lib.h"
546 void renderer_set_config(const struct rearmed_cbs *cbs)
548 force_interlace = cbs->gpu_unai_old.lineskip;
549 enableAbbeyHack = cbs->gpu_unai_old.abe_hack;
550 light = !cbs->gpu_unai_old.no_light;
551 blend = !cbs->gpu_unai_old.no_blend;
553 GPU_FrameBuffer = (u16 *)gpu.vram;
558 // vim:shiftwidth=2:expandtab