spu: stop at 0 volume
[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
9ed4ca47 114#define GPU_EXPANDSIGN(x) (((s32)(x)<<21)>>21)
6f2ee2be 115
9ed4ca47 116#define CHKMAX_X 1024
117#define CHKMAX_Y 512
6f2ee2be 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
6f2ee2be 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
e929dec5 157void renderer_finish(void)
158{
159}
160
161void renderer_notify_res_change(void)
162{
163}
164
6f2ee2be 165extern const unsigned char cmd_lengths[256];
166
b243416b 167int do_cmd_list(unsigned int *list, int list_len, int *last_cmd)
6f2ee2be 168{
42a261f1 169 unsigned int cmd = 0, len, i;
b243416b 170 unsigned int *list_start = list;
6f2ee2be 171 unsigned int *list_end = list + list_len;
172
89c0de42 173 linesInterlace = force_interlace;
174#ifndef __ARM_ARCH_7A__ /* XXX */
175 linesInterlace |= gpu.status.interlace;
176#endif
177
6f2ee2be 178 for (; list < list_end; list += 1 + len)
179 {
6f2ee2be 180 cmd = *list >> 24;
181 len = cmd_lengths[cmd];
b243416b 182 if (list + 1 + len > list_end) {
183 cmd = -1;
184 break;
185 }
186
42a261f1 187 #define PRIM cmd
188 PacketBuffer.U4[0] = list[0];
189 for (i = 1; i <= len; i++)
190 PacketBuffer.U4[i] = list[i];
6f2ee2be 191
42a261f1 192 switch (cmd)
6f2ee2be 193 {
42a261f1 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
6f2ee2be 296 case 0x48 ... 0x4F:
297 {
298 u32 num_vertexes = 1;
299 u32 *list_position = &(list[2]);
8aea5f5a 300
8aea5f5a 301 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
6f2ee2be 302
303 while(1)
304 {
8aea5f5a 305 PacketBuffer.U4[1] = PacketBuffer.U4[2];
306 PacketBuffer.U4[2] = *list_position++;
307 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
308
6f2ee2be 309 num_vertexes++;
b243416b 310 if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
311 break;
6f2ee2be 312 }
313
b243416b 314 len += (num_vertexes - 2);
6f2ee2be 315 break;
316 }
317
42a261f1 318 case 0x50:
319 case 0x51:
320 case 0x52:
321 case 0x53:
322 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
323 break;
324
6f2ee2be 325 case 0x58 ... 0x5F:
326 {
327 u32 num_vertexes = 1;
328 u32 *list_position = &(list[2]);
8aea5f5a 329
8aea5f5a 330 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
6f2ee2be 331
332 while(1)
333 {
8aea5f5a 334 PacketBuffer.U4[0] = PacketBuffer.U4[2];
335 PacketBuffer.U4[1] = PacketBuffer.U4[3];
336 PacketBuffer.U4[2] = *list_position++;
337 PacketBuffer.U4[3] = *list_position++;
338 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
339
6f2ee2be 340 num_vertexes++;
b243416b 341 if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
342 break;
6f2ee2be 343 }
344
b243416b 345 len += (num_vertexes - 2) * 2;
6f2ee2be 346 break;
347 }
348
42a261f1 349 case 0x60:
350 case 0x61:
351 case 0x62:
352 case 0x63:
353 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
354 break;
355
356 case 0x64:
357 case 0x65:
358 case 0x66:
359 case 0x67:
360 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
361 gpuSetTexture (GPU_GP1);
362 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
363 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
364 else
365 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
366 break;
367
368 case 0x68:
369 case 0x69:
370 case 0x6A:
371 case 0x6B:
372 PacketBuffer.U4[2] = 0x00010001;
373 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
374 break;
375
376 case 0x70:
377 case 0x71:
378 case 0x72:
379 case 0x73:
380 PacketBuffer.U4[2] = 0x00080008;
381 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
382 break;
383
384 case 0x74:
385 case 0x75:
386 case 0x76:
387 case 0x77:
388 PacketBuffer.U4[3] = 0x00080008;
389 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
390 gpuSetTexture (GPU_GP1);
391 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
392 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
393 else
394 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
395 break;
396
397 case 0x78:
398 case 0x79:
399 case 0x7A:
400 case 0x7B:
401 PacketBuffer.U4[2] = 0x00100010;
402 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
403 break;
404
405 case 0x7C:
406 case 0x7D:
407#ifdef __arm__
408 if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
409 {
410 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
411 gpuSetTexture (GPU_GP1);
412 gpuDrawS16();
413 break;
414 }
415 // fallthrough
416#endif
417 case 0x7E:
418 case 0x7F:
419 PacketBuffer.U4[3] = 0x00100010;
420 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
421 gpuSetTexture (GPU_GP1);
422 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
423 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
424 else
425 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
426 break;
427
428 case 0x80: // vid -> vid
429 gpuMoveImage(); // prim handles updateLace && skip
430 break;
9a6e7816 431#ifdef TEST
432 case 0xA0: // sys -> vid
433 {
434 u32 load_width = list[2] & 0xffff;
435 u32 load_height = list[2] >> 16;
436 u32 load_size = load_width * load_height;
437
438 len += load_size / 2;
439 break;
440 }
42a261f1 441 case 0xC0:
442 break;
443#else
444 case 0xA0: // sys ->vid
445 case 0xC0: // vid -> sys
446 goto breakloop;
9a6e7816 447#endif
42a261f1 448 case 0xE1: {
449 const u32 temp = PacketBuffer.U4[0];
450 GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
451 gpuSetTexture(temp);
452 gpu.ex_regs[1] = temp;
453 break;
454 }
455 case 0xE2: {
456 static const u8 TextureMask[32] = {
457 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
458 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
459 };
460 const u32 temp = PacketBuffer.U4[0];
461 TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
462 TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
463 TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
464 TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
465 gpuSetTexture(GPU_GP1);
466 gpu.ex_regs[2] = temp;
467 break;
468 }
469 case 0xE3: {
470 const u32 temp = PacketBuffer.U4[0];
471 DrawingArea[0] = temp & 0x3FF;
472 DrawingArea[1] = (temp >> 10) & 0x3FF;
473 gpu.ex_regs[3] = temp;
6f2ee2be 474 break;
42a261f1 475 }
476 case 0xE4: {
477 const u32 temp = PacketBuffer.U4[0];
478 DrawingArea[2] = (temp & 0x3FF) + 1;
479 DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
480 gpu.ex_regs[4] = temp;
481 break;
482 }
483 case 0xE5: {
484 const u32 temp = PacketBuffer.U4[0];
485 DrawingOffset[0] = ((long)temp<<(32-11))>>(32-11);
486 DrawingOffset[1] = ((long)temp<<(32-22))>>(32-11);
487 gpu.ex_regs[5] = temp;
488 break;
489 }
490 case 0xE6: {
491 const u32 temp = PacketBuffer.U4[0];
492 Masking = (temp & 0x2) << 1;
493 PixelMSB =(temp & 0x1) << 8;
494 gpu.ex_regs[6] = temp;
495 break;
496 }
6f2ee2be 497 }
498 }
b243416b 499
42a261f1 500breakloop:
b243416b 501 gpu.ex_regs[1] &= ~0x1ff;
502 gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
503
504 *last_cmd = cmd;
505 return list - list_start;
6f2ee2be 506}
507
508void renderer_sync_ecmds(uint32_t *ecmds)
509{
42a261f1 510 int dummy;
511 do_cmd_list(&ecmds[1], 6, &dummy);
6f2ee2be 512}
513
05740673 514void renderer_update_caches(int x, int y, int w, int h)
6f2ee2be 515{
516}
517
518void renderer_flush_queues(void)
519{
520}
914455e6 521
5440b88e 522void renderer_set_interlace(int enable, int is_odd)
523{
524}
525
9a6e7816 526#ifndef TEST
527
914455e6 528#include "../../frontend/plugin_lib.h"
529
530void renderer_set_config(const struct rearmed_cbs *cbs)
531{
89c0de42 532 force_interlace = cbs->gpu_unai.lineskip;
914455e6 533 enableAbbeyHack = cbs->gpu_unai.abe_hack;
534 light = !cbs->gpu_unai.no_light;
535 blend = !cbs->gpu_unai.no_blend;
9ee0fd5b 536
537 GPU_FrameBuffer = (u16 *)gpu.vram;
914455e6 538}
9a6e7816 539
540#endif
42a261f1 541
542// vim:shiftwidth=2:expandtab