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 #include "common/scummsys.h"
24 #include "backends/platform/psp/psppixelformat.h"
25 #include "backends/platform/psp/display_client.h"
26 #include "backends/platform/psp/default_display_client.h"
27 #include "backends/platform/psp/cursor.h"
28
29 //#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */
30 //#define __PSP_DEBUG_PRINT__
31
32 #include "backends/platform/psp/trace.h"
33
init()34 void Cursor::init() {
35 DEBUG_ENTER_FUNC();
36
37 _renderer.setBuffer(&_buffer); // We do this explicitly
38 _renderer.setPalette(&_screenPalette); // because we want to choose screenpalette by default
39 _renderer.setUseGlobalScaler(true);
40 setRendererModePalettized(true); // Assume we start in 8bit mode
41
42 // Default modes
43 _palette.setPixelFormats(PSPPixelFormat::Type_5551, PSPPixelFormat::Type_Palette_8bit); // default
44 _screenPalette.setPixelFormats(PSPPixelFormat::Type_5551, PSPPixelFormat::Type_Palette_8bit);
45 _buffer.setPixelFormat(PSPPixelFormat::Type_5551);
46 }
47
deallocate()48 void Cursor::deallocate() {
49 DEBUG_ENTER_FUNC();
50
51 _buffer.deallocate();
52 _palette.deallocate();
53 _screenPalette.deallocate();
54 }
55
setCursorPalette(const byte * colors,uint start,uint num)56 void Cursor::setCursorPalette(const byte *colors, uint start, uint num) {
57 DEBUG_ENTER_FUNC();
58
59 if (!_palette.isAllocated()) {
60 _palette.allocate();
61 }
62
63 // Workaround: This is wrong, but we seem to not be getting setScreenPalette
64 if (!_screenPalette.isAllocated()) {
65 _screenPalette.allocate();
66 }
67
68 _palette.setPartial(colors, start, num);
69 setDirty();
70 }
71
setScreenPalette(const byte * colors,uint start,uint num)72 void Cursor::setScreenPalette(const byte *colors, uint start, uint num) {
73 DEBUG_ENTER_FUNC();
74
75 if (!_screenPalette.isAllocated()) {
76 _screenPalette.allocate();
77 }
78
79 _screenPalette.setPartial(colors, start, num);
80 setDirty();
81 }
82
setKeyColor(uint32 color)83 void Cursor::setKeyColor(uint32 color) {
84 DEBUG_ENTER_FUNC();
85 PSP_DEBUG_PRINT("new color[%u], old color[%u]\n", color, _keyColor);
86
87 // If it's a different color, undo the last keycolor
88 if (_buffer.hasPalette() && color != _keyColor) {
89 if (_screenPalette.isAllocated())
90 _screenPalette.setColorPositionAlpha(_keyColor, true);
91 if (_palette.isAllocated())
92 _palette.setColorPositionAlpha(_keyColor, true);
93 }
94 // Don't need anything special for 16-bit
95 _keyColor = color;
96 }
97
clearKeyColor()98 void Cursor::clearKeyColor() {
99 DEBUG_ENTER_FUNC();
100 PSP_DEBUG_PRINT("keyColor[%d]\n", _keyColor);
101
102 // We need 2 mechanisms: one for palettized and one for 16 bit
103 if (_buffer.hasPalette()) {
104 if (_screenPalette.isAllocated())
105 _screenPalette.setColorPositionAlpha(_keyColor, false); // set keycolor to 0
106 if (_palette.isAllocated())
107 _palette.setColorPositionAlpha(_keyColor, false);
108 } else { // 16bit
109 _renderer.setKeyColor(_keyColor);
110 }
111 setDirty();
112 }
113
enableCursorPalette(bool enable)114 void Cursor::enableCursorPalette(bool enable) {
115 DEBUG_ENTER_FUNC();
116 PSP_DEBUG_PRINT("enable[%s]\n", enable ? "true" : "false");
117
118 _useCursorPalette = enable;
119 if (enable)
120 _renderer.setPalette(&_palette); // very important that we do this switch
121 else
122 _renderer.setPalette(&_screenPalette);
123
124 setDirty();
125 }
126
setSize(uint32 width,uint32 height)127 inline void Cursor::setSize(uint32 width, uint32 height) {
128 DEBUG_ENTER_FUNC();
129 PSP_DEBUG_PRINT("width[%u], height[%u]\n", width, height);
130
131 _buffer.setSize(width, height, Buffer::kSizeByTextureSize); // we'll use texture size for mouse
132 _renderer.setDrawWholeBuffer(); // We need to let the renderer know how much to draw
133 }
134
copyFromArray(const byte * array)135 void Cursor::copyFromArray(const byte *array) {
136 DEBUG_ENTER_FUNC();
137
138 if (!_buffer.isAllocated()) {
139 _buffer.allocate();
140 }
141
142 _buffer.copyFromArray(array, _buffer.getSourceWidthInBytes()); // pitch is source width
143 setDirty();
144
145 // debug
146 //PSP_DEBUG_DO(_buffer.print(0xF));
147 }
148
setHotspot(int32 x,int32 y)149 void Cursor::setHotspot(int32 x, int32 y) {
150 DEBUG_ENTER_FUNC();
151
152 _hotspotX = x;
153 _hotspotY = y;
154 updateRendererOffset(); // Important
155
156 PSP_DEBUG_PRINT("hotspotX[%d], hotspotY[%d]\n", x, y);
157 }
158
159 // Returns true if change in x or y
increaseXY(int32 incX,int32 incY)160 bool Cursor::increaseXY(int32 incX, int32 incY) {
161 DEBUG_ENTER_FUNC();
162
163 int32 oldX = _x, oldY = _y;
164
165 // adjust for screen resolution
166 adjustXYForScreenSize(incX, incY);
167
168 _x += incX;
169 _y += incY;
170
171 // Clamp mouse
172 if (_x < 0)
173 _x = 0;
174 if (_y < 0)
175 _y = 0;
176 if (_x >= (int)_mouseLimitWidth)
177 _x = (int)_mouseLimitWidth - 1;
178 if (_y >= (int)_mouseLimitHeight)
179 _y = (int)_mouseLimitHeight - 1;
180
181 PSP_DEBUG_PRINT("X[%d], Y[%d]\n", _x, _y);
182
183 if (oldX != _x || oldY != _y) {
184 updateRendererOffset();
185 setDirty();
186 return true;
187 }
188
189 return false;
190 }
191
192 // Set limits on the movement of the cursor ie. screen size
setLimits(uint32 width,uint32 height)193 void Cursor::setLimits(uint32 width, uint32 height) {
194 #define PSP_SCREEN_WIDTH 480
195 #define PSP_SCREEN_HEIGHT 272
196 DEBUG_ENTER_FUNC();
197
198 PSP_DEBUG_PRINT("width[%u], height[%u]\n", width, height);
199 _mouseLimitWidth = width;
200 _mouseLimitHeight = height;
201 }
202
203 // Adjust X,Y movement for the screen size to keep it consistent
adjustXYForScreenSize(int32 & x,int32 & y)204 inline void Cursor::adjustXYForScreenSize(int32 &x, int32 &y) {
205 DEBUG_ENTER_FUNC();
206 // We have our speed calibrated for the y axis at 480x272. The idea is to adjust this for other
207 // resolutions
208 int32 newX = x, newY = y;
209
210 if (_mouseLimitWidth >= 600) { // multiply by 2
211 newX *= 2;
212 newY *= 2;
213 } else if (_mouseLimitWidth >= 480) { // multiply by 1.5
214 newX = newX + (newX / 2);
215 newY = newY + (newY / 2);
216 }
217 }
218
219 // This is only called when we have a new screen
setScreenPaletteScummvmPixelFormat(const Graphics::PixelFormat * format)220 void Cursor::setScreenPaletteScummvmPixelFormat(const Graphics::PixelFormat *format) {
221 DEBUG_ENTER_FUNC();
222
223 PSPPixelFormat::Type bufferType = PSPPixelFormat::Type_Unknown;
224 PSPPixelFormat::Type paletteType = PSPPixelFormat::Type_Unknown;
225 bool swapRedBlue = false;
226
227 // Convert Scummvm Pixel Format to PSPPixelFormat
228 PSPPixelFormat::convertFromScummvmPixelFormat(format, bufferType, paletteType, swapRedBlue);
229
230 if (paletteType == PSPPixelFormat::Type_None) {
231 //_screenPalette.deallocate(); // leave palette for default CLUT8
232 setRendererModePalettized(false); // use 16-bit mechanism
233 } else { // We have a palette
234 _screenPalette.setPixelFormats(paletteType, bufferType);
235 _palette.setPixelFormats(paletteType, bufferType);
236 setRendererModePalettized(true); // use palettized mechanism
237 }
238 }
239
240 // This is called many many times
setSizeAndScummvmPixelFormat(uint32 width,uint32 height,const Graphics::PixelFormat * format)241 void Cursor::setSizeAndScummvmPixelFormat(uint32 width, uint32 height, const Graphics::PixelFormat *format) {
242 DEBUG_ENTER_FUNC();
243
244 PSP_DEBUG_PRINT("useCursorPalette[%s]\n", _useCursorPalette ? "true" : "false");
245
246 uint32 oldBufferSize = 0;
247
248 if (_buffer.isAllocated())
249 oldBufferSize = _buffer.getSizeInBytes();
250
251 setSize(width, height);
252
253 PSPPixelFormat::Type bufferType = PSPPixelFormat::Type_Unknown;
254 PSPPixelFormat::Type paletteType = PSPPixelFormat::Type_Unknown;
255 bool swapRedBlue = false;
256
257 PSPPixelFormat::convertFromScummvmPixelFormat(format, bufferType, paletteType, swapRedBlue);
258 PSP_DEBUG_PRINT("bufferType[%u], paletteType[%u]\n", bufferType, paletteType);
259
260 // Check if we need to set new pixel format
261 if (_buffer.getPixelFormat() != bufferType) {
262 PSP_DEBUG_PRINT("new buffer pixel format[%u] is different from [%u]. Setting it.\n", bufferType, _buffer.getPixelFormat());
263 _buffer.setPixelFormat(bufferType);
264 }
265
266 // Check if we need to reallocate
267 if (_buffer.getSizeInBytes() != oldBufferSize) {
268 _buffer.allocate();
269 PSP_DEBUG_PRINT("reallocating buffer. new size: width[%u], height[%u]\n", width, height);
270 }
271
272 PSP_DEBUG_PRINT("palette pixel format[%u]\n", paletteType);
273
274 if (paletteType == PSPPixelFormat::Type_None) {
275 setRendererModePalettized(false); // use palettized mechanism
276 } else { // We have a palette
277 _palette.setPixelFormats(paletteType, bufferType);
278 setRendererModePalettized(true); // use palettized mechanism
279 }
280
281 // debug
282 // PSP_DEBUG_DO(_palette.print(10));
283 // PSP_DEBUG_DO(_screenPalette.print(10));
284 }
285
setXY(int x,int y)286 void Cursor::setXY(int x, int y) {
287 DEBUG_ENTER_FUNC();
288
289 _x = x;
290 _y = y;
291 updateRendererOffset(); // Very important to let renderer know things changed
292 setDirty();
293 }
294
updateRendererOffset()295 inline void Cursor::updateRendererOffset() {
296 DEBUG_ENTER_FUNC();
297 _renderer.setOffsetOnScreen(_x - _hotspotX, _y - _hotspotY);
298 }
299
setRendererModePalettized(bool palettized)300 inline void Cursor::setRendererModePalettized(bool palettized) {
301 if (palettized) { // We have a palette. Use blending
302 _renderer.setAlphaBlending(true);
303 _renderer.setAlphaReverse(false);
304 _renderer.setColorTest(false);
305 } else { // 16 bits, no palette
306 // Color test is an easy way for the hardware to make our keycolor
307 // transparent.
308 _renderer.setColorTest(true);
309
310 // Alpha blending is not strictly required, but makes the cursor look
311 // much better
312 _renderer.setAlphaBlending(true);
313
314 // Pixel formats without alpha (5650) are considered to have their alpha set.
315 // Since pixel formats with alpha don't have their alpha bits set, we reverse
316 // the alpha format for them so that 0 alpha is 1.
317 if (_buffer.getPixelFormat() != PSPPixelFormat::Type_5650)
318 _renderer.setAlphaReverse(true);
319 else
320 _renderer.setAlphaReverse(false);
321 }
322 }
323