gpulib: handle vram copy in gpulib
[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"
8f2bb0cb 26#include "arm_features.h"
6f2ee2be 27
28#define u8 uint8_t
29#define s8 int8_t
30#define u16 uint16_t
31#define s16 int16_t
32#define u32 uint32_t
33#define s32 int32_t
34#define s64 int64_t
35
8aea5f5a 36#define INLINE static
6f2ee2be 37
38#define FRAME_BUFFER_SIZE (1024*512*2)
39#define FRAME_WIDTH 1024
40#define FRAME_HEIGHT 512
41#define FRAME_OFFSET(x,y) (((y)<<10)+(x))
42
89c0de42 43#define isSkip 0 /* skip frame (info coming from GPU) */
6f2ee2be 44#define alt_fps 0
89c0de42 45static int linesInterlace; /* internal lines interlace */
46static int force_interlace;
6f2ee2be 47
48static bool light = true; /* lighting */
49static bool blend = true; /* blending */
50static bool FrameToRead = false; /* load image in progress */
51static bool FrameToWrite = false; /* store image in progress */
52
53static bool enableAbbeyHack = false; /* Abe's Odyssey hack */
54
55static u8 BLEND_MODE;
56static u8 TEXT_MODE;
57static u8 Masking;
58
59static u16 PixelMSB;
60static u16 PixelData;
61
62///////////////////////////////////////////////////////////////////////////////
63// GPU Global data
64///////////////////////////////////////////////////////////////////////////////
65
66// Dma Transfers info
67static s32 px,py;
68static s32 x_end,y_end;
69static u16* pvram;
70
71static s32 PacketCount;
72static s32 PacketIndex;
73
74// Rasterizer status
75static u32 TextureWindow [4];
76static u32 DrawingArea [4];
77static u32 DrawingOffset [2];
78
79static u16* TBA;
80static u16* CBA;
81
82// Inner Loops
83static s32 u4, du4;
84static s32 v4, dv4;
85static s32 r4, dr4;
86static s32 g4, dg4;
87static s32 b4, db4;
88static u32 lInc;
89static u32 tInc, tMsk;
90
91union GPUPacket
92{
8aea5f5a 93 u32 U4[16];
94 s32 S4[16];
95 u16 U2[32];
96 s16 S2[32];
97 u8 U1[64];
98 s8 S1[64];
6f2ee2be 99};
100
101static GPUPacket PacketBuffer;
102static u16 *GPU_FrameBuffer;
103static u32 GPU_GP1;
104
105///////////////////////////////////////////////////////////////////////////////
106
107#include "../gpu_unai/gpu_fixedpoint.h"
108
109// Inner loop driver instanciation file
110#include "../gpu_unai/gpu_inner.h"
111
112// GPU Raster Macros
113#define GPU_RGB16(rgb) ((((rgb)&0xF80000)>>9)|(((rgb)&0xF800)>>6)|(((rgb)&0xF8)>>3))
114
9ed4ca47 115#define GPU_EXPANDSIGN(x) (((s32)(x)<<21)>>21)
6f2ee2be 116
9ed4ca47 117#define CHKMAX_X 1024
118#define CHKMAX_Y 512
6f2ee2be 119
120#define GPU_SWAP(a,b,t) {(t)=(a);(a)=(b);(b)=(t);}
121
122// GPU internal image drawing functions
123#include "../gpu_unai/gpu_raster_image.h"
124
125// GPU internal line drawing functions
126#include "../gpu_unai/gpu_raster_line.h"
127
128// GPU internal polygon drawing functions
129#include "../gpu_unai/gpu_raster_polygon.h"
130
131// GPU internal sprite drawing functions
132#include "../gpu_unai/gpu_raster_sprite.h"
133
134// GPU command buffer execution/store
135#include "../gpu_unai/gpu_command.h"
136
6f2ee2be 137/////////////////////////////////////////////////////////////////////////////
138
139int renderer_init(void)
140{
141 GPU_FrameBuffer = (u16 *)gpu.vram;
142
143 // s_invTable
144 for(int i=1;i<=(1<<TABLE_BITS);++i)
145 {
146 double v = 1.0 / double(i);
147 #ifdef GPU_TABLE_10_BITS
148 v *= double(0xffffffff>>1);
149 #else
150 v *= double(0x80000000);
151 #endif
152 s_invTable[i-1]=s32(v);
153 }
154
155 return 0;
156}
157
e929dec5 158void renderer_finish(void)
159{
160}
161
162void renderer_notify_res_change(void)
163{
164}
165
0b4038f8 166void renderer_notify_scanout_x_change(int x, int w)
167{
168}
169
6f2ee2be 170extern const unsigned char cmd_lengths[256];
171
b243416b 172int do_cmd_list(unsigned int *list, int list_len, int *last_cmd)
6f2ee2be 173{
42a261f1 174 unsigned int cmd = 0, len, i;
b243416b 175 unsigned int *list_start = list;
6f2ee2be 176 unsigned int *list_end = list + list_len;
177
89c0de42 178 linesInterlace = force_interlace;
8f2bb0cb 179#ifdef HAVE_PRE_ARMV7 /* XXX */
3499746e 180 linesInterlace |= !!(gpu.status & PSX_GPU_STATUS_INTERLACE);
89c0de42 181#endif
182
6f2ee2be 183 for (; list < list_end; list += 1 + len)
184 {
6f2ee2be 185 cmd = *list >> 24;
186 len = cmd_lengths[cmd];
b243416b 187 if (list + 1 + len > list_end) {
188 cmd = -1;
189 break;
190 }
191
42a261f1 192 #define PRIM cmd
193 PacketBuffer.U4[0] = list[0];
194 for (i = 1; i <= len; i++)
195 PacketBuffer.U4[i] = list[i];
6f2ee2be 196
42a261f1 197 switch (cmd)
6f2ee2be 198 {
42a261f1 199 case 0x02:
200 gpuClearImage();
201 break;
202
203 case 0x20:
204 case 0x21:
205 case 0x22:
206 case 0x23:
207 gpuDrawF3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB]);
208 break;
209
210 case 0x24:
211 case 0x25:
212 case 0x26:
213 case 0x27:
214 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
215 gpuSetTexture(PacketBuffer.U4[4] >> 16);
216 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
217 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB]);
218 else
219 gpuDrawFT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB]);
220 break;
221
222 case 0x28:
223 case 0x29:
224 case 0x2A:
225 case 0x2B: {
226 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | PixelMSB];
227 gpuDrawF3(gpuPolySpanDriver);
228 PacketBuffer.U4[1] = PacketBuffer.U4[4];
229 gpuDrawF3(gpuPolySpanDriver);
230 break;
231 }
232
233 case 0x2C:
234 case 0x2D:
235 case 0x2E:
236 case 0x2F: {
237 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
238 gpuSetTexture(PacketBuffer.U4[4] >> 16);
239 PP gpuPolySpanDriver;
240 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
241 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | PixelMSB];
242 else
243 gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | PixelMSB];
244 gpuDrawFT3(gpuPolySpanDriver);
245 PacketBuffer.U4[1] = PacketBuffer.U4[7];
246 PacketBuffer.U4[2] = PacketBuffer.U4[8];
247 gpuDrawFT3(gpuPolySpanDriver);
248 break;
249 }
250
251 case 0x30:
252 case 0x31:
253 case 0x32:
254 case 0x33:
255 gpuDrawG3(gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB]);
256 break;
257
258 case 0x34:
259 case 0x35:
260 case 0x36:
261 case 0x37:
262 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
263 gpuSetTexture (PacketBuffer.U4[5] >> 16);
264 gpuDrawGT3(gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB]);
265 break;
266
267 case 0x38:
268 case 0x39:
269 case 0x3A:
270 case 0x3B: {
271 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | Masking | Blending | 129 | PixelMSB];
272 gpuDrawG3(gpuPolySpanDriver);
273 PacketBuffer.U4[0] = PacketBuffer.U4[6];
274 PacketBuffer.U4[1] = PacketBuffer.U4[7];
275 gpuDrawG3(gpuPolySpanDriver);
276 break;
277 }
278
279 case 0x3C:
280 case 0x3D:
281 case 0x3E:
282 case 0x3F: {
283 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
284 gpuSetTexture (PacketBuffer.U4[5] >> 16);
285 const PP gpuPolySpanDriver = gpuPolySpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | ((Lighting)?129:0) | PixelMSB];
286 gpuDrawGT3(gpuPolySpanDriver);
287 PacketBuffer.U4[0] = PacketBuffer.U4[9];
288 PacketBuffer.U4[1] = PacketBuffer.U4[10];
289 PacketBuffer.U4[2] = PacketBuffer.U4[11];
290 gpuDrawGT3(gpuPolySpanDriver);
291 break;
292 }
293
294 case 0x40:
295 case 0x41:
296 case 0x42:
297 case 0x43:
298 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
299 break;
300
6f2ee2be 301 case 0x48 ... 0x4F:
302 {
303 u32 num_vertexes = 1;
304 u32 *list_position = &(list[2]);
8aea5f5a 305
8aea5f5a 306 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
6f2ee2be 307
308 while(1)
309 {
8aea5f5a 310 PacketBuffer.U4[1] = PacketBuffer.U4[2];
311 PacketBuffer.U4[2] = *list_position++;
312 gpuDrawLF(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
313
6f2ee2be 314 num_vertexes++;
804789d7 315 if(list_position >= list_end) {
316 cmd = -1;
317 goto breakloop;
318 }
319 if((*list_position & 0xf000f000) == 0x50005000)
b243416b 320 break;
6f2ee2be 321 }
322
b243416b 323 len += (num_vertexes - 2);
6f2ee2be 324 break;
325 }
326
42a261f1 327 case 0x50:
328 case 0x51:
329 case 0x52:
330 case 0x53:
331 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
332 break;
333
6f2ee2be 334 case 0x58 ... 0x5F:
335 {
336 u32 num_vertexes = 1;
337 u32 *list_position = &(list[2]);
8aea5f5a 338
8aea5f5a 339 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
6f2ee2be 340
341 while(1)
342 {
8aea5f5a 343 PacketBuffer.U4[0] = PacketBuffer.U4[2];
344 PacketBuffer.U4[1] = PacketBuffer.U4[3];
345 PacketBuffer.U4[2] = *list_position++;
346 PacketBuffer.U4[3] = *list_position++;
347 gpuDrawLG(gpuPixelDrivers [ (Blending_Mode | Masking | Blending | (PixelMSB>>3)) >> 1]);
348
6f2ee2be 349 num_vertexes++;
804789d7 350 if(list_position >= list_end) {
351 cmd = -1;
352 goto breakloop;
353 }
354 if((*list_position & 0xf000f000) == 0x50005000)
b243416b 355 break;
6f2ee2be 356 }
357
b243416b 358 len += (num_vertexes - 2) * 2;
6f2ee2be 359 break;
360 }
361
42a261f1 362 case 0x60:
363 case 0x61:
364 case 0x62:
365 case 0x63:
366 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
367 break;
368
369 case 0x64:
370 case 0x65:
371 case 0x66:
372 case 0x67:
373 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
374 gpuSetTexture (GPU_GP1);
375 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
376 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
377 else
378 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
379 break;
380
381 case 0x68:
382 case 0x69:
383 case 0x6A:
384 case 0x6B:
385 PacketBuffer.U4[2] = 0x00010001;
386 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
387 break;
388
389 case 0x70:
390 case 0x71:
391 case 0x72:
392 case 0x73:
393 PacketBuffer.U4[2] = 0x00080008;
394 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
395 break;
396
397 case 0x74:
398 case 0x75:
399 case 0x76:
400 case 0x77:
401 PacketBuffer.U4[3] = 0x00080008;
402 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
403 gpuSetTexture (GPU_GP1);
404 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
405 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
406 else
407 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
408 break;
409
410 case 0x78:
411 case 0x79:
412 case 0x7A:
413 case 0x7B:
414 PacketBuffer.U4[2] = 0x00100010;
415 gpuDrawT(gpuTileSpanDrivers [Blending_Mode | Masking | Blending | (PixelMSB>>3)]);
416 break;
417
418 case 0x7C:
419 case 0x7D:
420#ifdef __arm__
421 if ((GPU_GP1 & 0x180) == 0 && (Masking | PixelMSB) == 0)
422 {
423 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
424 gpuSetTexture (GPU_GP1);
425 gpuDrawS16();
426 break;
427 }
428 // fallthrough
429#endif
430 case 0x7E:
431 case 0x7F:
432 PacketBuffer.U4[3] = 0x00100010;
433 gpuSetCLUT (PacketBuffer.U4[2] >> 16);
434 gpuSetTexture (GPU_GP1);
435 if ((PacketBuffer.U1[0]>0x5F) && (PacketBuffer.U1[1]>0x5F) && (PacketBuffer.U1[2]>0x5F))
436 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | (enableAbbeyHack<<7) | PixelMSB]);
437 else
438 gpuDrawS(gpuSpriteSpanDrivers [Blending_Mode | TEXT_MODE | Masking | Blending | Lighting | (enableAbbeyHack<<7) | PixelMSB]);
439 break;
440
72583812 441#ifdef TEST
42a261f1 442 case 0x80: // vid -> vid
443 gpuMoveImage(); // prim handles updateLace && skip
444 break;
9a6e7816 445 case 0xA0: // sys -> vid
446 {
447 u32 load_width = list[2] & 0xffff;
448 u32 load_height = list[2] >> 16;
449 u32 load_size = load_width * load_height;
450
451 len += load_size / 2;
452 break;
453 }
42a261f1 454 case 0xC0:
455 break;
456#else
72583812 457 case 0x80 ... 0x9F: // vid -> vid
458 case 0xA0 ... 0xBF: // sys -> vid
459 case 0xC0 ... 0xDF: // vid -> sys
460 // Handled by gpulib
42a261f1 461 goto breakloop;
9a6e7816 462#endif
42a261f1 463 case 0xE1: {
464 const u32 temp = PacketBuffer.U4[0];
465 GPU_GP1 = (GPU_GP1 & ~0x000007FF) | (temp & 0x000007FF);
466 gpuSetTexture(temp);
467 gpu.ex_regs[1] = temp;
468 break;
469 }
470 case 0xE2: {
471 static const u8 TextureMask[32] = {
472 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7,
473 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7
474 };
475 const u32 temp = PacketBuffer.U4[0];
476 TextureWindow[0] = ((temp >> 10) & 0x1F) << 3;
477 TextureWindow[1] = ((temp >> 15) & 0x1F) << 3;
478 TextureWindow[2] = TextureMask[(temp >> 0) & 0x1F];
479 TextureWindow[3] = TextureMask[(temp >> 5) & 0x1F];
480 gpuSetTexture(GPU_GP1);
481 gpu.ex_regs[2] = temp;
482 break;
483 }
484 case 0xE3: {
485 const u32 temp = PacketBuffer.U4[0];
486 DrawingArea[0] = temp & 0x3FF;
487 DrawingArea[1] = (temp >> 10) & 0x3FF;
488 gpu.ex_regs[3] = temp;
6f2ee2be 489 break;
42a261f1 490 }
491 case 0xE4: {
492 const u32 temp = PacketBuffer.U4[0];
493 DrawingArea[2] = (temp & 0x3FF) + 1;
494 DrawingArea[3] = ((temp >> 10) & 0x3FF) + 1;
495 gpu.ex_regs[4] = temp;
496 break;
497 }
498 case 0xE5: {
499 const u32 temp = PacketBuffer.U4[0];
4144e9ab 500 DrawingOffset[0] = ((s32)temp<<(32-11))>>(32-11);
501 DrawingOffset[1] = ((s32)temp<<(32-22))>>(32-11);
42a261f1 502 gpu.ex_regs[5] = temp;
503 break;
504 }
505 case 0xE6: {
506 const u32 temp = PacketBuffer.U4[0];
507 Masking = (temp & 0x2) << 1;
508 PixelMSB =(temp & 0x1) << 8;
509 gpu.ex_regs[6] = temp;
510 break;
511 }
6f2ee2be 512 }
513 }
b243416b 514
42a261f1 515breakloop:
b243416b 516 gpu.ex_regs[1] &= ~0x1ff;
517 gpu.ex_regs[1] |= GPU_GP1 & 0x1ff;
518
519 *last_cmd = cmd;
520 return list - list_start;
6f2ee2be 521}
522
523void renderer_sync_ecmds(uint32_t *ecmds)
524{
42a261f1 525 int dummy;
526 do_cmd_list(&ecmds[1], 6, &dummy);
6f2ee2be 527}
528
0b4038f8 529void renderer_update_caches(int x, int y, int w, int h, int state_changed)
6f2ee2be 530{
531}
532
533void renderer_flush_queues(void)
534{
535}
914455e6 536
5440b88e 537void renderer_set_interlace(int enable, int is_odd)
538{
539}
540
9a6e7816 541#ifndef TEST
542
914455e6 543#include "../../frontend/plugin_lib.h"
544
545void renderer_set_config(const struct rearmed_cbs *cbs)
546{
89c0de42 547 force_interlace = cbs->gpu_unai.lineskip;
914455e6 548 enableAbbeyHack = cbs->gpu_unai.abe_hack;
549 light = !cbs->gpu_unai.no_light;
550 blend = !cbs->gpu_unai.no_blend;
9ee0fd5b 551
552 GPU_FrameBuffer = (u16 *)gpu.vram;
914455e6 553}
9a6e7816 554
555#endif
42a261f1 556
557// vim:shiftwidth=2:expandtab