diff options
Diffstat (limited to 'backends/platform')
27 files changed, 4315 insertions, 1520 deletions
diff --git a/backends/platform/psp/Makefile b/backends/platform/psp/Makefile index f5d6a16c7e..cf1eb1611e 100644 --- a/backends/platform/psp/Makefile +++ b/backends/platform/psp/Makefile @@ -66,7 +66,7 @@ endif #CC = psp-gcc CXX = psp-g++ CXXFLAGS = -O3 -Wall -Wno-multichar -fno-exceptions -fno-rtti -DEFINES = -D__PSP__ -DNONSTANDARD_PORT -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DUSE_ZLIB -DDISABLE_DOSBOX_OPL +DEFINES = -D__PSP__ -DNONSTANDARD_PORT -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DUSE_ZLIB -DDISABLE_DOSBOX_OPL -DUSE_RGB_COLOR LDFLAGS := INCDIR := $(srcdir) . $(srcdir)/engines/ $(PSPSDK)/include INCLUDES := $(addprefix -I, $(INCDIR)) @@ -133,6 +133,13 @@ LIBS += -lpng -lSDL -lz $(findstring -lGL,$(SDLLIBS)) -lstdc++ -lc -lm $(fil OBJS := powerman.o \ psp_main.o \ osys_psp.o \ + psppixelformat.o \ + memory.o \ + display_manager.o \ + display_client.o \ + default_display_client.o \ + input.o \ + cursor.o \ trace.o \ psploader.o \ pspkeyboard.o diff --git a/backends/platform/psp/README.PSP.in b/backends/platform/psp/README.PSP.in index bd1ce88fb6..d9f75974f1 100644 --- a/backends/platform/psp/README.PSP.in +++ b/backends/platform/psp/README.PSP.in @@ -16,12 +16,13 @@ Left trigger - ESC Right trigger - Modifier key (see below for uses) Analog - Mouse movement Right trigger + Analog - Fine control mouse -Directionals - Mouse movement +Directions - Arrow keys +Directions + Right Trigger - Diagonal arrow keys Triangle - Enter Cross - Mouse button 1 Circle - Mouse button 2 Square - '.' (skip dialogue in some games) -Start - F5 +Start - F5 (Main Menu) Right trigger + Start - Return-To-Launcher menu Virtual Keyboard diff --git a/backends/platform/psp/cursor.cpp b/backends/platform/psp/cursor.cpp new file mode 100644 index 0000000000..b6b9a70458 --- /dev/null +++ b/backends/platform/psp/cursor.cpp @@ -0,0 +1,365 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.h $ + * $Id: osys_psp.h 46120 2009-11-24 10:33:30Z Bluddy $ + * + */ + +#include "common/scummsys.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); + + DEBUG_EXIT_FUNC(); +} + +void Cursor::deallocate() { + DEBUG_ENTER_FUNC(); + + _buffer.deallocate(); + _palette.deallocate(); + _screenPalette.deallocate(); + + DEBUG_EXIT_FUNC(); +} + +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(); + + DEBUG_EXIT_FUNC(); +} + +void Cursor::setScreenPalette(const byte *colors, uint start, uint num) { + DEBUG_ENTER_FUNC(); + + if (!_screenPalette.isAllocated()) { + _screenPalette.allocate(); + } + + _screenPalette.setPartial(colors, start, num); + setDirty(); + + DEBUG_EXIT_FUNC(); +} + +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; + + DEBUG_EXIT_FUNC(); +} + +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(); + + DEBUG_EXIT_FUNC(); +} + +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(); + DEBUG_EXIT_FUNC(); +} + +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 + + DEBUG_EXIT_FUNC(); +} + +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)); + + DEBUG_EXIT_FUNC(); + +} + +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); + DEBUG_EXIT_FUNC(); +} + +// 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 differences in X and Y + 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(); + DEBUG_EXIT_FUNC(); + return true; + } + + DEBUG_EXIT_FUNC(); + 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; + + DEBUG_EXIT_FUNC(); +} + +// 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 and for x, which is wider. + int32 newX = x, newY = y; + + // adjust width movement to match height (usually around 1.5) + if (_mouseLimitWidth >= _mouseLimitHeight + (_mouseLimitHeight >> 1)) + newX = newX + (newX >> 1); + + if (_mouseLimitWidth >= 600) { // multiply by 2 + newX <<= 1; + newY <<= 1; + } else if (_mouseLimitWidth >= 480) { // multiply by 1.5 + newX = newX + (newX >> 1); + newY = newY + (newY >> 1); + } + + // Divide all movements by 8 + newX >>= 3; + newY >>= 3; + + // Make sure we didn't destroy minimum movement + if (!((x && !newX) || (y && !newY))) { + x = newX; + y = newY; + } + + DEBUG_EXIT_FUNC(); +} + +// This is only called when we have a new screen +void Cursor::setScreenPaletteScummvmPixelFormat(const Graphics::PixelFormat *format) { + DEBUG_ENTER_FUNC(); + + uint32 oldPaletteSize = 0; + if (_screenPalette.isAllocated()) + oldPaletteSize = _screenPalette.getSizeInBytes(); + + 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 + } + + DEBUG_EXIT_FUNC(); +} + +// 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, oldPaletteSize = 0; + + if (_buffer.isAllocated()) + oldBufferSize = _buffer.getSizeInBytes(); + + if (_palette.isAllocated()) + oldPaletteSize = _palette.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 palettized mechanism + } 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)); + + DEBUG_EXIT_FUNC(); +} + +void Cursor::setXY(int x, int y) { + DEBUG_ENTER_FUNC(); + + _x = x; + _y = y; + updateRendererOffset(); // Very important to let renderer know things changed + setDirty(); + + DEBUG_EXIT_FUNC(); +} + +inline void Cursor::updateRendererOffset() { + DEBUG_ENTER_FUNC(); + _renderer.setOffsetOnScreen(_x - _hotspotX, _y - _hotspotY); + DEBUG_EXIT_FUNC(); +} + +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 + _renderer.setAlphaBlending(true); + _renderer.setAlphaReverse(true); // We can't change all alpha values, so just reverse + _renderer.setColorTest(true); // Color test to make our key color transparent + } +} diff --git a/backends/platform/psp/cursor.h b/backends/platform/psp/cursor.h new file mode 100644 index 0000000000..49f58cd3f9 --- /dev/null +++ b/backends/platform/psp/cursor.h @@ -0,0 +1,81 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.h $ + * $Id: osys_psp.h 46120 2009-11-24 10:33:30Z Bluddy $ + * + */ + +#ifndef MOUSE_H +#define MOUSE_H + +class Cursor : public DefaultDisplayClient { +private: + int _hotspotX, _hotspotY; + uint32 _keyColor; + int _cursorTargetScale; + bool _useCursorPalette; + bool _hasCursorPalette; + uint32 _mouseLimitWidth; + uint32 _mouseLimitHeight; + int32 _x, _y; + Palette _screenPalette; // separate palette for screen. default 'palette' is cursor palette. + + void updateRendererOffset(); + +public: + Cursor() : _hotspotX(0), _hotspotY(0), _keyColor(0), _cursorTargetScale(0), + _useCursorPalette(false), _hasCursorPalette(false), _mouseLimitWidth(0), + _mouseLimitHeight(0), _x(0), _y(0) { } + virtual ~Cursor() { deallocate(); } + + void setKeyColor(uint32 color); + void setCursorTargetScale(int scale) { _cursorTargetScale = scale; } + void setScreenPalette(const byte *colors, uint start, uint num); + void copyFromArray(const byte *array); + Palette &palette() { return _palette; } + Buffer &buffer() { return _buffer; } + void setCursorPalette(const byte *colors, uint start, uint num); + void enableCursorPalette(bool enable); + void setLimits(uint32 width, uint32 height); + void setXY(int x, int y); + int32 getX() { return _x; } + int32 getY() { return _y; } + bool increaseXY(int32 incX, int32 incY); // returns true if there's a change in x or y + void adjustXYForScreenSize(int32 &x, int32 &y); + void init(); + void setHotspot(int32 x, int32 y); + void setScreenPaletteScummvmPixelFormat(const Graphics::PixelFormat *format); + void setSizeAndScummvmPixelFormat(uint32 widht, uint32 height, const Graphics::PixelFormat *format); + void clearKeyColor(); + void useGlobalScaler(bool val) { _renderer.setUseGlobalScaler(val); } + bool allocate(); + void deallocate(); + +private: + void setSize(uint32 width, uint32 height); + void getPixelFormatsFromScummvmPixelFormat(const Graphics::PixelFormat *format, + PSPPixelFormat::Type &bufferFormat, + PSPPixelFormat::Type &paletteFormat, + uint32 &numOfEntries); + void setRendererModePalettized(bool palettized); +}; + +#endif /* MOUSE_H */ diff --git a/backends/platform/psp/default_display_client.cpp b/backends/platform/psp/default_display_client.cpp new file mode 100644 index 0000000000..eb20980315 --- /dev/null +++ b/backends/platform/psp/default_display_client.cpp @@ -0,0 +1,238 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.h $ + * $Id: osys_psp.h 46120 2009-11-24 10:33:30Z Bluddy $ + * + */ + +#include "common/scummsys.h" +#include "backends/platform/psp/display_client.h" +#include "backends/platform/psp/default_display_client.h" + +//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ +//#define __PSP_DEBUG_PRINT__ + +#include "backends/platform/psp/trace.h" + +// Class DefaultDisplayClient --------------------------------------------- + +bool DefaultDisplayClient::allocate(bool bufferInVram /* = false */, bool paletteInVram /* = false */) { + DEBUG_ENTER_FUNC(); + + if (!_buffer.allocate(bufferInVram)) { + PSP_ERROR("Couldn't allocate buffer.\n"); + DEBUG_EXIT_FUNC(); + return false; + } + + if (_buffer.hasPalette()) + { + PSP_DEBUG_PRINT("_palette[%p]\n", &_palette); + + if (!_palette.allocate()) { + PSP_ERROR("Couldn't allocate pallette.\n"); + DEBUG_EXIT_FUNC(); + return false; + } + } + + DEBUG_EXIT_FUNC(); + return true; +} + +void DefaultDisplayClient::deallocate() { + _buffer.deallocate(); + if (_buffer.hasPalette()) + _palette.deallocate(); +} + + +void DefaultDisplayClient::clearBuffer() { + DEBUG_ENTER_FUNC(); + _buffer.clear(); + setDirty(); + DEBUG_EXIT_FUNC(); +} + +inline void DefaultDisplayClient::clearPalette() { + DEBUG_ENTER_FUNC(); + _palette.clear(); + setDirty(); + DEBUG_EXIT_FUNC(); +} + +void DefaultDisplayClient::init() { + DEBUG_ENTER_FUNC(); + _renderer.setBuffer(&_buffer); + _renderer.setPalette(&_palette); + DEBUG_EXIT_FUNC(); +} + +void DefaultDisplayClient::copyFromRect(const byte *buf, int pitch, int destX, int destY, int recWidth, int recHeight) { + DEBUG_ENTER_FUNC(); + _buffer.copyFromRect(buf, pitch, destX, destY, recWidth, recHeight); + setDirty(); + DEBUG_EXIT_FUNC(); +} + +void DefaultDisplayClient::copyToArray(byte *dst, int pitch) { + DEBUG_ENTER_FUNC(); + _buffer.copyToArray(dst, pitch); + DEBUG_EXIT_FUNC(); +} + +// Class Overlay ------------------------------------------------------- + +void Overlay::init() { + DEBUG_ENTER_FUNC(); + + DefaultDisplayClient::init(); + _renderer.setAlphaBlending(true); + _renderer.setColorTest(false); + _renderer.setUseGlobalScaler(false); + _renderer.setFullScreen(true); // speeds up render slightly + + DEBUG_EXIT_FUNC(); +} + +void Overlay::setBytesPerPixel(uint32 size) { + DEBUG_ENTER_FUNC(); + + switch (size) { + case 1: + _buffer.setPixelFormat(PSPPixelFormat::Type_Palette_8bit); + _palette.setPixelFormats(PSPPixelFormat::Type_4444, PSPPixelFormat::Type_Palette_8bit); + break; + case 2: + _buffer.setPixelFormat(PSPPixelFormat::Type_4444); + break; + case 4: + _buffer.setPixelFormat(PSPPixelFormat::Type_8888); + break; + } + + DEBUG_EXIT_FUNC(); +} + +void Overlay::setSize(uint32 width, uint32 height) { + DEBUG_ENTER_FUNC(); + _buffer.setSize(width, height, Buffer::kSizeBySourceSize); + _renderer.setDrawWholeBuffer(); // We need to let the renderer know how much to draw + DEBUG_EXIT_FUNC(); +} + +void Overlay::copyToArray(OverlayColor *buf, int pitch) { + DEBUG_ENTER_FUNC(); + _buffer.copyToArray((byte *)buf, pitch * sizeof(OverlayColor)); // Change to bytes + DEBUG_EXIT_FUNC(); +} + +void Overlay::copyFromRect(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { + DEBUG_ENTER_FUNC(); + + _buffer.copyFromRect((byte *)buf, pitch * sizeof(OverlayColor), x, y, w, h); // Change to bytes + // debug + //_buffer.print(0xFF); + setDirty(); + DEBUG_EXIT_FUNC(); +} + +bool Overlay::allocate() { + DEBUG_ENTER_FUNC(); + + bool ret = DefaultDisplayClient::allocate(true, false); // buffer in VRAM + + DEBUG_EXIT_FUNC(); + return ret; +} + +// Class Screen ----------------------------------------------------------- + +void Screen::init() { + DEBUG_ENTER_FUNC(); + + DefaultDisplayClient::init(); + _renderer.setAlphaBlending(false); + _renderer.setColorTest(false); + _renderer.setUseGlobalScaler(true); + _renderer.setFullScreen(true); + + DEBUG_EXIT_FUNC(); +} + +void Screen::setShakePos(int pos) { + _shakePos = pos; + _renderer.setOffsetOnScreen(0, pos); + setDirty(); +} + +void Screen::setSize(uint32 width, uint32 height) { + DEBUG_ENTER_FUNC(); + + _buffer.setSize(width, height, Buffer::kSizeBySourceSize); + _renderer.setDrawWholeBuffer(); // We need to let the renderer know how much to draw + + DEBUG_EXIT_FUNC(); +} + +void Screen::setScummvmPixelFormat(const Graphics::PixelFormat *format) { + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("format[%p], _buffer[%p], _palette[%p]\n", format, &_buffer, &_palette); + + if (!format) { + bzero(&_pixelFormat, sizeof(_pixelFormat)); + _pixelFormat.bytesPerPixel = 1; // default + } else { + _pixelFormat = *format; + } + + PSPPixelFormat::Type bufferFormat, paletteFormat; + bool swapRedBlue = false; + + PSPPixelFormat::convertFromScummvmPixelFormat(format, bufferFormat, paletteFormat, swapRedBlue); + _buffer.setPixelFormat(bufferFormat, swapRedBlue); + _palette.setPixelFormats(paletteFormat, bufferFormat, swapRedBlue); + + DEBUG_EXIT_FUNC(); +} + +Graphics::Surface *Screen::lockAndGetForEditing() { + DEBUG_ENTER_FUNC(); + + _frameBuffer.pixels = _buffer.getPixels(); + _frameBuffer.w = _buffer.getSourceWidth(); + _frameBuffer.h = _buffer.getSourceHeight(); + _frameBuffer.pitch = _buffer.getBytesPerPixel() * _buffer.getWidth(); + _frameBuffer.bytesPerPixel = _buffer.getBytesPerPixel(); + // We'll set to dirty once we unlock the screen + + DEBUG_EXIT_FUNC(); + + return &_frameBuffer; +} + +bool Screen::allocate() { + DEBUG_ENTER_FUNC(); + + return DefaultDisplayClient::allocate(true, false); // buffer in VRAM + + DEBUG_EXIT_FUNC(); +} diff --git a/backends/platform/psp/default_display_client.h b/backends/platform/psp/default_display_client.h new file mode 100644 index 0000000000..e83b0bf04d --- /dev/null +++ b/backends/platform/psp/default_display_client.h @@ -0,0 +1,108 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/trace.h $ + * $Id: trace.h 44276 2009-09-23 16:11:23Z joostp $ + * + */ + +#ifndef PSP_DEF_DISPLAY_CLIENT_H +#define PSP_DEF_DISPLAY_CLIENT_H + +/** + * Default display client that is useful for most purposes. + */ +class DefaultDisplayClient : public DisplayClient { +public: + DefaultDisplayClient() : _visible(false), _dirty(true) {} + + bool isVisible() { return _visible; } + void setVisible(bool v) { _visible = v; setDirty(); } + Buffer &buffer() { return _buffer; } + Palette &palette() { return _palette; } + void init(); + bool allocate(bool bufferInVram = false, bool paletteInVram = false); + void deallocate(); + void clearBuffer(); + void clearPalette(); + void render() { _renderer.render(); } + uint32 getWidth() { return _buffer.getSourceWidth(); } + uint32 getHeight() { return _buffer.getSourceHeight(); } + void setPartialPalette(const byte *colors, uint start, uint num) { setDirty(); return _palette.setPartial(colors, start, num); } + void getPartialPalette(byte *colors, uint start, uint num) { + return _palette.getPartial(colors, start, num); + } + void copyFromRect(const byte *buf, int pitch, int destX, int destY, int recWidth, int recHeight); + void copyToArray(byte *dst, int pitch); + void setDirty() { _dirty = true; } + void setClean() { _dirty = false; } + bool isDirty() { return _dirty; } + +protected: + Buffer _buffer; + Palette _palette; + GuRenderer _renderer; + bool _visible; + bool _dirty; +}; + +/** + * Screen overlay class. + */ +class Overlay : public DefaultDisplayClient { +public: + Overlay() {} + ~Overlay() { } + + void init(); + bool allocate(); + void setBytesPerPixel(uint32 size); + void setSize(uint32 width, uint32 height); + void copyToArray(OverlayColor *buf, int pitch); + void copyFromRect(const OverlayColor *buf, int pitch, int x, int y, int w, int h); +}; + +/** + * Screen class. + */ +class Screen : public DefaultDisplayClient { +public: + Screen() : _shakePos(0) { + memset(&_pixelFormat, 0, sizeof(_pixelFormat)); + memset(&_frameBuffer, 0, sizeof(_frameBuffer)); + } + ~Screen() {} + + void init(); + bool allocate(); + void setShakePos(int pos); + void setScummvmPixelFormat(const Graphics::PixelFormat *format); + const Graphics::PixelFormat &getScummvmPixelFormat() const { return _pixelFormat; } + Graphics::Surface *lockAndGetForEditing(); + void unlock() { setDirty(); } // set dirty here because of changes + void setSize(uint32 width, uint32 height); + +private: + uint32 _shakePos; + Graphics::PixelFormat _pixelFormat; + Graphics::Surface _frameBuffer; +}; + +#endif /* PSP_DEF_DISPLAY_CLIENT_H */ diff --git a/backends/platform/psp/display_client.cpp b/backends/platform/psp/display_client.cpp new file mode 100644 index 0000000000..73a3fefe5b --- /dev/null +++ b/backends/platform/psp/display_client.cpp @@ -0,0 +1,805 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $ + * + */ + +#include <pspgu.h> +#include <pspdisplay.h> +#include <psputils.h> + +#include "common/scummsys.h" +#include "backends/platform/psp/display_client.h" +#include "backends/platform/psp/display_manager.h" +#include "backends/platform/psp/memory.h" + +//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ +//#define __PSP_DEBUG_PRINT__ +#include "backends/platform/psp/trace.h" + +#define PSP_BUFFER_WIDTH (512) +#define PSP_SCREEN_WIDTH 480 +#define PSP_SCREEN_HEIGHT 272 +#define PSP_FRAME_SIZE (PSP_BUFFER_WIDTH * PSP_SCREEN_HEIGHT) + +DisplayManager *GuRenderer::_displayManager = 0; + + +// class Palette ------------------------------------------------------------ +// +void Palette::clear() { + DEBUG_ENTER_FUNC(); + + if (_values && _numOfEntries) + memset(_values, 0, getSizeInBytes()); + + PSP_DEBUG_PRINT("_values[%p]\n", _values); + + DEBUG_EXIT_FUNC(); +} + +// Used to clear the specific keycolor +// +void Palette::setColorPositionAlpha(uint32 position, bool alpha) { + DEBUG_ENTER_FUNC(); + + assert(_values); + assert(position < _numOfEntries); + + PSP_DEBUG_PRINT("position[%d], numofEntries[%u], bpp[%u], values[%p]\n", position, _numOfEntries, + _pixelFormat.bitsPerPixel, _values); + + if (_numOfEntries <= 16) + position &= 0xF; + else if (_numOfEntries <= 256) + position &= 0xFF; + + switch (_pixelFormat.bitsPerPixel) { + case 16: { + uint16 *shortVal = (uint16 *)&_values[_pixelFormat.pixelsToBytes(position)]; + *shortVal = _pixelFormat.setColorAlpha((uint32)*shortVal, alpha ? 255 : 0); + } + break; + case 32: { + uint32 *wordVal = (uint32 *)&_values[_pixelFormat.pixelsToBytes(position)]; + *wordVal = _pixelFormat.setColorAlpha((uint32)*wordVal, alpha ? 255 : 0); + } + break; + default: + PSP_ERROR("Incorrect bits per pixel value[%u]\n", _pixelFormat.bitsPerPixel); + } + + DEBUG_EXIT_FUNC(); +} + +// Set some of the palette to color values in array +// By default, ScummVm doesn't support alpha values in palettes +void Palette::setPartial(const byte *colors, uint32 start, uint32 num, bool supportsAlpha /* = false */) { + DEBUG_ENTER_FUNC(); + + assert(_values); + assert(_numOfEntries); + + const byte *src = colors; + + if (start + num > _numOfEntries) // Check boundary + num = _numOfEntries - start; + + if (_pixelFormat.bitsPerPixel == 16) { + uint16 *palette = (uint16 *)_values; + palette += start; + + for (uint32 i = 0; i < num; ++i) { + byte alphaVal = supportsAlpha ? src[3] : 0xFF; + *palette = (uint16)_pixelFormat.rgbaToColor(src[0], src[1], src[2], alphaVal); + src += 4; + palette++; + } + } + else if (_pixelFormat.bitsPerPixel == 32) { + uint32 *palette = (uint32 *)_values; + palette += start; + + for (uint32 i = 0; i < num; ++i) { + byte alphaVal = supportsAlpha ? src[3] : 0xFF; + *palette = _pixelFormat.rgbaToColor(src[0], src[1], src[2], alphaVal); + src += 4; + palette++; + } + } + + DEBUG_EXIT_FUNC(); +} + +// Sets pixel format and number of entries by the buffer's pixel format */ +void Palette::setPixelFormats(PSPPixelFormat::Type paletteType, PSPPixelFormat::Type bufferType, bool swapRedBlue /* = false */) { + DEBUG_ENTER_FUNC(); + + if (paletteType == PSPPixelFormat::Type_Unknown) + PSP_ERROR("Unknown paletteType[%u]\n", paletteType); + + switch (bufferType) { + case PSPPixelFormat::Type_Palette_8bit: + _numOfEntries = 256; + break; + case PSPPixelFormat::Type_Palette_4bit: + _numOfEntries = 16; + break; + case PSPPixelFormat::Type_Unknown: + case PSPPixelFormat::Type_None: + PSP_ERROR("Unhandled bufferType[%u]\n", bufferType); + break; + default: // No palette + _numOfEntries = 0; + break; + } + + _pixelFormat.set(paletteType, swapRedBlue); + + DEBUG_EXIT_FUNC(); +} + +bool Palette::allocate() { + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("_numOfEntries[%u]\n", _numOfEntries); + PSP_DEBUG_PRINT("_pixelFormat: format[%u], bpp[%u]\n", _pixelFormat.format, _pixelFormat.bitsPerPixel); + + if (_values) { + free (CACHED(_values)); + _values = 0; + } + + // We allocate on 64bytes to get a cache line, and round up to 64bytes to get the full line + uint32 amountInBytes = getSizeInBytes(); + if (amountInBytes < 64) + amountInBytes = 64; + _values = (byte *)memalign(64, amountInBytes); + + // Use uncached memory + GuRenderer::cacheInvalidate(_values, amountInBytes); + _values = UNCACHED(_values); + + if (!_values) { + PSP_ERROR("Couldn't allocate palette.\n"); + DEBUG_EXIT_FUNC(); + return false; + } + + PSP_DEBUG_PRINT("_values[%p]\n", _values); + clear(); + + DEBUG_EXIT_FUNC(); + return true; +} + +void Palette::deallocate() { + DEBUG_ENTER_FUNC(); + + free (CACHED(_values)); + _values = 0; + _numOfEntries = 0; + + DEBUG_EXIT_FUNC(); +} + +// Copy some of the palette to an array of colors +// +void Palette::getPartial(byte *colors, uint start, uint num) { + DEBUG_ENTER_FUNC(); + + assert(_values); + assert(_numOfEntries); + + uint32 r, g, b, a; + + if (start + num > _numOfEntries) // Check boundary + num = _numOfEntries - start; + + if (_pixelFormat.bitsPerPixel == 16) { + uint16 *palette = (uint16 *)_values; + palette += start; + + for (uint32 i = start; i < start + num; i++) { + _pixelFormat.colorToRgba(*palette, r, g, b, a); + + *colors++ = (byte)r; + *colors++ = (byte)g; + *colors++ = (byte)b; + *colors++ = (byte)a; + palette++; + } + } else if (_pixelFormat.bitsPerPixel == 32) { + uint32 *palette = (uint32 *)_values; + palette += start; + + for (uint32 i = start; i < start + num; i++) { + _pixelFormat.colorToRgba(*palette, r, g, b, a); + + *colors++ = (byte)r; + *colors++ = (byte)g; + *colors++ = (byte)b; + *colors++ = (byte)a; + palette++; + } + } + + DEBUG_EXIT_FUNC(); +} + +void Palette::setSingleColorRGBA(uint32 num, byte r, byte g, byte b, byte a) { + // DEBUG_ENTER_FUNC(); + uint16 *shortValues; + uint32 *wordValues; + + assert (_values); + assert (num < _numOfEntries); + + switch (_pixelFormat.bitsPerPixel) { + case 16: + shortValues = (uint16 *)_values; + shortValues[num] = _pixelFormat.rgbaToColor(r, g, b, a); + break; + case 32: + wordValues = (uint32 *)_values; + wordValues[num] = _pixelFormat.rgbaToColor(r, g, b, a); + break; + default: + PSP_ERROR("Incorrect bitsPerPixel[%d]\n", _pixelFormat.bitsPerPixel); + break; + } + // DEBUG_EXIT_FUNC(); +} + +// Print to screen +void Palette::print(uint32 numToPrint /* = 0 */) { + if (_numOfEntries > 0) { + assert (_values); + + if (numToPrint > _numOfEntries || numToPrint == 0) + numToPrint = _numOfEntries; + + PSP_INFO_PRINT("cursor palette:\n"); + + for (unsigned int i=0; i<numToPrint; i++) { + byte *pcolor = &_values[_pixelFormat.pixelsToBytes(i)]; + uint32 color = _pixelFormat.getColorValueAt(pcolor); + + PSP_INFO_PRINT("[%u=%x] ", i, color); + } + + PSP_INFO_PRINT("\n"); + } +} + +uint32 Palette::getRawColorAt(uint32 position) { + byte *pcolor = &_values[_pixelFormat.pixelsToBytes(position)]; + uint32 color = _pixelFormat.getColorValueAt(pcolor); + return color; +} + +uint32 Palette::getRGBAColorAt(uint32 position) { + uint32 color = getRawColorAt(position); + uint32 r, g, b, a; + _pixelFormat.colorToRgba(color, r, g, b, a); + return (a << 24 | b << 16 | g << 8 | r); +} + +// class Buffer --------------------------------------------------- + +void Buffer::setPixelFormat(PSPPixelFormat::Type type, bool swapRedBlue) { + if (type == PSPPixelFormat::Type_None || + type == PSPPixelFormat::Type_Unknown) + PSP_ERROR("Unhandled buffer format[%u]\n", type); + + _pixelFormat.set(type, swapRedBlue); +} + +bool Buffer::hasPalette() { + if (_pixelFormat.format == PSPPixelFormat::Type_Palette_8bit || + _pixelFormat.format == PSPPixelFormat::Type_Palette_4bit) + return true; + + return false; +} + +/* pitch is in bytes */ +void Buffer::copyFromArray(const byte *buffer, int pitch) { + DEBUG_ENTER_FUNC(); + + // We use sourceSize because outside, they won't know what the true size is + copyFromRect(buffer, pitch, 0, 0, _sourceSize.width, _sourceSize.height); + + DEBUG_EXIT_FUNC(); +} + +/* pitch is in bytes */ +void Buffer::copyFromRect(const byte *buf, uint32 pitch, int destX, int destY, uint32 recWidth, uint32 recHeight) { + // Removed silly clipping code + DEBUG_ENTER_FUNC(); + assert (_pixels); + + if (recWidth > _sourceSize.width - destX) { + recWidth = _sourceSize.width - destX; + } + + if (recHeight > _sourceSize.height - destY) { + recHeight = _sourceSize.height - destY; + } + + if (recWidth <= 0 || recHeight <= 0) { + DEBUG_EXIT_FUNC(); + return; + } + + byte *dst = _pixels + _pixelFormat.pixelsToBytes((destY * _width) + destX); + + uint32 recWidthInBytes = _pixelFormat.pixelsToBytes(recWidth); + uint32 realWidthInBytes = _pixelFormat.pixelsToBytes(_width); + + if (pitch == realWidthInBytes && pitch == recWidthInBytes) { + //memcpy(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth)); + Copier::copy(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth), &_pixelFormat); + } else { + do { + //memcpy(dst, buf, recWidthInBytes); + Copier::copy(dst, buf, recWidthInBytes, &_pixelFormat); + buf += pitch; + dst += realWidthInBytes; + } while (--recHeight); + } + + DEBUG_EXIT_FUNC(); +} + +/* pitch is in bytes */ +void Buffer::copyToArray(byte *dst, int pitch) { + DEBUG_ENTER_FUNC(); + assert (_pixels); + + uint32 h = _height; + byte *src = _pixels; + uint32 sourceWidthInBytes = _pixelFormat.pixelsToBytes(_sourceSize.width); + uint32 realWidthInBytes = _pixelFormat.pixelsToBytes(_width); + + do { + //memcpy(dst, src, sourceWidthInBytes); + Copier::copy(dst, src, sourceWidthInBytes, &_pixelFormat); + src += realWidthInBytes; + dst += pitch; + } while (--h); + + DEBUG_EXIT_FUNC(); +} + +/* We can size the buffer either by texture size (multiple of 2^n) or source size. The GU can + really handle both, but is supposed to get only 2^n size buffers */ +void Buffer::setSize(uint32 width, uint32 height, HowToSize textureOrSource/*=kSizeByTextureSize*/) { + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("w[%u], h[%u], %s\n", width, height, textureOrSource ? "size by source" : "size by texture"); + + _sourceSize.width = width; + _sourceSize.height = height; + + _textureSize.width = scaleUpToPowerOfTwo(width); + _textureSize.height = scaleUpToPowerOfTwo(height); + + if (textureOrSource == kSizeByTextureSize) { + _width = _textureSize.width; + _height = _textureSize.height; + } + else { /* kSizeBySourceSize */ + _width = _sourceSize.width; + _height = _sourceSize.height; + } + + DEBUG_EXIT_FUNC(); +} + +/* Scale a dimension (width/height) up to power of 2 for the texture */ +uint32 Buffer::scaleUpToPowerOfTwo(uint32 size) { + + uint32 textureDimension = 0; + if (size <= 16) + textureDimension = 16; + else if (size <= 32) + textureDimension = 32; + else if (size <= 64) + textureDimension = 64; + else if (size <= 128) + textureDimension = 128; + else if (size <= 256) + textureDimension = 256; + else + textureDimension = 512; + + PSP_DEBUG_PRINT("power of 2 = %u\n", textureDimension); + + return textureDimension; +} + +bool Buffer::allocate(bool inVram/*=false*/) { + DEBUG_ENTER_FUNC(); + + PSP_DEBUG_PRINT("_width[%u], _height[%u]\n", _width, _height); + PSP_DEBUG_PRINT("_pixelFormat: format[%u], bpp[%u]\n", _pixelFormat.format, _pixelFormat.bitsPerPixel); + + if (_pixels) { + if (VramAllocator::isAddressInVram(_pixels)) // Check if in VRAM + VramAllocator::instance().deallocate(_pixels); + else // not in VRAM + free (CACHED(_pixels)); + + _pixels = 0; + } + + uint32 size = getSizeInBytes(); + + if (inVram) { + _pixels = (byte *)VramAllocator::instance().allocate(size); + } + + if (!_pixels) { // Either we are not in vram or we didn't manage to allocate in vram + // Align to 64 bytes. All normal buffer sizes are multiples of 64 anyway + _pixels = (byte *)memalign(64, size); + } + + if (!_pixels) { + PSP_ERROR("couldn't allocate buffer.\n"); + DEBUG_EXIT_FUNC(); + return false; + } + + // Use uncached memory + GuRenderer::cacheInvalidate(_pixels, size); + _pixels = UNCACHED(_pixels); + + clear(); + DEBUG_EXIT_FUNC(); + return true; +} + +void Buffer::deallocate() { + DEBUG_ENTER_FUNC(); + + if (!_pixels) + return; + + if (VramAllocator::isAddressInVram(_pixels)) // Check if in VRAM + VramAllocator::instance().deallocate(_pixels); + else + free(CACHED(_pixels)); + + _pixels = 0; + + DEBUG_EXIT_FUNC(); +} + +void Buffer::clear() { + DEBUG_ENTER_FUNC(); + + if (_pixels) + memset(_pixels, 0, getSizeInBytes()); + + DEBUG_EXIT_FUNC(); +} + +/* Convert 4 bit images to match weird PSP format */ +void Buffer::flipNibbles() { + DEBUG_ENTER_FUNC(); + + if (_pixelFormat.bitsPerPixel != 4) + return; + + assert(_pixels); + + uint32 *dest = (uint32 *)_pixels; + + for (uint32 i = 0; i < getSourceHeight(); i++) { + for (uint32 j = 0; j < (getWidth() >> 3); j++) { // /8 because we do it in 32bit chunks + uint32 val = *dest; + *dest++ = ((val >> 4) & 0x0F0F0F0F) | ((val << 4) & 0xF0F0F0F0); + } + } + + DEBUG_EXIT_FUNC(); +} + +// Print buffer contents to screen (only source size is printed out) +void Buffer::print(uint32 mask, uint32 numToPrint /*=0*/) { + assert(_pixels); + + if (numToPrint > _sourceSize.width * _sourceSize.height || numToPrint == 0) + numToPrint = _sourceSize.width * _sourceSize.height; + + PSP_INFO_PRINT("buffer: \n"); + PSP_INFO_PRINT("width[%u], height[%u]\n\n", _sourceSize.width, _sourceSize.height); + + for (unsigned int i=0; i < _sourceSize.height; i++) { + for (unsigned int j=0; j < _sourceSize.width; j++) { + if (numToPrint <= 0) // check if done + break; + + byte *pcolor = &_pixels[_pixelFormat.pixelsToBytes((i * _width) + j)]; + uint32 color = _pixelFormat.getColorValueAt(pcolor); + + //if (color != 0) PSP_INFO_PRINT("[%x] ", color); + PSP_INFO_PRINT("[%x] ", mask & color); + + numToPrint--; + } + PSP_INFO_PRINT("\n"); + } + PSP_INFO_PRINT("\n"); +} + +// class GuRenderer ------------------------------------------------- +//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ +//#define __PSP_DEBUG_PRINT__ + +#include "backends/platform/psp/trace.h" + + +void GuRenderer::render() { + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("Buffer[%p] Palette[%p]\n", _buffer->getPixels(), _palette->getRawValues()); + + setMaxTextureOffsetByIndex(0, 0); + + guProgramDrawBehavior(); + + if (_buffer->hasPalette()) + guLoadPalette(); + + guProgramTextureFormat(); + guLoadTexture(); + + Vertex *vertices = guGetVertices(); + fillVertices(vertices); + + guDrawVertices(vertices); + + if (_buffer->getSourceWidth() > 512) { + setMaxTextureOffsetByIndex(1, 0); + + guLoadTexture(); + + vertices = guGetVertices(); + fillVertices(vertices); + + guDrawVertices(vertices); + } + + DEBUG_EXIT_FUNC(); +} + +inline void GuRenderer::setMaxTextureOffsetByIndex(uint32 x, uint32 y) { + DEBUG_ENTER_FUNC(); + const uint32 maxTextureSizeShift = 9; /* corresponds to 512 = max texture size*/ + + _maxTextureOffset.x = x << maxTextureSizeShift; /* x times 512 */ + _maxTextureOffset.y = y << maxTextureSizeShift; /* y times 512 */ + DEBUG_EXIT_FUNC(); +} + +inline void GuRenderer::guProgramDrawBehavior() { + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("blending[%s] colorTest[%s] reverseAlpha[%s] keyColor[%u]\n", _blending ? "on" : "off", _colorTest ? "on" : "off", _alphaReverse ? "on" : "off", _keyColor); + + if (_blending) { + sceGuEnable(GU_BLEND); + + if (_alphaReverse) // Reverse the alpha value (0 is 1) + sceGuBlendFunc(GU_ADD, GU_ONE_MINUS_SRC_ALPHA, GU_SRC_ALPHA, 0, 0); + else // Normal alpha values + sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); + + } else + sceGuDisable(GU_BLEND); + + if (_colorTest) { + sceGuEnable(GU_COLOR_TEST); + sceGuColorFunc(GU_NOTEQUAL, _keyColor, 0x00ffffff); + } else + sceGuDisable(GU_COLOR_TEST); + + DEBUG_EXIT_FUNC(); +} + +inline void GuRenderer::guLoadPalette() { + DEBUG_ENTER_FUNC(); + + uint32 mask; + + if (_buffer->getBitsPerPixel() == 4) + mask = 0x0F; + else if (_buffer->getBitsPerPixel() == 8) + mask = 0xFF; + else + assert(0); /* error */ + + PSP_DEBUG_PRINT("numOfEntries[%d]\n", _palette->getNumOfEntries()); + PSP_DEBUG_PRINT("bpp[%d], pixelformat[%d], mask[%x]\n", _buffer->getBitsPerPixel(), _palette->getPixelFormat(), mask); + + sceGuClutMode(convertToGuPixelFormat(_palette->getPixelFormat()), 0, mask, 0); + sceGuClutLoad(_palette->getNumOfEntries() >> 3, _palette->getRawValues()); + + DEBUG_EXIT_FUNC(); +} + +inline void GuRenderer::guProgramTextureFormat() { + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("pixelFormat[%d]\n", _buffer->getPixelFormat()); + + sceGuTexMode(convertToGuPixelFormat(_buffer->getPixelFormat()), 0, 0, 0); + DEBUG_EXIT_FUNC(); +} + +inline uint32 GuRenderer::convertToGuPixelFormat(PSPPixelFormat::Type format) { + DEBUG_ENTER_FUNC(); + + uint32 guFormat = 0; + + switch (format) { + case PSPPixelFormat::Type_4444: + guFormat = GU_PSM_4444; + break; + case PSPPixelFormat::Type_5551: + guFormat = GU_PSM_5551; + break; + case PSPPixelFormat::Type_5650: + guFormat = GU_PSM_5650; + break; + case PSPPixelFormat::Type_8888: + guFormat = GU_PSM_8888; + break; + case PSPPixelFormat::Type_Palette_8bit: + guFormat = GU_PSM_T8; + break; + case PSPPixelFormat::Type_Palette_4bit: + guFormat = GU_PSM_T4; + break; + default: + break; + } + + PSP_DEBUG_PRINT("Pixelformat[%d], guFormat[%d]\n", format, guFormat); + + DEBUG_EXIT_FUNC(); + return guFormat; + +} + +inline void GuRenderer::guLoadTexture() { + DEBUG_ENTER_FUNC(); + + sceGuTexImage(0, _buffer->getTextureWidth(), _buffer->getTextureHeight(), _buffer->getWidth(), _buffer->getPixels() + _buffer->_pixelFormat.pixelsToBytes(_maxTextureOffset.x)); + + DEBUG_EXIT_FUNC(); +} + +inline Vertex *GuRenderer::guGetVertices() { + DEBUG_ENTER_FUNC(); + + Vertex *ret = (Vertex *)sceGuGetMemory(2 * sizeof(Vertex)); + + DEBUG_EXIT_FUNC(); + return ret; +} + +// Fills the vertices. Most of the logic is here. +void GuRenderer::fillVertices(Vertex *vertices) { + DEBUG_ENTER_FUNC(); + + uint32 outputWidth = _displayManager->getOutputWidth(); + uint32 outputHeight = _displayManager->getOutputHeight(); + + float textureStartX, textureStartY, textureEndX, textureEndY; + + // Texture adjustments for eliminating half-pixel artifacts from scaling + // Not necessary if we don't scale + float textureAdjustment = 0.0f; + if (_useGlobalScaler && + (_displayManager->getScaleX() != 1.0f || _displayManager->getScaleX() != 1.0f)) + textureAdjustment = 0.5f; + + textureStartX = textureAdjustment + _offsetInBuffer.x; //debug + textureStartY = textureAdjustment + _offsetInBuffer.y; + // We subtract maxTextureOffset because our shifted texture starts at 512 and will go to 640 + textureEndX = _offsetInBuffer.x + _drawSize.width - textureAdjustment - _maxTextureOffset.x; + textureEndY = _offsetInBuffer.y + _drawSize.height - textureAdjustment; + + // For scaling to the final image size, calculate the gaps on both sides + uint32 gapX = _useGlobalScaler ? (PSP_SCREEN_WIDTH - outputWidth) >> 1 : 0; + uint32 gapY = _useGlobalScaler ? (PSP_SCREEN_HEIGHT - outputHeight) >> 1 : 0; + + float imageStartX, imageStartY, imageEndX, imageEndY; + + imageStartX = gapX + ( scaleSourceToOutputX(_maxTextureOffset.x) ); + imageStartY = gapY; + + imageStartX += scaleSourceToOutputX(_offsetOnScreen.x); + imageStartY += scaleSourceToOutputY(_offsetOnScreen.y); + + if (_fullScreen) { // shortcut + imageEndX = PSP_SCREEN_WIDTH - gapX; + imageEndY = PSP_SCREEN_HEIGHT - gapY; + } else { /* !fullScreen */ + imageEndX = imageStartX + scaleSourceToOutputX(_drawSize.width); + imageEndY = imageStartY + scaleSourceToOutputY(_drawSize.height); + } + + vertices[0].u = textureStartX; + vertices[0].v = textureStartY; + vertices[1].u = textureEndX; + vertices[1].v = textureEndY; + + vertices[0].x = imageStartX; + vertices[0].y = imageStartY; + vertices[0].z = 0; + vertices[1].x = imageEndX; + vertices[1].y = imageEndY; + vertices[1].z = 0; + + PSP_DEBUG_PRINT("TextureStart: X[%f] Y[%f] TextureEnd: X[%.1f] Y[%.1f]\n", textureStartX, textureStartY, textureEndX, textureEndY); + PSP_DEBUG_PRINT("ImageStart: X[%f] Y[%f] ImageEnd: X[%.1f] Y[%.1f]\n", imageStartX, imageStartY, imageEndX, imageEndY); + + DEBUG_EXIT_FUNC(); +} + +/* Scale the input X offset to appear in proper position on the screen */ +inline float GuRenderer::scaleSourceToOutputX(float offset) { + float result; + + if (!_useGlobalScaler) + result = offset; + else if (!offset) + result = 0.0f; + else + result = offset * _displayManager->getScaleX(); + + return result; +} + +/* Scale the input Y offset to appear in proper position on the screen */ +inline float GuRenderer::scaleSourceToOutputY(float offset) { + float result; + + if (!_useGlobalScaler) + result = offset; + else if (!offset) + result = 0.0f; + else + result = offset * _displayManager->getScaleY(); + + return result; +} + +inline void GuRenderer::guDrawVertices(Vertex *vertices) { + DEBUG_ENTER_FUNC(); + + sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices); + DEBUG_EXIT_FUNC(); +} + +void GuRenderer::cacheInvalidate(void *pointer, uint32 size) { + sceKernelDcacheWritebackInvalidateRange(pointer, size); +} diff --git a/backends/platform/psp/display_client.h b/backends/platform/psp/display_client.h new file mode 100644 index 0000000000..d96504ad04 --- /dev/null +++ b/backends/platform/psp/display_client.h @@ -0,0 +1,238 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $ + * + */ + +#ifndef PSP_GRAPHICS_H +#define PSP_GRAPHICS_H + +#include "common/singleton.h" +#include "graphics/surface.h" +#include "common/system.h" +#include "backends/platform/psp/psppixelformat.h" +#include "backends/platform/psp/memory.h" + +#define MAX_TEXTURE_SIZE 512 + +class DisplayManager; +class GuRenderer; + +/** + * Interface to inherit for all display clients + * We deliberately avoid virtual functions for speed. + */ +class DisplayClient { // Abstract class +public: + DisplayClient() {} + bool isVisible() { return true; } + bool isDirty() { return true; } + void setClean() {} + void render() {} + virtual ~DisplayClient() {} +}; + +/** + * Vertex used for GU rendering + */ +struct Vertex { + float u,v; + float x,y,z; +}; + +struct Point { + int x; + int y; + Point() : x(0), y(0) {} +}; + +/** + * Dimensions struct for simplification + */ +struct Dimensions { + uint32 width; + uint32 height; + Dimensions() : width(0), height(0) {} +}; + +/** + * Universal PSP Palette class + * Use this in any class that wishes to draw to the PSP screen. + * Use together with GuRenderer + */ +class Palette { +public: + Palette() : _values(0), _numOfEntries(0) {} + virtual ~Palette() { deallocate(); } + bool allocate(); + void deallocate(); + void clear(); + void setPixelFormats(PSPPixelFormat::Type paletteType, PSPPixelFormat::Type bufferType, bool swapRedBlue = false); + void setNumOfEntries(uint32 num) { _numOfEntries = num; } + uint32 getNumOfEntries() { return _numOfEntries; } + uint32 getSizeInBytes() { return _pixelFormat.pixelsToBytes(_numOfEntries); } + void set(byte *values) { setPartial(values, 0, _numOfEntries); } + void setPartial(const byte *colors, uint start, uint num, bool supportsAlpha = false); + void getPartial(byte *colors, uint start, uint num); + uint32 getRawColorAt(uint32 position); + uint32 getRGBAColorAt(uint32 position); + void setSingleColorRGBA(uint32 num, byte r, byte g, byte b, byte a); + void setColorPositionAlpha(uint32 position, bool alpha); + byte *getRawValues() { return _values; } + bool isAllocated() { return (_values != 0); } + PSPPixelFormat::Type getPixelFormat() { return _pixelFormat.format; } + void print(uint32 numToPrint = 0); // print to screen + +protected: + byte *_values; ///< array of palette data + uint32 _numOfEntries; ///< number of palette entries + PSPPixelFormat _pixelFormat; ///< pixel format of the palette data +}; + +/** + * Universal PSP buffer/texture object + * Use this in any class that wishes to draw to the PSP screen. + * Use together with GuRenderer + */ +class Buffer { +public: + enum HowToSize { + kSizeByTextureSize, // buffer size is determined by power of 2 roundup for texture + kSizeBySourceSize // buffer size is determined by source size + }; + + Buffer() : _pixels(0), _width(0), _height(0) {} + virtual ~Buffer() { deallocate(); } + + // setters + void setSize(uint32 width, uint32 height, HowToSize textureOrSource=kSizeByTextureSize); + void setBitsPerPixel(uint32 bits) { _pixelFormat.bitsPerPixel = bits; } + void setBytesPerPixel(uint32 bytes) { setBitsPerPixel(bytes << 3); } + void setPixelFormat(PSPPixelFormat::Type type, bool swapRedBlue = false); + + // getters + uint32 getWidth() { return _width; } + uint32 getWidthInBytes() { return _pixelFormat.pixelsToBytes(getWidth()); } + uint32 getHeight() { return _height; } + uint32 getSourceWidth() { return _sourceSize.width; } + uint32 getSourceWidthInBytes() { return _pixelFormat.pixelsToBytes(_sourceSize.width); } + uint32 getSourceHeight() { return _sourceSize.height; } + uint32 getTextureWidth() { return _textureSize.width; } + uint32 getTextureHeight() { return _textureSize.height; } + PSPPixelFormat::Type getPixelFormat() { return _pixelFormat.format; } + uint32 getBitsPerPixel() { return _pixelFormat.bitsPerPixel; } + uint32 getBytesPerPixel() { return getBitsPerPixel() >> 3; } /* won't work for 4-bit */ + byte *getPixels() { return _pixels; } + uint32 getSizeInBytes() { return _pixelFormat.pixelsToBytes(_width * _height); } + + bool hasPalette(); + void copyFromArray(const byte *buffer, int pitch); + void copyFromRect(const byte *buf, uint32 pitch, int destX, int destY, uint32 recWidth, uint32 recHeight); + void copyToArray(byte *dst, int pitch); + bool allocate(bool inVram = false); + void deallocate(); + bool isAllocated() { return (_pixels != 0) ; } + void clear(); + void flipNibbles(); // To handle peculiarities of PSP's 4 bit textures + static uint32 scaleUpToPowerOfTwo(uint32 size); + void print(uint32 mask, uint32 numToPrint = 0); + +protected: + friend class GuRenderer; + byte *_pixels; + uint32 _width; ///< True allocated width + uint32 _height; ///< True allocated height + Dimensions _textureSize; ///< Size rounded up to power of 2. Used for drawing + Dimensions _sourceSize; ///< Original size of the buffer + PSPPixelFormat _pixelFormat; ///< Format of the buffer +}; + +/** + * Universal rendering class for PSP + * Use this if you want to draw to the screen. + * Needs to be supplied with a Buffer and a Palette + */ +class GuRenderer { +public: + // Constructors + GuRenderer() : _useGlobalScaler(false), _buffer(0), _palette(0), _blending(false), _alphaReverse(false), _colorTest(false), _keyColor(0), _fullScreen(false) {} + GuRenderer(Buffer *buffer, Palette *palette) : _useGlobalScaler(false), _buffer(buffer), _palette(palette), _blending(false), _alphaReverse(false), _colorTest(false), _keyColor(0), _fullScreen(false) {} + static void setDisplayManager(DisplayManager *dm) { _displayManager = dm; } // Called by the Display Manager + + // Setters + void setDrawSize(uint32 width, uint32 height) { // How big of an area to draw + _drawSize.width = width; + _drawSize.height = height; + } + void setDrawWholeBuffer() { // Draw the full size of the current buffer + assert(_buffer); + _drawSize.width = _buffer->getSourceWidth(); + _drawSize.height = _buffer->getSourceHeight(); + } + void setBuffer(Buffer *buffer) { _buffer = buffer; } + void setPalette(Palette *palette) { _palette = palette; } + void setMaxTextureOffsetByIndex(uint32 x, uint32 y); // For drawing multiple textures + void setOffsetOnScreen(uint32 x, uint32 y) { _offsetOnScreen.x = x; _offsetOnScreen.y = y; } + void setOffsetInBuffer(uint32 x, uint32 y) { _offsetInBuffer.x = x; _offsetInBuffer.y = y; } + void setColorTest(bool value) { _colorTest = value; } + void setKeyColor(uint32 value) { _keyColor = _buffer->_pixelFormat.convertTo32BitColor(value); } + void setAlphaBlending(bool value) { _blending = value; } + void setAlphaReverse(bool value) { _alphaReverse = value; } + void setFullScreen(bool value) { _fullScreen = value; } // Shortcut for rendering + void setUseGlobalScaler(bool value) { _useGlobalScaler = value; } // Scale to screen + + static void cacheInvalidate(void *pointer, uint32 size); + + void render(); // Default rendering function. This should be good enough for most purposes + +protected: + // Gu functions + void fillVertices(Vertex *vertices); // Fill in vertices with coordinates + void guProgramDrawBehavior(); + Vertex *guGetVertices(); + void guLoadTexture(); + void guLoadPalette(); + void guProgramTextureFormat(); + void guProgramTextureBitDepth(); + void guDrawVertices(Vertex *vertices); + + uint32 convertToGuPixelFormat(PSPPixelFormat::Type format); + float scaleSourceToOutputX(float offset); + float scaleSourceToOutputY(float offset); + + friend class MasterGuRenderer; + Point _maxTextureOffset; ///> For rendering textures > 512 pixels + Point _offsetOnScreen; ///> Where on screen to draw + Point _offsetInBuffer; ///> Where in the texture to draw + bool _useGlobalScaler; ///> Scale to the output size on screen + Buffer *_buffer; + Palette *_palette; + static DisplayManager *_displayManager; + Dimensions _drawSize; ///> Actual size to draw out of the Buffer + bool _blending; + bool _alphaReverse; ///> 0 counts as full alpha + bool _colorTest; + uint32 _keyColor; ///> Color to test against for color test. in 32 bits. + bool _fullScreen; ///> Speeds up for fullscreen rendering +}; + +#endif /* PSP_SCREEN_H */ diff --git a/backends/platform/psp/display_manager.cpp b/backends/platform/psp/display_manager.cpp new file mode 100644 index 0000000000..a556a6e65f --- /dev/null +++ b/backends/platform/psp/display_manager.cpp @@ -0,0 +1,336 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 47541 2010-01-25 01:39:44Z lordhoto $ + * + */ + +//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */ +//#define __PSP_DEBUG_PRINT__ /* For debug printouts */ + +//#define ENABLE_RENDER_MEASURE + +#include "backends/platform/psp/trace.h" + +#include <pspgu.h> +#include <pspdisplay.h> + +#include "common/scummsys.h" +#include "backends/base-backend.h" +#include "backends/platform/psp/display_client.h" +#include "backends/platform/psp/default_display_client.h" +#include "backends/platform/psp/cursor.h" +#include "backends/platform/psp/pspkeyboard.h" +#include "backends/platform/psp/display_manager.h" + +#define PSP_BUFFER_WIDTH (512) +#define PSP_SCREEN_WIDTH 480 +#define PSP_SCREEN_HEIGHT 272 +#define PSP_FRAME_SIZE (PSP_BUFFER_WIDTH * PSP_SCREEN_HEIGHT) + +uint32 __attribute__((aligned(16))) MasterGuRenderer::_displayList[2048]; + + const OSystem::GraphicsMode DisplayManager::_supportedModes[] = { + { "320x200 (centered)", "320x200 16-bit centered", CENTERED_320X200 }, + { "435x272 (best-fit, centered)", "435x272 16-bit centered", CENTERED_435X272 }, + { "480x272 (full screen)", "480x272 16-bit stretched", STRETCHED_480X272 }, + { "362x272 (4:3, centered)", "362x272 16-bit centered", CENTERED_362X272 }, + {0, 0, 0} +}; + + +// Class MasterGuRenderer ---------------------------------------------- + +void MasterGuRenderer::guInit() { + DEBUG_ENTER_FUNC(); + + sceGuInit(); + sceGuStart(0, _displayList); + + guProgramDisplayBufferSizes(); + + sceGuOffset(2048 - (PSP_SCREEN_WIDTH/2), 2048 - (PSP_SCREEN_HEIGHT/2)); + sceGuViewport(2048, 2048, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT); + sceGuDepthRange(0xC350, 0x2710); + sceGuDisable(GU_DEPTH_TEST); // We'll use depth buffer area + sceGuDepthMask(GU_TRUE); // Prevent writes to depth buffer + sceGuScissor(0, 0, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT); + sceGuEnable(GU_SCISSOR_TEST); + sceGuFrontFace(GU_CW); + sceGuEnable(GU_TEXTURE_2D); + + sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT); + sceGuFinish(); + sceGuSync(0,0); + + sceDisplayWaitVblankStart(); + sceGuDisplay(1); + + DEBUG_EXIT_FUNC(); +} + +void MasterGuRenderer::guProgramDisplayBufferSizes() { + DEBUG_ENTER_FUNC(); + + PSP_DEBUG_PRINT("Outputbits[%u]\n", GuRenderer::_displayManager->getOutputBitsPerPixel()); + + switch (GuRenderer::_displayManager->getOutputBitsPerPixel()) { + case 16: + sceGuDrawBuffer(GU_PSM_4444, (void *)0, PSP_BUFFER_WIDTH); + sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, (void*)(PSP_FRAME_SIZE * sizeof(uint16)), PSP_BUFFER_WIDTH); + sceGuDepthBuffer((void*)(PSP_FRAME_SIZE * sizeof(uint16) * 2), PSP_BUFFER_WIDTH); + VramAllocator::instance().allocate(PSP_FRAME_SIZE * sizeof(uint16) * 2); + break; + case 32: + sceGuDrawBuffer(GU_PSM_8888, (void *)0, PSP_BUFFER_WIDTH); + sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, (void*)(PSP_FRAME_SIZE * sizeof(uint32)), PSP_BUFFER_WIDTH); + sceGuDepthBuffer((void*)(PSP_FRAME_SIZE * sizeof(uint32) * 2), PSP_BUFFER_WIDTH); + VramAllocator::instance().allocate(PSP_FRAME_SIZE * sizeof(uint32) * 2); + break; + } + + DEBUG_EXIT_FUNC(); +} + +// These are GU commands that should always stay the same +inline void MasterGuRenderer::guPreRender() { + DEBUG_ENTER_FUNC(); + +#ifdef ENABLE_RENDER_MEASURE + _lastRenderTime = g_system->getMillis(); +#endif /* ENABLE_RENDER_MEASURE */ + + sceGuStart(0, _displayList); + + sceGuClearColor(0xFF000000); + sceGuClear(GU_COLOR_BUFFER_BIT); + + sceGuAmbientColor(0xFFFFFFFF); + sceGuColor(0xFFFFFFFF); + sceGuTexOffset(0,0); + sceGuTexFilter(GU_LINEAR, GU_LINEAR); + + sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA); // Also good enough for all purposes + sceGuAlphaFunc(GU_GREATER, 0, 0xFF); // Also good enough for all purposes + + DEBUG_EXIT_FUNC(); +} + +inline void MasterGuRenderer::guPostRender() { + DEBUG_ENTER_FUNC(); + + sceGuFinish(); + sceGuSync(0,0); + +#ifdef ENABLE_RENDER_MEASURE + uint32 now = g_system->getMillis(); + PSP_INFO_PRINT("Render took %d milliseconds\n", now - _lastRenderTime); +#endif /* ENABLE_RENDER_MEASURE */ + + sceDisplayWaitVblankStart(); + sceGuSwapBuffers(); + + DEBUG_EXIT_FUNC(); +} + +void MasterGuRenderer::guShutDown() { + sceGuTerm(); +} + + +// Class DisplayManager ----------------------------------------------------- + +DisplayManager::~DisplayManager() { + _masterGuRenderer.guShutDown(); +} + +void DisplayManager::init() { + DEBUG_ENTER_FUNC(); + + _displayParams.outputBitsPerPixel = 32; // can be changed to produce 16-bit output + + GuRenderer::setDisplayManager(this); + _screen->init(); + _overlay->init(); + _cursor->init(); + + _masterGuRenderer.guInit(); // start up the renderer + + DEBUG_EXIT_FUNC(); +} + +void DisplayManager::setSizeAndPixelFormat(uint width, uint height, const Graphics::PixelFormat *format) { + + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("w[%u], h[%u], pformat[%p]\n", width, height, format); + + _overlay->deallocate(); + _screen->deallocate(); + + _screen->setScummvmPixelFormat(format); + _screen->setSize(width, height); + _screen->allocate(); + + _cursor->setScreenPaletteScummvmPixelFormat(format); + + _overlay->setBytesPerPixel(sizeof(OverlayColor)); + _overlay->setSize(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT); + _overlay->allocate(); + + _displayParams.screenSource.width = width; + _displayParams.screenSource.height = height; + calculateScaleParams(); + + DEBUG_EXIT_FUNC(); +} + +bool DisplayManager::setGraphicsMode(const char *name) { + DEBUG_ENTER_FUNC(); + + int i = 0; + + while (_supportedModes[i].name) { + if (!strcmpi(_supportedModes[i].name, name)) { + setGraphicsMode(_supportedModes[i].id); + DEBUG_EXIT_FUNC(); + return true; + } + i++; + } + + DEBUG_EXIT_FUNC(); + return false; +} + +bool DisplayManager::setGraphicsMode(int mode) { + DEBUG_ENTER_FUNC(); + + _graphicsMode = mode; + + switch (_graphicsMode) { + case CENTERED_320X200: + _displayParams.screenOutput.width = 320; + _displayParams.screenOutput.height = 200; + break; + case CENTERED_435X272: + _displayParams.screenOutput.width = 435; + _displayParams.screenOutput.height = 272; + break; + case STRETCHED_480X272: + _displayParams.screenOutput.width = 480; + _displayParams.screenOutput.height = 272; + break; + case CENTERED_362X272: + _displayParams.screenOutput.width = 362; + _displayParams.screenOutput.height = 272; + break; + default: + PSP_ERROR("Unsupported graphics mode[%d].\n", _graphicsMode); + } + + calculateScaleParams(); + + DEBUG_EXIT_FUNC(); + return true; +} + +void DisplayManager::calculateScaleParams() { + if (_displayParams.screenOutput.width && _displayParams.screenSource.width && + _displayParams.screenOutput.height && _displayParams.screenSource.height) { + _displayParams.scaleX = ((float)_displayParams.screenOutput.width) / _displayParams.screenSource.width; + _displayParams.scaleY = ((float)_displayParams.screenOutput.height) / _displayParams.screenSource.height; + } +} + +void DisplayManager::renderAll() { + DEBUG_ENTER_FUNC(); + + if (!isTimeToUpdate()) { + DEBUG_EXIT_FUNC(); + return; + } + + if (!_screen->isDirty() && + (!_overlay->isDirty()) && + (!_cursor->isDirty()) && + (!_keyboard->isDirty())) { + PSP_DEBUG_PRINT("Nothing dirty\n"); + DEBUG_EXIT_FUNC(); + return; + } + + PSP_DEBUG_PRINT("screen[%s], overlay[%s], cursor[%s], keyboard[%s]\n", + _screen->isDirty() ? "true" : "false", + _overlay->isDirty() ? "true" : "false", + _cursor->isDirty() ? "true" : "false", + _keyboard->isDirty() ? "true" : "false" + ); + + _masterGuRenderer.guPreRender(); // Set up rendering + + _screen->render(); + + _screen->setClean(); // clean out dirty bit + + if (_overlay->isVisible()) + _overlay->render(); + + _overlay->setClean(); + + if (_cursor->isVisible()) + _cursor->render(); + + _cursor->setClean(); + + if (_keyboard->isVisible()) + _keyboard->render(); + + _keyboard->setClean(); + + _masterGuRenderer.guPostRender(); + + DEBUG_EXIT_FUNC(); +} + +inline bool DisplayManager::isTimeToUpdate() { + +#define MAX_FPS 30 + + uint32 now = g_system->getMillis(); + if (now - _lastUpdateTime < (1000 / MAX_FPS)) + return false; + + _lastUpdateTime = now; + return true; +} + +Common::List<Graphics::PixelFormat> DisplayManager::getSupportedPixelFormats() { + Common::List<Graphics::PixelFormat> list; + + // In order of preference + list.push_back(PSPPixelFormat::convertToScummvmPixelFormat(PSPPixelFormat::Type_5650)); + list.push_back(PSPPixelFormat::convertToScummvmPixelFormat(PSPPixelFormat::Type_5551)); + list.push_back(PSPPixelFormat::convertToScummvmPixelFormat(PSPPixelFormat::Type_4444)); + list.push_back(Graphics::PixelFormat::createFormatCLUT8()); + + return list; +} + diff --git a/backends/platform/psp/display_manager.h b/backends/platform/psp/display_manager.h new file mode 100644 index 0000000000..de5fcf94c8 --- /dev/null +++ b/backends/platform/psp/display_manager.h @@ -0,0 +1,114 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 47541 2010-01-25 01:39:44Z lordhoto $ + * + */ + +#ifndef PSP_DISPLAY_MAN_H +#define PSP_DISPLAY_MAN_H + +/** + * Class used only by DisplayManager to start/stop GU rendering + */ +class MasterGuRenderer { +public: + MasterGuRenderer() : _lastRenderTime(0) {} + void guInit(); + void guPreRender(); + void guPostRender(); + void guShutDown(); +private: + static uint32 _displayList[]; + uint32 _lastRenderTime; // For measuring rendering + void guProgramDisplayBufferSizes(); +}; + +class Screen; +class Overlay; +class Cursor; +class PSPKeyboard; + +/** + * Class that manages all display clients + */ +class DisplayManager { +public: + enum GraphicsModeID { ///> Possible output formats onscreen + CENTERED_320X200, + CENTERED_435X272, + STRETCHED_480X272, + CENTERED_362X272 + }; + DisplayManager() : _screen(0), _cursor(0), _overlay(0), _keyboard(0), _lastUpdateTime(0), _graphicsMode(0) {} + ~DisplayManager(); + + void init(); + void renderAll(); + bool setGraphicsMode(int mode); + bool setGraphicsMode(const char *name); + int getGraphicsMode() const { return _graphicsMode; } + uint32 getDefaultGraphicsMode() const { return STRETCHED_480X272; } + const OSystem::GraphicsMode* getSupportedGraphicsModes() const { return _supportedModes; } + + // Setters + void setScreen(Screen *screen) { _screen = screen; } + void setCursor(Cursor *cursor) { _cursor = cursor; } + void setOverlay(Overlay *overlay) { _overlay = overlay; } + void setKeyboard(PSPKeyboard *keyboard) { _keyboard = keyboard; } + void setSizeAndPixelFormat(uint width, uint height, const Graphics::PixelFormat *format); + + // Getters + float getScaleX() { return _displayParams.scaleX; } + float getScaleY() { return _displayParams.scaleY; } + uint32 getOutputWidth() { return _displayParams.screenOutput.width; } + uint32 getOutputHeight() { return _displayParams.screenOutput.height; } + uint32 getOutputBitsPerPixel() { return _displayParams.outputBitsPerPixel; } + Common::List<Graphics::PixelFormat> getSupportedPixelFormats(); + +private: + struct GlobalDisplayParams { + Dimensions screenOutput; + Dimensions screenSource; + float scaleX; + float scaleY; + uint32 outputBitsPerPixel; // How many bits end up on-screen + GlobalDisplayParams() : scaleX(0.0f), scaleY(0.0f), outputBitsPerPixel(0) {} + }; + + // Pointers to DisplayClients + Screen *_screen; + Cursor *_cursor; + Overlay *_overlay; + PSPKeyboard *_keyboard; + + MasterGuRenderer _masterGuRenderer; + uint32 _lastUpdateTime; // For limiting FPS + int _graphicsMode; + GlobalDisplayParams _displayParams; + static const OSystem::GraphicsMode _supportedModes[]; + + void calculateScaleParams(); // calculates scaling factor + bool isTimeToUpdate(); // should we update the screen now +}; + + +#endif /* PSP_DISPLAY_MAN_H */ diff --git a/backends/platform/psp/input.cpp b/backends/platform/psp/input.cpp new file mode 100644 index 0000000000..bd33175f03 --- /dev/null +++ b/backends/platform/psp/input.cpp @@ -0,0 +1,317 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 43618 2009-08-21 22:44:49Z joostp $ + * + */ + +// Todo: handle events that should fire because of shift going off +// Solution: handle shift on a button-by-button basis, only allowing it when the button is up. Also a inputmap-wide button. At buttonup, shiftstate is inspected per button. + +//#define __PSP_DEBUG_FUNCS__ /* Uncomment for debugging the stack */ +//#define __PSP_DEBUG_PRINT__ /* Uncomment for debug prints */ + +#include "backends/platform/psp/trace.h" + +#include "backends/platform/psp/input.h" + +// Defines for working with PSP buttons +#define CHANGED(x) (_buttonsChanged & (x)) +#define PRESSED(x) ((_buttonsChanged & (x)) && (pad.Buttons & (x))) +#define UNPRESSED(x) ((_buttonsChanged & (x)) && !(pad.Buttons & (x))) +#define DOWN(x) (pad.Buttons & (x)) +#define UP(x) (!(pad.Buttons & (x))) +#define PSP_DPAD (PSP_CTRL_DOWN|PSP_CTRL_UP|PSP_CTRL_LEFT|PSP_CTRL_RIGHT) +#define PSP_4BUTTONS (PSP_CTRL_CROSS | PSP_CTRL_CIRCLE | PSP_CTRL_TRIANGLE | PSP_CTRL_SQUARE) +#define PSP_TRIGGERS (PSP_CTRL_LTRIGGER | PSP_CTRL_RTRIGGER) + +#define PAD_CHECK_TIME 53 + +void InputHandler::init() { + sceCtrlSetSamplingCycle(0); // set sampling to vsync. n = n usecs + sceCtrlSetSamplingMode(1); // analog +} + +bool InputHandler::getAllInputs(Common::Event &event) { + DEBUG_ENTER_FUNC(); + + uint32 time = g_system->getMillis(); // may not be necessary with read + if (time - _lastPadCheckTime < PAD_CHECK_TIME) { + DEBUG_EXIT_FUNC(); + return false; + } + + _lastPadCheckTime = time; + SceCtrlData pad; + + sceCtrlPeekBufferPositive(&pad, 1); // Peek ignores sleep. Read sleeps thread + + bool haveEvent; + + memset(&event, 0, sizeof(event)); + + if (_keyboard->isVisible()) + haveEvent = _keyboard->processInput(event, pad); + else + haveEvent = getEvent(event, pad); + + if (haveEvent) + { + PSP_DEBUG_PRINT("Have event[%s]\n", haveEvent ? "true" : "false"); + PSP_DEBUG_PRINT("event.type[%d]\n", event.type); + } + + DEBUG_EXIT_FUNC(); + + return haveEvent; +} + +bool InputHandler::getEvent(Common::Event &event, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + + _buttonsChanged = pad.Buttons ^ _prevButtons; + bool haveEvent = false; + + // Collect events from different sources + haveEvent = getDpadEvent(event, pad); + + if (!haveEvent) + haveEvent = getButtonEvent(event, pad); + + if (!haveEvent) + haveEvent = getNubEvent(event, pad); + + _prevButtons = pad.Buttons; + + DEBUG_EXIT_FUNC(); + return haveEvent; +} + +bool InputHandler::getDpadEvent(Common::Event &event, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + + int newDpadX = 0, newDpadY = 0; + bool haveEvent = false; + + if (DOWN(PSP_CTRL_UP)) { + newDpadY++; + if (DOWN(PSP_CTRL_RTRIGGER)) // Shifting causes diagonals + newDpadX++; + } + if (DOWN(PSP_CTRL_RIGHT)) { + newDpadX++; + if (DOWN(PSP_CTRL_RTRIGGER)) + newDpadY--; + } + if (DOWN(PSP_CTRL_DOWN)) { + newDpadY--; + if (DOWN(PSP_CTRL_RTRIGGER)) + newDpadX--; + } + if (DOWN(PSP_CTRL_LEFT)) { + newDpadX--; + if (DOWN(PSP_CTRL_RTRIGGER)) + newDpadY++; + } + + if (newDpadX != _dpadX || newDpadY != _dpadY) { + if (_dpadX == 0 && _dpadY == 0) { // We were in the middle so we pressed dpad + event.type = Common::EVENT_KEYDOWN; + event.kbd.keycode = translateDpad(newDpadX, newDpadY); + event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; // Get ascii + _dpadX = newDpadX; + _dpadY = newDpadY; + } + else if (newDpadX == 0 && newDpadY == 0) {// We're now centered so we unpressed dpad + event.type = Common::EVENT_KEYUP; + event.kbd.keycode = translateDpad(_dpadX, _dpadY); + event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; + _dpadX = newDpadX; + _dpadY = newDpadY; + } else { // we moved from one pressed dpad direction to another one + event.type = Common::EVENT_KEYUP; // first release the last dpad direction + event.kbd.keycode = translateDpad(_dpadX, _dpadY); + event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; + _dpadX = 0; // so that we'll pick up a new dpad movement the next round + _dpadY = 0; + } + + PSP_DEBUG_PRINT("Keypad event. DpadX[%d], DpadY[%d]\n", _dpadX, _dpadY); + haveEvent = true; + } + + DEBUG_EXIT_FUNC(); + return haveEvent; +} + +inline Common::KeyCode InputHandler::translateDpad(int x, int y) { + DEBUG_ENTER_FUNC(); + Common::KeyCode key; + + if (x == -1) { + if (y == -1) + key = Common::KEYCODE_KP1; + else if (y == 0) + key = Common::KEYCODE_KP4; + else /* y == 1 */ + key = Common::KEYCODE_KP7; + } else if (x == 0) { + if (y == -1) + key = Common::KEYCODE_KP2; + else /* y == 1 */ + key = Common::KEYCODE_KP8; + } else {/* x == 1 */ + if (y == -1) + key = Common::KEYCODE_KP3; + else if (y == 0) + key = Common::KEYCODE_KP6; + else /* y == 1 */ + key = Common::KEYCODE_KP9; + } + + DEBUG_EXIT_FUNC(); + return key; +} + + +bool InputHandler::getButtonEvent(Common::Event &event, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + bool haveEvent = false; + + if (PRESSED(PSP_CTRL_SELECT)) + _keyboard->setVisible(true); + + else if (CHANGED(PSP_4BUTTONS | PSP_TRIGGERS | PSP_CTRL_START)) { + if (CHANGED(PSP_CTRL_CROSS)) { + event.type = DOWN(PSP_CTRL_CROSS) ? Common::EVENT_LBUTTONDOWN : Common::EVENT_LBUTTONUP; + event.mouse.x = _cursor->getX(); // Could this have to do with SCI enter problem? + event.mouse.y = _cursor->getY(); + PSP_DEBUG_PRINT("%s\n", event.type == Common::EVENT_LBUTTONDOWN ? "LButtonDown" : "LButtonUp"); + } else if (CHANGED(PSP_CTRL_CIRCLE)) { + event.type = DOWN(PSP_CTRL_CIRCLE) ? Common::EVENT_RBUTTONDOWN : Common::EVENT_RBUTTONUP; + event.mouse.x = _cursor->getX(); + event.mouse.y = _cursor->getY(); + PSP_DEBUG_PRINT("%s\n", event.type == Common::EVENT_LBUTTONDOWN ? "RButtonDown" : "RButtonUp"); + } else { + //any of the other buttons. + event.type = _buttonsChanged & pad.Buttons ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP; + event.kbd.ascii = 0; + event.kbd.flags = 0; + + if (CHANGED(PSP_CTRL_LTRIGGER)) { + event.kbd.keycode = Common::KEYCODE_ESCAPE; + event.kbd.ascii = 27; + } else if (CHANGED(PSP_CTRL_START)) { + event.kbd.keycode = Common::KEYCODE_F5; + event.kbd.ascii = Common::ASCII_F5; + if (DOWN(PSP_CTRL_RTRIGGER)) { + event.kbd.flags |= Common::KBD_CTRL; // Main menu to allow RTL + } + } else if (CHANGED(PSP_CTRL_SQUARE)) { + event.kbd.keycode = Common::KEYCODE_PERIOD; + event.kbd.ascii = '.'; + } else if (CHANGED(PSP_CTRL_TRIANGLE)) { + event.kbd.keycode = Common::KEYCODE_RETURN; + event.kbd.ascii = '\r'; + } else if (DOWN(PSP_CTRL_RTRIGGER)) { // An event + event.kbd.flags |= Common::KBD_SHIFT; + } + PSP_DEBUG_PRINT("Ascii[%d]. Key %s.\n", event.kbd.ascii, event.type == Common::EVENT_KEYDOWN ? "down" : "up" ); + } + + haveEvent = true; + } + + DEBUG_EXIT_FUNC(); + return haveEvent; +} + +bool InputHandler::getNubEvent(Common::Event &event, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + + bool haveEvent = false; + int32 analogStepX = pad.Lx; // Goes up to 255. + int32 analogStepY = pad.Ly; + + int32 oldX = _cursor->getX(); + int32 oldY = _cursor->getY(); + + analogStepX = modifyNubAxisMotion(analogStepX); + analogStepY = modifyNubAxisMotion(analogStepY); + + if (analogStepX != 0 || analogStepY != 0) { + + PSP_DEBUG_PRINT("raw x[%d], y[%d]\n", analogStepX, analogStepY); + + // If no movement then this has no effect + if (DOWN(PSP_CTRL_RTRIGGER)) { + // Fine control mode for analog + if (analogStepX != 0) { + if (analogStepX > 0) + _cursor->increaseXY(2, 0); + else + _cursor->increaseXY(-2, 0); + } + + if (analogStepY != 0) { + if (analogStepY > 0) + _cursor->increaseXY(0, 2); + else + _cursor->increaseXY(0, -2); + } + } else { // Regular speed movement + _cursor->increaseXY(analogStepX, 0); + _cursor->increaseXY(0, analogStepY); + } + + int32 newX = _cursor->getX(); + int32 newY = _cursor->getY(); + + if ((oldX != newX) || (oldY != newY)) { + event.type = Common::EVENT_MOUSEMOVE; + event.mouse.x = newX; + event.mouse.y = newY; + haveEvent = true; + + PSP_DEBUG_PRINT("Nub event. X[%d], Y[%d]\n", newX, newY); + } + } + DEBUG_EXIT_FUNC(); + return haveEvent; +} + +inline int32 InputHandler::modifyNubAxisMotion(int32 input) { + DEBUG_ENTER_FUNC(); + const int MIN_NUB_MOTION = 30; + + input -= 128; // Center on 0. + + if (input < -MIN_NUB_MOTION - 1) + input += MIN_NUB_MOTION + 1; // reduce the velocity + else if (input > MIN_NUB_MOTION) + input -= MIN_NUB_MOTION; // same + else // between these points, dampen the response to 0 + input = 0; + + + DEBUG_EXIT_FUNC(); + return input; +} diff --git a/backends/platform/psp/input.h b/backends/platform/psp/input.h new file mode 100644 index 0000000000..64775b9b1d --- /dev/null +++ b/backends/platform/psp/input.h @@ -0,0 +1,63 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 43618 2009-08-21 22:44:49Z joostp $ + * + */ + +#ifndef PSP_INPUT_H +#define PSP_INPUT_H + +#include "common/scummsys.h" +#include "common/events.h" +#include "backends/platform/psp/display_client.h" +#include "backends/platform/psp/default_display_client.h" +#include "backends/platform/psp/pspkeyboard.h" +#include "backends/platform/psp/cursor.h" +#include <pspctrl.h> + +class InputHandler { +public: + InputHandler() : _cursor(0), _keyboard(0), _prevButtons(0), _lastPadCheckTime(0), _buttonsChanged(0), _dpadX(0), _dpadY(0) {} + + void init(); + bool getAllInputs(Common::Event &event); + void setKeyboard(PSPKeyboard *keyboard) { _keyboard = keyboard; } + void setCursor(Cursor *cursor) { _cursor = cursor; } + +private: + Cursor *_cursor; + PSPKeyboard *_keyboard; + uint32 _prevButtons; + uint32 _lastPadCheckTime; + uint32 _buttonsChanged; + int32 _dpadX, _dpadY; + int32 _accelX, _accelY; + + bool getEvent(Common::Event &event, SceCtrlData &pad); + bool getDpadEvent(Common::Event &event, SceCtrlData &pad); + bool getButtonEvent(Common::Event &event, SceCtrlData &pad); + bool getNubEvent(Common::Event &event, SceCtrlData &pad); + int32 modifyNubAxisMotion(int32 input); + Common::KeyCode translateDpad(int x, int y); +}; + +#endif /* PSP_INPUT_H */ diff --git a/backends/platform/psp/memory.cpp b/backends/platform/psp/memory.cpp new file mode 100644 index 0000000000..9cf7ba7c6c --- /dev/null +++ b/backends/platform/psp/memory.cpp @@ -0,0 +1,227 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $ + * + */ + +#include "common/scummsys.h" +#include "common/singleton.h" +#include "common/list.h" +#include "backends/platform/psp/psppixelformat.h" +#include "backends/platform/psp/memory.h" + +// Class Copier -------------------------------------------------------------------------- +//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ +//#define __PSP_DEBUG_PRINT__ + +#include "backends/platform/psp/trace.h" + +void Copier::copy(byte *dst, const byte *src, uint32 bytes, PSPPixelFormat *format /* = NULL */) { + DEBUG_ENTER_FUNC(); + + uint32 prefixDst = (((uint32)dst) & 0x3); + prefixDst = prefixDst ? 4 - prefixDst : 0; // prefix only if we have address % 4 != 0 + uint32 prefixSrc = (((uint32)src) & 0x3); + prefixSrc = prefixSrc ? 4 - prefixSrc : 0; // prefix only if we have address % 4 != 0 + uint32 *dst32, *src32; + bool swapRB = format ? format->swapRB : false; // take swap value from pixelformat if it's given +#ifdef __PSP_DEBUG_PRINT__ + uint32 debugBytes = bytes; + const byte *debugDst = dst, *debugSrc = src; +#endif + uint32 words, remainingBytes; + + //PSP_DEBUG_PRINT("dst[%p], src[%p], bytes[%d], swap[%s], prefixDst[%u], prefixSrc[%u]\n", dst, src, bytes, swapRB ? "true" : "false", prefixDst, prefixSrc); + + if (prefixDst || prefixSrc) { // we're not aligned to word boundaries + if (prefixDst != prefixSrc) { // worst case: we can never be aligned. this mode is highly inefficient. try to get engines not to use this mode too much + PSP_DEBUG_PRINT("misaligned copy of %u bytes from %p to %p\n", bytes, src, dst); + if ((prefixDst & 1) || (prefixSrc & 1)) + copy8(dst, src, bytes); // no swap is possible on 8 bit + else + copy16((uint16 *)dst, (uint16 *)src, bytes, format); + + goto test; + } + + // Do the prefix: the part to get us aligned + if (prefixDst & 1) { // byte + copy8(dst, src, prefixDst); // no swap available + } else { // short + copy16((uint16 *)dst, (uint16 *)src, prefixDst, format); + } + if (bytes > prefixDst) // check that we can afford to subtract from bytes + bytes -= prefixDst; + else { + DEBUG_EXIT_FUNC(); + return; + } + dst32 = (uint32 *)(dst + prefixDst); + src32 = (uint32 *)(src + prefixSrc); + } else { // We're aligned to word boundaries + dst32 = (uint32 *)dst; + src32 = (uint32 *)src; + } + + words = bytes >> 2; + remainingBytes = bytes & 0x3; + + if (swapRB) { // need to swap + for (; words > 0; words--) { + *dst32 = format->swapRedBlue32(*src32); + dst32++; + src32++; + } + } else { // no swapping + for (; words > 0; words--) { + *dst32 = *src32; + dst32++; + src32++; + } + } + + // Do any remaining bytes + if (remainingBytes) { + if (remainingBytes & 1) // we have bytes left + copy8((byte *)dst32, (byte *)src32, remainingBytes); + else // 16bits left + copy16((uint16*)dst32, (uint16 *)src32, remainingBytes, format); + } + +test: + // debug +#ifdef __PSP_DEBUG_PRINT__ + bool mismatch = false; + + for (uint32 i=0; i<debugBytes; i++) { + if (debugDst[i] != debugSrc[i]) { + if (mismatch == false) { + PSP_DEBUG_PRINT_SAMELN("mismatch in copy:\n"); + PSP_DEBUG_PRINT("dst[%p], src[%p], bytes[%u], swap[%s], prefixDst[%u], prefixSrc[%u]\n", debugDst, debugSrc, debugBytes, swapRB ? "true" : "false", prefixDst, prefixSrc); + mismatch = true; + } + PSP_DEBUG_PRINT_SAMELN("%x!=%x ", debugSrc[i], debugDst[i]); + } + } + if (mismatch) + PSP_DEBUG_PRINT("\n"); +#endif + + DEBUG_EXIT_FUNC(); +} + +inline void Copier::copy8(byte *dst, const byte *src, uint32 bytes) { + for (; bytes > 0; bytes--) { + *dst = *src; + dst++; + src++; + } +} + +inline void Copier::copy16(uint16 *dst, const uint16 *src, uint32 bytes, PSPPixelFormat *format /* = NULL */) { + uint32 shorts = bytes >> 1; + uint32 remainingBytes = bytes & 1; + bool swapRB = format ? format->swapRB : false; + + if (swapRB) { + for (; shorts > 0 ; shorts--) { + *dst = format->swapRedBlue16(*src); + dst++; + src++; + } + } else { + for (; shorts > 0 ; shorts--) { + *dst = *src; + dst++; + src++; + } + } + if (remainingBytes) + *(byte *)dst = *(byte *)src; +} + + +// Class VramAllocator ----------------------------------- + +DECLARE_SINGLETON(VramAllocator) + +//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ +//#define __PSP_DEBUG_PRINT__ + +#include "backends/platform/psp/trace.h" + + +void *VramAllocator::allocate(int32 size, bool smallAllocation /* = false */) { + DEBUG_ENTER_FUNC(); + assert (size > 0); + + byte *lastAddress = smallAllocation ? (byte *)VRAM_SMALL_ADDRESS : (byte *)VRAM_START_ADDRESS; + Common::List<Allocation>::iterator i; + + // Find a block that fits, starting from the beginning + for (i = _allocList.begin(); i != _allocList.end(); ++i) { + byte *currAddress = (*i).address; + + if (currAddress - lastAddress >= size) // We found a match + break; + + if ((*i).getEnd() > lastAddress) + lastAddress = (byte *)(*i).getEnd(); + } + + if (lastAddress + size > (byte *)VRAM_END_ADDRESS) { + PSP_DEBUG_PRINT("No space for allocation of %d bytes. %d bytes already allocated.\n", + size, _bytesAllocated); + return NULL; + } + + _allocList.insert(i, Allocation(lastAddress, size)); + _bytesAllocated += size; + + PSP_DEBUG_PRINT("Allocated in VRAM, size %u at %p.\n", size, lastAddress); + PSP_DEBUG_PRINT("Total allocated %u, remaining %u.\n", _bytesAllocated, (2 * 1024 * 1024) - _bytesAllocated); + + DEBUG_EXIT_FUNC(); + return lastAddress; +} + +// Deallocate a block from VRAM +void VramAllocator::deallocate(void *address) { + DEBUG_ENTER_FUNC(); + address = (byte *)CACHED(address); // Make sure all addresses are the same + + Common::List<Allocation>::iterator i; + + // Find the Allocator to deallocate + for (i = _allocList.begin(); i != _allocList.end(); ++i) { + if ((*i).address == address) { + _bytesAllocated -= (*i).size; + _allocList.erase(i); + PSP_DEBUG_PRINT("Deallocated address[%p], size[%u]\n", (*i).address, (*i).size); + DEBUG_EXIT_FUNC(); + return; + } + } + + PSP_DEBUG_PRINT("Address[%p] not allocated.\n", address); + DEBUG_EXIT_FUNC(); +} diff --git a/backends/platform/psp/memory.h b/backends/platform/psp/memory.h new file mode 100644 index 0000000000..79af46c68b --- /dev/null +++ b/backends/platform/psp/memory.h @@ -0,0 +1,80 @@ + +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $ + * + */ + +#ifndef PSP_MEMORY_H +#define PSP_MEMORY_H + +#define UNCACHED(x) ((byte *)(((uint32)(x)) | 0x40000000)) /* make an uncached access */ +#define CACHED(x) ((byte *)(((uint32)(x)) & 0xBFFFFFFF)) /* make an uncached access into a cached one */ + +/** + * Class that does memory copying and swapping if needed + */ +class Copier { +public: + static void copy(byte *dst, const byte *src, uint32 bytes, PSPPixelFormat *format = NULL); + static void copy8(byte *dst, const byte *src, uint32 bytes); + static void copy16(uint16 *dst, const uint16 *src, uint32 bytes, PSPPixelFormat *format = NULL); +}; + +/** + * Class that allocates memory in the VRAM + */ +class VramAllocator : public Common::Singleton<VramAllocator> { +public: + VramAllocator() : _bytesAllocated(0) {} + void *allocate(int32 size, bool smallAllocation = false); // smallAllocation e.g. palettes + void deallocate(void *pointer); + + static inline bool isAddressInVram(void *address) { + if ((uint32)(CACHED(address)) >= VRAM_START_ADDRESS && (uint32)(CACHED(address)) < VRAM_END_ADDRESS) + return true; + return false; +} + + +private: + /** + * Used to allocate in VRAM + */ + struct Allocation { + byte *address; + uint32 size; + void *getEnd() { return address + size; } + Allocation(void *Address, uint32 Size) : address((byte *)Address), size(Size) {} + Allocation() : address(0), size(0) {} + }; + + enum { + VRAM_START_ADDRESS = 0x04000000, + VRAM_END_ADDRESS = 0x04200000, + VRAM_SMALL_ADDRESS = VRAM_END_ADDRESS - (4*1024) // 4K in the end for small allocations + }; + Common::List <Allocation> _allocList; // List of allocations + uint32 _bytesAllocated; +}; + +#endif /* PSP_MEMORY_H */ diff --git a/backends/platform/psp/module.mk b/backends/platform/psp/module.mk index 4396530d5b..f7191fe14f 100644 --- a/backends/platform/psp/module.mk +++ b/backends/platform/psp/module.mk @@ -1,9 +1,15 @@ MODULE := backends/platform/psp -MODULE_OBJS := \ - powerman.o \ +MODULE_OBJS := powerman.o \ psp_main.o \ osys_psp.o \ + psppixelformat.o \ + memory.o \ + display_manager.o \ + display_client.o \ + default_display_client.o \ + input.o \ + cursor.o \ trace.o \ psploader.o \ pspkeyboard.o diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp index 8b4c005221..022c10f5a8 100644 --- a/backends/platform/psp/osys_psp.cpp +++ b/backends/platform/psp/osys_psp.cpp @@ -23,6 +23,7 @@ * */ +#include <pspuser.h> #include <pspgu.h> #include <pspdisplay.h> @@ -33,40 +34,21 @@ #include "common/events.h" #include "common/scummsys.h" -#include "osys_psp.h" -#include "trace.h" -#include "powerman.h" +#include "backends/platform/psp/osys_psp.h" +#include "backends/platform/psp/powerman.h" #include "backends/saves/psp/psp-saves.h" #include "backends/timer/default/default-timer.h" #include "graphics/surface.h" #include "sound/mixer_intern.h" -#include "backends/platform/psp/pspkeyboard.h" +//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */ +//#define __PSP_DEBUG_PRINT__ /* For debug printouts */ +#include "backends/platform/psp/trace.h" -#define SAMPLES_PER_SEC 44100 - -#define PIXEL_SIZE (4) -#define BUF_WIDTH (512) -#define PSP_SCREEN_WIDTH 480 -#define PSP_SCREEN_HEIGHT 272 -#define PSP_FRAME_SIZE (BUF_WIDTH * PSP_SCREEN_HEIGHT * PIXEL_SIZE) -#define MOUSE_SIZE 128 -#define KBD_DATA_SIZE 130560 - -#define MAX_FPS 30 - -unsigned int __attribute__((aligned(16))) displayList[2048]; -unsigned short __attribute__((aligned(16))) clut256[256]; -unsigned short __attribute__((aligned(16))) mouseClut[256]; -unsigned short __attribute__((aligned(16))) cursorPalette[256]; -unsigned int __attribute__((aligned(16))) mouseBuf256[MOUSE_SIZE*MOUSE_SIZE]; - -unsigned long RGBToColour(unsigned long r, unsigned long g, unsigned long b) { - return (((b >> 3) << 10) | ((g >> 3) << 5) | ((r >> 3) << 0)) | 0x8000; -} +#define SAMPLES_PER_SEC 44100 static int timer_handler(int t) { DefaultTimerManager *tm = (DefaultTimerManager *)g_system->getTimerManager(); @@ -74,87 +56,51 @@ static int timer_handler(int t) { return t; } -const OSystem::GraphicsMode OSystem_PSP::s_supportedGraphicsModes[] = { - { "320x200 (centered)", "320x200 16-bit centered", CENTERED_320X200 }, - { "435x272 (best-fit, centered)", "435x272 16-bit centered", CENTERED_435X272 }, - { "480x272 (full screen)", "480x272 16-bit stretched", STRETCHED_480X272 }, - { "362x272 (4:3, centered)", "362x272 16-bit centered", CENTERED_362X272 }, - {0, 0, 0} -}; - - -OSystem_PSP::OSystem_PSP() : _screenWidth(0), _screenHeight(0), _overlayWidth(0), _overlayHeight(0), - _offscreen(0), _overlayBuffer(0), _overlayVisible(false), _shakePos(0), _lastScreenUpdate(0), - _mouseBuf(0), _prevButtons(0), _lastPadCheck(0), _mixer(0) { - memset(_palette, 0, sizeof(_palette)); - - _cursorPaletteDisabled = true; - - //init SDL - uint32 sdlFlags = SDL_INIT_AUDIO | SDL_INIT_TIMER; - SDL_Init(sdlFlags); - - _clut = clut256; - _mouseBuf = (byte *)mouseBuf256; - _graphicMode = STRETCHED_480X272; - - _mouseX = PSP_SCREEN_WIDTH >> 1; // Mouse in the middle of the screen - _mouseY = PSP_SCREEN_HEIGHT >> 1; - _dpadX = _dpadY = 0; - - - // Init GU - sceGuInit(); - sceGuStart(0, displayList); - sceGuDrawBuffer(GU_PSM_8888, (void *)0, BUF_WIDTH); - sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, (void*)PSP_FRAME_SIZE, BUF_WIDTH); - sceGuDepthBuffer((void*)(PSP_FRAME_SIZE * 2), BUF_WIDTH); - sceGuOffset(2048 - (PSP_SCREEN_WIDTH/2), 2048 - (PSP_SCREEN_HEIGHT/2)); - sceGuViewport(2048, 2048, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT); - sceGuDepthRange(0xC350, 0x2710); - sceGuScissor(0, 0, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT); - sceGuEnable(GU_SCISSOR_TEST); - sceGuFrontFace(GU_CW); - sceGuEnable(GU_TEXTURE_2D); - sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT); - sceGuFinish(); - sceGuSync(0,0); - - sceDisplayWaitVblankStart(); - sceGuDisplay(1); - +void OSystem_PSP::initSDL() { + SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER); } -OSystem_PSP::~OSystem_PSP() { +OSystem_PSP::~OSystem_PSP() {} - free(_offscreen); - free(_overlayBuffer); - free(_mouseBuf); - delete _keyboard; +#define PSP_SCREEN_WIDTH 480 +#define PSP_SCREEN_HEIGHT 272 - _offscreen = 0; - _overlayBuffer = 0; - _mouseBuf = 0; - sceGuTerm(); -} +void OSystem_PSP::initBackend() { + DEBUG_ENTER_FUNC(); + _cursor.enableCursorPalette(false); + _cursor.setXY(PSP_SCREEN_WIDTH >> 1, PSP_SCREEN_HEIGHT >> 1); // Mouse in the middle of the screen + + // Set pointers for display manager + _displayManager.setCursor(&_cursor); + _displayManager.setScreen(&_screen); + _displayManager.setOverlay(&_overlay); + _displayManager.setKeyboard(&_keyboard); + _displayManager.init(); + + // Set pointers for input handler + _inputHandler.setCursor(&_cursor); + _inputHandler.setKeyboard(&_keyboard); + _inputHandler.init(); + + initSDL(); -void OSystem_PSP::initBackend() { _savefile = new PSPSaveFileManager; _timer = new DefaultTimerManager(); - _keyboard = new PSPKeyboard(); - _keyboard->load(); - + PSP_DEBUG_PRINT("calling keyboard.load()\n"); + _keyboard.load(); // Load virtual keyboard files into memory + setTimerCallback(&timer_handler, 10); setupMixer(); OSystem::initBackend(); + + DEBUG_EXIT_FUNC(); } - bool OSystem_PSP::hasFeature(Feature f) { return (f == kFeatureOverlaySupportsAlpha || f == kFeatureCursorHasPalette); } @@ -167,733 +113,251 @@ bool OSystem_PSP::getFeatureState(Feature f) { } const OSystem::GraphicsMode* OSystem_PSP::getSupportedGraphicsModes() const { - return s_supportedGraphicsModes; + return _displayManager.getSupportedGraphicsModes(); } - int OSystem_PSP::getDefaultGraphicsMode() const { - return STRETCHED_480X272; + DEBUG_ENTER_FUNC(); + + int ret = _displayManager.getDefaultGraphicsMode(); + + DEBUG_EXIT_FUNC(); + return ret; } bool OSystem_PSP::setGraphicsMode(int mode) { - _graphicMode = mode; - return true; + DEBUG_ENTER_FUNC(); + + int ret = _displayManager.setGraphicsMode(mode); + + DEBUG_EXIT_FUNC(); + return ret; } bool OSystem_PSP::setGraphicsMode(const char *name) { - int i = 0; - - while (s_supportedGraphicsModes[i].name) { - if (!strcmpi(s_supportedGraphicsModes[i].name, name)) { - _graphicMode = s_supportedGraphicsModes[i].id; - return true; - } - i++; - } - - return false; + DEBUG_ENTER_FUNC(); + + int ret = _displayManager.setGraphicsMode(name); + + DEBUG_EXIT_FUNC(); + return ret; } int OSystem_PSP::getGraphicsMode() const { - return _graphicMode; + DEBUG_ENTER_FUNC(); + + int ret = _displayManager.getGraphicsMode(); + + DEBUG_EXIT_FUNC(); + return ret; } -void OSystem_PSP::initSize(uint width, uint height, const Graphics::PixelFormat *format) { - PSPDebugTrace("initSize\n"); - - _screenWidth = width; - _screenHeight = height; +#ifdef USE_RGB_COLOR - const int scrBufSize = _screenWidth * _screenHeight * (format ? format->bytesPerPixel : 4); +Graphics::PixelFormat OSystem_PSP::getScreenFormat() const { + return _screen.getScummvmPixelFormat(); +} - _overlayWidth = PSP_SCREEN_WIDTH; //width; - _overlayHeight = PSP_SCREEN_HEIGHT; //height; +Common::List<Graphics::PixelFormat> OSystem_PSP::getSupportedFormats() { + return _displayManager.getSupportedPixelFormats(); +} - free(_overlayBuffer); - _overlayBuffer = (OverlayColor *)memalign(16, _overlayWidth * _overlayHeight * sizeof(OverlayColor)); +#endif - free(_offscreen); - _offscreen = (byte *)memalign(16, scrBufSize); - bzero(_offscreen, scrBufSize); +void OSystem_PSP::initSize(uint width, uint height, const Graphics::PixelFormat *format) { + DEBUG_ENTER_FUNC(); + + _displayManager.setSizeAndPixelFormat(width, height, format); - clearOverlay(); - memset(_palette, 0xFFFF, 256 * sizeof(unsigned short)); + _cursor.setVisible(false); + _cursor.setLimits(_screen.getWidth(), _screen.getHeight()); - _mouseVisible = false; - sceKernelDcacheWritebackAll(); + DEBUG_EXIT_FUNC(); } int16 OSystem_PSP::getWidth() { - return _screenWidth; + DEBUG_ENTER_FUNC(); + + int16 ret = (int16)_screen.getWidth(); + + DEBUG_EXIT_FUNC(); + return ret; } int16 OSystem_PSP::getHeight() { - return _screenHeight; + DEBUG_ENTER_FUNC(); + + int16 ret = (int16)_screen.getHeight(); + + DEBUG_EXIT_FUNC(); + return ret; } void OSystem_PSP::setPalette(const byte *colors, uint start, uint num) { - const byte *b = colors; + DEBUG_ENTER_FUNC(); + + _screen.setPartialPalette(colors, start, num); + _cursor.setScreenPalette(colors, start, num); + _cursor.clearKeyColor(); - for (uint i = 0; i < num; ++i) { - _palette[start + i] = RGBToColour(b[0], b[1], b[2]); - b += 4; - } - - //copy to CLUT - memcpy(_clut, _palette, 256 * sizeof(unsigned short)); - - //force update of mouse CLUT as well, as it may have been set up before this palette was set - memcpy(mouseClut, _palette, 256 * sizeof(unsigned short)); - mouseClut[_mouseKeyColour] = 0; - - sceKernelDcacheWritebackAll(); + DEBUG_EXIT_FUNC(); } void OSystem_PSP::setCursorPalette(const byte *colors, uint start, uint num) { - const byte *b = colors; - - for (uint i = 0; i < num; ++i) { - cursorPalette[start + i] = RGBToColour(b[0], b[1], b[2]); - b += 4; - } - - cursorPalette[0] = 0; + DEBUG_ENTER_FUNC(); - _cursorPaletteDisabled = false; + _cursor.setCursorPalette(colors, start, num); + _cursor.enableCursorPalette(true); + _cursor.clearKeyColor(); // Do we need this? - sceKernelDcacheWritebackAll(); + DEBUG_EXIT_FUNC(); } void OSystem_PSP::disableCursorPalette(bool disable) { - _cursorPaletteDisabled = disable; + DEBUG_ENTER_FUNC(); + + _cursor.enableCursorPalette(!disable); + + DEBUG_EXIT_FUNC(); } void OSystem_PSP::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) { - //Clip the coordinates - if (x < 0) { - w += x; - buf -= x; - x = 0; - } - - if (y < 0) { - h += y; - buf -= y * pitch; - y = 0; - } - - if (w > _screenWidth - x) { - w = _screenWidth - x; - } - - if (h > _screenHeight - y) { - h = _screenHeight - y; - } - - if (w <= 0 || h <= 0) - return; + DEBUG_ENTER_FUNC(); + _screen.copyFromRect(buf, pitch, x, y, w, h); - byte *dst = _offscreen + y * _screenWidth + x; - - if (_screenWidth == pitch && pitch == w) { - memcpy(dst, buf, h * w); - } else { - do { - memcpy(dst, buf, w); - buf += pitch; - dst += _screenWidth; - } while (--h); - } - sceKernelDcacheWritebackAll(); - + DEBUG_EXIT_FUNC(); } Graphics::Surface *OSystem_PSP::lockScreen() { - _framebuffer.pixels = _offscreen; - _framebuffer.w = _screenWidth; - _framebuffer.h = _screenHeight; - _framebuffer.pitch = _screenWidth; - _framebuffer.bytesPerPixel = 1; + DEBUG_ENTER_FUNC(); - return &_framebuffer; + Graphics::Surface *ret = _screen.lockAndGetForEditing(); + + DEBUG_EXIT_FUNC(); + return ret; } void OSystem_PSP::unlockScreen() { - // The screen is always completely update anyway, so we don't have to force a full update here. - sceKernelDcacheWritebackAll(); + DEBUG_ENTER_FUNC(); + // The screen is always completely updated anyway, so we don't have to force a full update here. + _screen.unlock(); + + DEBUG_EXIT_FUNC(); } void OSystem_PSP::updateScreen() { - u32 now = getMillis(); - if (now - _lastScreenUpdate < 1000 / MAX_FPS) - return; - - _lastScreenUpdate = now; - - sceGuStart(0, displayList); - - sceGuClearColor(0xFF000000); - sceGuClear(GU_COLOR_BUFFER_BIT); - - sceGuClutMode(GU_PSM_5551, 0, 0xFF, 0); - sceGuClutLoad(32, clut256); // upload 32*8 entries (256) - sceGuTexMode(GU_PSM_T8, 0, 0, 0); // 8-bit image - if (_screenWidth == 320) - sceGuTexImage(0, 512, 256, _screenWidth, _offscreen); - else - sceGuTexImage(0, 512, 512, _screenWidth, _offscreen); - sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB); - sceGuTexFilter(GU_LINEAR, GU_LINEAR); - sceGuTexOffset(0,0); - sceGuAmbientColor(0xFFFFFFFF); - sceGuColor(0xFFFFFFFF); - - Vertex *vertices = (Vertex *)sceGuGetMemory(2 * sizeof(Vertex)); - vertices[0].u = 0.5f; - vertices[0].v = 0.5f; - vertices[1].u = _screenWidth - 0.5f; - vertices[1].v = _screenHeight - 0.5f; - - switch (_graphicMode) { - case CENTERED_320X200: - vertices[0].x = (PSP_SCREEN_WIDTH - 320) / 2; - vertices[0].y = (PSP_SCREEN_HEIGHT - 200) / 2; - vertices[0].z = 0; - vertices[1].x = PSP_SCREEN_WIDTH - (PSP_SCREEN_WIDTH - 320) / 2; - vertices[1].y = PSP_SCREEN_HEIGHT - (PSP_SCREEN_HEIGHT - 200) / 2; - vertices[1].z = 0; - break; - case CENTERED_435X272: - vertices[0].x = (PSP_SCREEN_WIDTH - 435) / 2; - vertices[0].y = 0; vertices[0].z = 0; - vertices[1].x = PSP_SCREEN_WIDTH - (PSP_SCREEN_WIDTH - 435) / 2; - vertices[1].y = PSP_SCREEN_HEIGHT; - vertices[1].z = 0; - break; - case STRETCHED_480X272: - vertices[0].x = 0; - vertices[0].y = 0; - vertices[0].z = 0; - vertices[1].x = PSP_SCREEN_WIDTH; - vertices[1].y = PSP_SCREEN_HEIGHT; - vertices[1].z = 0; - break; - case CENTERED_362X272: - vertices[0].x = (PSP_SCREEN_WIDTH - 362) / 2; - vertices[0].y = 0; - vertices[0].z = 0; - vertices[1].x = PSP_SCREEN_WIDTH - (PSP_SCREEN_WIDTH - 362) / 2; - vertices[1].y = PSP_SCREEN_HEIGHT; - vertices[1].z = 0; - break; - } - - if (_shakePos) { - vertices[0].y += _shakePos; - vertices[1].y += _shakePos; - } - - sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices); - if (_screenWidth == 640) { - // 2nd draw - Vertex *vertices2 = (Vertex *)sceGuGetMemory(2 * sizeof(Vertex)); - sceGuTexImage(0, 512, 512, _screenWidth, _offscreen+512); - vertices2[0].u = 512 + 0.5f; - vertices2[0].v = vertices[0].v; - vertices2[1].u = vertices[1].u; - vertices2[1].v = _screenHeight - 0.5f; - vertices2[0].x = vertices[0].x + (vertices[1].x - vertices[0].x) * 511 / 640; - vertices2[0].y = 0; - vertices2[0].z = 0; - vertices2[1].x = vertices[1].x; - vertices2[1].y = vertices[1].y; - vertices2[1].z = 0; - sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices2); - } - - - // draw overlay - if (_overlayVisible) { - Vertex *vertOverlay = (Vertex *)sceGuGetMemory(2 * sizeof(Vertex)); - vertOverlay[0].x = 0; - vertOverlay[0].y = 0; - vertOverlay[0].z = 0; - vertOverlay[1].x = PSP_SCREEN_WIDTH; - vertOverlay[1].y = PSP_SCREEN_HEIGHT; - vertOverlay[1].z = 0; - vertOverlay[0].u = 0.5f; - vertOverlay[0].v = 0.5f; - vertOverlay[1].u = _overlayWidth - 0.5f; - vertOverlay[1].v = _overlayHeight - 0.5f; - sceGuTexMode(GU_PSM_4444, 0, 0, 0); // 16-bit image - sceGuDisable(GU_ALPHA_TEST); - sceGuEnable(GU_BLEND); - - //sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); - sceGuBlendFunc(GU_ADD, GU_FIX, GU_ONE_MINUS_SRC_ALPHA, 0xFFFFFFFF, 0); - - if (_overlayWidth > 320) - sceGuTexImage(0, 512, 512, _overlayWidth, _overlayBuffer); - else - sceGuTexImage(0, 512, 256, _overlayWidth, _overlayBuffer); - - sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA); - sceGuDrawArray(GU_SPRITES,GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D,2,0,vertOverlay); - // need to render twice for textures > 512 - if ( _overlayWidth > 512) { - Vertex *vertOverlay2 = (Vertex *)sceGuGetMemory(2 * sizeof(Vertex)); - sceGuTexImage(0, 512, 512, _overlayWidth, _overlayBuffer + 512); - vertOverlay2[0].u = 512 + 0.5f; - vertOverlay2[0].v = vertOverlay[0].v; - vertOverlay2[1].u = vertOverlay[1].u; - vertOverlay2[1].v = _overlayHeight - 0.5f; - vertOverlay2[0].x = PSP_SCREEN_WIDTH * 512 / 640; - vertOverlay2[0].y = 0; - vertOverlay2[0].z = 0; - vertOverlay2[1].x = PSP_SCREEN_WIDTH; - vertOverlay2[1].y = PSP_SCREEN_HEIGHT; - vertOverlay2[1].z = 0; - sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertOverlay2); - } - sceGuDisable(GU_BLEND); - } + DEBUG_ENTER_FUNC(); - // draw mouse - if (_mouseVisible) { - sceGuTexMode(GU_PSM_T8, 0, 0, 0); // 8-bit image - sceGuClutMode(GU_PSM_5551, 0, 0xFF, 0); - sceGuClutLoad(32, _cursorPaletteDisabled ? mouseClut : cursorPalette); // upload 32*8 entries (256) - sceGuAlphaFunc(GU_GREATER, 0, 0xFF); - sceGuEnable(GU_ALPHA_TEST); - sceGuTexImage(0, MOUSE_SIZE, MOUSE_SIZE, MOUSE_SIZE, _mouseBuf); - sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA); - - Vertex *vertMouse = (Vertex *)sceGuGetMemory(2 * sizeof(Vertex)); - vertMouse[0].u = 0.5f; - vertMouse[0].v = 0.5f; - vertMouse[1].u = _mouseWidth - 0.5f; - vertMouse[1].v = _mouseHeight - 0.5f; - - //adjust cursor position - int mX = _mouseX - _mouseHotspotX; - int mY = _mouseY - _mouseHotspotY; - - if (_overlayVisible) { - float scalex, scaley; - - scalex = (float)PSP_SCREEN_WIDTH /_overlayWidth; - scaley = (float)PSP_SCREEN_HEIGHT /_overlayHeight; - - vertMouse[0].x = mX * scalex; - vertMouse[0].y = mY * scaley; - vertMouse[0].z = 0; - vertMouse[1].x = vertMouse[0].x + _mouseWidth * scalex; - vertMouse[1].y = vertMouse[0].y + _mouseHeight * scaley; - vertMouse[1].z = 0; - } else - switch (_graphicMode) { - case CENTERED_320X200: - vertMouse[0].x = (PSP_SCREEN_WIDTH - 320) / 2 + mX; - vertMouse[0].y = (PSP_SCREEN_HEIGHT - 200) / 2 + mY; - vertMouse[0].z = 0; - vertMouse[1].x = vertMouse[0].x + _mouseWidth; - vertMouse[1].y = vertMouse[0].y + _mouseHeight; - vertMouse[1].z = 0; - break; - case CENTERED_435X272: - { - float scalex, scaley; - - scalex = 435.0f / _screenWidth; - scaley = 272.0f / _screenHeight; - - vertMouse[0].x = (PSP_SCREEN_WIDTH - 435) / 2 + mX * scalex; - vertMouse[0].y = mY * scaley; - vertMouse[0].z = 0; - vertMouse[1].x = vertMouse[0].x + _mouseWidth * scalex; - vertMouse[1].y = vertMouse[0].y + _mouseHeight * scaley; - vertMouse[1].z = 0; - } - break; - case CENTERED_362X272: - { - float scalex, scaley; - - scalex = 362.0f / _screenWidth; - scaley = 272.0f / _screenHeight; - - vertMouse[0].x = (PSP_SCREEN_WIDTH - 362) / 2 + mX * scalex; - vertMouse[0].y = mY * scaley; - vertMouse[0].z = 0; - vertMouse[1].x = vertMouse[0].x + _mouseWidth * scalex; - vertMouse[1].y = vertMouse[0].y + _mouseHeight * scaley; - vertMouse[1].z = 0; - } - break; - case STRETCHED_480X272: - { - float scalex, scaley; - - scalex = (float)PSP_SCREEN_WIDTH / _screenWidth; - scaley = (float)PSP_SCREEN_HEIGHT / _screenHeight; - - vertMouse[0].x = mX * scalex; - vertMouse[0].y = mY * scaley; - vertMouse[0].z = 0; - vertMouse[1].x = vertMouse[0].x + _mouseWidth * scalex; - vertMouse[1].y = vertMouse[0].y + _mouseHeight * scaley; - vertMouse[1].z = 0; - } - break; - } - sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertMouse); - } - - if (_keyboard->isVisible()) { - _keyboard->render(); - } - - sceGuFinish(); - sceGuSync(0,0); - - sceDisplayWaitVblankStart(); - sceGuSwapBuffers(); + _displayManager.renderAll(); + + DEBUG_EXIT_FUNC(); } void OSystem_PSP::setShakePos(int shakeOffset) { - _shakePos = shakeOffset; + DEBUG_ENTER_FUNC(); + + _screen.setShakePos(shakeOffset); + + DEBUG_EXIT_FUNC(); } void OSystem_PSP::showOverlay() { - _overlayVisible = true; + DEBUG_ENTER_FUNC(); + + _overlay.setVisible(true); + _cursor.setLimits(_overlay.getWidth(), _overlay.getHeight()); + _cursor.useGlobalScaler(false); // mouse with overlay is 1:1 + + DEBUG_EXIT_FUNC(); } void OSystem_PSP::hideOverlay() { - PSPDebugTrace("OSystem_PSP::hideOverlay called\n"); - _overlayVisible = false; + DEBUG_ENTER_FUNC(); + + _overlay.setVisible(false); + _cursor.setLimits(_screen.getWidth(), _screen.getHeight()); + _cursor.useGlobalScaler(true); // mouse needs to be scaled with screen + + DEBUG_EXIT_FUNC(); } void OSystem_PSP::clearOverlay() { - PSPDebugTrace("clearOverlay\n"); + DEBUG_ENTER_FUNC(); - bzero(_overlayBuffer, _overlayWidth * _overlayHeight * sizeof(OverlayColor)); - sceKernelDcacheWritebackAll(); -} + _overlay.clearBuffer(); -void OSystem_PSP::grabOverlay(OverlayColor *buf, int pitch) { - int h = _overlayHeight; - OverlayColor *src = _overlayBuffer; - - do { - memcpy(buf, src, _overlayWidth * sizeof(OverlayColor)); - src += _overlayWidth; - buf += pitch; - } while (--h); + DEBUG_EXIT_FUNC(); } -void OSystem_PSP::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { - PSPDebugTrace("copyRectToOverlay\n"); - - //Clip the coordinates - if (x < 0) { - w += x; - buf -= x; - x = 0; - } - - if (y < 0) { - h += y; - buf -= y * pitch; - y = 0; - } +void OSystem_PSP::grabOverlay(OverlayColor *buf, int pitch) { + DEBUG_ENTER_FUNC(); - if (w > _overlayWidth - x) { - w = _overlayWidth - x; - } + _overlay.copyToArray(buf, pitch); - if (h > _overlayHeight - y) { - h = _overlayHeight - y; - } - - if (w <= 0 || h <= 0) - return; + DEBUG_EXIT_FUNC(); +} +void OSystem_PSP::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { + DEBUG_ENTER_FUNC(); - OverlayColor *dst = _overlayBuffer + (y * _overlayWidth + x); + _overlay.copyFromRect(buf, pitch, x, y, w, h); - if (_overlayWidth == pitch && pitch == w) { - memcpy(dst, buf, h * w * sizeof(OverlayColor)); - } else { - do { - memcpy(dst, buf, w * sizeof(OverlayColor)); - buf += pitch; - dst += _overlayWidth; - } while (--h); - } - sceKernelDcacheWritebackAll(); + DEBUG_EXIT_FUNC(); } int16 OSystem_PSP::getOverlayWidth() { - return _overlayWidth; + return (int16) _overlay.getWidth(); } int16 OSystem_PSP::getOverlayHeight() { - return _overlayHeight; + return (int16) _overlay.getHeight(); } - void OSystem_PSP::grabPalette(byte *colors, uint start, uint num) { - uint i; - uint16 color; - - for (i = start; i < start + num; i++) { - color = _palette[i]; - *colors++ = ((color & 0x1F) << 3); - *colors++ = (((color >> 5) & 0x1F) << 3); - *colors++ = (((color >> 10) & 0x1F) << 3); - *colors++ = (color & 0x8000 ? 255 : 0); - } + DEBUG_ENTER_FUNC(); + + _screen.getPartialPalette(colors, start, num); + + DEBUG_EXIT_FUNC(); } -bool OSystem_PSP::showMouse(bool visible) { - bool last = _mouseVisible; - _mouseVisible = visible; +bool OSystem_PSP::showMouse(bool v) { + DEBUG_ENTER_FUNC(); + + PSP_DEBUG_PRINT("%s\n", v ? "true" : "false"); + bool last = _cursor.isVisible(); + _cursor.setVisible(v); + + DEBUG_EXIT_FUNC(); + return last; } void OSystem_PSP::warpMouse(int x, int y) { - //assert(x > 0 && x < _screenWidth); - //assert(y > 0 && y < _screenHeight); - _mouseX = x; - _mouseY = y; -} + DEBUG_ENTER_FUNC(); -void OSystem_PSP::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { - //TODO: handle cursorTargetScale - _mouseWidth = w; - _mouseHeight = h; - - _mouseHotspotX = hotspotX; - _mouseHotspotY = hotspotY; - - _mouseKeyColour = keycolor & 0xFF; - - memcpy(mouseClut, _palette, 256 * sizeof(unsigned short)); - mouseClut[_mouseKeyColour] = 0; - - for (unsigned int i = 0; i < h; i++) - memcpy(_mouseBuf + i * MOUSE_SIZE, buf + i * w, w); - - sceKernelDcacheWritebackAll(); + _cursor.setXY(x,y); + + DEBUG_EXIT_FUNC(); } -#define PAD_CHECK_TIME 40 -#define PAD_DIR_MASK (PSP_CTRL_UP | PSP_CTRL_DOWN | PSP_CTRL_LEFT | PSP_CTRL_RIGHT) - -bool OSystem_PSP::processInput(Common::Event &event) { - s8 analogStepAmountX = 0; - s8 analogStepAmountY = 0; - - sceCtrlSetSamplingCycle(0); - sceCtrlSetSamplingMode(1); - sceCtrlReadBufferPositive(&pad, 1); - - bool usedInput, haveEvent; - - haveEvent = _keyboard->processInput(event, pad, usedInput); - - if (usedInput) // Check if the keyboard used up the input - return haveEvent; - - uint32 buttonsChanged = pad.Buttons ^ _prevButtons; - - int newDpadX = 0, newDpadY = 0; - event.kbd.ascii = 0; - event.kbd.flags = 0; - - if (pad.Buttons & PSP_CTRL_UP) { - newDpadY += 1; - if (pad.Buttons & PSP_CTRL_RTRIGGER) - newDpadX += 1; - } - if (pad.Buttons & PSP_CTRL_RIGHT) { - newDpadX += 1; - if (pad.Buttons & PSP_CTRL_RTRIGGER) - newDpadY -= 1; - } - if (pad.Buttons & PSP_CTRL_DOWN) { - newDpadY -= 1; - if (pad.Buttons & PSP_CTRL_RTRIGGER) - newDpadX -= 1; - } - if (pad.Buttons & PSP_CTRL_LEFT) { - newDpadX -= 1; - if (pad.Buttons & PSP_CTRL_RTRIGGER) - newDpadY += 1; - } - //fprintf(stderr, "x=%d, y=%d, oldx=%d, oldy=%d\n", newDpadX, newDpadY, _dpadX, _dpadY); - if (newDpadX != _dpadX || newDpadY != _dpadY) { - if (_dpadX == 0 && _dpadY == 0) {// We pressed dpad - event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = getDpadEvent(newDpadX, newDpadY); - event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; - _dpadX = newDpadX; - _dpadY = newDpadY; - } - else if (newDpadX == 0 && newDpadY == 0) {// We unpressed dpad - event.type = Common::EVENT_KEYUP; - event.kbd.keycode = getDpadEvent(_dpadX, _dpadY); - event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; - _dpadX = newDpadX; - _dpadY = newDpadY; - } else { // we moved from one pressed dpad to another one - event.type = Common::EVENT_KEYUP; // first release the last dpad direction - event.kbd.keycode = getDpadEvent(_dpadX, _dpadY); - event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; - _dpadX = 0; // so that we'll pick up a new dpad movement - _dpadY = 0; - } - - _prevButtons = pad.Buttons; - return true; - - } else if (buttonsChanged & (PSP_CTRL_CROSS | PSP_CTRL_CIRCLE | PSP_CTRL_LTRIGGER | PSP_CTRL_RTRIGGER | PSP_CTRL_START | - PSP_CTRL_SELECT | PSP_CTRL_SQUARE | PSP_CTRL_TRIANGLE)) { - if (buttonsChanged & PSP_CTRL_CROSS) { - event.type = (pad.Buttons & PSP_CTRL_CROSS) ? Common::EVENT_LBUTTONDOWN : Common::EVENT_LBUTTONUP; - } else if (buttonsChanged & PSP_CTRL_CIRCLE) { - event.type = (pad.Buttons & PSP_CTRL_CIRCLE) ? Common::EVENT_RBUTTONDOWN : Common::EVENT_RBUTTONUP; - } else { - //any of the other buttons. - event.type = buttonsChanged & pad.Buttons ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP; - - if (buttonsChanged & PSP_CTRL_LTRIGGER) { - event.kbd.keycode = Common::KEYCODE_ESCAPE; - event.kbd.ascii = 27; - } else if (buttonsChanged & PSP_CTRL_START) { - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = Common::ASCII_F5; - if (pad.Buttons & PSP_CTRL_RTRIGGER) { - event.kbd.flags = Common::KBD_CTRL; // Main menu to allow RTL - } -/* } else if (buttonsChanged & PSP_CTRL_SELECT) { - event.kbd.keycode = Common::KEYCODE_0; - event.kbd.ascii = '0'; -*/ } else if (buttonsChanged & PSP_CTRL_SQUARE) { - event.kbd.keycode = Common::KEYCODE_PERIOD; - event.kbd.ascii = '.'; - } else if (buttonsChanged & PSP_CTRL_TRIANGLE) { - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = 13; - } else if (pad.Buttons & PSP_CTRL_RTRIGGER) { - event.kbd.flags |= Common::KBD_SHIFT; - } - - } - - event.mouse.x = _mouseX; - event.mouse.y = _mouseY; - _prevButtons = pad.Buttons; - return true; - } - - uint32 time = getMillis(); - if (time - _lastPadCheck > PAD_CHECK_TIME) { - _lastPadCheck = time; - int16 newX = _mouseX; - int16 newY = _mouseY; - - if (pad.Lx < 100) { - analogStepAmountX = pad.Lx - 100; - } else if (pad.Lx > 155) { - analogStepAmountX = pad.Lx - 155; - } - - if (pad.Ly < 100) { - analogStepAmountY = pad.Ly - 100; - } else if (pad.Ly > 155) { - analogStepAmountY = pad.Ly - 155; - } - - if (analogStepAmountX != 0 || analogStepAmountY != 0) { - - _prevButtons = pad.Buttons; - - // If no movement then this has no effect - if (pad.Buttons & PSP_CTRL_RTRIGGER) { - // Fine control mode for analog - if (analogStepAmountX != 0) { - if (analogStepAmountX > 0) - newX += 1; - else - newX -= 1; - } - - if (analogStepAmountY != 0) { - if (analogStepAmountY > 0) - newY += 1; - else - newY -= 1; - } - } else { - newX += analogStepAmountX >> ((_screenWidth == 640) ? 2 : 3); - newY += analogStepAmountY >> ((_screenWidth == 640) ? 2 : 3); - } - - if (newX < 0) - newX = 0; - if (newY < 0) - newY = 0; - if (_overlayVisible) { - if (newX >= _overlayWidth) - newX = _overlayWidth - 1; - if (newY >= _overlayHeight) - newY = _overlayHeight - 1; - } else { - if (newX >= _screenWidth) - newX = _screenWidth - 1; - if (newY >= _screenHeight) - newY = _screenHeight - 1; - } - - if ((_mouseX != newX) || (_mouseY != newY)) { - event.type = Common::EVENT_MOUSEMOVE; - event.mouse.x = _mouseX = newX; - event.mouse.y = _mouseY = newY; - return true; - } - } - } - - return false; -} +void OSystem_PSP::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { + DEBUG_ENTER_FUNC(); -inline Common::KeyCode OSystem_PSP::getDpadEvent(int x, int y) { - Common::KeyCode key; - - if (x == -1) { - if (y == -1) - key = Common::KEYCODE_KP1; - else if (y == 0) - key = Common::KEYCODE_KP4; - else /* y == 1 */ - key = Common::KEYCODE_KP7; - } else if (x == 0) { - if (y == -1) - key = Common::KEYCODE_KP2; - else /* y == 1 */ - key = Common::KEYCODE_KP8; - } else {/* x == 1 */ - if (y == -1) - key = Common::KEYCODE_KP3; - else if (y == 0) - key = Common::KEYCODE_KP6; - else /* y == 1 */ - key = Common::KEYCODE_KP9; + PSP_DEBUG_PRINT("pbuf[%p], w[%u], h[%u], hotspot:X[%d], Y[%d], keycolor[%d], scale[%d], pformat[%p]\n", buf, w, h, hotspotX, hotspotY, keycolor, cursorTargetScale, format); + if (format) { + PSP_DEBUG_PRINT("format: bpp[%d], rLoss[%d], gLoss[%d], bLoss[%d], aLoss[%d], rShift[%d], gShift[%d], bShift[%d], aShift[%d]\n", format->bytesPerPixel, format->rLoss, format->gLoss, format->bLoss, format->aLoss, format->rShift, format->gShift, format->bShift, format->aShift); } - - return key; + + _cursor.setKeyColor(keycolor); + _cursor.setCursorTargetScale(cursorTargetScale); + _cursor.setSizeAndScummvmPixelFormat(w, h, format); + _cursor.setHotspot(hotspotX, hotspotY); + _cursor.clearKeyColor(); + _cursor.copyFromArray(buf); + + DEBUG_EXIT_FUNC(); } bool OSystem_PSP::pollEvent(Common::Event &event) { @@ -905,8 +369,7 @@ bool OSystem_PSP::pollEvent(Common::Event &event) { PowerMan.pollPauseEngine(); - return processInput(event); - + return _inputHandler.getAllInputs(event); } @@ -997,7 +460,6 @@ void OSystem_PSP::setupMixer(void) { void OSystem_PSP::quit() { SDL_CloseAudio(); SDL_Quit(); - sceGuTerm(); sceKernelExitGame(); } diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h index ed920e53c1..23eba870e9 100644 --- a/backends/platform/psp/osys_psp.h +++ b/backends/platform/psp/osys_psp.h @@ -32,139 +32,123 @@ #include "sound/mixer_intern.h" #include "backends/base-backend.h" #include "backends/fs/psp/psp-fs-factory.h" +#include "backends/platform/psp/display_client.h" +#include "backends/platform/psp/default_display_client.h" +#include "backends/platform/psp/cursor.h" #include "backends/platform/psp/pspkeyboard.h" +#include "backends/platform/psp/display_manager.h" +#include "backends/platform/psp/input.h" #include <SDL.h> -#include <pspctrl.h> - -enum GraphicModeID { - CENTERED_320X200, - CENTERED_435X272, - STRETCHED_480X272, - CENTERED_362X272 -}; - class OSystem_PSP : public BaseBackend { -public: - static const OSystem::GraphicsMode s_supportedGraphicsModes[]; - static OSystem *instance(); - -protected: - struct Vertex { - float u,v; - float x,y,z; - }; - - uint16 _screenWidth; - uint16 _screenHeight; - uint16 _overlayWidth; - uint16 _overlayHeight; - byte *_offscreen; - OverlayColor *_overlayBuffer; - uint16 _palette[256]; - bool _overlayVisible; - uint32 _shakePos; - uint32 _lastScreenUpdate; - - Graphics::Surface _framebuffer; - - bool _mouseVisible; - int _mouseX, _mouseY; - int _dpadX, _dpadY; - int _mouseWidth, _mouseHeight; - int _mouseHotspotX, _mouseHotspotY; - byte _mouseKeyColour; - byte *_mouseBuf; - bool _cursorPaletteDisabled; - - int _graphicMode; - unsigned short* _clut; - PSPKeyboard *_keyboard; - - uint32 _prevButtons; - uint32 _lastPadCheck; - uint32 _padAccel; - - SceCtrlData pad; - +private: + Common::SaveFileManager *_savefile; Audio::MixerImpl *_mixer; Common::TimerManager *_timer; - Common::KeyCode getDpadEvent(int x, int y); + // All needed sub-members + Screen _screen; + Overlay _overlay; + Cursor _cursor; + DisplayManager _displayManager; + PSPKeyboard _keyboard; + InputHandler _inputHandler; -public: - OSystem_PSP(); - virtual ~OSystem_PSP(); + void initSDL(); - virtual void initBackend(); - - virtual bool hasFeature(Feature f); - virtual void setFeatureState(Feature f, bool enable); - virtual bool getFeatureState(Feature f); +public: + OSystem_PSP() : _savefile(0), _mixer(0), _timer(0) {} + ~OSystem_PSP(); - virtual const GraphicsMode *getSupportedGraphicsModes() const; - virtual int getDefaultGraphicsMode() const; - virtual bool setGraphicsMode(int mode); + static OSystem *instance(); + + void initBackend(); + + // Feature related + bool hasFeature(Feature f); + void setFeatureState(Feature f, bool enable); + bool getFeatureState(Feature f); + + // Graphics related + const GraphicsMode *getSupportedGraphicsModes() const; + int getDefaultGraphicsMode() const; + bool setGraphicsMode(int mode); bool setGraphicsMode(const char *name); - virtual int getGraphicsMode() const; - - virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format); - virtual int16 getWidth(); - virtual int16 getHeight(); - - virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); - virtual void setCursorPalette(const byte *colors, uint start, uint num); - virtual void disableCursorPalette(bool disable); - virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h); - virtual Graphics::Surface *lockScreen(); - virtual void unlockScreen(); - virtual void updateScreen(); - virtual void setShakePos(int shakeOffset); - - virtual void showOverlay(); - virtual void hideOverlay(); - virtual void clearOverlay(); - virtual void grabOverlay(OverlayColor *buf, int pitch); - virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); - virtual int16 getOverlayHeight(); - virtual int16 getOverlayWidth(); - virtual Graphics::PixelFormat getOverlayFormat() const { return Graphics::createPixelFormat<4444>(); } - - virtual bool showMouse(bool visible); - virtual void warpMouse(int x, int y); - virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); - - virtual bool pollEvent(Common::Event &event); - virtual bool processInput(Common::Event &event); - - virtual uint32 getMillis(); - virtual void delayMillis(uint msecs); - + int getGraphicsMode() const; +#ifdef USE_RGB_COLOR + virtual Graphics::PixelFormat getScreenFormat() const; + virtual Common::List<Graphics::PixelFormat> getSupportedFormats(); +#endif + + // Screen size + void initSize(uint width, uint height, const Graphics::PixelFormat *format); + int16 getWidth(); + int16 getHeight(); + + // Palette related + void setPalette(const byte *colors, uint start, uint num); + void grabPalette(byte *colors, uint start, uint num); + void setCursorPalette(const byte *colors, uint start, uint num); + void disableCursorPalette(bool disable); + + // Screen related + void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h); + Graphics::Surface *lockScreen(); + void unlockScreen(); + void updateScreen(); + void setShakePos(int shakeOffset); + + // Overlay related + void showOverlay(); + void hideOverlay(); + void clearOverlay(); + void grabOverlay(OverlayColor *buf, int pitch); + void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); + int16 getOverlayHeight(); + int16 getOverlayWidth(); + Graphics::PixelFormat getOverlayFormat() const { return Graphics::createPixelFormat<4444>(); } + + // Mouse related + bool showMouse(bool visible); + void warpMouse(int x, int y); + void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); + + // Events and input + bool pollEvent(Common::Event &event); + bool processInput(Common::Event &event); + + // Time + uint32 getMillis(); + void delayMillis(uint msecs); + + // Timer typedef int (*TimerProc)(int interval); - virtual void setTimerCallback(TimerProc callback, int interval); + void setTimerCallback(TimerProc callback, int interval); + Common::TimerManager *getTimerManager() { return _timer; } - virtual MutexRef createMutex(void); - virtual void lockMutex(MutexRef mutex); - virtual void unlockMutex(MutexRef mutex); - virtual void deleteMutex(MutexRef mutex); + // Mutex + MutexRef createMutex(void); + void lockMutex(MutexRef mutex); + void unlockMutex(MutexRef mutex); + void deleteMutex(MutexRef mutex); + // Sound static void mixCallback(void *sys, byte *samples, int len); - virtual void setupMixer(void); - - Common::SaveFileManager *getSavefileManager() { return _savefile; } + void setupMixer(void); Audio::Mixer *getMixer() { return _mixer; } - Common::TimerManager *getTimerManager() { return _timer; } + + // Misc + Common::SaveFileManager *getSavefileManager() { return _savefile; } FilesystemFactory *getFilesystemFactory() { return &PSPFilesystemFactory::instance(); } void getTimeAndDate(TimeDate &t) const; - virtual void quit(); + void quit(); - virtual Common::SeekableReadStream *createConfigReadStream(); - virtual Common::WriteStream *createConfigWriteStream(); -}; + Common::SeekableReadStream *createConfigReadStream(); + Common::WriteStream *createConfigWriteStream(); +}; #endif /* OSYS_PSP_H */ diff --git a/backends/platform/psp/powerman.cpp b/backends/platform/psp/powerman.cpp index 2f0086089c..b4391b0b8d 100644 --- a/backends/platform/psp/powerman.cpp +++ b/backends/platform/psp/powerman.cpp @@ -23,24 +23,23 @@ * */ +//#define __PSP_DEBUG_FUNCS__ /* can put this locally too */ +//#define __PSP_DEBUG_PRINT__ +#include "backends/platform/psp/trace.h" + #include <psppower.h> #include <pspthreadman.h> -#include "./powerman.h" -#include "./trace.h" +#include "backends/platform/psp/powerman.h" #include "engine.h" DECLARE_SINGLETON(PowerManager) -#ifdef __PSP_DEBUG_SUSPEND__ -void PowerManager::debugPM() { - PSPDebugTrace("PM status is %d. Listcount is %d. CriticalCount is %d. ThreadId is %x. Error = %d\n", _PMStatus, _listCounter, - _criticalCounter, sceKernelGetThreadId(), _error); +// Function to debug the Power Manager (we have no output to screen) +inline void PowerManager::debugPM() { + PSP_DEBUG_PRINT("PM status[%d]. Listcount[%d]. CriticalCount[%d]. ThreadId[%x]. Error[%d]\n", + _PMStatus, _listCounter, _criticalCounter, sceKernelGetThreadId(), _error); } -#else - #define debugPM() - #define PMStatusSet(x) -#endif /* __PSP_DEBUG_SUSPEND__ */ /******************************************* @@ -49,7 +48,8 @@ void PowerManager::debugPM() { * ********************************************/ PowerManager::PowerManager() { - + DEBUG_ENTER_FUNC(); + _flagMutex = NULL; /* Init mutex handle */ _listMutex = NULL; /* Init mutex handle */ _condSuspendable = NULL; /* Init condition variable */ @@ -57,33 +57,34 @@ PowerManager::PowerManager() { _condSuspendable = SDL_CreateCond(); if (_condSuspendable <= 0) { - PSPDebugSuspend("PowerManager::PowerManager(): Couldn't create condSuspendable\n"); + PSP_ERROR("Couldn't create Suspendable condition variable\n"); } _condPM = SDL_CreateCond(); if (_condPM <= 0) { - PSPDebugSuspend("PowerManager::PowerManager(): Couldn't create condPM\n"); + PSP_ERROR("Couldn't create PM condition variable\n"); } _flagMutex = SDL_CreateMutex(); if (_flagMutex <= 0) { - PSPDebugSuspend("PowerManager::PowerManager(): Couldn't create flagMutex\n"); + PSP_ERROR("Couldn't create flag Mutex\n"); } _listMutex = SDL_CreateMutex(); if (_listMutex <= 0) { - PSPDebugSuspend("PowerManager::PowerManager(): Couldn't create listMutex\n"); + PSP_ERROR("Couldn't create list Mutex\n"); } _suspendFlag = false; - _criticalCounter = 0; - _pauseFlag = 0; _pauseFlagOld = 0; _pauseClientState = 0; - -#ifdef __PSP_DEBUG_SUSPEND__ + _criticalCounter = 0; // How many are in the critical section + _pauseFlag = 0; + _pauseFlagOld = 0; + _pauseClientState = 0; _listCounter = 0; PMStatusSet(kInitDone); _error = 0; -#endif + + DEBUG_EXIT_FUNC(); } /******************************************* @@ -92,26 +93,24 @@ PowerManager::PowerManager() { * ********************************************/ int PowerManager::registerSuspend(Suspendable *item) { + DEBUG_ENTER_FUNC(); // Register in list - PSPDebugSuspend("In registerSuspend\n"); debugPM(); if (SDL_mutexP(_listMutex) != 0) { - PSPDebugTrace("PowerManager::registerSuspend(): Couldn't lock _listMutex %d\n", _listMutex); + PSP_ERROR("Couldn't lock _listMutex[%p]\n", _listMutex); } _suspendList.push_front(item); -#ifdef __PSP_DEBUG_SUSPEND__ _listCounter++; -#endif if (SDL_mutexV(_listMutex) != 0) { - PSPDebugTrace("PowerManager::registerSuspend(): Couldn't unlock _listMutex %d\n", _listMutex); + PSP_ERROR("Couldn't unlock _listMutex[%p]\n", _listMutex); } - - PSPDebugSuspend("Out of registerSuspend\n"); + debugPM(); + DEBUG_EXIT_FUNC(); return 0; } @@ -121,27 +120,25 @@ int PowerManager::registerSuspend(Suspendable *item) { * ********************************************/ int PowerManager::unregisterSuspend(Suspendable *item) { - - PSPDebugSuspend("In unregisterSuspend\n"); + DEBUG_ENTER_FUNC(); debugPM(); // Unregister from stream list if (SDL_mutexP(_listMutex) != 0) { - PSPDebugTrace("PowerManager::unregisterSuspend(): Couldn't unlock _listMutex %d\n", _listMutex); + PSP_ERROR("Couldn't unlock _listMutex[%p]\n", _listMutex); } _suspendList.remove(item); -#ifdef __PSP_DEBUG_SUSPEND__ _listCounter--; -#endif if (SDL_mutexV(_listMutex) != 0) { - PSPDebugTrace("PowerManager::unregisterSuspend(): Couldn't unlock _listMutex %d\n", _listMutex); + PSP_ERROR("Couldn't unlock _listMutex[%p]\n", _listMutex); } - PSPDebugSuspend("Out of unregisterSuspend\n"); + PSP_DEBUG_PRINT("Out of unregisterSuspend\n"); debugPM(); + DEBUG_EXIT_FUNC(); return 0; } @@ -151,10 +148,9 @@ int PowerManager::unregisterSuspend(Suspendable *item) { * ********************************************/ PowerManager::~PowerManager() { - -#ifdef __PSP_DEBUG_SUSPEND__ + DEBUG_ENTER_FUNC(); + PMStatusSet(kDestroyPM); -#endif SDL_DestroyCond(_condSuspendable); _condSuspendable = 0; @@ -167,6 +163,8 @@ int PowerManager::unregisterSuspend(Suspendable *item) { SDL_DestroyMutex(_listMutex); _listMutex = 0; + + DEBUG_EXIT_FUNC(); } /******************************************* @@ -184,14 +182,14 @@ void PowerManager::pollPauseEngine() { if ((pause != _pauseFlagOld) && g_engine) { // Check to see if we have an engine if (pause && _pauseClientState == PowerManager::Unpaused) { - _pauseClientState = PowerManager::Pausing; // Tell PM we're in the middle of pausing + _pauseClientState = PowerManager::Pausing; // Tell PM we're in the middle of pausing g_engine->pauseEngine(true); - PSPDebugSuspend("Pausing engine in PowerManager::pollPauseEngine()\n"); + PSP_DEBUG_PRINT_FUNC("Pausing engine\n"); _pauseClientState = PowerManager::Paused; // Tell PM we're done pausing } else if (!pause && _pauseClientState == PowerManager::Paused) { g_engine->pauseEngine(false); - PSPDebugSuspend("Unpausing for resume in PowerManager::pollPauseEngine()\n"); + PSP_DEBUG_PRINT_FUNC("Unpausing for resume\n"); _pauseClientState = PowerManager::Unpaused; // Tell PM we're in the middle of pausing } @@ -205,7 +203,7 @@ void PowerManager::pollPauseEngine() { * Use this for small critical sections where you can easily restore the previous state. * ********************************************/ - int PowerManager::blockOnSuspend() { +int PowerManager::blockOnSuspend() { return beginCriticalSection(true); } @@ -216,26 +214,28 @@ void PowerManager::pollPauseEngine() { * Make sure to call endCriticalSection or the PSP won't suspend. ********************************************/ - int PowerManager::beginCriticalSection(bool justBlock) { +int PowerManager::beginCriticalSection(bool justBlock) { + DEBUG_ENTER_FUNC(); + int ret = NotBlocked; if (SDL_mutexP(_flagMutex) != 0) { - PSPDebugTrace("PowerManager::blockOnSuspend(): Couldn't lock flagMutex %d\n", _flagMutex); + PSP_ERROR("PowerManager::blockOnSuspend(): Couldn't lock flagMutex[%p]\n", _flagMutex); ret = Error; } // Check the access flag if (_suspendFlag == true) { - PSPDebugSuspend("We're being blocked!\n"); + PSP_DEBUG_PRINT("We're being blocked!\n"); debugPM(); ret = Blocked; // If it's true, we wait for a signal to continue if (SDL_CondWait(_condSuspendable, _flagMutex) != 0) { - PSPDebugTrace("PowerManager::blockOnSuspend(): Couldn't wait on cond %d\n", _condSuspendable); + PSP_DEBUG_PRINT("PowerManager::blockOnSuspend(): Couldn't wait on cond[%p]\n", _condSuspendable); } - PSPDebugSuspend("We got blocked!!\n"); + PSP_DEBUG_PRINT("We got blocked!!\n"); debugPM(); } @@ -244,18 +244,20 @@ void PowerManager::pollPauseEngine() { _criticalCounter++; if (SDL_mutexV(_flagMutex) != 0) { - PSPDebugTrace("PowerManager::blockOnSuspend(): Couldn't unlock flagMutex %d\n", _flagMutex); + PSP_ERROR("PowerManager::blockOnSuspend(): Couldn't unlock flagMutex[%p]\n", _flagMutex); ret = Error; } + DEBUG_EXIT_FUNC(); return ret; } int PowerManager::endCriticalSection() { + DEBUG_ENTER_FUNC(); int ret = 0; if (SDL_mutexP(_flagMutex) != 0) { - PSPDebugTrace("PowerManager::endCriticalSection(): Couldn't lock flagMutex %d\n", _flagMutex); + PSP_ERROR("PowerManager::endCriticalSection(): Couldn't lock flagMutex[%p]\n", _flagMutex); ret = Error; } @@ -264,26 +266,27 @@ int PowerManager::endCriticalSection() { if (_criticalCounter <= 0) { if (_suspendFlag == true) { // If the PM is sleeping, this flag must be set - PSPDebugSuspend("Unblocked thread waking up the PM.\n"); + PSP_DEBUG_PRINT("Unblocked thread waking up the PM.\n"); debugPM(); SDL_CondBroadcast(_condPM); - PSPDebugSuspend("Woke up the PM\n"); + PSP_DEBUG_PRINT("Woke up the PM\n"); debugPM(); } if (_criticalCounter < 0) { // Check for bad usage of critical sections - PSPDebugTrace("PowerManager::endCriticalSection(): Error! Critical counter is %d\n", _criticalCounter); + PSP_ERROR("Critical counter[%d]\n", _criticalCounter); debugPM(); } } if (SDL_mutexV(_flagMutex) != 0) { - PSPDebugTrace("PowerManager::endCriticalSection(): Couldn't unlock flagMutex %d\n", _flagMutex); + PSP_ERROR("Couldn't unlock flagMutex[%p]\n", _flagMutex); ret = Error; } + DEBUG_EXIT_FUNC(); return ret; } @@ -293,6 +296,7 @@ int PowerManager::endCriticalSection() { * ********************************************/ int PowerManager::suspend() { + DEBUG_ENTER_FUNC(); int ret = 0; if (_pauseFlag) return ret; // Very important - make sure we only suspend once @@ -325,7 +329,7 @@ int PowerManager::suspend() { // Now we set the suspend flag to true to cause reading threads to block if (SDL_mutexP(_flagMutex) != 0) { - PSPDebugTrace("PowerManager::suspend(): Couldn't lock flagMutex %d\n", _flagMutex); + PSP_ERROR("Couldn't lock flagMutex[%p]\n", _flagMutex); _error = Error; ret = Error; } @@ -342,7 +346,7 @@ int PowerManager::suspend() { } if (SDL_mutexV(_flagMutex) != 0) { - PSPDebugTrace("PowerManager::suspend(): Couldn't unlock flagMutex %d\n", _flagMutex); + PSP_ERROR("Couldn't unlock flagMutex[%p]\n", _flagMutex); _error = Error; ret = Error; } @@ -351,22 +355,22 @@ int PowerManager::suspend() { // Loop over list, calling suspend() if (SDL_mutexP(_listMutex) != 0) { - PSPDebugTrace("PowerManager::suspend(): Couldn't lock listMutex %d\n", _listMutex); + PSP_ERROR("Couldn't lock listMutex[%p]\n", _listMutex); _error = Error; ret = Error; } PMStatusSet(kIteratingListSuspend); // Iterate - Common::List<Suspendable *>::iterator i = _suspendList.begin(); + Common::List<Suspendable *>::iterator i; - for (; i != _suspendList.end(); ++i) { + for (i = _suspendList.begin(); i != _suspendList.end(); ++i) { (*i)->suspend(); } PMStatusSet(kDoneIteratingListSuspend); if (SDL_mutexV(_listMutex) != 0) { - PSPDebugTrace("PowerManager::suspend(): Couldn't unlock listMutex %d\n", _listMutex); + PSP_ERROR("Couldn't unlock listMutex[%p]\n", _listMutex); _error = Error; ret = Error; } @@ -374,6 +378,7 @@ int PowerManager::suspend() { scePowerUnlock(0); // Allow the PSP to go to sleep now + DEBUG_EXIT_FUNC(); return ret; } @@ -383,6 +388,7 @@ int PowerManager::suspend() { * ********************************************/ int PowerManager::resume() { + DEBUG_ENTER_FUNC(); int ret = 0; // Make sure we can't get another suspend @@ -394,7 +400,7 @@ int PowerManager::resume() { // First we notify our Suspendables. Loop over list, calling resume() if (SDL_mutexP(_listMutex) != 0) { - PSPDebugTrace("PowerManager::resume(): Couldn't lock listMutex %d\n", _listMutex); + PSP_ERROR("Couldn't lock listMutex[%p]\n", _listMutex); _error = Error; ret = Error; } @@ -409,7 +415,7 @@ int PowerManager::resume() { PMStatusSet(kDoneIteratingListResume); if (SDL_mutexV(_listMutex) != 0) { - PSPDebugTrace("PowerManager::resume(): Couldn't unlock listMutex %d\n", _listMutex); + PSP_ERROR("Couldn't unlock listMutex[%p]\n", _listMutex); _error = Error; ret = Error; } @@ -418,7 +424,7 @@ int PowerManager::resume() { // Now we set the suspend flag to false if (SDL_mutexP(_flagMutex) != 0) { - PSPDebugTrace("PowerManager::resume(): Couldn't lock flagMutex %d\n", _flagMutex); + PSP_ERROR("Couldn't lock flagMutex %p\n", _flagMutex); _error = Error; ret = Error; } @@ -430,14 +436,14 @@ int PowerManager::resume() { // Signal the other threads to wake up if (SDL_CondBroadcast(_condSuspendable) != 0) { - PSPDebugTrace("PowerManager::resume(): Couldn't broadcast condition %d\n", _condSuspendable); + PSP_ERROR("Couldn't broadcast condition[%p]\n", _condSuspendable); _error = Error; ret = Error; } PMStatusSet(kDoneSignallingSuspendedThreadsResume); if (SDL_mutexV(_flagMutex) != 0) { - PSPDebugTrace("PowerManager::resume(): Couldn't unlock flagMutex %d\n", _flagMutex); + PSP_ERROR("Couldn't unlock flagMutex[%p]\n", _flagMutex); _error = Error; ret = Error; } @@ -447,5 +453,6 @@ int PowerManager::resume() { scePowerUnlock(0); // Allow new suspends + DEBUG_EXIT_FUNC(); return ret; } diff --git a/backends/platform/psp/powerman.h b/backends/platform/psp/powerman.h index 78c403fa5c..4a9167f2bf 100644 --- a/backends/platform/psp/powerman.h +++ b/backends/platform/psp/powerman.h @@ -118,7 +118,6 @@ public: kDoneSignallingSuspendedThreadsResume, kDoneResume }; -#ifdef __PSP_DEBUG_SUSPEND__ volatile int _listCounter; /* How many people are in the list - just for debugging */ @@ -129,11 +128,9 @@ public: public: int getPMStatus() { return _PMStatus; } -#endif /* __PSP_DEBUG_SUSPEND__ */ - }; // For easy access #define PowerMan PowerManager::instance() - #endif /* POWERMAN_H */ +#endif /* POWERMAN_H */ diff --git a/backends/platform/psp/psp_main.cpp b/backends/platform/psp/psp_main.cpp index 581f6234b4..c3770cb41f 100644 --- a/backends/platform/psp/psp_main.cpp +++ b/backends/platform/psp/psp_main.cpp @@ -26,8 +26,10 @@ #define USERSPACE_ONLY //don't use kernel mode features #ifndef USERSPACE_ONLY -#include <pspkernel.h> -#include <pspdebug.h> + #include <pspkernel.h> + #include <pspdebug.h> +#else + #include <pspuser.h> #endif #include <psppower.h> @@ -118,10 +120,10 @@ int CallbackThread(SceSize /*size*/, void *arg) { cbid = sceKernelCreateCallback("Power Callback", (SceKernelCallbackFunction)power_callback, 0); if (cbid >= 0) { if (scePowerRegisterCallback(-1, cbid) < 0) { - PSPDebugTrace("SetupCallbacks(): Couldn't register callback for power_callback\n"); + PSP_ERROR("Couldn't register callback for power_callback\n"); } } else { - PSPDebugTrace("SetupCallbacks(): Couldn't create a callback for power_callback\n"); + PSP_ERROR("Couldn't create a callback for power_callback\n"); } sceKernelSleepThreadCB(); @@ -167,4 +169,3 @@ int main(void) { return res; } - diff --git a/backends/platform/psp/pspkeyboard.cpp b/backends/platform/psp/pspkeyboard.cpp index be8b98a3f8..d6fa0621b9 100644 --- a/backends/platform/psp/pspkeyboard.cpp +++ b/backends/platform/psp/pspkeyboard.cpp @@ -24,16 +24,19 @@ */ //#define PSP_KB_SHELL /* Need a hack to properly load the keyboard from the PSP shell */ + #ifdef PSP_KB_SHELL -#define PSP_KB_SHELL_PATH "ms0:/psp/game4xx/scummvm-1.0.0rc1/" /* path to kbd.zip */ + #define PSP_KB_SHELL_PATH "ms0:/psp/game4xx/scummvm-solid/" /* path to kbd.zip */ #endif -//#define PSP_KB_DEBUG +//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ +//#define __PSP_DEBUG_PRINT__ + +#include "backends/platform/psp/trace.h" #include <malloc.h> #include "pspkernel.h" -#include <pspgu.h> #include "png.h" -#include "pspkeyboard.h" +#include "backends/platform/psp/pspkeyboard.h" #include "common/keyboard.h" #include "common/fs.h" #include "common/unzip.h" @@ -94,314 +97,145 @@ void pngReadStreamRead(png_structp png_ptr, png_bytep data, png_size_t length) { file->read(data, length); } +// Array with file names +const char *PSPKeyboard::_guiStrings[] = { + "keys4.png", "keys_s4.png", + "keys_c4.png", "keys_s_c4.png", + "nums4.png", "nums_s4.png", + "syms4.png", "syms_s4.png" +}; + // Constructor PSPKeyboard::PSPKeyboard() { + DEBUG_ENTER_FUNC(); + _init = false; // we're not initialized yet _prevButtons = 0; // Reset previous buttons - _dirty = true; // keyboard needs redrawing - _mode = 0; // charset selected. (0 - letters, 1 - uppercase 2 - numbers 3 - symbols) + _dirty = false; // keyboard needs redrawing + _mode = 0; // charset selected. (0: letters, 1: uppercase 2: numbers 3: symbols) _oldCursor = kCenter; // Center cursor by default - _moved_x = 20; // Default starting location - _moved_y = 50; + _movedX = 20; // Default starting location + _movedY = 50; _moved = false; // Keyboard wasn't moved recently _state = kInvisible; // We start invisible _lastState = kInvisible; + + // Constant renderer settings + _renderer.setAlphaBlending(true); + _renderer.setColorTest(false); + _renderer.setUseGlobalScaler(false); + + DEBUG_EXIT_FUNC(); } // Destructor PSPKeyboard::~PSPKeyboard() { - if (!_init) return; - - int a; - for (a = 0; a < guiStringsSize; a++) { - free(_keyTextures[a].texture); - free(_keyTextures[a].palette); - _keyTextures[a].texture = NULL; - _keyTextures[a].palette = NULL; + DEBUG_ENTER_FUNC(); + + if (!_init) { + DEBUG_EXIT_FUNC(); + return; + } + + for (int i = 0; i < guiStringsSize; i++) { + _buffers[i].deallocate(); + _palettes[i].deallocate(); } _init = false; + + DEBUG_EXIT_FUNC(); } -// Array with file names -const char *PSPKeyboard::_guiStrings[] = { - "keys4.png", "keys_s4.png", - "keys_c4.png", "keys_s_c4.png", - "nums4.png", "nums_s4.png", - "syms4.png", "syms_s4.png" -}; - -// Defines for working with PSP buttons -#define CHANGED(x) (buttonsChanged & (x)) -#define PRESSED(x) ((buttonsChanged & (x)) && (pad.Buttons & (x))) -#define UNPRESSED(x) ((buttonsChanged & (x)) && !(pad.Buttons & (x))) -#define DOWN(x) (pad.Buttons & (x)) -#define UP(x) (!(pad.Buttons & (x))) -#define PSP_DPAD (PSP_CTRL_DOWN|PSP_CTRL_UP|PSP_CTRL_LEFT|PSP_CTRL_RIGHT) -#define PSP_4BUTTONS (PSP_CTRL_CROSS | PSP_CTRL_CIRCLE | PSP_CTRL_TRIANGLE | PSP_CTRL_SQUARE) - -/* - * Attempts to read a character from the controller - * Uses the state machine. - */ -bool PSPKeyboard::processInput(Common::Event &event, SceCtrlData &pad, bool &usedInput) { - usedInput = false; // Assume we don't use an input - bool haveEvent = false; // Whether we have an event for the event manager to process - event.kbd.flags = 0; - unsigned int keyDown; - uint32 buttonsChanged = _prevButtons ^ pad.Buttons; - - if (!_init) // In case we never had init - goto END; - - if (PRESSED(PSP_CTRL_SELECT)) { +void PSPKeyboard::setVisible(bool val) { + if (val && _state == kInvisible && _init) { // Check also that were loaded correctly _lastState = _state; - _state = kMove; // Check for move or visible state - usedInput = true; - goto END; - } - - if (_state == kInvisible) // Return if we're invisible - goto END; - - if (DOWN(PSP_DPAD | PSP_4BUTTONS | PSP_CTRL_LTRIGGER | PSP_CTRL_RTRIGGER | PSP_CTRL_START)) - usedInput = true; // for now, we neutralize all button inputs - - // Check for moving the keyboard onscreen - if (_state == kMove) { - if (UNPRESSED(PSP_CTRL_SELECT)) { - _state = (_lastState == kInvisible) ? kDefault : kInvisible; // Back to previous state - _dirty = true; - - if (_moved) { // We moved the keyboard. Keep the keyboard onscreen - _state = kDefault; - _moved = false; // reset moved flag - } - } - else if (DOWN(PSP_DPAD)) { - _moved = true; - _dirty = true; - - if (DOWN(PSP_CTRL_DOWN)) - increaseKeyboardLocationY(5); - else if (DOWN(PSP_CTRL_UP)) - increaseKeyboardLocationY(-5); - else if (DOWN(PSP_CTRL_LEFT)) - increaseKeyboardLocationX(-5); - else /* DOWN(PSP_CTRL_RIGHT) */ - increaseKeyboardLocationX(5); - } - usedInput = true; // We used up the input (select was held down) - goto END; - } - - - // Handle 4 buttons + 2 triggers - if (_state == kDefault || _state == kCornersSelected) { - unsigned int changed; - - if (_state == kDefault) { // Handle default state - changed = CHANGED(PSP_4BUTTONS); // We only care about the 4 buttons - if (PRESSED(PSP_CTRL_LTRIGGER)) { // Don't say we used up the input - _state = kLTriggerDown; - goto END; - } - else if (PRESSED(PSP_CTRL_RTRIGGER)) { // Don't say we used up the input - _state = kRTriggerDown; - goto END; - } - - if (DOWN(PSP_4BUTTONS)) - usedInput = true; // Make sure these button presses don't get through - } else { /* _state == kCornersSelected */ - // We care about 4 buttons + triggers (for letter selection) - changed = CHANGED(PSP_4BUTTONS | PSP_CTRL_RTRIGGER | PSP_CTRL_LTRIGGER); - - if (DOWN(PSP_4BUTTONS | PSP_CTRL_RTRIGGER | PSP_CTRL_LTRIGGER)) - usedInput = true; // Make sure these button presses don't get through - } - - if (changed) { //pressing a char select button -- both states - - int innerChoice; - - if (UNPRESSED(PSP_CTRL_TRIANGLE)) { - innerChoice = 0; - event.type = Common::EVENT_KEYUP; // We give priority to key_up - } else if (UNPRESSED(PSP_CTRL_CIRCLE)) { - innerChoice = 1; - event.type = Common::EVENT_KEYUP; // We give priority to key_up - } else if (UNPRESSED(PSP_CTRL_CROSS)) { - innerChoice = 2; - event.type = Common::EVENT_KEYUP; // We give priority to key_up - } else if (UNPRESSED(PSP_CTRL_SQUARE)) { - innerChoice = 3; - event.type = Common::EVENT_KEYUP; // We give priority to key_up - } else if (UNPRESSED(PSP_CTRL_LTRIGGER) && _state == kCornersSelected) { - innerChoice = 4; - event.type = Common::EVENT_KEYUP; // We give priority to key_up - } else if (UNPRESSED(PSP_CTRL_RTRIGGER) && _state == kCornersSelected) { - innerChoice = 5; - event.type = Common::EVENT_KEYUP; // We give priority to key_up - } else if (PRESSED(PSP_CTRL_TRIANGLE)) { - innerChoice = 0; - event.type = Common::EVENT_KEYDOWN; - } else if (PRESSED(PSP_CTRL_CIRCLE)) { - innerChoice = 1; - event.type = Common::EVENT_KEYDOWN; - } else if (PRESSED(PSP_CTRL_CROSS)) { - innerChoice = 2; - event.type = Common::EVENT_KEYDOWN; - } else if (PRESSED(PSP_CTRL_SQUARE)) { - innerChoice = 3; - event.type = Common::EVENT_KEYDOWN; - } else if (PRESSED(PSP_CTRL_LTRIGGER) && _state == kCornersSelected) { - innerChoice = 4; - event.type = Common::EVENT_KEYDOWN; // We give priority to key_up - } else /* (UNPRESSED(PSP_CTRL_RTRIGGER)) && _state == kCornersSelected */ { - innerChoice = 5; - event.type = Common::EVENT_KEYDOWN; // We give priority to key_up - } - - #define IS_UPPERCASE(x) ((x) >= (unsigned short)'A' && (x) <= (unsigned short)'Z') - #define TO_LOWER(x) ((x) += 'a'-'A') - - //Now grab the value out of the array - short choice = _modeChar[_mode][_oldCursor][innerChoice]; - - event.kbd.ascii = choice <= 255 ? choice : 0; - - // Handle upper-case which is missing in Common::KeyCode - if (IS_UPPERCASE(choice)) { - event.kbd.keycode = (Common::KeyCode) TO_LOWER(choice); - event.kbd.flags = Common::KBD_SHIFT; - } else - event.kbd.keycode = (Common::KeyCode) choice; - - haveEvent = (choice != Common::KEYCODE_INVALID) ? true : false; // We have an event/don't if it's invalid - usedInput = true; - } - } - - // Check for movement of cursor - if (_state == kDefault || _state == kCornersSelected) { - // Check if a dependent button is down - if (_state == kDefault) - keyDown = DOWN(PSP_4BUTTONS); - else /* if (_state == kCornersSelected) */ - keyDown = DOWN(PSP_4BUTTONS | PSP_CTRL_RTRIGGER | PSP_CTRL_LTRIGGER); - - Cursor cursor = _oldCursor; - - // Find where the cursor is pointing - if (keyDown == false) { // Don't allow movement if a nub-dependent key is down - cursor = kCenter; - _state = kDefault; - - if (DOWN(PSP_DPAD)) { - _state = kCornersSelected; - usedInput = true; // Make sure the pressed d-pad is used up - - if (DOWN(PSP_CTRL_UP)) - cursor = kUp; - else if (DOWN(PSP_CTRL_RIGHT)) - cursor = kRight; - else if (DOWN(PSP_CTRL_DOWN)) - cursor = kDown; - else if (DOWN(PSP_CTRL_LEFT)) - cursor = kLeft; - } - } - - if (cursor != _oldCursor) { //If we've moved, update dirty and return - _dirty = true; - _oldCursor = cursor; - usedInput = true; // We 'used up' the input - //goto END; // We didn't find an event - } - } - - // Deal with trigger states - if (_state == kRTriggerDown) { - usedInput = true; - - if (UNPRESSED(PSP_CTRL_RTRIGGER)) { - _dirty = true; - - if(_mode > 1) - _mode = 0; - else - _mode = (_mode == 0) ? 1 : 0; - - usedInput = true; - _state = kDefault; - - goto END; - } - } else if (_state == kLTriggerDown) { - usedInput = true; - - if (UNPRESSED(PSP_CTRL_LTRIGGER)) { - _dirty = true; - - if(_mode < 2) - _mode = 2; - else - _mode = (_mode == 2) ? 3 : 2; - - usedInput = true; - _state = kDefault; - - goto END; - } + _state = kMove; } - - // Handle start button: enter plus make keyboard invisible - if (CHANGED(PSP_CTRL_START)) { - event.kbd.ascii = '\n'; - event.kbd.keycode = Common::KEYCODE_RETURN; - event.type = DOWN(PSP_CTRL_START) ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP; - usedInput = true; // Don't let start get through - haveEvent = true; - if (UP(PSP_CTRL_START)) - _state = kInvisible; // Make us invisible if unpressed + else if ( !val && _state != kInvisible) { + _lastState = _state; + _state = kInvisible; } - -END: - _prevButtons = pad.Buttons; - return haveEvent; + setDirty(); } - /* move the position the keyboard is currently drawn at */ void PSPKeyboard::moveTo(const int newX, const int newY) { - _moved_x = newX; - _moved_y = newY; + DEBUG_ENTER_FUNC(); + + _movedX = newX; + _movedY = newY; + setDirty(); + + DEBUG_EXIT_FUNC(); } /* move the position the keyboard is currently drawn at */ void PSPKeyboard::increaseKeyboardLocationX(int amount) { - int newX = _moved_x + amount; + DEBUG_ENTER_FUNC(); + + int newX = _movedX + amount; - if (newX > PSP_SCREEN_WIDTH - 5 || newX < 0 - 140) // clamp + if (newX > PSP_SCREEN_WIDTH - 5 || newX < 0 - 140) { // clamp + DEBUG_EXIT_FUNC(); return; - _moved_x = newX; + } + _movedX = newX; + setDirty(); + + DEBUG_EXIT_FUNC(); } /* move the position the keyboard is currently drawn at */ void PSPKeyboard::increaseKeyboardLocationY(int amount) { - int newY = _moved_y + amount; + DEBUG_ENTER_FUNC(); + + int newY = _movedY + amount; - if (newY > PSP_SCREEN_HEIGHT - 5 || newY < 0 - 140) // clamp + if (newY > PSP_SCREEN_HEIGHT - 5 || newY < 0 - 140) { // clamp + DEBUG_EXIT_FUNC(); return; - _moved_y = newY; + } + _movedY = newY; + setDirty(); + + DEBUG_EXIT_FUNC(); } /* draw the keyboard at the current position */ void PSPKeyboard::render() { - _dirty = false; + DEBUG_ENTER_FUNC(); + + unsigned int currentBuffer = _mode<<1; + + // Draw the background letters + // Set renderer to current buffer & palette + _renderer.setBuffer(&_buffers[currentBuffer]); + _renderer.setPalette(&_palettes[currentBuffer]); + _renderer.setOffsetOnScreen(_movedX, _movedY); + _renderer.setOffsetInBuffer(0, 0); + _renderer.setDrawWholeBuffer(); + _renderer.render(); + + // Get X and Y coordinates for the orange block int x, y; + convertCursorToXY(_oldCursor, x, y); + + const int OrangeBlockSize = 64; + const int GrayBlockSize = 43; + + // Draw the current Highlighted Selector (orange block) + _renderer.setBuffer(&_buffers[currentBuffer + 1]); + _renderer.setPalette(&_palettes[currentBuffer + 1]); + _renderer.setOffsetOnScreen(_movedX + (x * GrayBlockSize), _movedY + (y * GrayBlockSize)); + _renderer.setOffsetInBuffer(x * OrangeBlockSize, y * OrangeBlockSize); + _renderer.setDrawSize(OrangeBlockSize, OrangeBlockSize); + _renderer.render(); + + DEBUG_EXIT_FUNC(); +} - switch(_oldCursor) { +inline void PSPKeyboard::convertCursorToXY(CursorDirections cur, int &x, int &y) { + switch(cur) { case kUp: x = 1; y = 0; @@ -423,76 +257,17 @@ void PSPKeyboard::render() { y = 1; break; } - - // Draw the background letters - surface_draw_offset(&_keyTextures[_mode<<1], 0, 0, 0, 0, - _keyTextures[_mode<<1].texture_width, - _keyTextures[_mode<<1].texture_height); - - // Draw the current Highlighted Selector (orange bit) - surface_draw_offset(&_keyTextures[(_mode<<1) + 1], - //Offset from the current draw position to render at - x * 43, y * 43, - //internal offset of the image - x * 64, y * 64, - //size to render (always the same) - 64, 64); -} - - -// Render the given surface at the current screen position offset by screenX, screenY -// the surface will be internally offset by offsetX,offsetY. And the size of it to be drawn will be intWidth,intHeight -void PSPKeyboard::surface_draw_offset(struct gu_surface* surface, int screenX, int screenY, int offsetX, int offsetY, int intWidth, int intHeight) { - sceGuAlphaFunc( GU_GREATER, 0, 0xff ); - sceGuEnable( GU_ALPHA_TEST ); - sceGuTexFunc(GU_TFX_BLEND,GU_TCC_RGBA); - sceGuTexEnvColor(0xFF000000); - sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 ); - sceGuEnable(GU_BLEND); - if (surface->paletteSize == 256) { // 8-bit - sceGuClutMode(GU_PSM_8888, 0, 0xFF, 0); - sceGuClutLoad(32, surface->palette); // upload 32*8 entries (256) - sceGuTexMode(GU_PSM_T8, 0, 0, 0); // 8-bit image - } else if (surface->paletteSize == 16) { // 4-bit - sceGuClutMode(GU_PSM_8888, 0, 0x0F, 0); - sceGuClutLoad(2, surface->palette); // upload 2*8 entries (16) - sceGuTexMode(GU_PSM_T4, 0, 0, 0); // 4-bit image - } else { // 32-bit - sceGuTexMode(GU_PSM_8888,0,0,GU_FALSE); - } - sceGuTexImage(0,surface->surface_width, surface->surface_height,surface->surface_width, surface->texture); - sceGuTexFunc(GU_TFX_MODULATE,GU_TCC_RGBA); - - Vertex* c_vertices = (Vertex*)sceGuGetMemory(2 * sizeof(Vertex)); - - c_vertices[0].u = offsetX; - c_vertices[0].v = offsetY; - c_vertices[0].x = _moved_x + screenX; - c_vertices[0].y = _moved_y + screenY; - c_vertices[0].z = 0; - c_vertices[0].color = 0xFFFFFFFF; - - c_vertices[1].u = offsetX + intWidth; - c_vertices[1].v = offsetY + intHeight; - c_vertices[1].x = _moved_x + screenX + intWidth; - c_vertices[1].y = _moved_y + screenY + intHeight; - c_vertices[1].z = 0; - c_vertices[1].color = 0xFFFFFFFF; - - sceGuDrawArray(GU_SPRITES,GU_TEXTURE_32BITF|GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_2D,2,0,c_vertices); - - sceGuDisable( GU_BLEND ); - sceGuDisable( GU_ALPHA_TEST ); } -/* load all the guibits that make up the OSK */ +/* load the keyboard into memory */ bool PSPKeyboard::load() { - unsigned char *temp_texture = NULL; - uint32 *temp_palette = NULL; - int a; + DEBUG_ENTER_FUNC(); - if (_init) + if (_init) { + PSP_DEBUG_PRINT("keyboard already loaded into memory\n"); + DEBUG_EXIT_FUNC(); return true; + } // For the shell, we must use a hack #ifdef PSP_KB_SHELL @@ -500,221 +275,131 @@ bool PSPKeyboard::load() { #else /* normal mode */ Common::FSNode node("."); // Look in current directory #endif -#ifdef PSP_KB_DEBUG - fprintf(stderr, "path = %s\n", node.getPath().c_str()); -#endif + PSP_DEBUG_PRINT("path[%s]\n", node.getPath().c_str()); Common::Archive *fileArchive = NULL; Common::Archive *zipArchive = NULL; Common::SeekableReadStream * file = 0; if (node.getChild("kbd").exists() && node.getChild("kbd").isDirectory()) { -#ifdef PSP_KB_DEBUG - fprintf(stderr, "found directory ./kbd\n"); -#endif + PSP_DEBUG_PRINT("found directory ./kbd\n"); fileArchive = new Common::FSDirectory(node.getChild("kbd")); } if (node.getChild("kbd.zip").exists()) { -#ifdef PSP_KB_DEBUG - fprintf(stderr, "found kbd.zip\n"); -#endif + PSP_DEBUG_PRINT("found kbd.zip\n"); zipArchive = Common::makeZipArchive(node.getChild("kbd.zip")); } - // Loop through different png images - for (a = 0; a < guiStringsSize; a++) { + int i; + + // Loop through all png images + for (i = 0; i < guiStringsSize; i++) { uint32 height = 0, width = 0, paletteSize = 0; -#ifdef PSP_KB_DEBUG - fprintf(stderr, "load(): Opening %s.\n", _guiStrings[a]); -#endif + PSP_DEBUG_PRINT("Opening %s.\n", _guiStrings[i]); // Look for the file in the kbd directory - if (fileArchive && fileArchive->hasFile(_guiStrings[a])) { - -#ifdef PSP_KB_DEBUG - fprintf(stderr, "load(): found it in kbd directory.\n"); -#endif + if (fileArchive && fileArchive->hasFile(_guiStrings[i])) { + PSP_DEBUG_PRINT("found it in kbd directory.\n"); - file = fileArchive->createReadStreamForMember(_guiStrings[a]); + file = fileArchive->createReadStreamForMember(_guiStrings[i]); if (!file) { - fprintf(stderr, "load(): Can't open kbd/%s for keyboard. No keyboard will load.\n", _guiStrings[a]); + PSP_ERROR("Can't open kbd/%s for keyboard. No keyboard will load.\n", _guiStrings[i]); goto ERROR; } } // We didn't find it. Look for it in the zip file - else if (zipArchive && zipArchive->hasFile(_guiStrings[a])) { + else if (zipArchive && zipArchive->hasFile(_guiStrings[i])) { + PSP_DEBUG_PRINT("found it in kbd.zip.\n"); -#ifdef PSP_KB_DEBUG - fprintf(stderr, "load(): found it in kbd.zip.\n"); -#endif - - file = zipArchive->createReadStreamForMember(_guiStrings[a]); + file = zipArchive->createReadStreamForMember(_guiStrings[i]); if (!file) { - fprintf(stderr, "Can't open %s in kbd.zip for keyboard. No keyboard will load.\n", _guiStrings[a]); + PSP_ERROR("Can't open %s in kbd.zip for keyboard. No keyboard will load.\n", _guiStrings[i]); goto ERROR; } } else { // Couldn't find the file - fprintf(stderr, "load(): Can't find %s for keyboard. No keyboard will load.\n", _guiStrings[a]); + PSP_ERROR("Can't find %s for keyboard. No keyboard will load.\n", _guiStrings[i]); goto ERROR; } - if (get_png_image_size(file, &width, &height, &paletteSize) == 0) { // Check image size and palette size + if (getPngImageSize(file, &width, &height, &paletteSize) == 0) { // Check image size and palette size // Allocate memory for image -#ifdef PSP_KB_DEBUG - fprintf(stderr, "load(): width=%d, height=%d, paletteSize=%d\n", width, height, paletteSize); -#endif - + PSP_DEBUG_PRINT("width[%d], height[%d], paletteSize[%d]\n", width, height, paletteSize); + _buffers[i].setSize(width, height, Buffer::kSizeByTextureSize); + if (paletteSize) { // 8 or 4-bit image - uint32 textureSize = 0; - if (paletteSize <= 16) { // 4 bit - paletteSize = 16; - textureSize = (width * height)>>1; + _buffers[i].setPixelFormat(PSPPixelFormat::Type_Palette_4bit); + _palettes[i].setPixelFormats(PSPPixelFormat::Type_4444, PSPPixelFormat::Type_Palette_4bit); + paletteSize = 16; } else if (paletteSize <= 256){ // 8-bit image paletteSize = 256; - textureSize = width * height; + _buffers[i].setPixelFormat(PSPPixelFormat::Type_Palette_8bit); + _palettes[i].setPixelFormats(PSPPixelFormat::Type_4444, PSPPixelFormat::Type_Palette_8bit); } else { - fprintf(stderr, "Error: palette of %d too big!\n", paletteSize); + PSP_ERROR("palette of %d too big!\n", paletteSize); goto ERROR; } -#ifdef PSP_KB_DEBUG - fprintf(stderr, "load(): allocating %d bytes for texture and %d for palette\n", textureSize, paletteSize*4); -#endif - temp_texture = (u8 *)malloc(textureSize); - temp_palette = (uint32 *)memalign(16, paletteSize<<2); - memset(temp_palette, 0, paletteSize<<2); // Set to 0 since we might only fill some of it + } else { // 32-bit image - temp_texture = (unsigned char *)malloc((width * height)<<2); + _buffers[i].setPixelFormat(PSPPixelFormat::Type_8888); } + + _buffers[i].allocate(); + _palettes[i].allocate(); // Try to load the image file->seek(0); // Go back to start - if (load_png_image(file, temp_texture, temp_palette) != 0) + if (loadPngImage(file, _buffers[i], _palettes[i]) != 0) goto ERROR; else { // Success -#ifdef PSP_KB_DEBUG - fprintf(stderr, "Managed to load the image.\n"); -#endif - // we need to store the texture in an image of width and heights of 2^n sizes - _keyTextures[a].texture_width = width; // original size - _keyTextures[a].texture_height = height; - _keyTextures[a].surface_width = convert_pow2(width); // converted size - _keyTextures[a].surface_height = convert_pow2(height); - _keyTextures[a].palette = temp_palette; - _keyTextures[a].paletteSize = paletteSize; - - uint32 size; - - if (paletteSize == 16) // 4 bit - size = (_keyTextures[a].surface_width * _keyTextures[a].surface_height)>>1; - else if (paletteSize == 256) // 8-bit - size = _keyTextures[a].surface_width * _keyTextures[a].surface_height; - else // 32 bit - size = (_keyTextures[a].surface_width * _keyTextures[a].surface_height)<<2; - -#ifdef PSP_KB_DEBUG - fprintf(stderr, "load(): perm texture width=%d, height=%d, size=%d\n", _keyTextures[a].surface_width, _keyTextures[a].surface_height, size); -#endif - _keyTextures[a].texture = (unsigned char *)memalign(16, size); // Allocate memory - - block_copy(&_keyTextures[a], temp_texture); // Copy temp texture to permanent texture + PSP_DEBUG_PRINT("Managed to load the image\n"); if (paletteSize == 16) // 4-bit - flipNibbles(&_keyTextures[a]); - - free(temp_texture); + _buffers[i].flipNibbles(); delete file; } } - else + else { + PSP_ERROR("couldn't obtain PNG image size\n"); goto ERROR; + } } /* for loop */ + _init = true; delete fileArchive; delete zipArchive; + DEBUG_EXIT_FUNC(); return true; ERROR: - // Error .. Couldn't get png info from one of the needed files - free(temp_texture); delete file; delete fileArchive; delete zipArchive; - for (int b = 0; b < a; b++) { - free(_keyTextures[b].texture); - free(_keyTextures[b].palette); - _keyTextures[b].texture = NULL; + for (int j = 0; j < i; j++) { + _buffers[j].deallocate(); + _palettes[j].deallocate(); } _init = false; + + DEBUG_EXIT_FUNC(); return false; } -// Copy texture from regular size image to power of 2 size image -// -void PSPKeyboard::block_copy(gu_surface* surface, u8 *texture) { - u32 stride = 0, width = 0; - - switch(surface->paletteSize) { - case 16: // 4-bit - width = surface->texture_width >> 1; - stride = (surface->surface_width - surface->texture_width)>>1; - break; - case 256: // 8-bit - width = surface->texture_width; - stride = surface->surface_width - surface->texture_width; - break; - case 0: // 32-bit - width = surface->texture_width << 2; - stride = (surface->surface_width - surface->texture_width)<<2; - break; - default: - fprintf(stderr, "Error in block_copy: bad value in paletteSize = %d\n", surface->paletteSize); - return; - } - - u8 *src = texture; - u8 *dest = surface->texture; - - for (unsigned int y = 0; y < surface->texture_height; y++) { - memcpy(dest, src, width); - dest += width; - src += width; - - // skip at the end of each line - if (stride > 0) { - dest += stride; - } - } -} - -// Convert 4 bit images to match weird PSP format -// -void PSPKeyboard::flipNibbles(gu_surface* surface) { - u32 *dest = (u32 *)surface->texture; - - for (u32 y = 0; y < surface->texture_height; y++) { - for (u32 x = 0; x < (surface->surface_width >> 3); x++) { - u32 val = *dest; - *dest++ = ((val >> 4) & 0x0F0F0F0F) | ((val << 4) & 0xF0F0F0F0); - } - } - -} - - static void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) { // ignore PNG warnings } /* Get the width and height of a png image */ -int PSPKeyboard::get_png_image_size(Common::SeekableReadStream *file, uint32 *png_width, uint32 *png_height, u32 *paletteSize) { +int PSPKeyboard::getPngImageSize(Common::SeekableReadStream *file, uint32 *png_width, uint32 *png_height, u32 *paletteSize) { + DEBUG_ENTER_FUNC(); + png_structp png_ptr; png_infop info_ptr; unsigned int sig_read = 0; @@ -723,12 +408,14 @@ int PSPKeyboard::get_png_image_size(Common::SeekableReadStream *file, uint32 *pn png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { + DEBUG_EXIT_FUNC(); return -1; } png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, user_warning_fn); info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); + DEBUG_EXIT_FUNC(); return -1; } // Set the png lib to use our read function @@ -746,22 +433,27 @@ int PSPKeyboard::get_png_image_size(Common::SeekableReadStream *file, uint32 *pn *png_width = width; *png_height = height; + + DEBUG_EXIT_FUNC(); return 0; } // Load a texture from a png image // -int PSPKeyboard::load_png_image(Common::SeekableReadStream *file, unsigned char *ImageBuffer, uint32 *palette) { +int PSPKeyboard::loadPngImage(Common::SeekableReadStream *file, Buffer &buffer, Palette &palette) { + DEBUG_ENTER_FUNC(); + png_structp png_ptr; png_infop info_ptr; unsigned int sig_read = 0; png_uint_32 width, height; int bit_depth, color_type, interlace_type; - size_t x, y; + size_t y; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { - fprintf(stderr, "load_png_image(): Error: couldn't create read struct to load keyboard.\n"); + PSP_ERROR("Couldn't create read struct to load keyboard\n"); + DEBUG_EXIT_FUNC(); return -1; } // Use dummy error function @@ -769,11 +461,13 @@ int PSPKeyboard::load_png_image(Common::SeekableReadStream *file, unsigned char info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { + PSP_ERROR("Couldn't create info struct to load keyboard\n"); png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); + DEBUG_EXIT_FUNC(); return -1; } - // Set the png lib to use our read function + // Set the png lib to use our customized read function png_set_read_fn(png_ptr, (void *)file, pngReadStreamRead); png_set_sig_bytes(png_ptr, sig_read); @@ -784,71 +478,278 @@ int PSPKeyboard::load_png_image(Common::SeekableReadStream *file, unsigned char png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) { - // We copy the palette - uint32 *dstPal = palette; + // Copy the palette png_colorp srcPal = info_ptr->palette; for(int i=0; i < info_ptr->num_palette; i++) { unsigned char alphaVal = (i < info_ptr->num_trans) ? info_ptr->trans[i] : 0xFF; // Load alpha if it's there - *dstPal++ = GU_ARGB(alphaVal, srcPal->red, srcPal->green, srcPal->blue); + palette.setSingleColorRGBA(i, srcPal->red, srcPal->green, srcPal->blue, alphaVal); srcPal++; } - - unsigned char *line = (unsigned char*) malloc(info_ptr->rowbytes); - if (!line) { - png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); - return -1; - } - - for (y = 0; y < height; y++) { - png_read_row(png_ptr, line, png_bytep_NULL); - memcpy(&ImageBuffer[y * info_ptr->rowbytes], line, info_ptr->rowbytes); - } - - free(line); } else { // Not a palettized image + // Round up grayscale images if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); // Convert trans channel to alpha for 32 bits if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + // Filler for alpha? png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + } - u32* line = (u32*) malloc(width<<2); - if (!line) { - png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); - return -1; - } - - u32* Image = (u32 *)ImageBuffer; - for (y = 0; y < height; y++) { - png_read_row(png_ptr, (u8*) line, png_bytep_NULL); - for (x = 0; x < width; x++) { - Image[y*width + x] = line[x]; - } - } + unsigned char *line = (unsigned char*) malloc(info_ptr->rowbytes); + if (!line) { + png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); + PSP_ERROR("Couldn't allocate line\n"); + DEBUG_EXIT_FUNC(); + return -1; + } - free(line); + for (y = 0; y < height; y++) { + png_read_row(png_ptr, line, png_bytep_NULL); + buffer.copyFromRect(line, info_ptr->rowbytes, 0, y, width, 1); // Copy into buffer + //memcpy(buffer.getPixels()[y * buffer.getWidthInBytes()], line, info_ptr->rowbytes); } + free(line); + png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + DEBUG_EXIT_FUNC(); return 0; } -// Function to get the lowest power of 2 higher than our image size -// -uint32 PSPKeyboard::convert_pow2(uint32 size) { - uint32 pow_counter = 0; - - for (; pow_counter < 32; pow_counter++) { - // Find the first value which is higher - if ((size >> pow_counter) == 0) { - // take already good values into account - if (((uint32) 1 << pow_counter) != size) - return ((uint32)1 << pow_counter); - else - return ((uint32)1 << (pow_counter-1)); +// Defines for working with PSP buttons +#define CHANGED(x) (_buttonsChanged & (x)) +#define PRESSED(x) ((_buttonsChanged & (x)) && (pad.Buttons & (x))) +#define UNPRESSED(x) ((_buttonsChanged & (x)) && !(pad.Buttons & (x))) +#define DOWN(x) (pad.Buttons & (x)) +#define UP(x) (!(pad.Buttons & (x))) +#define PSP_DPAD (PSP_CTRL_DOWN|PSP_CTRL_UP|PSP_CTRL_LEFT|PSP_CTRL_RIGHT) +#define PSP_4BUTTONS (PSP_CTRL_CROSS | PSP_CTRL_CIRCLE | PSP_CTRL_TRIANGLE | PSP_CTRL_SQUARE) + +/* + * Attempts to read a character from the controller + * Uses the state machine. + * returns whether we have an event + */ +bool PSPKeyboard::processInput(Common::Event &event, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + + bool haveEvent = false; // Whether we have an event for the event manager to process + event.kbd.flags = 0; + + _buttonsChanged = _prevButtons ^ pad.Buttons; + + if (!_init) // In case we never had init + return false; + if (_state == kInvisible) // Return if we're invisible + return false; + if (_state != kMove && PRESSED(PSP_CTRL_SELECT)) { + _lastState = _state; + _state = kMove; // Check for move or visible state + } + else if (CHANGED(PSP_CTRL_START)) { // Handle start button: enter, make KB invisible + event.kbd.ascii = '\r'; + event.kbd.keycode = Common::KEYCODE_RETURN; + event.type = DOWN(PSP_CTRL_START) ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP; + haveEvent = true; + _dirty = true; + if (UP(PSP_CTRL_START)) + _state = kInvisible; // Make us invisible if unpressed + } + // Check for being in state of moving the keyboard onscreen or pressing select + else if (_state == kMove) + handleMoveState(pad); + else if (_state == kDefault) + haveEvent = handleDefaultState(event, pad); + else if (_state == kCornersSelected) + haveEvent = handleCornersSelectedState(event, pad); + else if (_state == kRTriggerDown) + handleRTriggerDownState(pad); // Deal with trigger states + else if (_state == kLTriggerDown) + handleLTriggerDownState(pad); // Deal with trigger states + + _prevButtons = pad.Buttons; + + DEBUG_EXIT_FUNC(); + return haveEvent; +} + +void PSPKeyboard::handleMoveState(SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + if (UP(PSP_CTRL_SELECT)) { + // Toggle between visible and invisible + _state = (_lastState == kInvisible) ? kDefault : kInvisible; + _dirty = true; + + if (_moved) { // We moved the keyboard. Keep the keyboard onscreen anyway + _state = kDefault; + _moved = false; // reset moved flag } + } else if (DOWN(PSP_DPAD)) { // How we move the KB onscreen + _moved = true; + _dirty = true; + + if (DOWN(PSP_CTRL_DOWN)) + increaseKeyboardLocationY(5); + else if (DOWN(PSP_CTRL_UP)) + increaseKeyboardLocationY(-5); + else if (DOWN(PSP_CTRL_LEFT)) + increaseKeyboardLocationX(-5); + else /* DOWN(PSP_CTRL_RIGHT) */ + increaseKeyboardLocationX(5); } - return 0; + DEBUG_EXIT_FUNC(); +} + +bool PSPKeyboard::handleDefaultState(Common::Event &event, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + bool haveEvent = false; + + if (PRESSED(PSP_CTRL_LTRIGGER)) // Don't say we used up the input + _state = kLTriggerDown; + else if (PRESSED(PSP_CTRL_RTRIGGER)) // Don't say we used up the input + _state = kRTriggerDown; + else if (CHANGED(PSP_4BUTTONS)) // We only care about the 4 buttons + haveEvent = getInputChoice(event, pad); + else if (!DOWN(PSP_4BUTTONS)) // Must be up to move cursor + getCursorMovement(pad); + + DEBUG_EXIT_FUNC(); + return haveEvent; } +bool PSPKeyboard::handleCornersSelectedState(Common::Event &event, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + // We care about 4 buttons + triggers (for letter selection) + bool haveEvent = false; + + if (CHANGED(PSP_4BUTTONS | PSP_CTRL_RTRIGGER | PSP_CTRL_LTRIGGER)) + haveEvent = getInputChoice(event, pad); + if (!DOWN(PSP_4BUTTONS | PSP_CTRL_RTRIGGER | PSP_CTRL_LTRIGGER)) // Must be up to move cursor + getCursorMovement(pad) + + DEBUG_EXIT_FUNC(); + return haveEvent; +} + +bool PSPKeyboard::getInputChoice(Common::Event &event, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + int innerChoice; + bool haveEvent = false; + + if (UNPRESSED(PSP_CTRL_TRIANGLE)) { + innerChoice = 0; + event.type = Common::EVENT_KEYUP; // We give priority to key_up + } else if (UNPRESSED(PSP_CTRL_CIRCLE)) { + innerChoice = 1; + event.type = Common::EVENT_KEYUP; // We give priority to key_up + } else if (UNPRESSED(PSP_CTRL_CROSS)) { + innerChoice = 2; + event.type = Common::EVENT_KEYUP; // We give priority to key_up + } else if (UNPRESSED(PSP_CTRL_SQUARE)) { + innerChoice = 3; + event.type = Common::EVENT_KEYUP; // We give priority to key_up + } else if (UNPRESSED(PSP_CTRL_LTRIGGER) && _state == kCornersSelected) { + innerChoice = 4; + event.type = Common::EVENT_KEYUP; // We give priority to key_up + } else if (UNPRESSED(PSP_CTRL_RTRIGGER) && _state == kCornersSelected) { + innerChoice = 5; + event.type = Common::EVENT_KEYUP; // We give priority to key_up + } else if (PRESSED(PSP_CTRL_TRIANGLE)) { + innerChoice = 0; + event.type = Common::EVENT_KEYDOWN; + } else if (PRESSED(PSP_CTRL_CIRCLE)) { + innerChoice = 1; + event.type = Common::EVENT_KEYDOWN; + } else if (PRESSED(PSP_CTRL_CROSS)) { + innerChoice = 2; + event.type = Common::EVENT_KEYDOWN; + } else if (PRESSED(PSP_CTRL_SQUARE)) { + innerChoice = 3; + event.type = Common::EVENT_KEYDOWN; + } else if (PRESSED(PSP_CTRL_LTRIGGER) && _state == kCornersSelected) { + innerChoice = 4; + event.type = Common::EVENT_KEYDOWN; // We give priority to key_up + } else /* (PRESSED(PSP_CTRL_RTRIGGER)) && _state == kCornersSelected */ { + innerChoice = 5; + event.type = Common::EVENT_KEYDOWN; // We give priority to key_up + } + + #define IS_UPPERCASE(x) ((x) >= (unsigned short)'A' && (x) <= (unsigned short)'Z') + #define TO_LOWER(x) ((x) += 'a'-'A') + + //Now grab the value out of the array + short choice = _modeChar[_mode][_oldCursor][innerChoice]; + + event.kbd.ascii = choice <= 255 ? choice : 0; + + // Handle upper-case which is missing in Common::KeyCode + if (IS_UPPERCASE(choice)) { + event.kbd.keycode = (Common::KeyCode) TO_LOWER(choice); + event.kbd.flags = Common::KBD_SHIFT; + } else + event.kbd.keycode = (Common::KeyCode) choice; + + haveEvent = (choice != Common::KEYCODE_INVALID) ? true : false; // We have an event/don't if it's invalid + + DEBUG_EXIT_FUNC(); + return haveEvent; +} + +void PSPKeyboard::getCursorMovement(SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + CursorDirections cursor; + + // Find where the cursor is pointing + cursor = kCenter; + _state = kDefault; + + if (DOWN(PSP_DPAD)) { + _state = kCornersSelected; + + if (DOWN(PSP_CTRL_UP)) + cursor = kUp; + else if (DOWN(PSP_CTRL_RIGHT)) + cursor = kRight; + else if (DOWN(PSP_CTRL_DOWN)) + cursor = kDown; + else if (DOWN(PSP_CTRL_LEFT)) + cursor = kLeft; + } + + if (cursor != _oldCursor) { //If we've moved, update dirty and return + _dirty = true; + _oldCursor = cursor; + } + DEBUG_EXIT_FUNC(); +} + +void PSPKeyboard::handleLTriggerDownState(SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + if (UNPRESSED(PSP_CTRL_LTRIGGER)) { + _dirty = true; + + if(_mode < 2) + _mode = 2; + else + _mode = (_mode == 2) ? 3 : 2; + + _state = kDefault; + } + DEBUG_EXIT_FUNC(); +} + +void PSPKeyboard::handleRTriggerDownState(SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + if (UNPRESSED(PSP_CTRL_RTRIGGER)) { + _dirty = true; + + if(_mode > 1) + _mode = 0; + else + _mode = (_mode == 0) ? 1 : 0; + + _state = kDefault; + } + DEBUG_EXIT_FUNC(); +} diff --git a/backends/platform/psp/pspkeyboard.h b/backends/platform/psp/pspkeyboard.h index b9681c1e0e..457476e844 100644 --- a/backends/platform/psp/pspkeyboard.h +++ b/backends/platform/psp/pspkeyboard.h @@ -28,13 +28,14 @@ #include "common/events.h" #include "common/stream.h" +#include "backends/platform/psp/display_client.h" #include <pspctrl.h> //number of modes #define MODE_COUNT 4 #define guiStringsSize 8 /* size of guistrings array */ -class PSPKeyboard { +class PSPKeyboard : public DisplayClient { private: enum State { @@ -49,67 +50,63 @@ private: public: PSPKeyboard(); ~PSPKeyboard(); + bool load(); // Load keyboard into memory bool isInit() { return _init; } // Check for initialization bool isDirty() { return _dirty; } // Check if needs redrawing + void setDirty() { _dirty = true; } + void setClean() { _dirty = false; } bool isVisible() { return _state != kInvisible; } // Check if visible - bool processInput(Common::Event &event, SceCtrlData &pad, bool &usedInput); // Process input + void setVisible(bool val); + bool processInput(Common::Event &event, SceCtrlData &pad); // Process input void moveTo(const int newX, const int newY); // Move keyboard void render(); // Draw the keyboard onscreen private: - struct gu_surface { - u32 surface_width; - u32 surface_height; - u32 texture_width; - u32 texture_height; - u8 *texture; - u32 *palette; - u32 paletteSize; + enum CursorDirections { + kUp = 0, + kRight, + kDown, + kLeft, + kCenter }; + Buffer _buffers[guiStringsSize]; + Palette _palettes[guiStringsSize]; + GuRenderer _renderer; -// structures used for drawing the keyboard - struct Vertex { - float u, v; - unsigned int color; - float x,y,z; - }; - - void surface_draw_offset(struct gu_surface* surface, - int screenX, int screenY, int offsetX, int offsetY, int intWidth, int intHeight); - void block_copy(gu_surface* surface, u8 *texture); - int load_png_image(Common::SeekableReadStream *, unsigned char *ImageBuffer, uint32 *palette); - int get_png_image_size(Common::SeekableReadStream *, uint32 *png_width, uint32 *png_height, u32 *paletteSize); + int loadPngImage(Common::SeekableReadStream *file, Buffer &buffer, Palette &palette); + int getPngImageSize(Common::SeekableReadStream *, uint32 *png_width, uint32 *png_height, u32 *paletteSize); uint32 convert_pow2(uint32 size); - void flipNibbles(gu_surface* surface); // Convert to PSP 4-bit format void increaseKeyboardLocationX(int amount); // Move keyboard onscreen void increaseKeyboardLocationY(int amount); - + void convertCursorToXY(CursorDirections cur, int &x, int &y); + + void handleMoveState(SceCtrlData &pad); + bool handleDefaultState(Common::Event &event, SceCtrlData &pad); + bool handleCornersSelectedState(Common::Event &event, SceCtrlData &pad); + bool getInputChoice(Common::Event &event, SceCtrlData &pad); + void getCursorMovement(SceCtrlData &pad); + void handleRTriggerDownState(SceCtrlData &pad); + void handleLTriggerDownState(SceCtrlData &pad); + static short _modeChar[MODE_COUNT][5][6]; static const char *_guiStrings[]; bool _init; - unsigned int _prevButtons; // A bit pattern. + uint32 _prevButtons; // A bit pattern. + uint32 _buttonsChanged; + bool _dirty; // keyboard needs redrawing int _mode; // charset selected. (0 - letters or 1 - numbers) - int _moved_x; // location we've moved the KB to onscreen - int _moved_y; + int _movedX; // location we've moved the KB to onscreen + int _movedY; bool _moved; // whether the keyboard was moved - gu_surface _keyTextures[guiStringsSize]; - + State _state; // State of keyboard Keyboard state machine State _lastState; - enum Cursor { - kUp = 0, - kRight, - kDown, - kLeft, - kCenter - }; - - Cursor _oldCursor; // Point to place of last cursor + CursorDirections _oldCursor; // Point to place of last cursor }; -#endif /* PSPKEYBOARD_H */
\ No newline at end of file +#endif /* PSPKEYBOARD_H */ diff --git a/backends/platform/psp/psploader.h b/backends/platform/psp/psploader.h index 70022d65de..13dcf6ef98 100644 --- a/backends/platform/psp/psploader.h +++ b/backends/platform/psp/psploader.h @@ -135,4 +135,3 @@ extern "C" { } #endif /* PSPLOADER_H */ - diff --git a/backends/platform/psp/psppixelformat.cpp b/backends/platform/psp/psppixelformat.cpp new file mode 100644 index 0000000000..7758f2c26b --- /dev/null +++ b/backends/platform/psp/psppixelformat.cpp @@ -0,0 +1,166 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $ + * + */ + +#include "common/scummsys.h" +#include "backends/platform/psp/psppixelformat.h" + +//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */ +//#define __PSP_DEBUG_PRINT__ /* For debug printouts */ + +#include "backends/platform/psp/trace.h" + +// class PSPPixelFormat -------------------------------------- + +void PSPPixelFormat::set(Type type, bool swap /* = false */) { + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("type = %d\n", type); + + format = type; + swapRB = swap; + + switch (type) { + case Type_4444: + case Type_5551: + case Type_5650: + bitsPerPixel = 16; + break; + case Type_8888: + bitsPerPixel = 32; + break; + case Type_Palette_8bit: + bitsPerPixel = 8; + break; + case Type_Palette_4bit: + bitsPerPixel = 4; + break; + case Type_None: + bitsPerPixel = 0; + break; + default: // This is an error, but let's continue anyway + PSP_ERROR("Unhandled value of pixel type[%d]\n", type); + bitsPerPixel = 16; + break; + } + + PSP_DEBUG_PRINT("bitsPerPixel[%u]\n", bitsPerPixel); + DEBUG_EXIT_FUNC(); +} + +// Convert from ScummVM general PixelFormat to our pixel format +// For buffer and palette. +void PSPPixelFormat::convertFromScummvmPixelFormat(const Graphics::PixelFormat *pf, + PSPPixelFormat::Type &bufferType, + PSPPixelFormat::Type &paletteType, + bool &swapRedBlue) { + swapRedBlue = false; // no red-blue swap by default + PSPPixelFormat::Type *target = 0; // which one we'll be filling + + if (!pf) { // Default, pf is NULL + bufferType = Type_Palette_8bit; + paletteType = Type_5551; + } else { // We have a pf + if (pf->bytesPerPixel == 1) { + bufferType = Type_Palette_8bit; + target = &paletteType; // The type describes the palette + } else if (pf->bytesPerPixel == 2) { + paletteType = Type_None; + target = &bufferType; // The type describes the buffer + } else { + PSP_ERROR("Unknown bpp[%u] in pixeltype. Reverting to 8bpp\n", pf->bytesPerPixel); + bufferType = Type_Palette_8bit; + target = &paletteType; // The type describes the palette + } + + // Find out the exact type of the target + if (pf->rLoss == 3 && pf->bLoss == 3) { + if (pf->gLoss == 3) + *target = Type_5551; + else + *target = Type_5650; + } else if (pf->rLoss == 4 && pf->gLoss == 4 && pf->bLoss == 4) { + *target = Type_4444; + } else if (pf->gLoss == 0 && pf->gShift == 8) { + *target = Type_8888; + } else if ((pf->gLoss == 0 && pf->gShift == 0) || + (pf->gLoss == 8 && pf->gShift == 0)) { // Default CLUT8 can have weird values + *target = Type_5551; + } else { + PSP_ERROR("Unknown Scummvm pixel format.\n"); + PSP_ERROR("\trLoss[%d], gLoss[%d], bLoss[%d], aLoss[%d]\n\trShift[%d], gShift[%d], bShift[%d], aShift[%d]\n", + pf->rLoss, pf->gLoss, pf->bLoss, pf->aLoss, + pf->rShift, pf->gShift, pf->bShift, pf->aShift); + *target = Type_Unknown; + } + + if (pf->rShift != 0) {// We allow backend swap of red and blue + swapRedBlue = true; + PSP_DEBUG_PRINT("detected red/blue swap\n"); + } + } +} + +Graphics::PixelFormat PSPPixelFormat::convertToScummvmPixelFormat(PSPPixelFormat::Type type) { + Graphics::PixelFormat pf; + + switch(type) { + case Type_4444: + pf.bytesPerPixel = 2; + pf.aLoss = 4; pf.rLoss = 4; pf.gLoss = 4; pf.bLoss = 4; + pf.aShift = 12; pf.rShift = 0; pf.gShift = 4; pf.bShift = 8; + break; + case Type_5551: + pf.bytesPerPixel = 2; + pf.aLoss = 7; pf.rLoss = 3; pf.gLoss = 3; pf.bLoss = 3; + pf.aShift = 15; pf.rShift = 0; pf.gShift = 5; pf.bShift = 10; + break; + case Type_5650: + pf.bytesPerPixel = 2; + pf.aLoss = 8; pf.rLoss = 3; pf.gLoss = 2; pf.bLoss = 3; + pf.aShift = 0; pf.rShift = 0; pf.gShift = 5; pf.bShift = 11; + break; + case Type_8888: + pf.bytesPerPixel = 4; + pf.aLoss = 0; pf.rLoss = 0; pf.gLoss = 0; pf.bLoss = 0; + pf.aShift = 24; pf.rShift = 0; pf.gShift = 8; pf.bShift = 16; + break; + default: + PSP_ERROR("Unhandled PSPPixelFormat[%u]\n", type); + break; + } + + return pf; +} + +uint32 PSPPixelFormat::convertTo32BitColor(uint32 color) { + DEBUG_ENTER_FUNC(); + uint32 r,g,b,a, output; + + colorToRgba(color, r, g, b, a); + output = ((b << 16) | (g << 8) | (r << 0) | (a << 24)); + PSP_DEBUG_PRINT_FUNC("input color[%x], output[%x]\n", color, output); + + DEBUG_EXIT_FUNC(); + return output; +} diff --git a/backends/platform/psp/psppixelformat.h b/backends/platform/psp/psppixelformat.h new file mode 100644 index 0000000000..8a7283df43 --- /dev/null +++ b/backends/platform/psp/psppixelformat.h @@ -0,0 +1,240 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $ + * + */ + +#ifndef PSP_PIXEL_FORMAT_H +#define PSP_PIXEL_FORMAT_H + +#include "graphics/pixelformat.h" +#include "backends/platform/psp/trace.h" + +/** + * Specialized PixelFormat class + * Supports only those formats which the PSP allows, including 4 bit palettes. + * Also provides accurate color conversion (needed for color masking) + * As well as swapping of red and blue channels (needed by HE games, for example) + */ +struct PSPPixelFormat{ + enum Type { + Type_None, + Type_4444, + Type_5551, + Type_5650, + Type_8888, + Type_Palette_8bit, + Type_Palette_4bit, + Type_Unknown + }; + + Type format; + uint32 bitsPerPixel; ///< Must match bpp of selected type + bool swapRB; ///< Swap red and blue values when reading and writing + + PSPPixelFormat() : format(Type_Unknown), bitsPerPixel(0), swapRB(false) {} + void set(Type type, bool swap = false); + static void convertFromScummvmPixelFormat(const Graphics::PixelFormat *pf, + PSPPixelFormat::Type &bufferType, + PSPPixelFormat::Type &paletteType, + bool &swapRedBlue); + static Graphics::PixelFormat convertToScummvmPixelFormat(PSPPixelFormat::Type type); + uint32 convertTo32BitColor(uint32 color); + + inline uint32 rgbaToColor(uint32 r, uint32 g, uint32 b, uint32 a) { + uint32 color; + + switch(format) { + case Type_4444: + color = (((b >> 4) << 8) | ((g >> 4) << 4) | ((r >> 4) << 0) | ((a >> 4) << 12)); + break; + case Type_5551: + color = (((b >> 3) << 10) | ((g >> 3) << 5) | ((r >> 3) << 0) | ((a >> 7) << 15)); + break; + case Type_5650: + color = (((b >> 3) << 11) | ((g >> 2) << 5) | ((r >> 3) << 0)); + break; + case Type_8888: + color = (((b >> 0) << 16) | ((g >> 0) << 8) | ((r >> 0) << 0) | ((a >> 0) << 24)); + break; + default: + color = 0; + break; + } + return color; + } + + inline void colorToRgba(uint32 color, uint32 &r, uint32 &g, uint32 &b, uint32 &a) { + switch(format) { + case Type_4444: + a = (color >> 12) & 0xF; // Interpolate to get true colors + b = (color >> 8) & 0xF; + g = (color >> 4) & 0xF; + r = (color >> 0) & 0xF; + a = a << 4 | a; + b = b << 4 | b; + g = g << 4 | g; + r = r << 4 | r; + break; + case Type_5551: + a = (color >> 15) ? 0xFF : 0; + b = (color >> 10) & 0x1F; + g = (color >> 5) & 0x1F; + r = (color >> 0) & 0x1F; + b = b << 3 | b >> 2; + g = g << 3 | g >> 2; + r = r << 3 | r >> 2; + break; + case Type_5650: + a = 0xFF; + b = (color >> 11) & 0x1F; + g = (color >> 5) & 0x3F; + r = (color >> 0) & 0x1F; + b = b << 3 | b >> 2; + g = g << 2 | g >> 4; + r = r << 3 | r >> 2; + break; + case Type_8888: + a = (color >> 24) & 0xFF; + b = (color >> 16) & 0xFF; + g = (color >> 8) & 0xFF; + r = (color >> 0) & 0xFF; + break; + default: + a = b = g = r = 0; + break; + } + } + + inline uint32 setColorAlpha(uint32 color, byte alpha) { + switch(format) { + case Type_4444: + color = (color & 0x0FFF) | (((uint32)alpha >> 4) << 12); + break; + case Type_5551: + color = (color & 0x7FFF) | (((uint32)alpha >> 7) << 15); + break; + case Type_8888: + color = (color & 0x00FFFFFF) | ((uint32)alpha << 24); + break; + case Type_5650: + default: + break; + } + return color; + } + + inline uint32 pixelsToBytes(uint32 pixels) { + switch (bitsPerPixel) { + case 4: + pixels >>= 1; + break; + case 16: + pixels <<= 1; + break; + case 32: + pixels <<= 2; + break; + case 8: + break; + default: + PSP_ERROR("Incorrect bitsPerPixel value[%u]. pixels[%u]\n", bitsPerPixel, pixels); + break; + } + return pixels; + } + + inline uint16 swapRedBlue16(uint16 color) { + uint16 output; + + switch (format) { + case Type_4444: + output = (color & 0xf0f0) | ((color & 0x000f)<<8) | ((color & 0x0f00)>>8); + break; + case Type_5551: + output = (color & 0x83e0) | ((color & 0x001f)<<10) | ((color & 0x7c00)>>10); + break; + case Type_5650: + output = (color & 0x07e0) | ((color & 0x001f)<<11) | ((color & 0xf800)>>11); + break; + default: + PSP_ERROR("invalid format[%u] for swapping\n", format); + output = 0; + break; + } + return output; + } + + inline uint32 swapRedBlue32(uint32 color) { + uint32 output; + + switch (format) { + case Type_4444: + output = (color & 0xf0f0f0f0) | + ((color & 0x000f000f)<<8) | ((color & 0x0f000f00)>>8); + break; + case Type_5551: + output = (color & 0x83e083e0) | + ((color & 0x001f001f)<<10) | ((color & 0x7c007c00)>>10); + break; + case Type_5650: + output = (color & 0x07e007e0) | + ((color & 0x001f001f)<<11) | ((color & 0xf800f800)>>11); + break; + case Type_8888: + output = (color & 0xff00ff00) | + ((color & 0x000000ff)<<16) | ((color & 0x00ff0000)>>16); + break; + default: + PSP_ERROR("invalid format[%u] for swapping\n", format); + output = 0; + break; + } + + return output; + } + + // Return whatever color we point at + inline uint32 getColorValueAt(byte *pointer) { + uint32 result; + + switch (bitsPerPixel) { + case 4: // We can't distinguish a 4 bit color with a pointer + case 8: + result = (uint32)*pointer; + break; + case 16: + result = (uint32)*(uint16 *)pointer; + break; + case 32: + result = *(uint32 *)pointer; + break; + default: + result = 0; + PSP_ERROR("Incorrect bitsPerPixel value[%u].\n", bitsPerPixel); + break; + } + return result; + } +}; + +#endif /* PSP_PIXEL_FORMAT_H */ diff --git a/backends/platform/psp/trace.cpp b/backends/platform/psp/trace.cpp index 28696c30a6..030dafdf1d 100644 --- a/backends/platform/psp/trace.cpp +++ b/backends/platform/psp/trace.cpp @@ -23,47 +23,33 @@ * */ +#define TRACE_C +#include <pspkernel.h> +#include <pspdebug.h> +#include "backends/platform/psp/trace.h" -#include "./trace.h" +int psp_debug_indent = 0; - -void PSPDebugTrace (const char *format, ...) { -#ifdef __PSP_DEBUG__ - va_list opt; - char buff[2048]; - int bufsz, fd; - - va_start(opt, format); - bufsz = vsnprintf( buff, (size_t) sizeof(buff), format, opt); - va_end(opt); - - fd = sceIoOpen("MS0:/DTRACE.TXT", PSP_O_RDWR | PSP_O_CREAT | PSP_O_APPEND, 0777); - - if (fd <= 0) - return; - - sceIoWrite(fd, (const void*)buff, bufsz); - sceIoClose(fd); -#endif /* __PSP_DEBUG__ */ -} - -void PSPDebugTrace (const char * filename, const char *format, ...) { -#ifdef __PSP_DEBUG__ +void PSPDebugTrace (bool alsoToScreen, const char *format, ...) { va_list opt; - char buff[2048]; - int bufsz, fd; + char buffer[2048]; + int bufsz; + FILE *fd = 0; va_start(opt, format); - bufsz = vsnprintf( buff, (size_t) sizeof(buff), format, opt); + bufsz = vsnprintf( buffer, (size_t) sizeof(buffer), format, opt); va_end(opt); - fd = sceIoOpen(filename, PSP_O_RDWR | PSP_O_CREAT | PSP_O_APPEND, 0777); - - if (fd <= 0) + //fd = fopen("MS0:/SCUMMTRACE.TXT", "ab"); + fd = fopen("SCUMMTRACE.TXT", "ab"); + + if (fd == 0) return; - sceIoWrite(fd, (const void*)buff, bufsz); - sceIoClose(fd); -#endif /* __PSP_DEBUG__ */ + fwrite(buffer, 1, bufsz, fd); + fclose(fd); + + if (alsoToScreen) + fprintf(stderr, buffer); } diff --git a/backends/platform/psp/trace.h b/backends/platform/psp/trace.h index ef8992ceb2..b77ecb4732 100644 --- a/backends/platform/psp/trace.h +++ b/backends/platform/psp/trace.h @@ -29,25 +29,94 @@ #include <stdio.h> #include <psptypes.h> -#include <pspkernel.h> #include <stdarg.h> -#include <pspdebug.h> // Use these defines for debugging -//#define __PSP_DEBUG__ -//#define __PSP_DEBUG_SUSPEND__ +//#define __PSP_PRINT_TO_FILE__ +//#define __PSP_PRINT_TO_FILE_AND_SCREEN__ +//#define __PSP_DEBUG_FUNCS__ /* can put this locally too */ +//#define __PSP_DEBUG_PRINT__ -void PSPDebugTrace (const char *filename, const char *format, ...); -void PSPDebugTrace (const char *format, ...); +void PSPDebugTrace (bool alsoToScreen, const char *format, ...); -#ifdef __PSP_DEBUG_SUSPEND__ -#define PSPDebugSuspend(format,...) PSPDebugTrace(format, ## __VA_ARGS__) -#else -#define PSPDegbugSuspend(x) -#define PSPDebugSuspend(format,...) -#endif /* __PSP_DEBUG_SUSPEND__ */ +#ifndef TRACE_C +extern int psp_debug_indent; +#endif +#endif /* TRACE_H */ -#endif // TRACE_H +// From here on, we allow multiple definitions +#undef __PSP_PRINT__ +#undef PSP_ERROR +#undef __PSP_INDENT__ +#undef PSP_INFO_PRINT +#undef PSP_INFO_PRINT_INDENT +#undef PSP_DEBUG_PRINT +#undef PSP_DEBUG_PRINT_FUNC +#undef PSP_DEBUG_PRINT_SAMELN +#undef PSP_DEBUG_DO +#undef DEBUG_ENTER_FUNC +#undef DEBUG_EXIT_FUNC +#undef INLINE +/* Choose to print to file/screen/both */ +#ifdef __PSP_PRINT_TO_FILE__ + #define __PSP_PRINT__(format,...) PSPDebugTrace(false, format, ## __VA_ARGS__) +#elif defined __PSP_PRINT_TO_FILE_AND_SCREEN__ + #define __PSP_PRINT__(format,...) PSPDebugTrace(true, format, ## __VA_ARGS__) +#else /* default - print to screen */ + #define __PSP_PRINT__(format,...) fprintf(stderr, format, ## __VA_ARGS__) +#endif /* PSP_PRINT_TO_FILE/SCREEN */ + +/* Error function */ +#define PSP_ERROR(format,...) __PSP_PRINT__("Error in %s: " format, __PRETTY_FUNCTION__, ## __VA_ARGS__) + +/* Do the indent */ +#define __PSP_INDENT__ for(int _i=psp_debug_indent; _i>0; _i--) \ + __PSP_PRINT__( " ") + +/* always print */ +#define PSP_INFO_PRINT(format,...) __PSP_PRINT__(format, ## __VA_ARGS__) +/* always print, with indent */ +#define PSP_INFO_PRINT_INDENT(format,...) { __PSP_INDENT__; \ + __PSP_PRINT__(format, ## __VA_ARGS__); } + +#ifdef __PSP_DEBUG_PRINT__ + /* printf with indents */ + #define PSP_DEBUG_PRINT_SAMELN(format,...) __PSP_PRINT__(format, ## __VA_ARGS__) + #define PSP_DEBUG_PRINT(format,...) { __PSP_INDENT__; \ + __PSP_PRINT__(format, ## __VA_ARGS__); } + #define PSP_DEBUG_PRINT_FUNC(format,...) { __PSP_INDENT__; \ + __PSP_PRINT__("In %s: " format, __PRETTY_FUNCTION__, ## __VA_ARGS__); } + #define PSP_DEBUG_DO(x) (x) + +#else /* no debug print */ + #define PSP_DEBUG_PRINT_SAMELN(format,...) + #define PSP_DEBUG_PRINT(format,...) + #define PSP_DEBUG_PRINT_FUNC(format,...) + #define PSP_DEBUG_DO(x) +#endif /* __PSP_DEBUG_PRINT__ */ + +/* Debugging function calls */ +#ifdef __PSP_DEBUG_FUNCS__ + #define DEBUG_ENTER_FUNC() PSP_INFO_PRINT_INDENT("++ %s\n", __PRETTY_FUNCTION__); \ + psp_debug_indent++ + + #define DEBUG_EXIT_FUNC() psp_debug_indent--; \ + if (psp_debug_indent < 0) PSP_ERROR("debug indent < 0\n"); \ + PSP_INFO_PRINT_INDENT("-- %s\n", __PRETTY_FUNCTION__) + + #define INLINE /* don't want to inline so we get function names properly */ + +#else /* Don't debug function calls */ + #define DEBUG_ENTER_FUNC() + #define DEBUG_EXIT_FUNC() + #define INLINE inline +#endif /* __PSP_DEBUG_FUNCS__ */ + +// Undef the main defines for next time +#undef __PSP_PRINT_TO_FILE__ +#undef __PSP_PRINT_TO_FILE_AND_SCREEN__ +#undef __PSP_DEBUG_FUNCS__ +#undef __PSP_DEBUG_PRINT__ |