scummvm/backends/platform/psp/cursor.cpp
2021-12-26 18:48:43 +01:00

328 lines
9.6 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/scummsys.h"
#include "backends/platform/psp/psppixelformat.h"
#include "backends/platform/psp/display_client.h"
#include "backends/platform/psp/default_display_client.h"
#include "backends/platform/psp/cursor.h"
//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */
//#define __PSP_DEBUG_PRINT__
#include "backends/platform/psp/trace.h"
void Cursor::init() {
DEBUG_ENTER_FUNC();
_renderer.setBuffer(&_buffer); // We do this explicitly
_renderer.setPalette(&_screenPalette); // because we want to choose screenpalette by default
_renderer.setUseGlobalScaler(true);
setRendererModePalettized(true); // Assume we start in 8bit mode
// Default modes
_palette.setPixelFormats(PSPPixelFormat::Type_5551, PSPPixelFormat::Type_Palette_8bit); // default
_screenPalette.setPixelFormats(PSPPixelFormat::Type_5551, PSPPixelFormat::Type_Palette_8bit);
_buffer.setPixelFormat(PSPPixelFormat::Type_5551);
}
void Cursor::deallocate() {
DEBUG_ENTER_FUNC();
_buffer.deallocate();
_palette.deallocate();
_screenPalette.deallocate();
}
void Cursor::setCursorPalette(const byte *colors, uint start, uint num) {
DEBUG_ENTER_FUNC();
if (!_palette.isAllocated()) {
_palette.allocate();
}
// Workaround: This is wrong, but we seem to not be getting setScreenPalette
if (!_screenPalette.isAllocated()) {
_screenPalette.allocate();
}
_palette.setPartial(colors, start, num);
setDirty();
}
void Cursor::setScreenPalette(const byte *colors, uint start, uint num) {
DEBUG_ENTER_FUNC();
if (!_screenPalette.isAllocated()) {
_screenPalette.allocate();
}
_screenPalette.setPartial(colors, start, num);
setDirty();
}
void Cursor::setKeyColor(uint32 color) {
DEBUG_ENTER_FUNC();
PSP_DEBUG_PRINT("new color[%u], old color[%u]\n", color, _keyColor);
// If it's a different color, undo the last keycolor
if (_buffer.hasPalette() && color != _keyColor) {
if (_screenPalette.isAllocated())
_screenPalette.setColorPositionAlpha(_keyColor, true);
if (_palette.isAllocated())
_palette.setColorPositionAlpha(_keyColor, true);
}
// Don't need anything special for 16-bit
_keyColor = color;
}
void Cursor::clearKeyColor() {
DEBUG_ENTER_FUNC();
PSP_DEBUG_PRINT("keyColor[%d]\n", _keyColor);
// We need 2 mechanisms: one for palettized and one for 16 bit
if (_buffer.hasPalette()) {
if (_screenPalette.isAllocated())
_screenPalette.setColorPositionAlpha(_keyColor, false); // set keycolor to 0
if (_palette.isAllocated())
_palette.setColorPositionAlpha(_keyColor, false);
} else { // 16bit
_renderer.setKeyColor(_keyColor);
}
setDirty();
}
void Cursor::enableCursorPalette(bool enable) {
DEBUG_ENTER_FUNC();
PSP_DEBUG_PRINT("enable[%s]\n", enable ? "true" : "false");
_useCursorPalette = enable;
if (enable)
_renderer.setPalette(&_palette); // very important that we do this switch
else
_renderer.setPalette(&_screenPalette);
setDirty();
}
inline void Cursor::setSize(uint32 width, uint32 height) {
DEBUG_ENTER_FUNC();
PSP_DEBUG_PRINT("width[%u], height[%u]\n", width, height);
_buffer.setSize(width, height, Buffer::kSizeByTextureSize); // we'll use texture size for mouse
_renderer.setDrawWholeBuffer(); // We need to let the renderer know how much to draw
}
void Cursor::copyFromArray(const byte *array) {
DEBUG_ENTER_FUNC();
if (!_buffer.isAllocated()) {
_buffer.allocate();
}
_buffer.copyFromArray(array, _buffer.getSourceWidthInBytes()); // pitch is source width
setDirty();
// debug
//PSP_DEBUG_DO(_buffer.print(0xF));
}
void Cursor::setHotspot(int32 x, int32 y) {
DEBUG_ENTER_FUNC();
_hotspotX = x;
_hotspotY = y;
updateRendererOffset(); // Important
PSP_DEBUG_PRINT("hotspotX[%d], hotspotY[%d]\n", x, y);
}
// Returns true if change in x or y
bool Cursor::increaseXY(int32 incX, int32 incY) {
DEBUG_ENTER_FUNC();
int32 oldX = _x, oldY = _y;
// adjust for screen resolution
adjustXYForScreenSize(incX, incY);
_x += incX;
_y += incY;
// Clamp mouse
if (_x < 0)
_x = 0;
if (_y < 0)
_y = 0;
if (_x >= (int)_mouseLimitWidth)
_x = (int)_mouseLimitWidth - 1;
if (_y >= (int)_mouseLimitHeight)
_y = (int)_mouseLimitHeight - 1;
PSP_DEBUG_PRINT("X[%d], Y[%d]\n", _x, _y);
if (oldX != _x || oldY != _y) {
updateRendererOffset();
setDirty();
return true;
}
return false;
}
// Set limits on the movement of the cursor ie. screen size
void Cursor::setLimits(uint32 width, uint32 height) {
#define PSP_SCREEN_WIDTH 480
#define PSP_SCREEN_HEIGHT 272
DEBUG_ENTER_FUNC();
PSP_DEBUG_PRINT("width[%u], height[%u]\n", width, height);
_mouseLimitWidth = width;
_mouseLimitHeight = height;
}
// Adjust X,Y movement for the screen size to keep it consistent
inline void Cursor::adjustXYForScreenSize(int32 &x, int32 &y) {
DEBUG_ENTER_FUNC();
// We have our speed calibrated for the y axis at 480x272. The idea is to adjust this for other
// resolutions
int32 newX = x, newY = y;
if (_mouseLimitWidth >= 600) { // multiply by 2
newX *= 2;
newY *= 2;
} else if (_mouseLimitWidth >= 480) { // multiply by 1.5
newX = newX + (newX / 2);
newY = newY + (newY / 2);
}
}
// This is only called when we have a new screen
void Cursor::setScreenPaletteScummvmPixelFormat(const Graphics::PixelFormat *format) {
DEBUG_ENTER_FUNC();
PSPPixelFormat::Type bufferType = PSPPixelFormat::Type_Unknown;
PSPPixelFormat::Type paletteType = PSPPixelFormat::Type_Unknown;
bool swapRedBlue = false;
// Convert Scummvm Pixel Format to PSPPixelFormat
PSPPixelFormat::convertFromScummvmPixelFormat(format, bufferType, paletteType, swapRedBlue);
if (paletteType == PSPPixelFormat::Type_None) {
//_screenPalette.deallocate(); // leave palette for default CLUT8
setRendererModePalettized(false); // use 16-bit mechanism
} else { // We have a palette
_screenPalette.setPixelFormats(paletteType, bufferType);
_palette.setPixelFormats(paletteType, bufferType);
setRendererModePalettized(true); // use palettized mechanism
}
}
// This is called many many times
void Cursor::setSizeAndScummvmPixelFormat(uint32 width, uint32 height, const Graphics::PixelFormat *format) {
DEBUG_ENTER_FUNC();
PSP_DEBUG_PRINT("useCursorPalette[%s]\n", _useCursorPalette ? "true" : "false");
uint32 oldBufferSize = 0;
if (_buffer.isAllocated())
oldBufferSize = _buffer.getSizeInBytes();
setSize(width, height);
PSPPixelFormat::Type bufferType = PSPPixelFormat::Type_Unknown;
PSPPixelFormat::Type paletteType = PSPPixelFormat::Type_Unknown;
bool swapRedBlue = false;
PSPPixelFormat::convertFromScummvmPixelFormat(format, bufferType, paletteType, swapRedBlue);
PSP_DEBUG_PRINT("bufferType[%u], paletteType[%u]\n", bufferType, paletteType);
// Check if we need to set new pixel format
if (_buffer.getPixelFormat() != bufferType) {
PSP_DEBUG_PRINT("new buffer pixel format[%u] is different from [%u]. Setting it.\n", bufferType, _buffer.getPixelFormat());
_buffer.setPixelFormat(bufferType);
}
// Check if we need to reallocate
if (_buffer.getSizeInBytes() != oldBufferSize) {
_buffer.allocate();
PSP_DEBUG_PRINT("reallocating buffer. new size: width[%u], height[%u]\n", width, height);
}
PSP_DEBUG_PRINT("palette pixel format[%u]\n", paletteType);
if (paletteType == PSPPixelFormat::Type_None) {
setRendererModePalettized(false); // use non-palettized mechanism
if (format) {
if (format->aBits() == 0)
_fakeAlpha = true; // we are treating e.g. 555 as 5551
else
_fakeAlpha = false; // we have a genuine alpha channel
}
} else { // We have a palette
_palette.setPixelFormats(paletteType, bufferType);
setRendererModePalettized(true); // use palettized mechanism
}
// debug
// PSP_DEBUG_DO(_palette.print(10));
// PSP_DEBUG_DO(_screenPalette.print(10));
}
void Cursor::setXY(int x, int y) {
DEBUG_ENTER_FUNC();
_x = x;
_y = y;
updateRendererOffset(); // Very important to let renderer know things changed
setDirty();
}
inline void Cursor::updateRendererOffset() {
DEBUG_ENTER_FUNC();
_renderer.setOffsetOnScreen(_x - _hotspotX, _y - _hotspotY);
}
inline void Cursor::setRendererModePalettized(bool palettized) {
if (palettized) { // We have a palette. Use blending
_renderer.setAlphaBlending(true);
_renderer.setAlphaReverse(false);
_renderer.setColorTest(false);
} else { // 16 bits, no palette
// Color test is an easy way for the hardware to make our keycolor
// transparent.
_renderer.setColorTest(true);
// Alpha blending is not strictly required, but makes the cursor look
// much better
_renderer.setAlphaBlending(true);
// Pixel formats without alpha (5650) are considered to have their alpha set.
// Since pixel formats like 555 are treated as 5551 on PSP, we reverse
// the alpha format for them so that 0 alpha is 1.
if (_buffer.getPixelFormat() != PSPPixelFormat::Type_5650 && _fakeAlpha)
_renderer.setAlphaReverse(true);
else
_renderer.setAlphaReverse(false);
}
}