frontend: fix minor glitches on video mode changes
[pcsx_rearmed.git] / plugins / gpu_unai / gpulib_if.cpp
... / ...
CommitLineData
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
44static int linesInterlace; /* internal lines interlace */
45static int force_interlace;
46
47static bool light = true; /* lighting */
48static bool blend = true; /* blending */
49static bool FrameToRead = false; /* load image in progress */
50static bool FrameToWrite = false; /* store image in progress */
51
52static bool enableAbbeyHack = false; /* Abe's Odyssey hack */
53
54static u8 BLEND_MODE;
55static u8 TEXT_MODE;
56static u8 Masking;
57
58static u16 PixelMSB;
59static u16 PixelData;
60
61///////////////////////////////////////////////////////////////////////////////
62// GPU Global data
63///////////////////////////////////////////////////////////////////////////////
64
65// Dma Transfers info
66static s32 px,py;
67static s32 x_end,y_end;
68static u16* pvram;
69
70static s32 PacketCount;
71static s32 PacketIndex;
72
73// Rasterizer status
74static u32 TextureWindow [4];
75static u32 DrawingArea [4];
76static u32 DrawingOffset [2];
77
78static u16* TBA;
79static u16* CBA;
80
81// Inner Loops
82static s32 u4, du4;
83static s32 v4, dv4;
84static s32 r4, dr4;
85static s32 g4, dg4;
86static s32 b4, db4;
87static u32 lInc;
88static u32 tInc, tMsk;
89
90union 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
100static GPUPacket PacketBuffer;
101static u16 *GPU_FrameBuffer;
102static 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
138int 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
157void renderer_finish(void)
158{
159}
160
161void renderer_notify_res_change(void)
162{
163}
164
165extern const unsigned char cmd_lengths[256];
166
167int 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] = ((long)temp<<(32-11))>>(32-11);
494 DrawingOffset[1] = ((long)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
508breakloop:
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
516void renderer_sync_ecmds(uint32_t *ecmds)
517{
518 int dummy;
519 do_cmd_list(&ecmds[1], 6, &dummy);
520}
521
522void renderer_update_caches(int x, int y, int w, int h)
523{
524}
525
526void renderer_flush_queues(void)
527{
528}
529
530void renderer_set_interlace(int enable, int is_odd)
531{
532}
533
534#ifndef TEST
535
536#include "../../frontend/plugin_lib.h"
537
538void 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