gpulib: yet another frameskip hack
[pcsx_rearmed.git] / plugins / gpu_unai / gpulib_if.cpp
1 /***************************************************************************
2 *   Copyright (C) 2010 PCSX4ALL Team                                      *
3 *   Copyright (C) 2010 Unai                                               *
4 *   Copyright (C) 2011 notaz                                              *
5 *                                                                         *
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.                                   *
10 *                                                                         *
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.                          *
15 *                                                                         *
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 ***************************************************************************/
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include "../gpulib/gpu.h"
26
27 #define u8 uint8_t
28 #define s8 int8_t
29 #define u16 uint16_t
30 #define s16 int16_t
31 #define u32 uint32_t
32 #define s32 int32_t
33 #define s64 int64_t
34
35 #define INLINE static
36
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))
41
42 #define isSkip 0 /* skip frame (info coming from GPU) */
43 #define alt_fps 0
44 static int linesInterlace;  /* internal lines interlace */
45 static int force_interlace;
46
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 */
51
52 static bool enableAbbeyHack = false; /* Abe's Odyssey hack */
53
54 static u8 BLEND_MODE;
55 static u8 TEXT_MODE;
56 static u8 Masking;
57
58 static u16 PixelMSB;
59 static u16 PixelData;
60
61 ///////////////////////////////////////////////////////////////////////////////
62 //  GPU Global data
63 ///////////////////////////////////////////////////////////////////////////////
64
65 //  Dma Transfers info
66 static s32              px,py;
67 static s32              x_end,y_end;
68 static u16*  pvram;
69
70 static s32 PacketCount;
71 static s32 PacketIndex;
72
73 //  Rasterizer status
74 static u32 TextureWindow [4];
75 static u32 DrawingArea   [4];
76 static u32 DrawingOffset [2];
77
78 static u16* TBA;
79 static u16* CBA;
80
81 //  Inner Loops
82 static s32   u4, du4;
83 static s32   v4, dv4;
84 static s32   r4, dr4;
85 static s32   g4, dg4;
86 static s32   b4, db4;
87 static u32   lInc;
88 static u32   tInc, tMsk;
89
90 union GPUPacket
91 {
92         u32 U4[16];
93         s32 S4[16];
94         u16 U2[32];
95         s16 S2[32];
96         u8  U1[64];
97         s8  S1[64];
98 };
99
100 static GPUPacket PacketBuffer;
101 static u16  *GPU_FrameBuffer;
102 static u32   GPU_GP1;
103
104 ///////////////////////////////////////////////////////////////////////////////
105
106 #include "../gpu_unai/gpu_fixedpoint.h"
107
108 //  Inner loop driver instanciation file
109 #include "../gpu_unai/gpu_inner.h"
110
111 //  GPU Raster Macros
112 #define GPU_RGB16(rgb)        ((((rgb)&0xF80000)>>9)|(((rgb)&0xF800)>>6)|(((rgb)&0xF8)>>3))
113
114 #define GPU_EXPANDSIGN_POLY(x)  (((s32)(x)<<20)>>20)
115 //#define GPU_EXPANDSIGN_POLY(x)  (((s32)(x)<<21)>>21)
116 #define GPU_EXPANDSIGN_SPRT(x)  (((s32)(x)<<21)>>21)
117
118 //#define       GPU_TESTRANGE(x)      { if((u32)(x+1024) > 2047) return; }
119 #define GPU_TESTRANGE(x)      { if ((x<-1023) || (x>1023)) return; }
120
121 #define GPU_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);}
122
123 // GPU internal image drawing functions
124 #include "../gpu_unai/gpu_raster_image.h"
125
126 // GPU internal line drawing functions
127 #include "../gpu_unai/gpu_raster_line.h"
128
129 // GPU internal polygon drawing functions
130 #include "../gpu_unai/gpu_raster_polygon.h"
131
132 // GPU internal sprite drawing functions
133 #include "../gpu_unai/gpu_raster_sprite.h"
134
135 // GPU command buffer execution/store
136 #include "../gpu_unai/gpu_command.h"
137
138 /////////////////////////////////////////////////////////////////////////////
139
140 int renderer_init(void)
141 {
142         GPU_FrameBuffer = (u16 *)gpu.vram;
143
144         // s_invTable
145         for(int i=1;i<=(1<<TABLE_BITS);++i)
146         {
147                 double v = 1.0 / double(i);
148                 #ifdef GPU_TABLE_10_BITS
149                 v *= double(0xffffffff>>1);
150                 #else
151                 v *= double(0x80000000);
152                 #endif
153                 s_invTable[i-1]=s32(v);
154         }
155
156         return 0;
157 }
158
159 extern const unsigned char cmd_lengths[256];
160
161 int do_cmd_list(unsigned int *list, int list_len, int *last_cmd)
162 {
163   unsigned int cmd = 0, len, i;
164   unsigned int *list_start = list;
165   unsigned int *list_end = list + list_len;
166
167   linesInterlace = force_interlace;
168 #ifndef __ARM_ARCH_7A__ /* XXX */
169   linesInterlace |= gpu.status.interlace;
170 #endif
171
172   for (; list < list_end; list += 1 + len)
173   {
174     cmd = *list >> 24;
175     len = cmd_lengths[cmd];
176     if (list + 1 + len > list_end) {
177       cmd = -1;
178       break;
179     }
180
181     #define PRIM cmd
182     PacketBuffer.U4[0] = list[0];
183     for (i = 1; i <= len; i++)
184       PacketBuffer.U4[i] = list[i];
185
186     switch (cmd)
187     {
188       case 0x02:
189         gpuClearImage();
190         break;
191
192       case 0x20:
193       case 0x21:
194       case 0x22:
195       case 0x23:
196         gpuDrawF3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB]);
197         break;
198
199       case 0x24:
200       case 0x25:
201       case 0x26:
202       case 0x27:
203         gpuSetCLUT   (PacketBuffer.U4[2] >> 16);
204         gpuSetTexture(PacketBuffer.U4[4] >> 16);
205         if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
206           gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB]);
207         else
208           gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB]);
209         break;
210
211       case 0x28:
212       case 0x29:
213       case 0x2A:
214       case 0x2B: {
215         const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB];
216         gpuDrawF3(gpuPolySpanDriver);
217         PacketBuffer.U4[1] = PacketBuffer.U4[4];
218         gpuDrawF3(gpuPolySpanDriver);
219         break;
220       }
221
222       case 0x2C:
223       case 0x2D:
224       case 0x2E:
225       case 0x2F: {
226         gpuSetCLUT   (PacketBuffer.U4[2] >> 16);
227         gpuSetTexture(PacketBuffer.U4[4] >> 16);
228         PP gpuPolySpanDriver;
229         if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
230           gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB];
231         else
232           gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB];
233         gpuDrawFT3(gpuPolySpanDriver);
234         PacketBuffer.U4[1] = PacketBuffer.U4[7];
235         PacketBuffer.U4[2] = PacketBuffer.U4[8];
236         gpuDrawFT3(gpuPolySpanDriver);
237         break;
238       }
239
240       case 0x30:
241       case 0x31:
242       case 0x32:
243       case 0x33:
244         gpuDrawG3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB]);
245         break;
246
247       case 0x34:
248       case 0x35:
249       case 0x36:
250       case 0x37:
251         gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
252         gpuSetTexture (PacketBuffer.U4[5] >> 16);
253         gpuDrawGT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB]);
254         break;
255
256       case 0x38:
257       case 0x39:
258       case 0x3A:
259       case 0x3B: {
260         const PP gpuPolySpanDriver  = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB];
261         gpuDrawG3(gpuPolySpanDriver);
262         PacketBuffer.U4[0] = PacketBuffer.U4[6];
263         PacketBuffer.U4[1] = PacketBuffer.U4[7];
264         gpuDrawG3(gpuPolySpanDriver);
265         break;
266       }
267
268       case 0x3C:
269       case 0x3D:
270       case 0x3E:
271       case 0x3F: {
272         gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
273         gpuSetTexture (PacketBuffer.U4[5] >> 16);
274         const PP gpuPolySpanDriver  = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB];
275         gpuDrawGT3(gpuPolySpanDriver);
276         PacketBuffer.U4[0] = PacketBuffer.U4[9];
277         PacketBuffer.U4[1] = PacketBuffer.U4[10];
278         PacketBuffer.U4[2] = PacketBuffer.U4[11];
279         gpuDrawGT3(gpuPolySpanDriver);
280         break;
281       }
282
283       case 0x40:
284       case 0x41:
285       case 0x42:
286       case 0x43:
287         gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
288         break;
289
290       case 0x48 ... 0x4F:
291       {
292         u32 num_vertexes = 1;
293         u32 *list_position = &(list[2]);
294
295         gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
296
297         while(1)
298         {
299           PacketBuffer.U4[1] = PacketBuffer.U4[2];
300           PacketBuffer.U4[2] = *list_position++;
301           gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
302
303           num_vertexes++;
304           if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
305             break;
306         }
307
308         len += (num_vertexes - 2);
309         break;
310       }
311
312       case 0x50:
313       case 0x51:
314       case 0x52:
315       case 0x53:
316         gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
317         break;
318
319       case 0x58 ... 0x5F:
320       {
321         u32 num_vertexes = 1;
322         u32 *list_position = &(list[2]);
323
324         gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
325
326         while(1)
327         {
328           PacketBuffer.U4[0] = PacketBuffer.U4[2];
329           PacketBuffer.U4[1] = PacketBuffer.U4[3];
330           PacketBuffer.U4[2] = *list_position++;
331           PacketBuffer.U4[3] = *list_position++;
332           gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
333
334           num_vertexes++;
335           if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
336             break;
337         }
338
339         len += (num_vertexes - 2) * 2;
340         break;
341       }
342
343       case 0x60:
344       case 0x61:
345       case 0x62:
346       case 0x63:
347         gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
348         break;
349
350       case 0x64:
351       case 0x65:
352       case 0x66:
353       case 0x67:
354         gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
355         gpuSetTexture (GPU_GP1);
356         if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
357           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7)  | PixelMSB]);
358         else
359           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7)  | PixelMSB]);
360         break;
361
362       case 0x68:
363       case 0x69:
364       case 0x6A:
365       case 0x6B:
366         PacketBuffer.U4[2] = 0x00010001;
367         gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
368         break;
369
370       case 0x70:
371       case 0x71:
372       case 0x72:
373       case 0x73:
374         PacketBuffer.U4[2] = 0x00080008;
375         gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
376         break;
377
378       case 0x74:
379       case 0x75:
380       case 0x76:
381       case 0x77:
382         PacketBuffer.U4[3] = 0x00080008;
383         gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
384         gpuSetTexture (GPU_GP1);
385         if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
386           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7)  | PixelMSB]);
387         else
388           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7)  | PixelMSB]);
389         break;
390
391       case 0x78:
392       case 0x79:
393       case 0x7A:
394       case 0x7B:
395         PacketBuffer.U4[2] = 0x00100010;
396         gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
397         break;
398
399       case 0x7C:
400       case 0x7D:
401 #ifdef __arm__
402         if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
403         {
404           gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
405           gpuSetTexture (GPU_GP1);
406           gpuDrawS16();
407           break;
408         }
409         // fallthrough
410 #endif
411       case 0x7E:
412       case 0x7F:
413         PacketBuffer.U4[3] = 0x00100010;
414         gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
415         gpuSetTexture (GPU_GP1);
416         if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
417           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7)  | PixelMSB]);
418         else
419           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7)  | PixelMSB]);
420         break;
421
422       case 0x80:          //  vid -> vid
423         gpuMoveImage();   //  prim handles updateLace && skip
424         break;
425 #ifdef TEST
426       case 0xA0:          //  sys -> vid
427       {
428         u32 load_width = list[2] & 0xffff;
429         u32 load_height = list[2] >> 16;
430         u32 load_size = load_width * load_height;
431
432         len += load_size / 2;
433         break;
434       }
435       case 0xC0:
436         break;
437 #else
438       case 0xA0:          //  sys ->vid
439       case 0xC0:          //  vid -> sys
440         goto breakloop;
441 #endif
442       case 0xE1: {
443         const u32 temp = PacketBuffer.U4[0];
444         GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
445         gpuSetTexture(temp);
446         gpu.ex_regs[1] = temp;
447         break;
448       }
449       case 0xE2: {
450         static const u8  TextureMask[32] = {
451           255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
452           127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
453         };
454         const u32 temp = PacketBuffer.U4[0];
455         TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
456         TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
457         TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
458         TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
459         gpuSetTexture(GPU_GP1);
460         gpu.ex_regs[2] = temp;
461         break;
462       }
463       case 0xE3: {
464         const u32 temp = PacketBuffer.U4[0];
465         DrawingArea[0] = temp         & 0x3FF;
466         DrawingArea[1] = (temp >> 10) & 0x3FF;
467         gpu.ex_regs[3] = temp;
468         break;
469       }
470       case 0xE4: {
471         const u32 temp = PacketBuffer.U4[0];
472         DrawingArea[2] = (temp         & 0x3FF) + 1;
473         DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
474         gpu.ex_regs[4] = temp;
475         break;
476       }
477       case 0xE5: {
478         const u32 temp = PacketBuffer.U4[0];
479         DrawingOffset[0] = ((long)temp<<(32-11))>>(32-11);
480         DrawingOffset[1] = ((long)temp<<(32-22))>>(32-11);
481         gpu.ex_regs[5] = temp;
482         break;
483       }
484       case 0xE6: {
485         const u32 temp = PacketBuffer.U4[0];
486         Masking = (temp & 0x2) <<  1;
487         PixelMSB =(temp & 0x1) <<  8;
488         gpu.ex_regs[6] = temp;
489         break;
490       }
491     }
492   }
493
494 breakloop:
495   gpu.ex_regs[1] &= ~0x1ff;
496   gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
497
498   *last_cmd = cmd;
499   return list - list_start;
500 }
501
502 void renderer_sync_ecmds(uint32_t *ecmds)
503 {
504   int dummy;
505   do_cmd_list(&ecmds[1], 6, &dummy);
506 }
507
508 void renderer_update_caches(int x, int y, int w, int h)
509 {
510 }
511
512 void renderer_flush_queues(void)
513 {
514 }
515
516 void renderer_set_interlace(int enable, int is_odd)
517 {
518 }
519
520 #ifndef TEST
521
522 #include "../../frontend/plugin_lib.h"
523
524 void renderer_set_config(const struct rearmed_cbs *cbs)
525 {
526   force_interlace = cbs->gpu_unai.lineskip;
527   enableAbbeyHack = cbs->gpu_unai.abe_hack;
528   light = !cbs->gpu_unai.no_light;
529   blend = !cbs->gpu_unai.no_blend;
530 }
531
532 #endif
533
534 // vim:shiftwidth=2:expandtab