1 /***************************************************************************
2 copyright : (C) 2001 by Pete Bernert, 2011 notaz
4 ***************************************************************************/
5 /***************************************************************************
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. *
13 ***************************************************************************/
18 #include "../gpulib/gpu.h"
19 #include "../../include/arm_features.h"
21 #if defined(__GNUC__) && (__GNUC__ >= 6 || (defined(__clang_major__) && __clang_major__ >= 10))
22 #pragma GCC diagnostic ignored "-Wmisleading-indentation"
25 #ifdef THREAD_RENDERING
26 #include "../gpulib/gpulib_thread_if.h"
27 #define do_cmd_list real_do_cmd_list
28 #define renderer_init real_renderer_init
29 #define renderer_finish real_renderer_finish
30 #define renderer_sync_ecmds real_renderer_sync_ecmds
31 #define renderer_update_caches real_renderer_update_caches
32 #define renderer_flush_queues real_renderer_flush_queues
33 #define renderer_set_interlace real_renderer_set_interlace
34 #define renderer_set_config real_renderer_set_config
35 #define renderer_notify_res_change real_renderer_notify_res_change
36 #define renderer_notify_update_lace real_renderer_notify_update_lace
37 #define renderer_sync real_renderer_sync
38 #define ex_regs scratch_ex_regs
44 #define INFO_DRAWSTART 1
45 #define INFO_DRAWEND 2
46 #define INFO_DRAWOFF 3
48 #define SHADETEXBIT(x) ((x>>24) & 0x1)
49 #define SEMITRANSBIT(x) ((x>>25) & 0x1)
50 #define PSXRGB(r,g,b) ((g<<10)|(b<<5)|r)
52 #define DATAREGISTERMODES unsigned short
55 #define DR_VRAMTRANSFER 1
57 #define GPUSTATUS_READYFORVRAM 0x08000000
61 #define SWAP16(x) __builtin_bswap16(x)
62 #define SWAP32(x) __builtin_bswap32(x)
64 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
67 #define HOST2LE32(x) SWAP32(x)
68 #define HOST2BE32(x) (x)
69 #define LE2HOST32(x) SWAP32(x)
70 #define BE2HOST32(x) (x)
72 #define HOST2LE16(x) SWAP16(x)
73 #define HOST2BE16(x) (x)
74 #define LE2HOST16(x) SWAP16(x)
75 #define BE2HOST16(x) (x)
79 // little endian config
80 #define HOST2LE32(x) (x)
81 #define HOST2BE32(x) SWAP32(x)
82 #define LE2HOST32(x) (x)
83 #define BE2HOST32(x) SWAP32(x)
85 #define HOST2LE16(x) (x)
86 #define HOST2BE16(x) SWAP16(x)
87 #define LE2HOST16(x) (x)
88 #define BE2HOST16(x) SWAP16(x)
92 #define GETLEs16(X) ((int16_t)GETLE16((uint16_t *)(X)))
94 #define GETLE16(X) LE2HOST16(*(uint16_t *)(X))
95 #define GETLE32_(X) LE2HOST32(*(uint32_t *)(X))
96 #define PUTLE16(X, Y) do{*((uint16_t *)(X))=HOST2LE16((uint16_t)(Y));}while(0)
97 #define PUTLE32_(X, Y) do{*((uint32_t *)(X))=HOST2LE32((uint32_t)(Y));}while(0)
98 #if defined(__arm__) && !defined(HAVE_ARMV6)
99 // for (very) old ARMs with no unaligned loads?
100 #define GETLE32(X) (*(uint16_t *)(X)|((uint32_t)((uint16_t *)(X))[1]<<16))
101 #define PUTLE32(X, Y) do{uint16_t *p_=(uint16_t *)(X);uint32_t y_=Y;p_[0]=y_;p_[1]=y_>>16;}while(0)
103 #define GETLE32 GETLE32_
104 #define PUTLE32 PUTLE32_
107 /////////////////////////////////////////////////////////////////////////////
109 typedef struct VRAMLOADTTAG
117 unsigned short *ImagePtr;
120 /////////////////////////////////////////////////////////////////////////////
122 typedef struct PSXPOINTTAG
128 typedef struct PSXSPOINTTAG
134 typedef struct PSXRECTTAG
142 // linux defines for some windows stuff
146 #define BOOL unsigned short
147 #define LOWORD(l) ((unsigned short)(l))
148 #define HIWORD(l) ((unsigned short)(((uint32_t)(l) >> 16) & 0xFFFF))
149 #define max(a,b) (((a) > (b)) ? (a) : (b))
150 #define min(a,b) (((a) < (b)) ? (a) : (b))
151 #define DWORD uint32_t
153 #define __int64 long long int
156 typedef struct RECTTAG
164 /////////////////////////////////////////////////////////////////////////////
166 typedef struct TWINTAG
172 /////////////////////////////////////////////////////////////////////////////
174 typedef struct PSXDISPLAYTAG
176 PSXPoint_t DisplayModeNew;
177 PSXPoint_t DisplayMode;
178 PSXPoint_t DisplayPosition;
179 PSXPoint_t DisplayEnd;
184 int32_t InterlacedNew;
188 PSXSPoint_t DrawOffset;
194 /////////////////////////////////////////////////////////////////////////////
198 extern int32_t GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP;
199 extern int32_t GlobalTextABR,GlobalTextPAGE;
200 extern short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3;
201 extern long lLowerpart;
202 extern BOOL bCheckMask;
203 extern unsigned short sSetMask;
204 extern unsigned long lSetMask;
208 extern short DrawSemiTrans;
212 extern BOOL bUsingTWin;
214 extern void (*primTableJ[256])(unsigned char *);
215 extern void (*primTableSkip[256])(unsigned char *);
216 extern unsigned short usMirror;
218 extern uint32_t dwCfgFixes;
219 extern uint32_t dwActFixes;
220 extern int iUseFixes;
221 extern int iUseDither;
222 extern BOOL bDoVSyncUpdate;
223 extern int32_t drawX;
224 extern int32_t drawY;
225 extern int32_t drawW;
226 extern int32_t drawH;
233 #define KEY_RESETTEXSTORE 1
234 #define KEY_SHOWFPS 2
235 #define KEY_RESETOPAQUE 4
236 #define KEY_RESETDITHER 8
237 #define KEY_RESETFILTER 16
238 #define KEY_RESETADVBLEND 32
239 #define KEY_BADTEXTURES 128
240 #define KEY_CHECKTHISOUT 256
242 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
243 #define RED(x) (x & 0xff)
244 #define BLUE(x) ((x>>16) & 0xff)
245 #define GREEN(x) ((x>>8) & 0xff)
246 #define COLOR(x) (x & 0xffffff)
248 #define RED(x) ((x>>24) & 0xff)
249 #define BLUE(x) ((x>>8) & 0xff)
250 #define GREEN(x) ((x>>16) & 0xff)
251 #define COLOR(x) SWAP32(x & 0xffffff)
254 PSXDisplay_t PSXDisplay;
255 unsigned char *psxVub;
256 unsigned short *psxVuw;
257 unsigned short *psxVuw_eom;
260 uint32_t lGPUInfoVals[16];
262 VRAMLoad_t VRAMWrite;
265 DATAREGISTERMODES DataWriteMode;
266 DATAREGISTERMODES DataReadMode;
268 BOOL bCheckMask = FALSE;
269 unsigned short sSetMask = 0;
270 unsigned long lSetMask = 0;
273 #if defined(__GNUC__) && __GNUC__ >= 6
274 #pragma GCC diagnostic ignored "-Wmisleading-indentation"
280 /////////////////////////////////////////////////////////////////////////////
282 static void set_vram(void *vram)
285 psxVuw=(unsigned short *)psxVub;
286 psxVuw_eom=psxVuw+1024*512; // pre-calc of end of vram
289 int renderer_init(void)
293 PSXDisplay.RGB24 = FALSE; // init some stuff
294 PSXDisplay.Interlaced = FALSE;
295 PSXDisplay.DrawOffset.x = 0;
296 PSXDisplay.DrawOffset.y = 0;
297 PSXDisplay.DisplayMode.x= 320;
298 PSXDisplay.DisplayMode.y= 240;
299 PSXDisplay.Disabled = FALSE;
300 PSXDisplay.Range.x0=0;
301 PSXDisplay.Range.x1=0;
302 PSXDisplay.Double = 1;
304 DataWriteMode = DR_NORMAL;
305 lGPUstatusRet = 0x14802000;
310 void renderer_finish(void)
314 void renderer_notify_res_change(void)
318 void renderer_notify_scanout_change(int x, int y)
322 #include "../gpulib/gpu_timing.h"
323 extern const unsigned char cmd_lengths[256];
325 int do_cmd_list(uint32_t *list, int list_len,
326 int *cycles_sum_out, int *cycles_last, int *last_cmd)
328 int cpu_cycles_sum = 0, cpu_cycles = *cycles_last;
329 unsigned int cmd = 0, len;
330 uint32_t *list_start = list;
331 uint32_t *list_end = list + list_len;
333 for (; list < list_end; list += 1 + len)
335 short *slist = (void *)list;
336 cmd = GETLE32(list) >> 24;
337 len = cmd_lengths[cmd];
338 if (list + 1 + len > list_end) {
344 if (0x80 <= cmd && cmd < 0xe0)
345 break; // image i/o, forward to upper layer
346 else if ((cmd & 0xf8) == 0xe0)
347 gpu.ex_regs[cmd & 7] = GETLE32(list);
350 primTableJ[cmd]((void *)list);
356 u32 num_vertexes = 2;
357 u32 *list_position = &(list[3]);
361 gput_sum(cpu_cycles_sum, cpu_cycles, gput_line(0));
363 if(list_position >= list_end) {
368 if((*list_position & HOST2LE32(0xf000f000)) == HOST2LE32(0x50005000))
375 len += (num_vertexes - 2);
381 u32 num_vertexes = 2;
382 u32 *list_position = &(list[4]);
386 gput_sum(cpu_cycles_sum, cpu_cycles, gput_line(0));
388 if(list_position >= list_end) {
393 if((*list_position & HOST2LE32(0xf000f000)) == HOST2LE32(0x50005000))
400 len += (num_vertexes - 2) * 2;
405 case 0xA0: // sys -> vid
407 u32 load_width = LE2HOST16(slist[4]);
408 u32 load_height = LE2HOST16(slist[5]);
409 u32 load_size = load_width * load_height;
411 len += load_size / 2;
418 gput_sum(cpu_cycles_sum, cpu_cycles,
419 gput_fill(LE2HOST16(slist[4]) & 0x3ff, LE2HOST16(slist[5]) & 0x1ff));
421 case 0x20 ... 0x23: gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base()); break;
422 case 0x24 ... 0x27: gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base_t()); break;
423 case 0x28 ... 0x2B: gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base()); break;
424 case 0x2C ... 0x2F: gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base_t()); break;
425 case 0x30 ... 0x33: gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base_g()); break;
426 case 0x34 ... 0x37: gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base_gt()); break;
427 case 0x38 ... 0x3B: gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base_g()); break;
428 case 0x3C ... 0x3F: gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base_gt()); break;
429 case 0x40 ... 0x47: gput_sum(cpu_cycles_sum, cpu_cycles, gput_line(0)); break;
430 case 0x50 ... 0x57: gput_sum(cpu_cycles_sum, cpu_cycles, gput_line(0)); break;
432 gput_sum(cpu_cycles_sum, cpu_cycles,
433 gput_sprite(LE2HOST16(slist[4]) & 0x3ff, LE2HOST16(slist[5]) & 0x1ff));
436 gput_sum(cpu_cycles_sum, cpu_cycles,
437 gput_sprite(LE2HOST16(slist[6]) & 0x3ff, LE2HOST16(slist[7]) & 0x1ff));
439 case 0x68 ... 0x6B: gput_sum(cpu_cycles_sum, cpu_cycles, gput_sprite(1, 1)); break;
441 case 0x74 ... 0x77: gput_sum(cpu_cycles_sum, cpu_cycles, gput_sprite(8, 8)); break;
443 case 0x7C ... 0x7F: gput_sum(cpu_cycles_sum, cpu_cycles, gput_sprite(16, 16)); break;
448 gpu.ex_regs[1] &= ~0x1ff;
449 gpu.ex_regs[1] |= lGPUstatusRet & 0x1ff;
451 *cycles_sum_out += cpu_cycles_sum;
452 *cycles_last = cpu_cycles;
454 return list - list_start;
457 void renderer_sync_ecmds(uint32_t *ecmds_)
459 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
460 // the funcs below expect LE
461 uint32_t i, ecmds[8];
462 for (i = 1; i <= 6; i++)
463 ecmds[i] = HTOLE32(ecmds_[i]);
465 uint32_t *ecmds = ecmds_;
467 cmdTexturePage((unsigned char *)&ecmds[1]);
468 cmdTextureWindow((unsigned char *)&ecmds[2]);
469 cmdDrawAreaStart((unsigned char *)&ecmds[3]);
470 cmdDrawAreaEnd((unsigned char *)&ecmds[4]);
471 cmdDrawOffset((unsigned char *)&ecmds[5]);
472 cmdSTP((unsigned char *)&ecmds[6]);
475 void renderer_update_caches(int x, int y, int w, int h, int state_changed)
479 void renderer_flush_queues(void)
483 void renderer_set_interlace(int enable, int is_odd)
487 void renderer_sync(void)
491 void renderer_notify_update_lace(int updated)
495 #include "../../frontend/plugin_lib.h"
497 void renderer_set_config(const struct rearmed_cbs *cbs)
499 iUseDither = cbs->gpu_peops.iUseDither;
500 dwActFixes = cbs->gpu_peops.dwActFixes;
501 if (cbs->pl_set_gpu_caps)
502 cbs->pl_set_gpu_caps(0);
506 // vim:ts=2:shiftwidth=2:expandtab