1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef PSP_PIXEL_FORMAT_H
24 #define PSP_PIXEL_FORMAT_H
25 
26 #include "graphics/pixelformat.h"
27 #include "backends/platform/psp/trace.h"
28 
29 /**
30  *	Specialized PixelFormat class
31  *  Supports only those formats which the PSP allows, including 4 bit palettes.
32  *  Also provides accurate color conversion (needed for color masking)
33  *  As well as swapping of red and blue channels (needed by HE games, for example)
34  */
35 struct PSPPixelFormat {
36 	enum Type {
37 		Type_None,
38 		Type_4444,
39 		Type_5551,
40 		Type_5650,
41 		Type_8888,
42 		Type_Palette_8bit,
43 		Type_Palette_4bit,
44 		Type_Unknown
45 	};
46 
47 	Type format;
48 	uint32 bitsPerPixel;					///< Must match bpp of selected type
49 	bool swapRB;							///< Swap red and blue values when reading and writing
50 
PSPPixelFormatPSPPixelFormat51 	PSPPixelFormat() : format(Type_Unknown), bitsPerPixel(0), swapRB(false) {}
52 	void set(Type type, bool swap = false);
53 	static void convertFromScummvmPixelFormat(const Graphics::PixelFormat *pf,
54 	        PSPPixelFormat::Type &bufferType,
55 	        PSPPixelFormat::Type &paletteType,
56 	        bool &swapRedBlue);
57 	static Graphics::PixelFormat convertToScummvmPixelFormat(PSPPixelFormat::Type type);
58 	uint32 convertTo32BitColor(uint32 color) const;
59 
rgbaToColorPSPPixelFormat60 	inline uint32 rgbaToColor(uint32 r, uint32 g, uint32 b, uint32 a) const {
61 		uint32 color;
62 
63 		switch (format) {
64 		case Type_4444:
65 			color = (((b >> 4) << 8) | ((g >> 4) << 4) | ((r >> 4) << 0) | ((a >> 4) << 12));
66 			break;
67 		case Type_5551:
68 			color = (((b >> 3) << 10) | ((g >> 3) << 5) | ((r >> 3) << 0) | ((a >> 7) << 15));
69 			break;
70 		case Type_5650:
71 			color = (((b >> 3) << 11) | ((g >> 2) << 5) | ((r >> 3) << 0));
72 			break;
73 		case Type_8888:
74 			color = (((b >> 0) << 16) | ((g >> 0) << 8) | ((r >> 0) << 0) | ((a >> 0) << 24));
75 			break;
76 		default:
77 			color = 0;
78 			break;
79 		}
80 		return color;
81 	}
82 
colorToRgbaPSPPixelFormat83 	inline void colorToRgba(uint32 color, uint32 &r, uint32 &g, uint32 &b, uint32 &a) const {
84 		switch (format) {
85 		case Type_4444:
86 			a = (color >> 12) & 0xF; // Interpolate to get true colors
87 			b = (color >> 8)  & 0xF;
88 			g = (color >> 4)  & 0xF;
89 			r = (color >> 0)  & 0xF;
90 			a = a << 4 | a;
91 			b = b << 4 | b;
92 			g = g << 4 | g;
93 			r = r << 4 | r;
94 			break;
95 		case Type_5551:
96 			a = (color >> 15) ? 0xFF : 0;
97 			b = (color >> 10) & 0x1F;
98 			g = (color >> 5)  & 0x1F;
99 			r = (color >> 0)  & 0x1F;
100 			b = b << 3 | b >> 2;
101 			g = g << 3 | g >> 2;
102 			r = r << 3 | r >> 2;
103 			break;
104 		case Type_5650:
105 			a = 0xFF;
106 			b = (color >> 11) & 0x1F;
107 			g = (color >> 5)  & 0x3F;
108 			r = (color >> 0)  & 0x1F;
109 			b = b << 3 | b >> 2;
110 			g = g << 2 | g >> 4;
111 			r = r << 3 | r >> 2;
112 			break;
113 		case Type_8888:
114 			a = (color >> 24) & 0xFF;
115 			b = (color >> 16) & 0xFF;
116 			g = (color >> 8)  & 0xFF;
117 			r = (color >> 0)  & 0xFF;
118 			break;
119 		default:
120 			a = b = g = r = 0;
121 			break;
122 		}
123 	}
124 
setColorAlphaPSPPixelFormat125 	inline uint32 setColorAlpha(uint32 color, byte alpha) {
126 		switch (format) {
127 		case Type_4444:
128 			color = (color & 0x0FFF) | (((uint32)alpha >> 4) << 12);
129 			break;
130 		case Type_5551:
131 			color = (color & 0x7FFF) | (((uint32)alpha >> 7) << 15);
132 			break;
133 		case Type_8888:
134 			color = (color & 0x00FFFFFF) | ((uint32)alpha << 24);
135 			break;
136 		case Type_5650:
137 		default:
138 			break;
139 		}
140 		return color;
141 	}
142 
pixelsToBytesPSPPixelFormat143 	inline uint32 pixelsToBytes(uint32 pixels) const {
144 		switch (bitsPerPixel) {
145 		case 4:
146 			pixels >>= 1;
147 			break;
148 		case 16:
149 			pixels <<= 1;
150 			break;
151 		case 32:
152 			pixels <<= 2;
153 			break;
154 		case 8:
155 			break;
156 		default:
157 			PSP_ERROR("Incorrect bitsPerPixel value[%u]. pixels[%u]\n", bitsPerPixel, pixels);
158 			break;
159 		}
160 		return pixels;
161 	}
162 
swapRedBlue16PSPPixelFormat163 	inline uint16 swapRedBlue16(uint16 color) const {
164 		uint16 output;
165 
166 		switch (format) {
167 		case Type_4444:
168 			output = (color & 0xf0f0) | ((color & 0x000f) << 8)  | ((color & 0x0f00) >> 8);
169 			break;
170 		case Type_5551:
171 			output = (color & 0x83e0) | ((color & 0x001f) << 10) | ((color & 0x7c00) >> 10);
172 			break;
173 		case Type_5650:
174 			output = (color & 0x07e0) | ((color & 0x001f) << 11) | ((color & 0xf800) >> 11);
175 			break;
176 		default:
177 			PSP_ERROR("invalid format[%u] for swapping\n", format);
178 			output = 0;
179 			break;
180 		}
181 		return output;
182 	}
183 
swapRedBlue32PSPPixelFormat184 	inline uint32 swapRedBlue32(uint32 color) const {
185 		uint32 output;
186 
187 		switch (format) {
188 		case Type_4444:
189 			output = (color & 0xf0f0f0f0) |
190 			         ((color & 0x000f000f) << 8)  | ((color & 0x0f000f00) >> 8);
191 			break;
192 		case Type_5551:
193 			output = (color & 0x83e083e0) |
194 			         ((color & 0x001f001f) << 10) | ((color & 0x7c007c00) >> 10);
195 			break;
196 		case Type_5650:
197 			output = (color & 0x07e007e0) |
198 			         ((color & 0x001f001f) << 11) | ((color & 0xf800f800) >> 11);
199 			break;
200 		case Type_8888:
201 			output = (color & 0xff00ff00) |
202 			         ((color & 0x000000ff) << 16) | ((color & 0x00ff0000) >> 16);
203 			break;
204 		default:
205 			PSP_ERROR("invalid format[%u] for swapping\n", format);
206 			output = 0;
207 			break;
208 		}
209 
210 		return output;
211 	}
212 
213 	// Return whatever color we point at
getColorValueAtPSPPixelFormat214 	inline uint32 getColorValueAt(byte *pointer) const {
215 		uint32 result;
216 
217 		switch (bitsPerPixel) {
218 		case 4:	// We can't distinguish a 4 bit color with a pointer
219 		case 8:
220 			result = *pointer;
221 			break;
222 		case 16:
223 			result = *(uint16 *)pointer;
224 			break;
225 		case 32:
226 			result = *(uint32 *)pointer;
227 			break;
228 		default:
229 			result = 0;
230 			PSP_ERROR("Incorrect bitsPerPixel value[%u].\n", bitsPerPixel);
231 			break;
232 		}
233 		return result;
234 	}
235 };
236 
237 #endif /* PSP_PIXEL_FORMAT_H */
238