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 void renderer_finish(void)
161 void renderer_notify_res_change(void)
165 extern const unsigned char cmd_lengths[256];
167 int do_cmd_list(unsigned int *list, int list_len, int *last_cmd)
169 unsigned int cmd = 0, len, i;
170 unsigned int *list_start = list;
171 unsigned int *list_end = list + list_len;
173 linesInterlace = force_interlace;
174 #ifndef __ARM_ARCH_7A__ /* XXX */
175 linesInterlace |= gpu.status.interlace;
178 for (; list < list_end; list += 1 + len)
181 len = cmd_lengths[cmd];
182 if (list + 1 + len > list_end) {
188 PacketBuffer.U4[0] = list[0];
189 for (i = 1; i <= len; i++)
190 PacketBuffer.U4[i] = list[i];
202 gpuDrawF3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB]);
209 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
210 gpuSetTexture(PacketBuffer.U4[4] >> 16);
211 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
212 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB]);
214 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB]);
221 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB];
222 gpuDrawF3(gpuPolySpanDriver);
223 PacketBuffer.U4[1] = PacketBuffer.U4[4];
224 gpuDrawF3(gpuPolySpanDriver);
232 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
233 gpuSetTexture(PacketBuffer.U4[4] >> 16);
234 PP gpuPolySpanDriver;
235 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
236 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB];
238 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB];
239 gpuDrawFT3(gpuPolySpanDriver);
240 PacketBuffer.U4[1] = PacketBuffer.U4[7];
241 PacketBuffer.U4[2] = PacketBuffer.U4[8];
242 gpuDrawFT3(gpuPolySpanDriver);
250 gpuDrawG3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB]);
257 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
258 gpuSetTexture (PacketBuffer.U4[5] >> 16);
259 gpuDrawGT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB]);
266 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB];
267 gpuDrawG3(gpuPolySpanDriver);
268 PacketBuffer.U4[0] = PacketBuffer.U4[6];
269 PacketBuffer.U4[1] = PacketBuffer.U4[7];
270 gpuDrawG3(gpuPolySpanDriver);
278 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
279 gpuSetTexture (PacketBuffer.U4[5] >> 16);
280 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB];
281 gpuDrawGT3(gpuPolySpanDriver);
282 PacketBuffer.U4[0] = PacketBuffer.U4[9];
283 PacketBuffer.U4[1] = PacketBuffer.U4[10];
284 PacketBuffer.U4[2] = PacketBuffer.U4[11];
285 gpuDrawGT3(gpuPolySpanDriver);
293 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
298 u32 num_vertexes = 1;
299 u32 *list_position = &(list[2]);
301 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
305 PacketBuffer.U4[1] = PacketBuffer.U4[2];
306 PacketBuffer.U4[2] = *list_position++;
307 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
310 if(list_position >= list_end) {
314 if((*list_position & 0xf000f000) == 0x50005000)
318 len += (num_vertexes - 2);
326 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
331 u32 num_vertexes = 1;
332 u32 *list_position = &(list[2]);
334 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
338 PacketBuffer.U4[0] = PacketBuffer.U4[2];
339 PacketBuffer.U4[1] = PacketBuffer.U4[3];
340 PacketBuffer.U4[2] = *list_position++;
341 PacketBuffer.U4[3] = *list_position++;
342 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
345 if(list_position >= list_end) {
349 if((*list_position & 0xf000f000) == 0x50005000)
353 len += (num_vertexes - 2) * 2;
361 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
368 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
369 gpuSetTexture (GPU_GP1);
370 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
371 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
373 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
380 PacketBuffer.U4[2] = 0x00010001;
381 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
388 PacketBuffer.U4[2] = 0x00080008;
389 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
396 PacketBuffer.U4[3] = 0x00080008;
397 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
398 gpuSetTexture (GPU_GP1);
399 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
400 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
402 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
409 PacketBuffer.U4[2] = 0x00100010;
410 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
416 if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
418 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
419 gpuSetTexture (GPU_GP1);
427 PacketBuffer.U4[3] = 0x00100010;
428 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
429 gpuSetTexture (GPU_GP1);
430 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
431 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
433 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
436 case 0x80: // vid -> vid
437 gpuMoveImage(); // prim handles updateLace && skip
440 case 0xA0: // sys -> vid
442 u32 load_width = list[2] & 0xffff;
443 u32 load_height = list[2] >> 16;
444 u32 load_size = load_width * load_height;
446 len += load_size / 2;
452 case 0xA0: // sys ->vid
453 case 0xC0: // vid -> sys
457 const u32 temp = PacketBuffer.U4[0];
458 GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
460 gpu.ex_regs[1] = temp;
464 static const u8 TextureMask[32] = {
465 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
466 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
468 const u32 temp = PacketBuffer.U4[0];
469 TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
470 TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
471 TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
472 TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
473 gpuSetTexture(GPU_GP1);
474 gpu.ex_regs[2] = temp;
478 const u32 temp = PacketBuffer.U4[0];
479 DrawingArea[0] = temp & 0x3FF;
480 DrawingArea[1] = (temp >> 10) & 0x3FF;
481 gpu.ex_regs[3] = temp;
485 const u32 temp = PacketBuffer.U4[0];
486 DrawingArea[2] = (temp & 0x3FF) + 1;
487 DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
488 gpu.ex_regs[4] = temp;
492 const u32 temp = PacketBuffer.U4[0];
493 DrawingOffset[0] = ((long)temp<<(32-11))>>(32-11);
494 DrawingOffset[1] = ((long)temp<<(32-22))>>(32-11);
495 gpu.ex_regs[5] = temp;
499 const u32 temp = PacketBuffer.U4[0];
500 Masking = (temp & 0x2) << 1;
501 PixelMSB =(temp & 0x1) << 8;
502 gpu.ex_regs[6] = temp;
509 gpu.ex_regs[1] &= ~0x1ff;
510 gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
513 return list - list_start;
516 void renderer_sync_ecmds(uint32_t *ecmds)
519 do_cmd_list(&ecmds[1], 6, &dummy);
522 void renderer_update_caches(int x, int y, int w, int h)
526 void renderer_flush_queues(void)
530 void renderer_set_interlace(int enable, int is_odd)
536 #include "../../frontend/plugin_lib.h"
538 void renderer_set_config(const struct rearmed_cbs *cbs)
540 force_interlace = cbs->gpu_unai.lineskip;
541 enableAbbeyHack = cbs->gpu_unai.abe_hack;
542 light = !cbs->gpu_unai.no_light;
543 blend = !cbs->gpu_unai.no_blend;
545 GPU_FrameBuffer = (u16 *)gpu.vram;
550 // vim:shiftwidth=2:expandtab