psx_gpu: fix a blending issue
[pcsx_rearmed.git] / plugins / gpu_unai / gpulib_if.cpp
CommitLineData
6f2ee2be 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>
62d7fa95 25#include "../gpulib/gpu.h"
6f2ee2be 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
8aea5f5a 35#define INLINE static
6f2ee2be 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
89c0de42 42#define isSkip 0 /* skip frame (info coming from GPU) */
6f2ee2be 43#define alt_fps 0
89c0de42 44static int linesInterlace; /* internal lines interlace */
45static int force_interlace;
6f2ee2be 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{
8aea5f5a 92 u32 U4[16];
93 s32 S4[16];
94 u16 U2[32];
95 s16 S2[32];
96 u8 U1[64];
97 s8 S1[64];
6f2ee2be 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_POLY(x) (((s32)(x)<<20)>>20)
115//#define GPU_EXPANDSIGN_POLY(x) (((s32)(x)<<21)>>21)
116#define GPU_EXPANDSIGN_SPRT(x) (((s32)(x)<<21)>>21)
117
118//#define GPU_TESTRANGE(x) { if((u32)(x+1024) > 2047) return; }
119#define GPU_TESTRANGE(x) { if ((x<-1023) || (x>1023)) return; }
120
121#define GPU_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);}
122
123// GPU internal image drawing functions
124#include "../gpu_unai/gpu_raster_image.h"
125
126// GPU internal line drawing functions
127#include "../gpu_unai/gpu_raster_line.h"
128
129// GPU internal polygon drawing functions
130#include "../gpu_unai/gpu_raster_polygon.h"
131
132// GPU internal sprite drawing functions
133#include "../gpu_unai/gpu_raster_sprite.h"
134
135// GPU command buffer execution/store
136#include "../gpu_unai/gpu_command.h"
137
6f2ee2be 138/////////////////////////////////////////////////////////////////////////////
139
140int renderer_init(void)
141{
142 GPU_FrameBuffer = (u16 *)gpu.vram;
143
144 // s_invTable
145 for(int i=1;i<=(1<<TABLE_BITS);++i)
146 {
147 double v = 1.0 / double(i);
148 #ifdef GPU_TABLE_10_BITS
149 v *= double(0xffffffff>>1);
150 #else
151 v *= double(0x80000000);
152 #endif
153 s_invTable[i-1]=s32(v);
154 }
155
156 return 0;
157}
158
159extern const unsigned char cmd_lengths[256];
160
b243416b 161int do_cmd_list(unsigned int *list, int list_len, int *last_cmd)
6f2ee2be 162{
42a261f1 163 unsigned int cmd = 0, len, i;
b243416b 164 unsigned int *list_start = list;
6f2ee2be 165 unsigned int *list_end = list + list_len;
166
89c0de42 167 linesInterlace = force_interlace;
168#ifndef __ARM_ARCH_7A__ /* XXX */
169 linesInterlace |= gpu.status.interlace;
170#endif
171
6f2ee2be 172 for (; list < list_end; list += 1 + len)
173 {
6f2ee2be 174 cmd = *list >> 24;
175 len = cmd_lengths[cmd];
b243416b 176 if (list + 1 + len > list_end) {
177 cmd = -1;
178 break;
179 }
180
42a261f1 181 #define PRIM cmd
182 PacketBuffer.U4[0] = list[0];
183 for (i = 1; i <= len; i++)
184 PacketBuffer.U4[i] = list[i];
6f2ee2be 185
42a261f1 186 switch (cmd)
6f2ee2be 187 {
42a261f1 188 case 0x02:
189 gpuClearImage();
190 break;
191
192 case 0x20:
193 case 0x21:
194 case 0x22:
195 case 0x23:
196 gpuDrawF3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB]);
197 break;
198
199 case 0x24:
200 case 0x25:
201 case 0x26:
202 case 0x27:
203 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
204 gpuSetTexture(PacketBuffer.U4[4] >> 16);
205 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
206 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB]);
207 else
208 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB]);
209 break;
210
211 case 0x28:
212 case 0x29:
213 case 0x2A:
214 case 0x2B: {
215 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB];
216 gpuDrawF3(gpuPolySpanDriver);
217 PacketBuffer.U4[1] = PacketBuffer.U4[4];
218 gpuDrawF3(gpuPolySpanDriver);
219 break;
220 }
221
222 case 0x2C:
223 case 0x2D:
224 case 0x2E:
225 case 0x2F: {
226 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
227 gpuSetTexture(PacketBuffer.U4[4] >> 16);
228 PP gpuPolySpanDriver;
229 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
230 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB];
231 else
232 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB];
233 gpuDrawFT3(gpuPolySpanDriver);
234 PacketBuffer.U4[1] = PacketBuffer.U4[7];
235 PacketBuffer.U4[2] = PacketBuffer.U4[8];
236 gpuDrawFT3(gpuPolySpanDriver);
237 break;
238 }
239
240 case 0x30:
241 case 0x31:
242 case 0x32:
243 case 0x33:
244 gpuDrawG3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB]);
245 break;
246
247 case 0x34:
248 case 0x35:
249 case 0x36:
250 case 0x37:
251 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
252 gpuSetTexture (PacketBuffer.U4[5] >> 16);
253 gpuDrawGT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB]);
254 break;
255
256 case 0x38:
257 case 0x39:
258 case 0x3A:
259 case 0x3B: {
260 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB];
261 gpuDrawG3(gpuPolySpanDriver);
262 PacketBuffer.U4[0] = PacketBuffer.U4[6];
263 PacketBuffer.U4[1] = PacketBuffer.U4[7];
264 gpuDrawG3(gpuPolySpanDriver);
265 break;
266 }
267
268 case 0x3C:
269 case 0x3D:
270 case 0x3E:
271 case 0x3F: {
272 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
273 gpuSetTexture (PacketBuffer.U4[5] >> 16);
274 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB];
275 gpuDrawGT3(gpuPolySpanDriver);
276 PacketBuffer.U4[0] = PacketBuffer.U4[9];
277 PacketBuffer.U4[1] = PacketBuffer.U4[10];
278 PacketBuffer.U4[2] = PacketBuffer.U4[11];
279 gpuDrawGT3(gpuPolySpanDriver);
280 break;
281 }
282
283 case 0x40:
284 case 0x41:
285 case 0x42:
286 case 0x43:
287 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
288 break;
289
6f2ee2be 290 case 0x48 ... 0x4F:
291 {
292 u32 num_vertexes = 1;
293 u32 *list_position = &(list[2]);
8aea5f5a 294
8aea5f5a 295 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
6f2ee2be 296
297 while(1)
298 {
8aea5f5a 299 PacketBuffer.U4[1] = PacketBuffer.U4[2];
300 PacketBuffer.U4[2] = *list_position++;
301 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
302
6f2ee2be 303 num_vertexes++;
b243416b 304 if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
305 break;
6f2ee2be 306 }
307
b243416b 308 len += (num_vertexes - 2);
6f2ee2be 309 break;
310 }
311
42a261f1 312 case 0x50:
313 case 0x51:
314 case 0x52:
315 case 0x53:
316 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
317 break;
318
6f2ee2be 319 case 0x58 ... 0x5F:
320 {
321 u32 num_vertexes = 1;
322 u32 *list_position = &(list[2]);
8aea5f5a 323
8aea5f5a 324 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
6f2ee2be 325
326 while(1)
327 {
8aea5f5a 328 PacketBuffer.U4[0] = PacketBuffer.U4[2];
329 PacketBuffer.U4[1] = PacketBuffer.U4[3];
330 PacketBuffer.U4[2] = *list_position++;
331 PacketBuffer.U4[3] = *list_position++;
332 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
333
6f2ee2be 334 num_vertexes++;
b243416b 335 if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
336 break;
6f2ee2be 337 }
338
b243416b 339 len += (num_vertexes - 2) * 2;
6f2ee2be 340 break;
341 }
342
42a261f1 343 case 0x60:
344 case 0x61:
345 case 0x62:
346 case 0x63:
347 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
348 break;
349
350 case 0x64:
351 case 0x65:
352 case 0x66:
353 case 0x67:
354 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
355 gpuSetTexture (GPU_GP1);
356 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
357 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
358 else
359 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
360 break;
361
362 case 0x68:
363 case 0x69:
364 case 0x6A:
365 case 0x6B:
366 PacketBuffer.U4[2] = 0x00010001;
367 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
368 break;
369
370 case 0x70:
371 case 0x71:
372 case 0x72:
373 case 0x73:
374 PacketBuffer.U4[2] = 0x00080008;
375 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
376 break;
377
378 case 0x74:
379 case 0x75:
380 case 0x76:
381 case 0x77:
382 PacketBuffer.U4[3] = 0x00080008;
383 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
384 gpuSetTexture (GPU_GP1);
385 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
386 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
387 else
388 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
389 break;
390
391 case 0x78:
392 case 0x79:
393 case 0x7A:
394 case 0x7B:
395 PacketBuffer.U4[2] = 0x00100010;
396 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
397 break;
398
399 case 0x7C:
400 case 0x7D:
401#ifdef __arm__
402 if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
403 {
404 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
405 gpuSetTexture (GPU_GP1);
406 gpuDrawS16();
407 break;
408 }
409 // fallthrough
410#endif
411 case 0x7E:
412 case 0x7F:
413 PacketBuffer.U4[3] = 0x00100010;
414 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
415 gpuSetTexture (GPU_GP1);
416 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
417 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
418 else
419 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
420 break;
421
422 case 0x80: // vid -> vid
423 gpuMoveImage(); // prim handles updateLace && skip
424 break;
9a6e7816 425#ifdef TEST
426 case 0xA0: // sys -> vid
427 {
428 u32 load_width = list[2] & 0xffff;
429 u32 load_height = list[2] >> 16;
430 u32 load_size = load_width * load_height;
431
432 len += load_size / 2;
433 break;
434 }
42a261f1 435 case 0xC0:
436 break;
437#else
438 case 0xA0: // sys ->vid
439 case 0xC0: // vid -> sys
440 goto breakloop;
9a6e7816 441#endif
42a261f1 442 case 0xE1: {
443 const u32 temp = PacketBuffer.U4[0];
444 GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
445 gpuSetTexture(temp);
446 gpu.ex_regs[1] = temp;
447 break;
448 }
449 case 0xE2: {
450 static const u8 TextureMask[32] = {
451 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
452 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
453 };
454 const u32 temp = PacketBuffer.U4[0];
455 TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
456 TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
457 TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
458 TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
459 gpuSetTexture(GPU_GP1);
460 gpu.ex_regs[2] = temp;
461 break;
462 }
463 case 0xE3: {
464 const u32 temp = PacketBuffer.U4[0];
465 DrawingArea[0] = temp & 0x3FF;
466 DrawingArea[1] = (temp >> 10) & 0x3FF;
467 gpu.ex_regs[3] = temp;
6f2ee2be 468 break;
42a261f1 469 }
470 case 0xE4: {
471 const u32 temp = PacketBuffer.U4[0];
472 DrawingArea[2] = (temp & 0x3FF) + 1;
473 DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
474 gpu.ex_regs[4] = temp;
475 break;
476 }
477 case 0xE5: {
478 const u32 temp = PacketBuffer.U4[0];
479 DrawingOffset[0] = ((long)temp<<(32-11))>>(32-11);
480 DrawingOffset[1] = ((long)temp<<(32-22))>>(32-11);
481 gpu.ex_regs[5] = temp;
482 break;
483 }
484 case 0xE6: {
485 const u32 temp = PacketBuffer.U4[0];
486 Masking = (temp & 0x2) << 1;
487 PixelMSB =(temp & 0x1) << 8;
488 gpu.ex_regs[6] = temp;
489 break;
490 }
6f2ee2be 491 }
492 }
b243416b 493
42a261f1 494breakloop:
b243416b 495 gpu.ex_regs[1] &= ~0x1ff;
496 gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
497
498 *last_cmd = cmd;
499 return list - list_start;
6f2ee2be 500}
501
502void renderer_sync_ecmds(uint32_t *ecmds)
503{
42a261f1 504 int dummy;
505 do_cmd_list(&ecmds[1], 6, &dummy);
6f2ee2be 506}
507
05740673 508void renderer_update_caches(int x, int y, int w, int h)
6f2ee2be 509{
510}
511
512void renderer_flush_queues(void)
513{
514}
914455e6 515
5440b88e 516void renderer_set_interlace(int enable, int is_odd)
517{
518}
519
9a6e7816 520#ifndef TEST
521
914455e6 522#include "../../frontend/plugin_lib.h"
523
524void renderer_set_config(const struct rearmed_cbs *cbs)
525{
89c0de42 526 force_interlace = cbs->gpu_unai.lineskip;
914455e6 527 enableAbbeyHack = cbs->gpu_unai.abe_hack;
528 light = !cbs->gpu_unai.no_light;
529 blend = !cbs->gpu_unai.no_blend;
530}
9a6e7816 531
532#endif
42a261f1 533
534// vim:shiftwidth=2:expandtab