PSP: refactoring/redesign of the backend

svn-id: r48632
This commit is contained in:
Yotam Barnoy 2010-04-12 06:49:05 +00:00
parent 18609a70b3
commit 9a2eac7eee
32 changed files with 4458 additions and 1611 deletions

View file

@ -35,6 +35,7 @@
*/
class PSPFilesystemFactory : public FilesystemFactory, public Common::Singleton<PSPFilesystemFactory> {
public:
const char *getObjectName() const { return "PSPFilesystemFactory"; }
virtual AbstractFSNode *makeRootFileNode() const;
virtual AbstractFSNode *makeCurrentDirectoryFileNode() const;
virtual AbstractFSNode *makeFileNodePath(const Common::String &path) const;

View file

@ -35,6 +35,9 @@
#define ROOT_PATH "ms0:/"
//#define __PSP_PRINT_TO_FILE__
//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
#include "backends/platform/psp/trace.h"
/**
@ -63,6 +66,7 @@ public:
*/
PSPFilesystemNode(const Common::String &p, bool verify = true);
const char *getObjectName() const { return "PSPFileSystemNode"; }
virtual bool exists() const;
virtual Common::String getDisplayName() const { return _displayName; }
virtual Common::String getName() const { return _displayName; }
@ -87,6 +91,7 @@ PSPFilesystemNode::PSPFilesystemNode() {
}
PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) {
DEBUG_ENTER_FUNC();
assert(p.size() > 0);
_path = p;
@ -94,54 +99,70 @@ PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) {
_isValid = true;
_isDirectory = true;
PSP_DEBUG_PRINT_FUNC("path [%s]\n", _path.c_str());
if (verify) {
struct stat st;
if (PowerMan.beginCriticalSection()==PowerManager::Blocked)
PSPDebugSuspend("Suspended in PSPFilesystemNode::PSPFilesystemNode\n");
PSP_DEBUG_PRINT_FUNC("Suspended\n");
_isValid = (0 == stat(_path.c_str(), &st));
PowerMan.endCriticalSection();
_isDirectory = S_ISDIR(st.st_mode);
}
DEBUG_EXIT_FUNC();
}
bool PSPFilesystemNode::exists() const {
DEBUG_ENTER_FUNC();
int ret = 0;
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSPDebugSuspend("Suspended in PSPFilesystemNode::exists()\n"); // Make sure to block in case of suspend
PSP_DEBUG_PRINT_FUNC("Suspended\n"); // Make sure to block in case of suspend
PSP_DEBUG_PRINT_FUNC("path [%s]\n", _path.c_str());
ret = access(_path.c_str(), F_OK);
PowerMan.endCriticalSection();
return ret == 0;
DEBUG_EXIT_FUNC();
return (ret == 0);
}
bool PSPFilesystemNode::isReadable() const {
DEBUG_ENTER_FUNC();
int ret = 0;
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSPDebugSuspend("Suspended in PSPFilesystemNode::isReadable()\n"); // Make sure to block in case of suspend
PSP_DEBUG_PRINT_FUNC("Suspended\n"); // Make sure to block in case of suspend
PSP_DEBUG_PRINT_FUNC("path [%s]\n", _path.c_str());
ret = access(_path.c_str(), R_OK);
PowerMan.endCriticalSection();
return ret == 0;
DEBUG_EXIT_FUNC();
return (ret == 0);
}
bool PSPFilesystemNode::isWritable() const {
DEBUG_ENTER_FUNC();
int ret = 0;
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSPDebugSuspend("Suspended in PSPFilesystemNode::isWritable()\n"); // Make sure to block in case of suspend
PSP_DEBUG_PRINT_FUNC("Suspended\n"); // Make sure to block in case of suspend
PSP_DEBUG_PRINT_FUNC("path [%s]\n", _path.c_str());
ret = access(_path.c_str(), W_OK);
PowerMan.endCriticalSection();
DEBUG_EXIT_FUNC();
return ret == 0;
}
AbstractFSNode *PSPFilesystemNode::getChild(const Common::String &n) const {
DEBUG_ENTER_FUNC();
// FIXME: Pretty lame implementation! We do no error checking to speak
// of, do not check if this is a special node, etc.
assert(_isDirectory);
@ -151,10 +172,16 @@ AbstractFSNode *PSPFilesystemNode::getChild(const Common::String &n) const {
newPath += '/';
newPath += n;
return new PSPFilesystemNode(newPath, true);
PSP_DEBUG_PRINT_FUNC("child [%s]\n", newPath.c_str());
AbstractFSNode *node = new PSPFilesystemNode(newPath, true);
DEBUG_EXIT_FUNC();
return node;
}
bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
DEBUG_ENTER_FUNC();
assert(_isDirectory);
//TODO: honor the hidden flag
@ -162,8 +189,10 @@ bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
bool ret = true;
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSPDebugSuspend("Suspended in PSPFilesystemNode::getChildren\n"); // Make sure to block in case of suspend
PSP_DEBUG_PRINT_FUNC("Suspended\n"); // Make sure to block in case of suspend
PSP_DEBUG_PRINT_FUNC("Current path[%s]\n", _path.c_str());
int dfd = sceIoDopen(_path.c_str());
if (dfd > 0) {
SceIoDirent dir;
@ -186,7 +215,9 @@ bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
entry._path = newPath;
entry._isDirectory = dir.d_stat.st_attr & FIO_SO_IFDIR;
PSP_DEBUG_PRINT_FUNC("Child[%s], %s\n", entry._path.c_str(), entry._isDirectory ? "dir" : "file");
// Honor the chosen mode
if ((mode == Common::FSNode::kListFilesOnly && entry._isDirectory) ||
(mode == Common::FSNode::kListDirectoriesOnly && !entry._isDirectory))
@ -202,17 +233,24 @@ bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
}
PowerMan.endCriticalSection();
DEBUG_EXIT_FUNC();
return ret;
}
AbstractFSNode *PSPFilesystemNode::getParent() const {
DEBUG_ENTER_FUNC();
if (_path == ROOT_PATH)
return 0;
PSP_DEBUG_PRINT_FUNC("current[%s]\n", _path.c_str());
const char *start = _path.c_str();
const char *end = lastPathComponent(_path, '/');
return new PSPFilesystemNode(Common::String(start, end - start), false);
AbstractFSNode *node = new PSPFilesystemNode(Common::String(start, end - start), false);
DEBUG_EXIT_FUNC();
return node;
}
Common::SeekableReadStream *PSPFilesystemNode::createReadStream() {

View file

@ -27,15 +27,20 @@
#include <SDL/SDL_thread.h>
#include <SDL/SDL_mutex.h>
#include "backends/platform/psp/trace.h"
#include "backends/platform/psp/powerman.h"
#include "backends/fs/psp/psp-stream.h"
#include <errno.h>
//#define __PSP_PRINT_TO_FILE__
//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
#include "backends/platform/psp/trace.h"
PSPIoStream::PSPIoStream(const Common::String &path, bool writeMode)
: StdioStream((void *)1), _path(path), _writeMode(writeMode) {
DEBUG_ENTER_FUNC();
assert(!path.empty());
_handle = (void *)0; // Need to do this since base class asserts not 0.
@ -43,34 +48,40 @@ PSPIoStream::PSPIoStream(const Common::String &path, bool writeMode)
_feof = false;
_pos = 0;
#ifdef __PSP_DEBUG_SUSPEND__
/* for error checking */
_errorSuspend = 0;
_errorSource = 0;
_errorPos = 0;
_errorHandle = 0;
_suspendCount = 0;
#endif
DEBUG_EXIT_FUNC();
}
PSPIoStream::~PSPIoStream() {
DEBUG_ENTER_FUNC();
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSPDebugSuspend("Suspended in PSPIoStream::~PSPIoStream()\n");
PSP_DEBUG_PRINT_FUNC("Suspended\n");
PowerMan.unregisterSuspend(this); // Unregister with powermanager to be suspended
// Must do this before fclose() or resume() will reopen.
// Must do this before fclose() or resume() will reopen.
fclose((FILE *)_handle); // We don't need a critical section(?). Worst case, the handle gets closed on its own
PowerMan.endCriticalSection();
DEBUG_EXIT_FUNC();
}
// Function to open the file pointed to by the path.
//
//
/* Function to open the file pointed to by the path.
*
*/
void *PSPIoStream::open() {
DEBUG_ENTER_FUNC();
if (PowerMan.beginCriticalSection() == PowerManager::Blocked) {
// No need to open. Just return the _handle resume() already opened.
PSPDebugSuspend("Suspended in PSPIoStream::open\n");
PSP_DEBUG_PRINT_FUNC("Suspended\n");
}
_handle = fopen(_path.c_str(), _writeMode ? "wb" : "rb"); // open
@ -79,20 +90,22 @@ void *PSPIoStream::open() {
PowerMan.endCriticalSection();
DEBUG_EXIT_FUNC();
return _handle;
}
bool PSPIoStream::err() const {
DEBUG_ENTER_FUNC();
if (_ferror)
PSPDebugSuspend("In PSPIoStream::err - mem_ferror=%d, source=%d, suspend error=%d, pos=%d, _errorPos=%d, _errorHandle=%p, suspendCount=%d _handle\n",
PSP_ERROR("mem_ferror[%d], source[%d], suspend error[%d], pos[%d], _errorPos[%d], _errorHandle[%p], suspendCount[%d]\n",
_ferror, _errorSource, _errorSuspend, _pos, _errorPos, _errorHandle, _suspendCount);
DEBUG_EXIT_FUNC();
return _ferror;
}
void PSPIoStream::clearErr() {
_ferror = false; // Remove regular error bit
}
bool PSPIoStream::eos() const {
@ -105,45 +118,43 @@ int32 PSPIoStream::pos() const {
int32 PSPIoStream::size() const {
DEBUG_ENTER_FUNC();
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSPDebugSuspend("Suspended in PSPIoStream::size()\n");
PSP_DEBUG_PRINT_FUNC("Suspended\n");
fseek((FILE *)_handle, 0, SEEK_END);
int32 length = ftell((FILE *)_handle);
fseek((FILE *)_handle, _pos, SEEK_SET);
if (_pos < 0 || length < 0) { // Check for errors
PSPDebugSuspend("In PSPIoStream::size(). encountered an error!\n");
_errorSource = 2;
PSP_ERROR("pos[%d] or length[%d] < 0!\n", _pos, length);
_ferror = true;
length = -1; // If our oldPos is bad, we want length to be bad too to signal
clearerr((FILE *)_handle);
#ifdef __PSP_DEBUG_SUSPEND__
_errorSource = 2;
#endif
}
PowerMan.endCriticalSection();
DEBUG_EXIT_FUNC();
return length;
}
bool PSPIoStream::seek(int32 offs, int whence) {
DEBUG_ENTER_FUNC();
// Check if we can access the file
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSPDebugSuspend("Suspended in PSPIoStream::seek()\n");
PSP_DEBUG_PRINT_FUNC("Suspended\n");
int ret = fseek((FILE *)_handle, offs, whence);
if (ret != 0) {
_ferror = true;
PSPDebugSuspend("In PSPIoStream::seek(). encountered an error!\n");
PSP_ERROR("fseek returned with [%d], non-zero\n", ret);
clearerr((FILE *)_handle);
_feof = feof((FILE *)_handle);
#ifdef __PSP_DEBUG_SUSPEND__
_errorSource = 3;
#endif
}
else { // everything ok
_feof = false; // Reset eof flag since we know it was ok
@ -153,13 +164,17 @@ bool PSPIoStream::seek(int32 offs, int whence) {
PowerMan.endCriticalSection();
return ret == 0;
DEBUG_EXIT_FUNC();
return (ret == 0);
}
uint32 PSPIoStream::read(void *ptr, uint32 len) {
DEBUG_ENTER_FUNC();
// Check if we can access the file
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSPDebugSuspend("Suspended in PSPIoStream::read()\n");
PSP_DEBUG_PRINT_FUNC("Suspended\n");
PSP_DEBUG_PRINT_FUNC("filename[%s], len[%d]\n", _path.c_str(), len);
size_t ret = fread((byte *)ptr, 1, len, (FILE *)_handle);
@ -171,24 +186,25 @@ uint32 PSPIoStream::read(void *ptr, uint32 len) {
_ferror = true;
clearerr((FILE *)_handle);
_pos = ftell((FILE *)_handle); // Update our position
PSPDebugSuspend("In PSPIoStream::read(). encountered an error!\n");
#ifdef __PSP_DEBUG_SUSPEND__
_errorSource = 4;
#endif
PSP_ERROR("fread returned ret[%d] instead of len[%d]\n", ret, len);
}
}
PowerMan.endCriticalSection();
DEBUG_EXIT_FUNC();
return ret;
}
uint32 PSPIoStream::write(const void *ptr, uint32 len) {
DEBUG_ENTER_FUNC();
// Check if we can access the file
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSPDebugSuspend("Suspended in PSPIoStream::read()\n");
PSP_DEBUG_PRINT_FUNC("Suspended\n");
PSP_DEBUG_PRINT_FUNC("filename[%s], len[%d]\n", _path.c_str(), len);
size_t ret = fwrite(ptr, 1, len, (FILE *)_handle);
_pos += ret;
@ -197,73 +213,73 @@ uint32 PSPIoStream::write(const void *ptr, uint32 len) {
_ferror = true;
clearerr((FILE *)_handle);
_pos = ftell((FILE *)_handle); // Update pos
PSPDebugTrace("In PSPIoStream::write(). encountered an error!\n");
#ifdef __PSP_DEBUG_SUSPEND__
_errorSource = 5;
#endif
PSP_ERROR("fwrite returned[%d] instead of len[%d]\n", ret, len);
}
PowerMan.endCriticalSection();
DEBUG_EXIT_FUNC();
return ret;
}
bool PSPIoStream::flush() {
DEBUG_ENTER_FUNC();
// Enter critical section
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSPDebugSuspend("Suspended in PSPIoStream::read()\n");
PSP_DEBUG_PRINT_FUNC("Suspended\n");
int ret = fflush((FILE *)_handle);
if (ret != 0) {
_ferror = true;
clearerr((FILE *)_handle);
PSPDebugSuspend("In PSPIoStream::flush(). encountered an error!\n");
#ifdef __PSP_DEBUG_SUSPEND__
_errorSource = 6;
#endif
PSP_ERROR("fflush returned ret[%u]\n", ret);
}
PowerMan.endCriticalSection();
return ret == 0;
DEBUG_EXIT_FUNC();
return (ret == 0);
}
// For the PSP, since we're building in suspend support, we moved opening
// the actual file to an open function since we need an actual PSPIoStream object to suspend.
//
PSPIoStream *PSPIoStream::makeFromPath(const Common::String &path, bool writeMode) {
DEBUG_ENTER_FUNC();
PSPIoStream *stream = new PSPIoStream(path, writeMode);
if (stream->open() > 0) {
return stream;
} else {
if (stream->open() <= 0) {
delete stream;
return 0;
stream = 0;
}
DEBUG_EXIT_FUNC();
return stream;
}
/*
* Function to suspend the IO stream (called by PowerManager)
* we can have no output here
*/
int PSPIoStream::suspend() {
#ifdef __PSP_DEBUG_SUSPEND__
DEBUG_ENTER_FUNC();
_suspendCount++;
if (_handle > 0 && _pos < 0) {
if (_handle > 0 && _pos < 0) { /* check for error */
_errorSuspend = SuspendError;
_errorPos = _pos;
_errorHandle = _handle;
}
#endif /* __PSP_DEBUG_SUSPEND__ */
if (_handle > 0) {
fclose((FILE *)_handle); // close our file descriptor
_handle = (void *)0xFFFFFFFF; // Set handle to non-null invalid value so makeFromPath doesn't return error
}
DEBUG_EXIT_FUNC();
return 0;
}
@ -271,31 +287,27 @@ int PSPIoStream::suspend() {
* Function to resume the IO stream (called by Power Manager)
*/
int PSPIoStream::resume() {
DEBUG_ENTER_FUNC();
int ret = 0;
#ifdef __PSP_DEBUG_SUSPEND__
_suspendCount--;
#endif
// We reopen our file descriptor
_handle = fopen(_path.c_str(), _writeMode ? "wb" : "rb");
if (_handle <= 0) {
PSPDebugSuspend("PSPIoStream::resume(): Couldn't reopen file %s\n", _path.c_str());
PSP_ERROR("Couldn't reopen file %s\n", _path.c_str());
}
// Resume our previous position
if (_handle > 0 && _pos > 0) {
ret = fseek((FILE *)_handle, _pos, SEEK_SET);
#ifdef __PSP_DEBUG_SUSPEND__
if (ret != 0) { // Check for problem
_errorSuspend = ResumeError;
_errorPos = _pos;
_errorHandle = _handle;
}
#endif
}
DEBUG_EXIT_FUNC();
return ret;
}

View file

@ -49,13 +49,14 @@ protected:
int _errorSuspend;
mutable int _errorSource;
#ifdef __PSP_DEBUG_SUSPEND__
// Error checking
int _errorPos;
void * _errorHandle;
int _suspendCount;
#endif /* __PSP_DEBUG_SUSPEND__ */
public:
const char *getObjectName() const { return "PSPIoStream"; }
/**
* Given a path, invoke fopen on that path and wrap the result in a
* PSPIoStream instance.

View file

@ -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

View file

@ -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

View file

@ -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
}
}

View file

@ -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 */

View file

@ -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();
}

View file

@ -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 */

View file

@ -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);
}

View file

@ -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 */

View file

@ -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;
}

View file

@ -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 */

View file

@ -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;
}

View file

@ -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 */

View file

@ -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();
}

View file

@ -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 */

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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;
void initSDL();
public:
OSystem_PSP();
virtual ~OSystem_PSP();
OSystem_PSP() : _savefile(0), _mixer(0), _timer(0) {}
~OSystem_PSP();
virtual void initBackend();
virtual bool hasFeature(Feature f);
virtual void setFeatureState(Feature f, bool enable);
virtual bool getFeatureState(Feature f);
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;
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);
virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format);
virtual int16 getWidth();
virtual int16 getHeight();
// Events and input
bool pollEvent(Common::Event &event);
bool processInput(Common::Event &event);
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);
// Time
uint32 getMillis();
void delayMillis(uint msecs);
// Timer
typedef int (*TimerProc)(int interval);
virtual void setTimerCallback(TimerProc callback, int interval);
virtual MutexRef createMutex(void);
virtual void lockMutex(MutexRef mutex);
virtual void unlockMutex(MutexRef mutex);
virtual void deleteMutex(MutexRef mutex);
static void mixCallback(void *sys, byte *samples, int len);
virtual void setupMixer(void);
Common::SaveFileManager *getSavefileManager() { return _savefile; }
Audio::Mixer *getMixer() { return _mixer; }
void setTimerCallback(TimerProc callback, int interval);
Common::TimerManager *getTimerManager() { return _timer; }
// 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);
void setupMixer(void);
Audio::Mixer *getMixer() { return _mixer; }
// Misc
Common::SaveFileManager *getSavefileManager() { return _savefile; }
FilesystemFactory *getFilesystemFactory() { return &PSPFilesystemFactory::instance(); }
void getTimeAndDate(TimeDate &t) const;
virtual void quit();
void quit();
Common::SeekableReadStream *createConfigReadStream();
Common::WriteStream *createConfigWriteStream();
virtual Common::SeekableReadStream *createConfigReadStream();
virtual Common::WriteStream *createConfigWriteStream();
};
#endif /* OSYS_PSP_H */

View file

@ -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;
}

View file

@ -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 */

View file

@ -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;
}

File diff suppressed because it is too large Load diff

View file

@ -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,58 +50,20 @@ 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;
};
// 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);
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);
static short _modeChar[MODE_COUNT][5][6];
static const char *_guiStrings[];
bool _init;
unsigned int _prevButtons; // A bit pattern.
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;
bool _moved; // whether the keyboard was moved
gu_surface _keyTextures[guiStringsSize];
State _state; // State of keyboard Keyboard state machine
State _lastState;
enum Cursor {
enum CursorDirections {
kUp = 0,
kRight,
kDown,
@ -108,8 +71,42 @@ private:
kCenter
};
Cursor _oldCursor; // Point to place of last cursor
Buffer _buffers[guiStringsSize];
Palette _palettes[guiStringsSize];
GuRenderer _renderer;
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 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;
uint32 _prevButtons; // A bit pattern.
uint32 _buttonsChanged;
bool _dirty; // keyboard needs redrawing
int _mode; // charset selected. (0 - letters or 1 - numbers)
int _movedX; // location we've moved the KB to onscreen
int _movedY;
bool _moved; // whether the keyboard was moved
State _state; // State of keyboard Keyboard state machine
State _lastState;
CursorDirections _oldCursor; // Point to place of last cursor
};
#endif /* PSPKEYBOARD_H */
#endif /* PSPKEYBOARD_H */

View file

@ -135,4 +135,3 @@ extern "C" {
}
#endif /* PSPLOADER_H */

View file

@ -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;
}

View file

@ -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 */

View file

@ -23,47 +23,33 @@
*
*/
#include "./trace.h"
#define TRACE_C
#include <pspkernel.h>
#include <pspdebug.h>
#include "backends/platform/psp/trace.h"
int psp_debug_indent = 0;
void PSPDebugTrace (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("MS0:/DTRACE.TXT", 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__ */
}
void PSPDebugTrace (const char * filename, 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(filename, 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__ */
fwrite(buffer, 1, bufsz, fd);
fclose(fd);
if (alsoToScreen)
fprintf(stderr, buffer);
}

View file

@ -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__

2
configure vendored
View file

@ -1649,7 +1649,7 @@ fi
# Enable 16bit support only for backends which support it
#
case $_backend in
dreamcast | samsungtv | sdl | wii)
dreamcast | samsungtv | sdl | wii | psp)
if test "$_16bit" = auto ; then
_16bit=yes
else