cdrom: change pause timing again
[pcsx_rearmed.git] / plugins / dfxvideo / gpulib_if.c
1 /***************************************************************************
2     copyright            : (C) 2001 by Pete Bernert, 2011 notaz
3
4  ***************************************************************************/
5 /***************************************************************************
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version. See also the license.txt file for *
11  *   additional informations.                                              *
12  *                                                                         *
13  ***************************************************************************/
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include "../gpulib/gpu.h"
19 #include "../../include/arm_features.h"
20
21 #if defined(__GNUC__) && (__GNUC__ >= 6 || (defined(__clang_major__) && __clang_major__ >= 10))
22 #pragma GCC diagnostic ignored "-Wmisleading-indentation"
23 #endif
24
25 #define u32 uint32_t
26
27 #define INFO_TW        0
28 #define INFO_DRAWSTART 1
29 #define INFO_DRAWEND   2
30 #define INFO_DRAWOFF   3
31
32 #define SHADETEXBIT(x) ((x>>24) & 0x1)
33 #define SEMITRANSBIT(x) ((x>>25) & 0x1)
34 #define PSXRGB(r,g,b) ((g<<10)|(b<<5)|r)
35
36 #define DATAREGISTERMODES unsigned short
37
38 #define DR_NORMAL        0
39 #define DR_VRAMTRANSFER  1
40
41 #define GPUSTATUS_READYFORVRAM        0x08000000
42
43 // byteswappings
44
45 #define SWAP16(x) __builtin_bswap16(x)
46 #define SWAP32(x) __builtin_bswap32(x)
47
48 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
49
50 // big endian config
51 #define HOST2LE32(x) SWAP32(x)
52 #define HOST2BE32(x) (x)
53 #define LE2HOST32(x) SWAP32(x)
54 #define BE2HOST32(x) (x)
55
56 #define HOST2LE16(x) SWAP16(x)
57 #define HOST2BE16(x) (x)
58 #define LE2HOST16(x) SWAP16(x)
59 #define BE2HOST16(x) (x)
60
61 #else
62
63 // little endian config
64 #define HOST2LE32(x) (x)
65 #define HOST2BE32(x) SWAP32(x)
66 #define LE2HOST32(x) (x)
67 #define BE2HOST32(x) SWAP32(x)
68
69 #define HOST2LE16(x) (x)
70 #define HOST2BE16(x) SWAP16(x)
71 #define LE2HOST16(x) (x)
72 #define BE2HOST16(x) SWAP16(x)
73
74 #endif
75
76 #define GETLEs16(X) ((int16_t)GETLE16((uint16_t *)(X)))
77
78 #define GETLE16(X) LE2HOST16(*(uint16_t *)(X))
79 #define GETLE32_(X) LE2HOST32(*(uint32_t *)(X))
80 #define PUTLE16(X, Y) do{*((uint16_t *)(X))=HOST2LE16((uint16_t)(Y));}while(0)
81 #define PUTLE32_(X, Y) do{*((uint32_t *)(X))=HOST2LE32((uint32_t)(Y));}while(0)
82 #if defined(__arm__) && !defined(HAVE_ARMV6)
83 // for (very) old ARMs with no unaligned loads?
84 #define GETLE32(X) (*(uint16_t *)(X)|((uint32_t)((uint16_t *)(X))[1]<<16))
85 #define PUTLE32(X, Y) do{uint16_t *p_=(uint16_t *)(X);uint32_t y_=Y;p_[0]=y_;p_[1]=y_>>16;}while(0)
86 #else
87 #define GETLE32 GETLE32_
88 #define PUTLE32 PUTLE32_
89 #endif
90
91 /////////////////////////////////////////////////////////////////////////////
92
93 typedef struct VRAMLOADTTAG
94 {
95  short x;
96  short y;
97  short Width;
98  short Height;
99  short RowsRemaining;
100  short ColsRemaining;
101  unsigned short *ImagePtr;
102 } VRAMLoad_t;
103
104 /////////////////////////////////////////////////////////////////////////////
105
106 typedef struct PSXPOINTTAG
107 {
108  int32_t x;
109  int32_t y;
110 } PSXPoint_t;
111
112 typedef struct PSXSPOINTTAG
113 {
114  short x;
115  short y;
116 } PSXSPoint_t;
117
118 typedef struct PSXRECTTAG
119 {
120  short x0;
121  short x1;
122  short y0;
123  short y1;
124 } PSXRect_t;
125
126 // linux defines for some windows stuff
127
128 #define FALSE 0
129 #define TRUE 1
130 #define BOOL unsigned short
131 #define LOWORD(l)           ((unsigned short)(l))
132 #define HIWORD(l)           ((unsigned short)(((uint32_t)(l) >> 16) & 0xFFFF))
133 #define max(a,b)            (((a) > (b)) ? (a) : (b))
134 #define min(a,b)            (((a) < (b)) ? (a) : (b))
135 #define DWORD uint32_t
136 #ifndef __int64
137 #define __int64 long long int
138 #endif
139
140 typedef struct RECTTAG
141 {
142  int left;
143  int top;
144  int right;
145  int bottom;
146 }RECT;
147
148 /////////////////////////////////////////////////////////////////////////////
149
150 typedef struct TWINTAG
151 {
152  PSXRect_t  Position;
153  int xmask, ymask;
154 } TWin_t;
155
156 /////////////////////////////////////////////////////////////////////////////
157
158 typedef struct PSXDISPLAYTAG
159 {
160  PSXPoint_t  DisplayModeNew;
161  PSXPoint_t  DisplayMode;
162  PSXPoint_t  DisplayPosition;
163  PSXPoint_t  DisplayEnd;
164
165  int32_t        Double;
166  int32_t        Height;
167  int32_t        PAL;
168  int32_t        InterlacedNew;
169  int32_t        Interlaced;
170  int32_t        RGB24New;
171  int32_t        RGB24;
172  PSXSPoint_t DrawOffset;
173  int32_t        Disabled;
174  PSXRect_t   Range;
175
176 } PSXDisplay_t;
177
178 /////////////////////////////////////////////////////////////////////////////
179
180 // draw.c
181
182 extern int32_t           GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP;
183 extern int32_t           GlobalTextABR,GlobalTextPAGE;
184 extern short          ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3;
185 extern long           lLowerpart;
186 extern BOOL           bCheckMask;
187 extern unsigned short sSetMask;
188 extern unsigned long  lSetMask;
189 extern short          g_m1;
190 extern short          g_m2;
191 extern short          g_m3;
192 extern short          DrawSemiTrans;
193
194 // prim.c
195
196 extern BOOL           bUsingTWin;
197 extern TWin_t         TWin;
198 extern void (*primTableJ[256])(unsigned char *);
199 extern void (*primTableSkip[256])(unsigned char *);
200 extern unsigned short  usMirror;
201 extern int            iDither;
202 extern uint32_t  dwCfgFixes;
203 extern uint32_t  dwActFixes;
204 extern int            iUseFixes;
205 extern int            iUseDither;
206 extern BOOL           bDoVSyncUpdate;
207 extern int32_t           drawX;
208 extern int32_t           drawY;
209 extern int32_t           drawW;
210 extern int32_t           drawH;
211
212 // gpu.h
213
214 #define OPAQUEON   10
215 #define OPAQUEOFF  11
216
217 #define KEY_RESETTEXSTORE 1
218 #define KEY_SHOWFPS       2
219 #define KEY_RESETOPAQUE   4
220 #define KEY_RESETDITHER   8
221 #define KEY_RESETFILTER   16
222 #define KEY_RESETADVBLEND 32
223 #define KEY_BADTEXTURES   128
224 #define KEY_CHECKTHISOUT  256
225
226 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
227 #define RED(x) (x & 0xff)
228 #define BLUE(x) ((x>>16) & 0xff)
229 #define GREEN(x) ((x>>8) & 0xff)
230 #define COLOR(x) (x & 0xffffff)
231 #else
232 #define RED(x) ((x>>24) & 0xff)
233 #define BLUE(x) ((x>>8) & 0xff)
234 #define GREEN(x) ((x>>16) & 0xff)
235 #define COLOR(x) SWAP32(x & 0xffffff)
236 #endif
237
238 PSXDisplay_t      PSXDisplay;
239 unsigned char  *psxVub;
240 unsigned short *psxVuw;
241 unsigned short *psxVuw_eom;
242
243 long              lGPUstatusRet;
244 uint32_t          lGPUInfoVals[16];
245
246 VRAMLoad_t        VRAMWrite;
247 VRAMLoad_t        VRAMRead;
248
249 DATAREGISTERMODES DataWriteMode;
250 DATAREGISTERMODES DataReadMode;
251
252 BOOL           bCheckMask = FALSE;
253 unsigned short sSetMask = 0;
254 unsigned long  lSetMask = 0;
255 long           lLowerpart;
256
257 #if defined(__GNUC__) && __GNUC__ >= 6
258 #pragma GCC diagnostic ignored "-Wmisleading-indentation"
259 #endif
260
261 #include "soft.c"
262 #include "prim.c"
263
264 /////////////////////////////////////////////////////////////////////////////
265
266 static void set_vram(void *vram)
267 {
268  psxVub=vram;
269  psxVuw=(unsigned short *)psxVub;
270  psxVuw_eom=psxVuw+1024*512;                           // pre-calc of end of vram
271 }
272
273 int renderer_init(void)
274 {
275  set_vram(gpu.vram);
276
277  PSXDisplay.RGB24        = FALSE;                      // init some stuff
278  PSXDisplay.Interlaced   = FALSE;
279  PSXDisplay.DrawOffset.x = 0;
280  PSXDisplay.DrawOffset.y = 0;
281  PSXDisplay.DisplayMode.x= 320;
282  PSXDisplay.DisplayMode.y= 240;
283  PSXDisplay.Disabled     = FALSE;
284  PSXDisplay.Range.x0=0;
285  PSXDisplay.Range.x1=0;
286  PSXDisplay.Double = 1;
287
288  DataWriteMode = DR_NORMAL;
289  lGPUstatusRet = 0x14802000;
290
291  return 0;
292 }
293
294 void renderer_finish(void)
295 {
296 }
297
298 void renderer_notify_res_change(void)
299 {
300 }
301
302 void renderer_notify_scanout_change(int x, int y)
303 {
304 }
305
306 #include "../gpulib/gpu_timing.h"
307 extern const unsigned char cmd_lengths[256];
308
309 int do_cmd_list(uint32_t *list, int list_len,
310  int *cycles_sum_out, int *cycles_last, int *last_cmd)
311 {
312   int cpu_cycles_sum = 0, cpu_cycles = *cycles_last;
313   unsigned int cmd = 0, len;
314   uint32_t *list_start = list;
315   uint32_t *list_end = list + list_len;
316
317   for (; list < list_end; list += 1 + len)
318   {
319     short *slist = (void *)list;
320     cmd = GETLE32(list) >> 24;
321     len = cmd_lengths[cmd];
322     if (list + 1 + len > list_end) {
323       cmd = -1;
324       break;
325     }
326
327 #ifndef TEST
328     if (0x80 <= cmd && cmd < 0xe0)
329       break; // image i/o, forward to upper layer
330     else if ((cmd & 0xf8) == 0xe0)
331       gpu.ex_regs[cmd & 7] = GETLE32(list);
332 #endif
333
334     primTableJ[cmd]((void *)list);
335
336     switch(cmd)
337     {
338       case 0x48 ... 0x4F:
339       {
340         u32 num_vertexes = 2;
341         u32 *list_position = &(list[3]);
342
343         while(1)
344         {
345           gput_sum(cpu_cycles_sum, cpu_cycles, gput_line(0));
346
347           if(list_position >= list_end) {
348             cmd = -1;
349             goto breakloop;
350           }
351
352           if((*list_position & HOST2LE32(0xf000f000)) == HOST2LE32(0x50005000))
353             break;
354
355           list_position++;
356           num_vertexes++;
357         }
358
359         len += (num_vertexes - 2);
360         break;
361       }
362
363       case 0x58 ... 0x5F:
364       {
365         u32 num_vertexes = 2;
366         u32 *list_position = &(list[4]);
367
368         while(1)
369         {
370           gput_sum(cpu_cycles_sum, cpu_cycles, gput_line(0));
371
372           if(list_position >= list_end) {
373             cmd = -1;
374             goto breakloop;
375           }
376
377           if((*list_position & HOST2LE32(0xf000f000)) == HOST2LE32(0x50005000))
378             break;
379
380           list_position += 2;
381           num_vertexes++;
382         }
383
384         len += (num_vertexes - 2) * 2;
385         break;
386       }
387
388 #ifdef TEST
389       case 0xA0:          //  sys -> vid
390       {
391         u32 load_width = LE2HOST16(slist[4]);
392         u32 load_height = LE2HOST16(slist[5]);
393         u32 load_size = load_width * load_height;
394
395         len += load_size / 2;
396         break;
397       }
398 #endif
399
400       // timing
401       case 0x02:
402         gput_sum(cpu_cycles_sum, cpu_cycles,
403             gput_fill(LE2HOST16(slist[4]) & 0x3ff, LE2HOST16(slist[5]) & 0x1ff));
404         break;
405       case 0x20 ... 0x23: gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base());    break;
406       case 0x24 ... 0x27: gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base_t());  break;
407       case 0x28 ... 0x2B: gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base());    break;
408       case 0x2C ... 0x2F: gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base_t());  break;
409       case 0x30 ... 0x33: gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base_g());  break;
410       case 0x34 ... 0x37: gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base_gt()); break;
411       case 0x38 ... 0x3B: gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base_g());  break;
412       case 0x3C ... 0x3F: gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base_gt()); break;
413       case 0x40 ... 0x47: gput_sum(cpu_cycles_sum, cpu_cycles, gput_line(0));        break;
414       case 0x50 ... 0x57: gput_sum(cpu_cycles_sum, cpu_cycles, gput_line(0));        break;
415       case 0x60 ... 0x63:
416         gput_sum(cpu_cycles_sum, cpu_cycles,
417             gput_sprite(LE2HOST16(slist[4]) & 0x3ff, LE2HOST16(slist[5]) & 0x1ff));
418         break;
419       case 0x64 ... 0x67:
420         gput_sum(cpu_cycles_sum, cpu_cycles,
421             gput_sprite(LE2HOST16(slist[6]) & 0x3ff, LE2HOST16(slist[7]) & 0x1ff));
422         break;
423       case 0x68 ... 0x6B: gput_sum(cpu_cycles_sum, cpu_cycles, gput_sprite(1, 1));   break;
424       case 0x70 ... 0x73:
425       case 0x74 ... 0x77: gput_sum(cpu_cycles_sum, cpu_cycles, gput_sprite(8, 8));   break;
426       case 0x78 ... 0x7B:
427       case 0x7C ... 0x7F: gput_sum(cpu_cycles_sum, cpu_cycles, gput_sprite(16, 16)); break;
428     }
429   }
430
431 breakloop:
432   gpu.ex_regs[1] &= ~0x1ff;
433   gpu.ex_regs[1] |= lGPUstatusRet & 0x1ff;
434
435   *cycles_sum_out += cpu_cycles_sum;
436   *cycles_last = cpu_cycles;
437   *last_cmd = cmd;
438   return list - list_start;
439 }
440
441 void renderer_sync_ecmds(uint32_t *ecmds_)
442 {
443 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
444   // the funcs below expect LE
445   uint32_t i, ecmds[8];
446   for (i = 1; i <= 6; i++)
447     ecmds[i] = HTOLE32(ecmds_[i]);
448 #else
449   uint32_t *ecmds = ecmds_;
450 #endif
451   cmdTexturePage((unsigned char *)&ecmds[1]);
452   cmdTextureWindow((unsigned char *)&ecmds[2]);
453   cmdDrawAreaStart((unsigned char *)&ecmds[3]);
454   cmdDrawAreaEnd((unsigned char *)&ecmds[4]);
455   cmdDrawOffset((unsigned char *)&ecmds[5]);
456   cmdSTP((unsigned char *)&ecmds[6]);
457 }
458
459 void renderer_update_caches(int x, int y, int w, int h, int state_changed)
460 {
461 }
462
463 void renderer_flush_queues(void)
464 {
465 }
466
467 void renderer_set_interlace(int enable, int is_odd)
468 {
469 }
470
471 #include "../../frontend/plugin_lib.h"
472
473 void renderer_set_config(const struct rearmed_cbs *cbs)
474 {
475  iUseDither = cbs->gpu_peops.iUseDither;
476  dwActFixes = cbs->gpu_peops.dwActFixes;
477  if (cbs->pl_set_gpu_caps)
478   cbs->pl_set_gpu_caps(0);
479  set_vram(gpu.vram);
480 }
481
482 // vim:ts=2:shiftwidth=2:expandtab