diff options
author | Yotam Barnoy | 2010-07-18 06:49:56 +0000 |
---|---|---|
committer | Yotam Barnoy | 2010-07-18 06:49:56 +0000 |
commit | 58a1fbc13c116d3fa69c426c0cdeb459d354fbf0 (patch) | |
tree | b76fd89b1bdc5c153a30929a22ea0da232138b37 | |
parent | 59bb9f8fe82432b35de103f7e705d91fde3f3f2a (diff) | |
download | scummvm-rg350-58a1fbc13c116d3fa69c426c0cdeb459d354fbf0.tar.gz scummvm-rg350-58a1fbc13c116d3fa69c426c0cdeb459d354fbf0.tar.bz2 scummvm-rg350-58a1fbc13c116d3fa69c426c0cdeb459d354fbf0.zip |
Made memcpy faster but not as fast with uncached mem.
svn-id: r50980
-rw-r--r-- | backends/platform/psp/display_client.cpp | 15 | ||||
-rw-r--r-- | backends/platform/psp/memory.cpp | 627 | ||||
-rw-r--r-- | backends/platform/psp/memory.h | 211 | ||||
-rw-r--r-- | backends/platform/psp/module.mk | 3 | ||||
-rw-r--r-- | backends/platform/psp/psp_main.cpp | 11 |
5 files changed, 559 insertions, 308 deletions
diff --git a/backends/platform/psp/display_client.cpp b/backends/platform/psp/display_client.cpp index c5a6250188..71b505ec7c 100644 --- a/backends/platform/psp/display_client.cpp +++ b/backends/platform/psp/display_client.cpp @@ -340,11 +340,17 @@ void Buffer::copyFromRect(const byte *buf, uint32 pitch, int destX, int destY, u if (pitch == realWidthInBytes && pitch == recWidthInBytes) { //memcpy(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth)); - Copier::copy(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth), &_pixelFormat); + if (_pixelFormat.swapRB) + PspMemory::fastSwap(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth), _pixelFormat); + else + PspMemory::fastCopy(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth)); } else { do { //memcpy(dst, buf, recWidthInBytes); - Copier::copy(dst, buf, recWidthInBytes, &_pixelFormat); + if (_pixelFormat.swapRB) + PspMemory::fastSwap(dst, buf, recWidthInBytes, _pixelFormat); + else + PspMemory::fastCopy(dst, buf, recWidthInBytes); buf += pitch; dst += realWidthInBytes; } while (--recHeight); @@ -363,7 +369,10 @@ void Buffer::copyToArray(byte *dst, int pitch) { do { //memcpy(dst, src, sourceWidthInBytes); - Copier::copy(dst, src, sourceWidthInBytes, &_pixelFormat); + if (_pixelFormat.swapRB) + PspMemory::fastSwap(dst, src, sourceWidthInBytes, _pixelFormat); + else + PspMemory::fastCopy(dst, src, sourceWidthInBytes); src += realWidthInBytes; dst += pitch; } while (--h); diff --git a/backends/platform/psp/memory.cpp b/backends/platform/psp/memory.cpp index e134a7d0f4..d66650aee5 100644 --- a/backends/platform/psp/memory.cpp +++ b/backends/platform/psp/memory.cpp @@ -1,223 +1,404 @@ -/* 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 { - 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 - - return; // So we have something to jump to with the label -} - -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); - - 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); - return; - } - } - - PSP_DEBUG_PRINT("Address[%p] not allocated.\n", address); -} +/* 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"
+
+//#define TEST_MEMORY_COPY
+
+// swapRB is used to swap red and blue in the display
+void PspMemory::copy(byte *dst, const byte *src, uint32 bytes) {
+ DEBUG_ENTER_FUNC();
+
+#ifdef TEST_MEMORY_COPY
+ uint32 debugBytes = bytes;
+ const byte *debugDst = dst, *debugSrc = src;
+#endif
+
+ PSP_DEBUG_PRINT("copy(): dst[%p], src[%p], bytes[%d]\n", dst, src, bytes);
+
+ // align the destination pointer first
+ uint32 prefixDst = (((uint32)dst) & 0x3);
+
+ if (prefixDst) {
+ prefixDst = 4 - prefixDst; // prefix only if we have address % 4 != 0
+ PSP_DEBUG_PRINT("prefixDst[%d]\n", prefixDst);
+
+ bytes -= prefixDst; // remember we assume bytes >= 4
+
+ if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY) { // check if it's worthwhile to continue
+ copy8(dst, src, bytes);
+#ifdef TEST_MEMORY_COPY
+ testCopy(debugDst, debugSrc, debugBytes);
+#endif
+ return;
+ }
+
+ while (prefixDst--) {
+ *dst++ = *src++;
+ }
+ }
+
+ // check the source pointer alignment now
+ uint32 alignSrc = (((uint32)src) & 0x3);
+
+ if (alignSrc) { // we'll need to realign our reads
+ copy32Misaligned((uint32 *)dst, src, bytes, alignSrc);
+ } else {
+ copy32Aligned((uint32 *)dst, (uint32 *)src, bytes);
+ }
+
+#ifdef TEST_MEMORY_COPY
+ testCopy(debugDst, debugSrc, debugBytes);
+#endif
+}
+
+void PspMemory::testCopy(const byte *debugDst, const byte *debugSrc, uint32 debugBytes) {
+
+ bool mismatch = false;
+ PSP_INFO_PRINT("testing memcpy...");
+
+ 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]\n", debugDst, debugSrc, debugBytes);
+ mismatch = true;
+ }
+ PSP_DEBUG_PRINT_SAMELN("%x!=%x ", debugSrc[i], debugDst[i]);
+ }
+ }
+ if (mismatch) {
+ PSP_DEBUG_PRINT("\n");
+ } else {
+ PSP_INFO_PRINT("ok\n");
+ }
+}
+
+//
+// used to swap red and blue
+void PspMemory::swap(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) {
+ DEBUG_ENTER_FUNC();
+
+ // align the destination pointer first
+ uint32 prefixDst = (((uint32)dst16) & 0x3); // for swap, we can only have 2 or 0 as our prefix
+
+ if (prefixDst) {
+ bytes -= prefixDst; // remember we assume bytes > 4
+ *dst16++ = *src16++;
+
+ if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY * 2) { // check if it's worthwhile to continue
+ swap16(dst16, src16, bytes, format);
+ return;
+ }
+ }
+
+ // check the source pointer alignment now
+ uint32 alignSrc = (((uint32)src16) & 0x3);
+
+ if (alignSrc) { // we'll need to realign our reads
+ PSP_DEBUG_PRINT("misaligned copy of %u bytes from %p to %p\n", bytes, src16, dst16);
+ swap32Misaligned((uint32 *)dst16, (uint16 *)src16, bytes, format);
+ } else {
+ swap32Aligned((uint32 *)dst16, (uint32 *)src16, bytes, format);
+ }
+}
+
+void PspMemory::copy32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes) {
+ PSP_DEBUG_PRINT("copy32Aligned(): dst32[%p], src32[%p], bytes[%d]\n", dst32, src32, bytes);
+
+ int words8 = bytes >> 5;
+
+ // try blocks of 8 words at a time
+ if (words8) {
+ while (words8--) {
+ dst32[0] = src32[0];
+ dst32[1] = src32[1];
+ dst32[2] = src32[2];
+ dst32[3] = src32[3];
+ dst32[4] = src32[4];
+ dst32[5] = src32[5];
+ dst32[6] = src32[6];
+ dst32[7] = src32[7];
+ dst32 += 8;
+ src32 += 8;
+ }
+ }
+
+ int words4 = (bytes & 0x1F) >> 4;
+
+ // try blocks of 4 words at a time
+ if (words4) {
+ dst32[0] = src32[0];
+ dst32[1] = src32[1];
+ dst32[2] = src32[2];
+ dst32[3] = src32[3];
+ dst32 += 4;
+ src32 += 4;
+ }
+
+ int bytesLeft = (bytes & 0xF); // only look at bytes left after we did the above
+ int wordsLeft = bytesLeft >> 2;
+
+ // now just do single words
+ while (wordsLeft) {
+ *dst32++ = *src32++;
+ wordsLeft--;
+ }
+
+ bytesLeft = bytes & 0x3; // get remaining bytes
+
+ PSP_DEBUG_PRINT("bytesLeft[%d]\n", bytesLeft);
+
+ byte *dst = (byte *)dst32;
+ byte *src = (byte *)src32;
+
+ while (bytesLeft--) {
+ *dst++ = *src++;
+ }
+}
+
+void PspMemory::swap32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes, PSPPixelFormat &format) {
+ DEBUG_ENTER_FUNC();
+ int words = bytes >> 2;
+
+ // try blocks of 4 words at a time
+ for (; words - 4 >= 0; words -= 4) {
+ dst32[0] = format.swapRedBlue32(src32[0]);
+ dst32[1] = format.swapRedBlue32(src32[1]);
+ dst32[2] = format.swapRedBlue32(src32[2]);
+ dst32[3] = format.swapRedBlue32(src32[3]);
+ dst32 += 4;
+ src32 += 4;
+ }
+
+ // now just do words
+ for (; words > 0; words--) {
+ *dst32++ = format.swapRedBlue32(*src32++);
+ }
+
+ uint32 remainingBytes = bytes & 0x3;
+
+ if (remainingBytes) { // for swap, must be a 16 bit value
+ *((uint16 *)dst32) = format.swapRedBlue16(*((uint16 *)src32)); // only 1 short left
+ }
+}
+
+
+// More challenging -- need to shift
+// Assume dst is aligned
+void PspMemory::copy32Misaligned(uint32 *dst32, const byte *src, uint32 bytes, uint32 alignSrc) {
+ PSP_DEBUG_PRINT("copy32Misaligned: dst32[%p], src[%p], bytes[%d], alignSrc[%d]\n", dst32, src, bytes, alignSrc);
+
+ uint32 *src32 = (uint32 *)(((uint32)src) & 0xFFFFFFFC); // remove misalignment
+ uint32 offset;
+
+ switch (alignSrc) {
+ case 1:
+ offset = misaligned32Detail(dst32, src32, bytes, alignSrc, 8, 24);
+ break;
+ case 2:
+ offset = misaligned32Detail(dst32, src32, bytes, alignSrc, 16, 16);
+ break;
+ case 3:
+ offset = misaligned32Detail(dst32, src32, bytes, alignSrc, 24, 8);
+ break;
+ }
+
+ uint32 remainingBytes = bytes & 3;
+
+ if (remainingBytes) {
+ byte *dst = (byte *)dst32;
+ src += offset;
+ dst += offset;
+ copy8(dst, src, remainingBytes);
+ }
+}
+
+// returns offset in dst
+uint32 PspMemory::misaligned32Detail(uint32 *dst32, uint32 *src32, uint32 bytes, uint32 alignSrc, const uint32 shiftValue, const uint32 lastShiftValue) {
+ uint32 *origDst32 = dst32;
+ register uint32 dstWord, srcWord;
+
+ PSP_DEBUG_PRINT("misaligned32Detail(): alignSrc[%d], dst32[%p], src32[%p], words[%d]\n", alignSrc, dst32, src32, words);
+
+ // Try to do groups of 4 words
+ uint32 words4 = bytes >> 4;
+
+ srcWord = src32[0];
+
+ while (words4--) {
+ dstWord = srcWord >> shiftValue;
+ srcWord = src32[1];
+ dstWord |= srcWord << lastShiftValue;
+ dst32[0] = dstWord;
+ dstWord = srcWord >> shiftValue;
+ srcWord = src32[2];
+ dstWord |= srcWord << lastShiftValue;
+ dst32[1] = dstWord;
+ dstWord = srcWord >> shiftValue;
+ srcWord = src32[3];
+ dstWord |= srcWord << lastShiftValue;
+ dst32[2] = dstWord;
+ dstWord = srcWord >> shiftValue;
+ srcWord = src32[4];
+ dstWord |= srcWord << lastShiftValue;
+ dst32[3] = dstWord;
+ src32 += 4;
+ dst32 += 4;
+ }
+
+ uint32 words = (bytes & 0xF) >> 2;
+
+ // we read one word ahead of what we write
+ // setup the first read
+ if (words) {
+ srcWord = *src32++;
+
+ while (words--) {
+ dstWord = srcWord >> shiftValue;
+ srcWord = *src32++;
+ dstWord |= srcWord << lastShiftValue;
+ *dst32++ = dstWord;
+ }
+ }
+
+ return (byte *)dst32 - (byte *)origDst32;
+}
+// More challenging -- need to shift
+// Assume dst is aligned
+void PspMemory::swap32Misaligned(uint32 *dst32, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) {
+ DEBUG_ENTER_FUNC();
+ if (bytes < MIN_AMOUNT_FOR_MISALIGNED_COPY) { // less than a certain number of bytes it's just not worth it
+ swap16((uint16 *)dst32, src16, bytes, format);
+ return;
+ }
+
+ int words = bytes >> 2;
+ uint32 remainingBytes = bytes & 3;
+
+ uint32 *src32 = (uint32 *)(((uint32)src16) & 0xFFFFFFFC); // remove misalignment
+
+ // we read one word ahead of what we write
+ // setup the first read
+ uint32 lastWord = ((*src32++) >> 16) & 0xFFFF;
+
+ for (; words; words--) {
+ uint32 srcWord = *src32++;
+ uint32 curWord = (srcWord >> 16) & 0xFFFF;
+ lastWord |= (srcWord & 0xFFFF) << 16; // take the part of the src that belongs to this word
+ *dst32++ = format.swapRedBlue32(lastWord);
+ lastWord = curWord;
+ }
+
+ if (remainingBytes) { // add in the remaining stuff
+ *(uint16 *)dst32 = format.swapRedBlue16((uint16)lastWord);
+ }
+}
+
+inline void PspMemory::copy16(uint16 *dst16, const uint16 *src16, uint32 bytes) {
+ PSP_DEBUG_PRINT("copy16(): dst16[%p], src16[%p], bytes[%d]\n", dst16, src16, bytes);
+
+ uint32 shorts = bytes >> 1;
+ uint32 remainingBytes = bytes & 1;
+
+ for (; shorts > 0 ; shorts--) {
+ *dst16++ = *src16++;
+ }
+ if (remainingBytes)
+ *(byte *)dst16 = *(byte *)src16;
+}
+
+// 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);
+
+ 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);
+ return;
+ }
+ }
+
+ PSP_DEBUG_PRINT("Address[%p] not allocated.\n", address);
+}
diff --git a/backends/platform/psp/memory.h b/backends/platform/psp/memory.h index a198095090..81a77cca1c 100644 --- a/backends/platform/psp/memory.h +++ b/backends/platform/psp/memory.h @@ -1,80 +1,131 @@ - -/* 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 */ +
+/* 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
+
+#include "backends/platform/psp/psppixelformat.h"
+#include "common/list.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 */
+
+#define MIN_AMOUNT_FOR_COMPLEX_COPY 8
+#define MIN_AMOUNT_FOR_MISALIGNED_COPY 8
+
+//#define __PSP_DEBUG_PRINT__
+
+#include "backends/platform/psp/trace.h"
+
+/**
+ * Class that does memory copying and swapping if needed
+ */
+class PspMemory {
+private:
+ static void testCopy(const byte *debugDst, const byte *debugSrc, uint32 debugBytes);
+ static void copy(byte *dst, const byte *src, uint32 bytes);
+ static void swap(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format);
+ static void copy32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes);
+ static void swap32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes, PSPPixelFormat &format);
+ static void copy32Misaligned(uint32 *dst32, const byte *src, uint32 bytes, uint32 alignSrc);
+ static uint32 misaligned32Detail(uint32 *dst32, uint32 *src32, uint32 bytes, uint32 alignSrc, const uint32 shiftValue, const uint32 lastShiftValue);
+ static void swap32Misaligned(uint32 *dst32, const uint16 *src16, uint32 bytes, PSPPixelFormat &format);
+ static void copy16(uint16 *dst, const uint16 *src, uint32 bytes);
+
+ // For swapping, we know that we have multiples of 16 bits
+ static void swap16(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) {
+ PSP_DEBUG_PRINT("swap16 called with dst16[%p], src16[%p], bytes[%d]\n", dst16, src16, bytes);
+ uint32 shorts = bytes >> 1;
+
+ for (; shorts > 0 ; shorts--) {
+ *dst16++ = format.swapRedBlue16(*src16++);
+ }
+ }
+
+ static void copy8(byte *dst, const byte *src, uint32 bytes) {
+ PSP_DEBUG_PRINT("copy8 called with dst[%p], src[%p], bytes[%d]\n", dst, src, bytes);
+ while (bytes--) {
+ *dst++ = *src++;
+ }
+ }
+
+public:
+ // This is the interface to the outside world
+ static void fastCopy(byte *dst, const byte *src, uint32 bytes) {
+ if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY) {
+ copy8(dst, src, bytes);
+ } else { // go to more powerful copy
+ copy(dst, src, bytes);
+ }
+ }
+
+ static void fastSwap(byte *dst, const byte *src, uint32 bytes, PSPPixelFormat &format) {
+ if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY * 2) {
+ swap16((uint16 *)dst, (uint16 *)src, bytes, format);
+ } else { // go to more powerful copy
+ swap((uint16 *)dst, (uint16 *)src, bytes, format);
+ }
+ }
+};
+
+/**
+ * Class that allocates memory in the VRAM
+ */
+class VramAllocator : public Common::Singleton<VramAllocator> {
+public:
+ VramAllocator() : _bytesAllocated(0) {}
+ void *allocate(int32 size, bool smallAllocation = false); // smallAllocation e.g. palettes
+ void deallocate(void *pointer);
+
+ static inline bool isAddressInVram(void *address) {
+ if ((uint32)(CACHED(address)) >= VRAM_START_ADDRESS && (uint32)(CACHED(address)) < VRAM_END_ADDRESS)
+ return true;
+ return false;
+ }
+
+
+private:
+ /**
+ * Used to allocate in VRAM
+ */
+ struct Allocation {
+ byte *address;
+ uint32 size;
+ void *getEnd() { return address + size; }
+ Allocation(void *Address, uint32 Size) : address((byte *)Address), size(Size) {}
+ Allocation() : address(0), size(0) {}
+ };
+
+ enum {
+ VRAM_START_ADDRESS = 0x04000000,
+ VRAM_END_ADDRESS = 0x04200000,
+ VRAM_SMALL_ADDRESS = VRAM_END_ADDRESS - (4 * 1024) // 4K in the end for small allocations
+ };
+ Common::List <Allocation> _allocList; // List of allocations
+ uint32 _bytesAllocated;
+};
+
+#endif /* PSP_MEMORY_H */
diff --git a/backends/platform/psp/module.mk b/backends/platform/psp/module.mk index e9c896acfd..855554e980 100644 --- a/backends/platform/psp/module.mk +++ b/backends/platform/psp/module.mk @@ -16,7 +16,8 @@ MODULE_OBJS := powerman.o \ audio.o \ thread.o \ rtc.o \ - mp3.o + mp3.o \ + tests.o MODULE_DIRS += \ backends/platform/psp/ diff --git a/backends/platform/psp/psp_main.cpp b/backends/platform/psp/psp_main.cpp index c26aed539e..b84702115f 100644 --- a/backends/platform/psp/psp_main.cpp +++ b/backends/platform/psp/psp_main.cpp @@ -44,12 +44,15 @@ #include "backends/plugins/psp/psp-provider.h" #include "backends/platform/psp/psppixelformat.h" #include "backends/platform/psp/osys_psp.h" +#include "backends/platform/psp/tests.h" #include "backends/platform/psp/trace.h" #ifdef ENABLE_PROFILING #include <pspprof.h> #endif +#define ENABLE_TESTS /* to enable tests of PSP architecture */ + /** * Define the module info section * @@ -153,7 +156,7 @@ int SetupCallbacks(void) { #undef main int main(void) { //change clock rate to 333mhz - scePowerSetClockFrequency(333, 333, 166); + scePowerSetClockFrequency(222, 222, 111); PowerManager::instance(); // Setup power manager @@ -169,6 +172,12 @@ int main(void) { PluginManager::instance().addPluginProvider(new PSPPluginProvider()); #endif +#ifdef ENABLE_TESTS + PSP_INFO_PRINT("running tests\n"); + tests(); + sceKernelSleepThread(); +#endif + int res = scummvm_main(argc, argv); g_system->quit(); // TODO: Consider removing / replacing this! |