aboutsummaryrefslogtreecommitdiff
path: root/backends/platform/psp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/platform/psp')
-rw-r--r--backends/platform/psp/Makefile9
-rw-r--r--backends/platform/psp/README.PSP.in5
-rw-r--r--backends/platform/psp/cursor.cpp365
-rw-r--r--backends/platform/psp/cursor.h81
-rw-r--r--backends/platform/psp/default_display_client.cpp238
-rw-r--r--backends/platform/psp/default_display_client.h108
-rw-r--r--backends/platform/psp/display_client.cpp805
-rw-r--r--backends/platform/psp/display_client.h238
-rw-r--r--backends/platform/psp/display_manager.cpp336
-rw-r--r--backends/platform/psp/display_manager.h114
-rw-r--r--backends/platform/psp/input.cpp317
-rw-r--r--backends/platform/psp/input.h63
-rw-r--r--backends/platform/psp/memory.cpp227
-rw-r--r--backends/platform/psp/memory.h80
-rw-r--r--backends/platform/psp/module.mk10
-rw-r--r--backends/platform/psp/osys_psp.cpp910
-rw-r--r--backends/platform/psp/osys_psp.h206
-rw-r--r--backends/platform/psp/powerman.cpp133
-rw-r--r--backends/platform/psp/powerman.h5
-rw-r--r--backends/platform/psp/psp_main.cpp11
-rw-r--r--backends/platform/psp/pspkeyboard.cpp945
-rw-r--r--backends/platform/psp/pspkeyboard.h75
-rw-r--r--backends/platform/psp/psploader.h1
-rw-r--r--backends/platform/psp/psppixelformat.cpp166
-rw-r--r--backends/platform/psp/psppixelformat.h240
-rw-r--r--backends/platform/psp/trace.cpp52
-rw-r--r--backends/platform/psp/trace.h95
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__