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