38e7ce1a0035043269a58b2b43bcdea8cfb29cc0
[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(x)  (((s32)(x)<<21)>>21)
115
116 #define CHKMAX_X 1024
117 #define CHKMAX_Y 512
118
119 #define GPU_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);}
120
121 // GPU internal image drawing functions
122 #include "../gpu_unai/gpu_raster_image.h"
123
124 // GPU internal line drawing functions
125 #include "../gpu_unai/gpu_raster_line.h"
126
127 // GPU internal polygon drawing functions
128 #include "../gpu_unai/gpu_raster_polygon.h"
129
130 // GPU internal sprite drawing functions
131 #include "../gpu_unai/gpu_raster_sprite.h"
132
133 // GPU command buffer execution/store
134 #include "../gpu_unai/gpu_command.h"
135
136 /////////////////////////////////////////////////////////////////////////////
137
138 int renderer_init(void)
139 {
140         GPU_FrameBuffer = (u16 *)gpu.vram;
141
142         // s_invTable
143         for(int i=1;i<=(1<<TABLE_BITS);++i)
144         {
145                 double v = 1.0 / double(i);
146                 #ifdef GPU_TABLE_10_BITS
147                 v *= double(0xffffffff>>1);
148                 #else
149                 v *= double(0x80000000);
150                 #endif
151                 s_invTable[i-1]=s32(v);
152         }
153
154         return 0;
155 }
156
157 extern const unsigned char cmd_lengths[256];
158
159 int do_cmd_list(unsigned int *list, int list_len, int *last_cmd)
160 {
161   unsigned int cmd = 0, len, i;
162   unsigned int *list_start = list;
163   unsigned int *list_end = list + list_len;
164
165   linesInterlace = force_interlace;
166 #ifndef __ARM_ARCH_7A__ /* XXX */
167   linesInterlace |= gpu.status.interlace;
168 #endif
169
170   for (; list < list_end; list += 1 + len)
171   {
172     cmd = *list >> 24;
173     len = cmd_lengths[cmd];
174     if (list + 1 + len > list_end) {
175       cmd = -1;
176       break;
177     }
178
179     #define PRIM cmd
180     PacketBuffer.U4[0] = list[0];
181     for (i = 1; i <= len; i++)
182       PacketBuffer.U4[i] = list[i];
183
184     switch (cmd)
185     {
186       case 0x02:
187         gpuClearImage();
188         break;
189
190       case 0x20:
191       case 0x21:
192       case 0x22:
193       case 0x23:
194         gpuDrawF3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB]);
195         break;
196
197       case 0x24:
198       case 0x25:
199       case 0x26:
200       case 0x27:
201         gpuSetCLUT   (PacketBuffer.U4[2] >> 16);
202         gpuSetTexture(PacketBuffer.U4[4] >> 16);
203         if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
204           gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB]);
205         else
206           gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB]);
207         break;
208
209       case 0x28:
210       case 0x29:
211       case 0x2A:
212       case 0x2B: {
213         const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB];
214         gpuDrawF3(gpuPolySpanDriver);
215         PacketBuffer.U4[1] = PacketBuffer.U4[4];
216         gpuDrawF3(gpuPolySpanDriver);
217         break;
218       }
219
220       case 0x2C:
221       case 0x2D:
222       case 0x2E:
223       case 0x2F: {
224         gpuSetCLUT   (PacketBuffer.U4[2] >> 16);
225         gpuSetTexture(PacketBuffer.U4[4] >> 16);
226         PP gpuPolySpanDriver;
227         if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
228           gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB];
229         else
230           gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB];
231         gpuDrawFT3(gpuPolySpanDriver);
232         PacketBuffer.U4[1] = PacketBuffer.U4[7];
233         PacketBuffer.U4[2] = PacketBuffer.U4[8];
234         gpuDrawFT3(gpuPolySpanDriver);
235         break;
236       }
237
238       case 0x30:
239       case 0x31:
240       case 0x32:
241       case 0x33:
242         gpuDrawG3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB]);
243         break;
244
245       case 0x34:
246       case 0x35:
247       case 0x36:
248       case 0x37:
249         gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
250         gpuSetTexture (PacketBuffer.U4[5] >> 16);
251         gpuDrawGT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB]);
252         break;
253
254       case 0x38:
255       case 0x39:
256       case 0x3A:
257       case 0x3B: {
258         const PP gpuPolySpanDriver  = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB];
259         gpuDrawG3(gpuPolySpanDriver);
260         PacketBuffer.U4[0] = PacketBuffer.U4[6];
261         PacketBuffer.U4[1] = PacketBuffer.U4[7];
262         gpuDrawG3(gpuPolySpanDriver);
263         break;
264       }
265
266       case 0x3C:
267       case 0x3D:
268       case 0x3E:
269       case 0x3F: {
270         gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
271         gpuSetTexture (PacketBuffer.U4[5] >> 16);
272         const PP gpuPolySpanDriver  = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB];
273         gpuDrawGT3(gpuPolySpanDriver);
274         PacketBuffer.U4[0] = PacketBuffer.U4[9];
275         PacketBuffer.U4[1] = PacketBuffer.U4[10];
276         PacketBuffer.U4[2] = PacketBuffer.U4[11];
277         gpuDrawGT3(gpuPolySpanDriver);
278         break;
279       }
280
281       case 0x40:
282       case 0x41:
283       case 0x42:
284       case 0x43:
285         gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
286         break;
287
288       case 0x48 ... 0x4F:
289       {
290         u32 num_vertexes = 1;
291         u32 *list_position = &(list[2]);
292
293         gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
294
295         while(1)
296         {
297           PacketBuffer.U4[1] = PacketBuffer.U4[2];
298           PacketBuffer.U4[2] = *list_position++;
299           gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
300
301           num_vertexes++;
302           if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
303             break;
304         }
305
306         len += (num_vertexes - 2);
307         break;
308       }
309
310       case 0x50:
311       case 0x51:
312       case 0x52:
313       case 0x53:
314         gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
315         break;
316
317       case 0x58 ... 0x5F:
318       {
319         u32 num_vertexes = 1;
320         u32 *list_position = &(list[2]);
321
322         gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
323
324         while(1)
325         {
326           PacketBuffer.U4[0] = PacketBuffer.U4[2];
327           PacketBuffer.U4[1] = PacketBuffer.U4[3];
328           PacketBuffer.U4[2] = *list_position++;
329           PacketBuffer.U4[3] = *list_position++;
330           gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
331
332           num_vertexes++;
333           if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
334             break;
335         }
336
337         len += (num_vertexes - 2) * 2;
338         break;
339       }
340
341       case 0x60:
342       case 0x61:
343       case 0x62:
344       case 0x63:
345         gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
346         break;
347
348       case 0x64:
349       case 0x65:
350       case 0x66:
351       case 0x67:
352         gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
353         gpuSetTexture (GPU_GP1);
354         if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
355           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7)  | PixelMSB]);
356         else
357           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7)  | PixelMSB]);
358         break;
359
360       case 0x68:
361       case 0x69:
362       case 0x6A:
363       case 0x6B:
364         PacketBuffer.U4[2] = 0x00010001;
365         gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
366         break;
367
368       case 0x70:
369       case 0x71:
370       case 0x72:
371       case 0x73:
372         PacketBuffer.U4[2] = 0x00080008;
373         gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
374         break;
375
376       case 0x74:
377       case 0x75:
378       case 0x76:
379       case 0x77:
380         PacketBuffer.U4[3] = 0x00080008;
381         gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
382         gpuSetTexture (GPU_GP1);
383         if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
384           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7)  | PixelMSB]);
385         else
386           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7)  | PixelMSB]);
387         break;
388
389       case 0x78:
390       case 0x79:
391       case 0x7A:
392       case 0x7B:
393         PacketBuffer.U4[2] = 0x00100010;
394         gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
395         break;
396
397       case 0x7C:
398       case 0x7D:
399 #ifdef __arm__
400         if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
401         {
402           gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
403           gpuSetTexture (GPU_GP1);
404           gpuDrawS16();
405           break;
406         }
407         // fallthrough
408 #endif
409       case 0x7E:
410       case 0x7F:
411         PacketBuffer.U4[3] = 0x00100010;
412         gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
413         gpuSetTexture (GPU_GP1);
414         if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
415           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7)  | PixelMSB]);
416         else
417           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7)  | PixelMSB]);
418         break;
419
420       case 0x80:          //  vid -> vid
421         gpuMoveImage();   //  prim handles updateLace && skip
422         break;
423 #ifdef TEST
424       case 0xA0:          //  sys -> vid
425       {
426         u32 load_width = list[2] & 0xffff;
427         u32 load_height = list[2] >> 16;
428         u32 load_size = load_width * load_height;
429
430         len += load_size / 2;
431         break;
432       }
433       case 0xC0:
434         break;
435 #else
436       case 0xA0:          //  sys ->vid
437       case 0xC0:          //  vid -> sys
438         goto breakloop;
439 #endif
440       case 0xE1: {
441         const u32 temp = PacketBuffer.U4[0];
442         GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
443         gpuSetTexture(temp);
444         gpu.ex_regs[1] = temp;
445         break;
446       }
447       case 0xE2: {
448         static const u8  TextureMask[32] = {
449           255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
450           127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
451         };
452         const u32 temp = PacketBuffer.U4[0];
453         TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
454         TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
455         TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
456         TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
457         gpuSetTexture(GPU_GP1);
458         gpu.ex_regs[2] = temp;
459         break;
460       }
461       case 0xE3: {
462         const u32 temp = PacketBuffer.U4[0];
463         DrawingArea[0] = temp         & 0x3FF;
464         DrawingArea[1] = (temp >> 10) & 0x3FF;
465         gpu.ex_regs[3] = temp;
466         break;
467       }
468       case 0xE4: {
469         const u32 temp = PacketBuffer.U4[0];
470         DrawingArea[2] = (temp         & 0x3FF) + 1;
471         DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
472         gpu.ex_regs[4] = temp;
473         break;
474       }
475       case 0xE5: {
476         const u32 temp = PacketBuffer.U4[0];
477         DrawingOffset[0] = ((long)temp<<(32-11))>>(32-11);
478         DrawingOffset[1] = ((long)temp<<(32-22))>>(32-11);
479         gpu.ex_regs[5] = temp;
480         break;
481       }
482       case 0xE6: {
483         const u32 temp = PacketBuffer.U4[0];
484         Masking = (temp & 0x2) <<  1;
485         PixelMSB =(temp & 0x1) <<  8;
486         gpu.ex_regs[6] = temp;
487         break;
488       }
489     }
490   }
491
492 breakloop:
493   gpu.ex_regs[1] &= ~0x1ff;
494   gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
495
496   *last_cmd = cmd;
497   return list - list_start;
498 }
499
500 void renderer_sync_ecmds(uint32_t *ecmds)
501 {
502   int dummy;
503   do_cmd_list(&ecmds[1], 6, &dummy);
504 }
505
506 void renderer_update_caches(int x, int y, int w, int h)
507 {
508 }
509
510 void renderer_flush_queues(void)
511 {
512 }
513
514 void renderer_set_interlace(int enable, int is_odd)
515 {
516 }
517
518 #ifndef TEST
519
520 #include "../../frontend/plugin_lib.h"
521
522 void renderer_set_config(const struct rearmed_cbs *cbs)
523 {
524   force_interlace = cbs->gpu_unai.lineskip;
525   enableAbbeyHack = cbs->gpu_unai.abe_hack;
526   light = !cbs->gpu_unai.no_light;
527   blend = !cbs->gpu_unai.no_blend;
528 }
529
530 #endif
531
532 // vim:shiftwidth=2:expandtab