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