Merge branch 'gpu_unai_plugin_update'
[pcsx_rearmed.git] / plugins / gpu_unai / gpu_raster_sprite.h
1 /***************************************************************************
2 *   Copyright (C) 2010 PCSX4ALL Team                                      *
3 *   Copyright (C) 2010 Unai                                               *
4 *                                                                         *
5 *   This program is free software; you can redistribute it and/or modify  *
6 *   it under the terms of the GNU General Public License as published by  *
7 *   the Free Software Foundation; either version 2 of the License, or     *
8 *   (at your option) any later version.                                   *
9 *                                                                         *
10 *   This program is distributed in the hope that it will be useful,       *
11 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13 *   GNU General Public License for more details.                          *
14 *                                                                         *
15 *   You should have received a copy of the GNU General Public License     *
16 *   along with this program; if not, write to the                         *
17 *   Free Software Foundation, Inc.,                                       *
18 *   51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA.           *
19 ***************************************************************************/
20
21 ///////////////////////////////////////////////////////////////////////////////
22 //  GPU internal sprite drawing functions
23
24 void gpuDrawS(PtrUnion packet, const PS gpuSpriteSpanDriver)
25 {
26         s32 x0, x1, y0, y1;
27         u32 u0, v0;
28
29         //NOTE: Must 11-bit sign-extend the whole sum here, not just packet X/Y,
30         // or sprites in 1st level of SkullMonkeys disappear when walking right.
31         // This now matches behavior of Mednafen and PCSX Rearmed's gpu_neon:
32         x0 = GPU_EXPANDSIGN(packet.S2[2] + gpu_unai.DrawingOffset[0]);
33         y0 = GPU_EXPANDSIGN(packet.S2[3] + gpu_unai.DrawingOffset[1]);
34
35         u32 w = packet.U2[6] & 0x3ff; // Max width is 1023
36         u32 h = packet.U2[7] & 0x1ff; // Max height is 511
37         x1 = x0 + w;
38         y1 = y0 + h;
39
40         s32 xmin, xmax, ymin, ymax;
41         xmin = gpu_unai.DrawingArea[0]; xmax = gpu_unai.DrawingArea[2];
42         ymin = gpu_unai.DrawingArea[1]; ymax = gpu_unai.DrawingArea[3];
43
44         u0 = packet.U1[8];
45         v0 = packet.U1[9];
46
47         s32 temp;
48         temp = ymin - y0;
49         if (temp > 0) { y0 = ymin; v0 += temp; }
50         if (y1 > ymax) y1 = ymax;
51         if (y1 <= y0) return;
52
53         temp = xmin - x0;
54         if (temp > 0) { x0 = xmin; u0 += temp; }
55         if (x1 > xmax) x1 = xmax;
56         x1 -= x0;
57         if (x1 <= 0) return;
58
59         gpu_unai.r5 = packet.U1[0] >> 3;
60         gpu_unai.g5 = packet.U1[1] >> 3;
61         gpu_unai.b5 = packet.U1[2] >> 3;
62
63         u16 *Pixel = &((u16*)gpu_unai.vram)[FRAME_OFFSET(x0, y0)];
64         const int li=gpu_unai.ilace_mask;
65         const int pi=(ProgressiveInterlaceEnabled()?(gpu_unai.ilace_mask+1):0);
66         const int pif=(ProgressiveInterlaceEnabled()?(gpu_unai.prog_ilace_flag?(gpu_unai.ilace_mask+1):0):1);
67         unsigned int tmode = gpu_unai.TEXT_MODE >> 5;
68         const u32 v0_mask = gpu_unai.TextureWindow[3];
69         u8* pTxt_base = (u8*)gpu_unai.TBA;
70
71         // Texture is accessed byte-wise, so adjust idx if 16bpp
72         if (tmode == 3) u0 <<= 1;
73
74         for (; y0<y1; ++y0) {
75                 u8* pTxt = pTxt_base + ((v0 & v0_mask) * 2048);
76                 if (!(y0&li) && (y0&pi)!=pif)
77                         gpuSpriteSpanDriver(Pixel, x1, pTxt, u0);
78                 Pixel += FRAME_WIDTH;
79                 v0++;
80         }
81 }
82
83 #ifdef __arm__
84 #include "gpu_arm.h"
85
86 /* Notaz 4bit sprites optimization */
87 void gpuDrawS16(PtrUnion packet)
88 {
89         s32 x0, y0;
90         s32 u0, v0;
91         s32 xmin, xmax;
92         s32 ymin, ymax;
93         u32 h = 16;
94
95         //NOTE: Must 11-bit sign-extend the whole sum here, not just packet X/Y,
96         // or sprites in 1st level of SkullMonkeys disappear when walking right.
97         // This now matches behavior of Mednafen and PCSX Rearmed's gpu_neon:
98         x0 = GPU_EXPANDSIGN(packet.S2[2] + gpu_unai.DrawingOffset[0]);
99         y0 = GPU_EXPANDSIGN(packet.S2[3] + gpu_unai.DrawingOffset[1]);
100
101         xmin = gpu_unai.DrawingArea[0]; xmax = gpu_unai.DrawingArea[2];
102         ymin = gpu_unai.DrawingArea[1]; ymax = gpu_unai.DrawingArea[3];
103         u0 = packet.U1[8];
104         v0 = packet.U1[9];
105
106         if (x0 > xmax - 16 || x0 < xmin ||
107             ((u0 | v0) & 15) || !(gpu_unai.TextureWindow[2] & gpu_unai.TextureWindow[3] & 8)) {
108                 // send corner cases to general handler
109                 packet.U4[3] = 0x00100010;
110                 gpuDrawS(packet, gpuSpriteSpanFn<0x20>);
111                 return;
112         }
113
114         if (y0 >= ymax || y0 <= ymin - 16)
115                 return;
116         if (y0 < ymin) {
117                 h -= ymin - y0;
118                 v0 += ymin - y0;
119                 y0 = ymin;
120         }
121         else if (ymax - y0 < 16)
122                 h = ymax - y0;
123
124         draw_spr16_full(&gpu_unai.vram[FRAME_OFFSET(x0, y0)], &gpu_unai.TBA[FRAME_OFFSET(u0/4, v0)], gpu_unai.CBA, h);
125 }
126 #endif // __arm__
127
128 void gpuDrawT(PtrUnion packet, const PT gpuTileSpanDriver)
129 {
130         s32 x0, x1, y0, y1;
131
132         // This now matches behavior of Mednafen and PCSX Rearmed's gpu_neon:
133         x0 = GPU_EXPANDSIGN(packet.S2[2] + gpu_unai.DrawingOffset[0]);
134         y0 = GPU_EXPANDSIGN(packet.S2[3] + gpu_unai.DrawingOffset[1]);
135
136         u32 w = packet.U2[4] & 0x3ff; // Max width is 1023
137         u32 h = packet.U2[5] & 0x1ff; // Max height is 511
138         x1 = x0 + w;
139         y1 = y0 + h;
140
141         s32 xmin, xmax, ymin, ymax;
142         xmin = gpu_unai.DrawingArea[0]; xmax = gpu_unai.DrawingArea[2];
143         ymin = gpu_unai.DrawingArea[1]; ymax = gpu_unai.DrawingArea[3];
144
145         if (y0 < ymin) y0 = ymin;
146         if (y1 > ymax) y1 = ymax;
147         if (y1 <= y0) return;
148
149         if (x0 < xmin) x0 = xmin;
150         if (x1 > xmax) x1 = xmax;
151         x1 -= x0;
152         if (x1 <= 0) return;
153
154         const u16 Data = GPU_RGB16(packet.U4[0]);
155         u16 *Pixel = &((u16*)gpu_unai.vram)[FRAME_OFFSET(x0, y0)];
156         const int li=gpu_unai.ilace_mask;
157         const int pi=(ProgressiveInterlaceEnabled()?(gpu_unai.ilace_mask+1):0);
158         const int pif=(ProgressiveInterlaceEnabled()?(gpu_unai.prog_ilace_flag?(gpu_unai.ilace_mask+1):0):1);
159
160         for (; y0<y1; ++y0) {
161                 if (!(y0&li) && (y0&pi)!=pif)
162                         gpuTileSpanDriver(Pixel,x1,Data);
163                 Pixel += FRAME_WIDTH;
164         }
165 }