1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
/* 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);
}
|