646b0f22b057a205c8cfa40581b56b32a3aec9a8
[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 void renderer_finish(void)
158 {
159 }
160
161 void renderer_notify_res_change(void)
162 {
163 }
164
165 extern const unsigned char cmd_lengths[256];
166
167 int do_cmd_list(unsigned int *list, int list_len, int *last_cmd)
168 {
169   unsigned int cmd = 0, len, i;
170   unsigned int *list_start = list;
171   unsigned int *list_end = list + list_len;
172
173   linesInterlace = force_interlace;
174 #ifndef __ARM_ARCH_7A__ /* XXX */
175   linesInterlace |= gpu.status.interlace;
176 #endif
177
178   for (; list < list_end; list += 1 + len)
179   {
180     cmd = *list >> 24;
181     len = cmd_lengths[cmd];
182     if (list + 1 + len > list_end) {
183       cmd = -1;
184       break;
185     }
186
187     #define PRIM cmd
188     PacketBuffer.U4[0] = list[0];
189     for (i = 1; i <= len; i++)
190       PacketBuffer.U4[i] = list[i];
191
192     switch (cmd)
193     {
194       case 0x02:
195         gpuClearImage();
196         break;
197
198       case 0x20:
199       case 0x21:
200       case 0x22:
201       case 0x23:
202         gpuDrawF3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB]);
203         break;
204
205       case 0x24:
206       case 0x25:
207       case 0x26:
208       case 0x27:
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]);
213         else
214           gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB]);
215         break;
216
217       case 0x28:
218       case 0x29:
219       case 0x2A:
220       case 0x2B: {
221         const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB];
222         gpuDrawF3(gpuPolySpanDriver);
223         PacketBuffer.U4[1] = PacketBuffer.U4[4];
224         gpuDrawF3(gpuPolySpanDriver);
225         break;
226       }
227
228       case 0x2C:
229       case 0x2D:
230       case 0x2E:
231       case 0x2F: {
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];
237         else
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);
243         break;
244       }
245
246       case 0x30:
247       case 0x31:
248       case 0x32:
249       case 0x33:
250         gpuDrawG3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB]);
251         break;
252
253       case 0x34:
254       case 0x35:
255       case 0x36:
256       case 0x37:
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]);
260         break;
261
262       case 0x38:
263       case 0x39:
264       case 0x3A:
265       case 0x3B: {
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);
271         break;
272       }
273
274       case 0x3C:
275       case 0x3D:
276       case 0x3E:
277       case 0x3F: {
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);
286         break;
287       }
288
289       case 0x40:
290       case 0x41:
291       case 0x42:
292       case 0x43:
293         gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
294         break;
295
296       case 0x48 ... 0x4F:
297       {
298         u32 num_vertexes = 1;
299         u32 *list_position = &(list[2]);
300
301         gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
302
303         while(1)
304         {
305           PacketBuffer.U4[1] = PacketBuffer.U4[2];
306           PacketBuffer.U4[2] = *list_position++;
307           gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
308
309           num_vertexes++;
310           if(list_position >= list_end) {
311             cmd = -1;
312             goto breakloop;
313           }
314           if((*list_position & 0xf000f000) == 0x50005000)
315             break;
316         }
317
318         len += (num_vertexes - 2);
319         break;
320       }
321
322       case 0x50:
323       case 0x51:
324       case 0x52:
325       case 0x53:
326         gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
327         break;
328
329       case 0x58 ... 0x5F:
330       {
331         u32 num_vertexes = 1;
332         u32 *list_position = &(list[2]);
333
334         gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
335
336         while(1)
337         {
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]);
343
344           num_vertexes++;
345           if(list_position >= list_end) {
346             cmd = -1;
347             goto breakloop;
348           }
349           if((*list_position & 0xf000f000) == 0x50005000)
350             break;
351         }
352
353         len += (num_vertexes - 2) * 2;
354         break;
355       }
356
357       case 0x60:
358       case 0x61:
359       case 0x62:
360       case 0x63:
361         gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
362         break;
363
364       case 0x64:
365       case 0x65:
366       case 0x66:
367       case 0x67:
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]);
372         else
373           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7)  | PixelMSB]);
374         break;
375
376       case 0x68:
377       case 0x69:
378       case 0x6A:
379       case 0x6B:
380         PacketBuffer.U4[2] = 0x00010001;
381         gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
382         break;
383
384       case 0x70:
385       case 0x71:
386       case 0x72:
387       case 0x73:
388         PacketBuffer.U4[2] = 0x00080008;
389         gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
390         break;
391
392       case 0x74:
393       case 0x75:
394       case 0x76:
395       case 0x77:
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]);
401         else
402           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7)  | PixelMSB]);
403         break;
404
405       case 0x78:
406       case 0x79:
407       case 0x7A:
408       case 0x7B:
409         PacketBuffer.U4[2] = 0x00100010;
410         gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
411         break;
412
413       case 0x7C:
414       case 0x7D:
415 #ifdef __arm__
416         if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
417         {
418           gpuSetCLUT    (PacketBuffer.U4[2] >> 16);
419           gpuSetTexture (GPU_GP1);
420           gpuDrawS16();
421           break;
422         }
423         // fallthrough
424 #endif
425       case 0x7E:
426       case 0x7F:
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]);
432         else
433           gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7)  | PixelMSB]);
434         break;
435
436       case 0x80:          //  vid -> vid
437         gpuMoveImage();   //  prim handles updateLace && skip
438         break;
439 #ifdef TEST
440       case 0xA0:          //  sys -> vid
441       {
442         u32 load_width = list[2] & 0xffff;
443         u32 load_height = list[2] >> 16;
444         u32 load_size = load_width * load_height;
445
446         len += load_size / 2;
447         break;
448       }
449       case 0xC0:
450         break;
451 #else
452       case 0xA0:          //  sys ->vid
453       case 0xC0:          //  vid -> sys
454         goto breakloop;
455 #endif
456       case 0xE1: {
457         const u32 temp = PacketBuffer.U4[0];
458         GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
459         gpuSetTexture(temp);
460         gpu.ex_regs[1] = temp;
461         break;
462       }
463       case 0xE2: {
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
467         };
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;
475         break;
476       }
477       case 0xE3: {
478         const u32 temp = PacketBuffer.U4[0];
479         DrawingArea[0] = temp         & 0x3FF;
480         DrawingArea[1] = (temp >> 10) & 0x3FF;
481         gpu.ex_regs[3] = temp;
482         break;
483       }
484       case 0xE4: {
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;
489         break;
490       }
491       case 0xE5: {
492         const u32 temp = PacketBuffer.U4[0];
493         DrawingOffset[0] = ((s32)temp<<(32-11))>>(32-11);
494         DrawingOffset[1] = ((s32)temp<<(32-22))>>(32-11);
495         gpu.ex_regs[5] = temp;
496         break;
497       }
498       case 0xE6: {
499         const u32 temp = PacketBuffer.U4[0];
500         Masking = (temp & 0x2) <<  1;
501         PixelMSB =(temp & 0x1) <<  8;
502         gpu.ex_regs[6] = temp;
503         break;
504       }
505     }
506   }
507
508 breakloop:
509   gpu.ex_regs[1] &= ~0x1ff;
510   gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
511
512   *last_cmd = cmd;
513   return list - list_start;
514 }
515
516 void renderer_sync_ecmds(uint32_t *ecmds)
517 {
518   int dummy;
519   do_cmd_list(&ecmds[1], 6, &dummy);
520 }
521
522 void renderer_update_caches(int x, int y, int w, int h)
523 {
524 }
525
526 void renderer_flush_queues(void)
527 {
528 }
529
530 void renderer_set_interlace(int enable, int is_odd)
531 {
532 }
533
534 #ifndef TEST
535
536 #include "../../frontend/plugin_lib.h"
537
538 void renderer_set_config(const struct rearmed_cbs *cbs)
539 {
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;
544
545   GPU_FrameBuffer = (u16 *)gpu.vram;
546 }
547
548 #endif
549
550 // vim:shiftwidth=2:expandtab