the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1/* SCE CONFIDENTIAL
2PlayStation(R)3 Programmer Tool Runtime Library 430.001
3* Copyright (C) 2007 Sony Computer Entertainment Inc.
4* All Rights Reserved.
5*/
6
7/* common headers */
8#include <stdint.h>
9#include <stdlib.h>
10#include <string.h>
11#include <spu_intrinsics.h>
12#include <cell/spurs.h>
13#include <cell/dma.h>
14#include <cell/spurs/job_queue.h>
15
16#include "..\Common\DmaData.h"
17
18#include "CompressedTileStorage_compress.h"
19
20static const bool sc_verbose = false;
21
22CellSpursJobContext2* g_pSpursJobContext;
23
24
25
26
27class CCompressedTileStorage_compress
28{
29public:
30 unsigned char indicesAndData[32768+4096];
31 unsigned char newIndicesAndData[32768+4096];
32 int allocatedSize;
33 int newAllocatedSize;
34 uint32_t newIndicesPPU;
35private:
36
37 static const int INDEX_OFFSET_MASK = 0x7ffe;
38 static const int INDEX_OFFSET_SHIFT = 1;
39 static const int INDEX_TILE_MASK = 0x00ff;
40 static const int INDEX_TILE_SHIFT = 8;
41 static const int INDEX_TYPE_MASK = 0x0003;
42 static const int INDEX_TYPE_1_BIT = 0x0000;
43 static const int INDEX_TYPE_2_BIT = 0x0001;
44 static const int INDEX_TYPE_4_BIT = 0x0002;
45 static const int INDEX_TYPE_0_OR_8_BIT = 0x0003;
46 static const int INDEX_TYPE_0_BIT_FLAG = 0x0004;
47
48public:
49 CCompressedTileStorage_compress(CompressedTileStorage_compress_dataIn& dataIn)
50 {
51 allocatedSize = dataIn.allocatedSize;
52 newIndicesPPU = (uint32_t)dataIn.newIndicesAndData;
53 spu_assert(allocatedSize < (int)sizeof(indicesAndData));
54 DmaData_SPU::getAndWait(indicesAndData, (uintptr_t)dataIn.indicesAndData, DmaData_SPU::roundUpDMASize(allocatedSize));
55 }
56 bool compress(int upgradeBlock = -1);
57};
58
59// Compresses the data currently stored in one of two ways:
60// (1) Attempt to compresses every block as much as possible (if upgradeBlock is -1)
61// (2) Copy all blocks as-is apart from the block specified by upgradeBlock ( if > -1 ), which is changed to be the next-most-accomodating storage from its current state
62bool CCompressedTileStorage_compress::compress(int upgradeBlock/*=-1*/)
63{
64 unsigned char tempdata[64];
65 unsigned short _blockIndices[512];
66 bool needsCompressed = ( upgradeBlock > -1 ); // If an upgrade block is specified, we'll always need to recompress - otherwise default to false
67
68
69 unsigned short *blockIndices = (unsigned short *)indicesAndData;
70 unsigned char *data = indicesAndData + 1024;
71
72 int memToAlloc = 0;
73 for( int i = 0; i < 512; i++ )
74 {
75 unsigned short indexType = blockIndices[i] & INDEX_TYPE_MASK;
76
77 unsigned char *unpacked_data = NULL;
78 unsigned char *packed_data;
79
80 // First task is to find out what type of storage each block needs. Need to unpack each where required.
81 // Note that we don't need to fully unpack the data at this stage since we are only interested in working out how many unique types of tiles are in each block, not
82 // what those actual tile ids are.
83 if( upgradeBlock == -1 )
84 {
85 if( indexType == INDEX_TYPE_0_OR_8_BIT )
86 {
87 // Note that we are only interested in data that can be packed further, so we don't need to consider things that are already at their most compressed
88 // (ie with INDEX_TYPE_0_BIT_FLAG set)
89 if( ( blockIndices[i] & INDEX_TYPE_0_BIT_FLAG ) == 0 )
90 {
91 unpacked_data = data + ( ( blockIndices[i] >> INDEX_OFFSET_SHIFT ) & INDEX_OFFSET_MASK );
92 }
93 }
94 else
95 {
96 int bitspertile = 1 << indexType; // will be 1, 2 or 4 (from index values of 0, 1, 2)
97 int tiletypecount = 1 << bitspertile; // will be 2, 4 or 16
98 int tiletypemask = tiletypecount - 1; // will be 1, 3 or 15
99 int indexshift = 3 - indexType; // will be 3, 2 or 1 (from index values of 0, 1, 2)
100 int indexmask_bits = 7 >> indexType; // will be 7, 3 or 1 (from index values of 0, 1, 2)
101 int indexmask_bytes = 62 >> indexshift; // will be 7, 15 or 31 (from index values of 0, 1, 2)
102
103 unpacked_data = tempdata;
104 packed_data = data + ( ( blockIndices[i] >> INDEX_OFFSET_SHIFT ) & INDEX_OFFSET_MASK ) + tiletypecount;
105
106 for( int j = 0; j < 64; j++ )
107 {
108 int idx = (j >> indexshift) & indexmask_bytes;
109 int bit = ( j & indexmask_bits ) * bitspertile;
110
111 unpacked_data[j] = ( packed_data[idx] >> bit ) & tiletypemask; // Doesn't need the actual data for each tile, just unique values
112 }
113 }
114
115 if( unpacked_data )
116 {
117 // Now count how many unique tile types are in the block - if unpacked_data isn't set then there isn't any data so we can't compress any further and require no storage.
118 // Store flags for each tile type used in an array of 4 64-bit flags.
119
120 uint64_t usedFlags[4] = {0,0,0,0};
121
122 int64_t i64_1 = 1; // MGH - instead of 1i64, which is MS specific
123 for( int j = 0; j < 64; j++ ) // This loop of 64 is to go round the 4x4x4 tiles in the block
124 {
125 int tiletype = unpacked_data[j];
126 usedFlags[tiletype & 3] |= ( i64_1 << ( tiletype >> 2 ) );
127 }
128 int count = 0;
129 for( int tiletype = 0; tiletype < 256; tiletype++ ) // This loop of 256 is to go round the 256 possible values that the tiles might have had to find how many are actually used
130 {
131 if( usedFlags[tiletype & 3] & ( i64_1 << ( tiletype >> 2 ) ) )
132 {
133 count++;
134 }
135 }
136 if( count == 1 )
137 {
138 _blockIndices[i] = INDEX_TYPE_0_OR_8_BIT | INDEX_TYPE_0_BIT_FLAG;
139
140 // We'll need to compress if this isn't the same type as before. If it *was* a 0-bit one though, then unpacked_data wouldn't have been set and we wouldn't be here
141 needsCompressed = true;
142 }
143 else if( count == 2 )
144 {
145 _blockIndices[i] = INDEX_TYPE_1_BIT;
146 if( indexType != INDEX_TYPE_1_BIT ) needsCompressed = true;
147 memToAlloc += 10; // 8 bytes + 2 tile index
148 }
149 else if ( count <= 4 )
150 {
151 _blockIndices[i] = INDEX_TYPE_2_BIT;
152 if( indexType != INDEX_TYPE_2_BIT ) needsCompressed = true;
153 memToAlloc += 20; // 16 bytes + 4 tile index
154 }
155 else if ( count <= 16 )
156 {
157 _blockIndices[i] = INDEX_TYPE_4_BIT;
158 if( indexType != INDEX_TYPE_4_BIT ) needsCompressed = true;
159 memToAlloc += 48; // 32 bytes + 16 tile index
160 }
161 else
162 {
163 _blockIndices[i] = INDEX_TYPE_0_OR_8_BIT;
164 memToAlloc = ( memToAlloc + 3 ) & 0xfffc; // Make sure we are 4-byte aligned for 8-bit storage
165 memToAlloc += 64;
166 }
167 }
168 else
169 {
170 // Already will be 0 bits, so we can't do any further compression - just copy the index over.
171 _blockIndices[i] = blockIndices[i];
172 }
173 }
174 else
175 {
176 if( i == upgradeBlock )
177 {
178 // INDEX_TYPE_1_BIT (0) -> INDEX_TYPE_2_BIT (1)
179 // INDEX_TYPE_2_BIT (1) -> INDEX_TYPE_4_BIT (2)
180 // INDEX_TYPE_4_BIT (2) -> INDEX_TYPE_0_OR_8_BIT (3) (new will be 8-bit)
181 // INDEX_TYPE_0_OR_8_BIT (3) -> INDEX_TYPE_1_BIT (0) (assuming old was 0-bit)
182 _blockIndices[i] = ( ( blockIndices[i] & INDEX_TYPE_MASK ) + 1 ) & INDEX_TYPE_MASK;
183 }
184 else
185 {
186 // Copy over the index, without the offset.
187 _blockIndices[i] = blockIndices[i] & INDEX_TYPE_MASK;
188 if( _blockIndices[i] == INDEX_TYPE_0_OR_8_BIT )
189 {
190 _blockIndices[i] |= ( blockIndices[i] & INDEX_TYPE_0_BIT_FLAG );
191 }
192 }
193 switch(_blockIndices[i])
194 {
195 case INDEX_TYPE_1_BIT:
196 memToAlloc += 10;
197 break;
198 case INDEX_TYPE_2_BIT:
199 memToAlloc += 20;
200 break;
201 case INDEX_TYPE_4_BIT:
202 memToAlloc += 48;
203 break;
204 case INDEX_TYPE_0_OR_8_BIT:
205 memToAlloc = ( memToAlloc + 3 ) & 0xfffc; // Make sure we are 4-byte aligned for 8-bit storage
206 memToAlloc += 64;
207 break;
208 // Note that INDEX_TYPE_8_BIT|INDEX_TYPE_0_BIT_FLAG not in here as it doesn't need any further allocation
209 }
210 }
211 }
212
213 // If we need to do something here, then lets allocate some memory
214 if( needsCompressed )
215 {
216 memToAlloc += 1024; // For the indices
217 unsigned char *pucData = newIndicesAndData + 1024;
218 unsigned short usDataOffset = 0;
219 unsigned short *newIndices = (unsigned short *) newIndicesAndData;
220
221 // Now pass through again actually making the final compressed data
222 for( int i = 0; i < 512; i++ )
223 {
224 unsigned short indexTypeNew = _blockIndices[i] & INDEX_TYPE_MASK;
225 unsigned short indexTypeOld = blockIndices[i] & INDEX_TYPE_MASK;
226 newIndices[i] = indexTypeNew;
227
228 // Is the type unmodifed? Then can just copy over
229 bool done = false;
230 if( indexTypeOld == indexTypeNew )
231 {
232 unsigned char *packed_data;
233 if( indexTypeOld == INDEX_TYPE_0_OR_8_BIT )
234 {
235 if( ( blockIndices[i] & INDEX_TYPE_0_BIT_FLAG ) == ( _blockIndices[i] & INDEX_TYPE_0_BIT_FLAG ) )
236 {
237 if( blockIndices[i] & INDEX_TYPE_0_BIT_FLAG )
238 {
239 newIndices[i] = blockIndices[i];
240 }
241 else
242 {
243 packed_data = data + ( ( blockIndices[i] >> INDEX_OFFSET_SHIFT ) & INDEX_OFFSET_MASK);
244 usDataOffset = (usDataOffset + 3 ) & 0xfffc;
245 memcpy( pucData + usDataOffset, packed_data, 64 );
246 newIndices[i] |= ( usDataOffset & INDEX_OFFSET_MASK) << INDEX_OFFSET_SHIFT;
247 usDataOffset += 64;
248 }
249 done = true;
250 }
251 }
252 else
253 {
254 packed_data = data + ( ( blockIndices[i] >> INDEX_OFFSET_SHIFT ) & INDEX_OFFSET_MASK);
255
256 int dataSize = 8 << indexTypeOld; // 8, 16 or 32 bytes of per-tile storage
257 dataSize += 1 << ( 1 << indexTypeOld ); // 2, 4 or 16 bytes to store each tile type
258 newIndices[i] |= ( usDataOffset & INDEX_OFFSET_MASK) << INDEX_OFFSET_SHIFT;
259 memcpy( pucData + usDataOffset, packed_data, dataSize );
260 usDataOffset += dataSize;
261 done = true;
262 }
263 }
264
265
266 // If we're not done, then we actually need to recompress this block. First of all decompress from its current format.
267 if( !done )
268 {
269 unsigned char *unpacked_data = NULL;
270 unsigned char *tile_types = NULL;
271 unsigned char *packed_data = NULL;
272 if( indexTypeOld == INDEX_TYPE_0_OR_8_BIT )
273 {
274 if( blockIndices[i] & INDEX_TYPE_0_BIT_FLAG )
275 {
276 unpacked_data = tempdata;
277 int value = ( blockIndices[i] >> INDEX_TILE_SHIFT ) & INDEX_TILE_MASK;
278 memset( tempdata, value, 64 );
279 }
280 else
281 {
282 unpacked_data = data + ( ( blockIndices[i] >> INDEX_OFFSET_SHIFT ) & INDEX_OFFSET_MASK );
283 }
284 }
285 else
286 {
287 int bitspertile = 1 << indexTypeOld; // will be 1, 2 or 4 (from index values of 0, 1, 2)
288 int tiletypecount = 1 << bitspertile; // will be 2, 4 or 16
289 int tiletypemask = tiletypecount - 1; // will be 1, 3 or 15
290 int indexshift = 3 - indexTypeOld; // will be 3, 2 or 1 (from index values of 0, 1, 2)
291 int indexmask_bits = 7 >> indexTypeOld; // will be 7, 3 or 1 (from index values of 0, 1, 2)
292 int indexmask_bytes = 62 >> indexshift; // will be 7, 15 or 31 (from index values of 0, 1, 2)
293
294 unpacked_data = tempdata;
295 tile_types = data + ( ( blockIndices[i] >> INDEX_OFFSET_SHIFT ) & INDEX_OFFSET_MASK );
296 packed_data = tile_types + tiletypecount;
297 for( int j = 0; j < 64; j++ )
298 {
299 int idx = ( j >> indexshift ) & indexmask_bytes;
300 int bit = ( j & indexmask_bits ) * bitspertile;
301
302 unpacked_data[j] = tile_types[(packed_data[idx] >> bit) & tiletypemask];
303 }
304 }
305
306 // And finally repack
307 unsigned char ucMappings[256] = {0};
308 for( int j = 0; j < 256; j++ )
309 {
310 ucMappings[j] = 255;
311 }
312
313 unsigned char *repacked = NULL;
314
315 if( indexTypeNew == INDEX_TYPE_0_OR_8_BIT )
316 {
317 if( _blockIndices[i] & INDEX_TYPE_0_BIT_FLAG )
318 {
319 newIndices[i] = INDEX_TYPE_0_OR_8_BIT | INDEX_TYPE_0_BIT_FLAG | (((unsigned short)unpacked_data[0]) << INDEX_TILE_SHIFT);
320 }
321 else
322 {
323 usDataOffset = (usDataOffset + 3 ) & 0xfffc; // Make sure offset is 4 byte aligned
324 memcpy( pucData + usDataOffset, unpacked_data, 64 );
325 newIndices[i] |= ( usDataOffset & INDEX_OFFSET_MASK) << INDEX_OFFSET_SHIFT;
326 usDataOffset += 64;
327 }
328 }
329 else
330 {
331 int bitspertile = 1 << indexTypeNew; // will be 1, 2 or 4 (from index values of 0, 1, 2)
332 int tiletypecount = 1 << bitspertile; // will be 2, 4 or 16 (from index values of 0, 1, 2)
333 int tiletypemask = tiletypecount - 1; // will be 1, 3 or 15 (from index values of 0, 1, 2)
334 int tiledatasize = 8 << indexTypeNew; // will be 8, 16 or 32 (from index values of 0, 1, 2)
335 int indexshift = 3 - indexTypeNew; // will be 3, 2 or 1 (from index values of 0, 1, 2)
336 int indexmask_bits = 7 >> indexTypeNew; // will be 7, 3 or 1 (from index values of 0, 1, 2)
337 int indexmask_bytes = 62 >> indexshift; // will be 7, 15 or 31 (from index values of 0, 1, 2)
338
339 tile_types = pucData + usDataOffset;
340 repacked = tile_types + tiletypecount;
341 memset(tile_types, 255, tiletypecount);
342 memset(repacked, 0,tiledatasize);
343 newIndices[i] |= ( usDataOffset & INDEX_OFFSET_MASK) << INDEX_OFFSET_SHIFT;
344 usDataOffset += tiletypecount + tiledatasize;
345 int count = 0;
346 for( int j = 0; j < 64; j++ )
347 {
348 int tile = unpacked_data[j];
349 if( ucMappings[tile] == 255 )
350 {
351 ucMappings[tile] = count;
352 tile_types[count++] = tile;
353 }
354 int idx = (j >> indexshift) & indexmask_bytes;
355 int bit = ( j & indexmask_bits ) * bitspertile;
356 repacked[idx] |= ucMappings[tile] << bit;
357 }
358 }
359 }
360 }
361
362 newAllocatedSize = memToAlloc;
363
364 DmaData_SPU::putAndWait(&newIndicesAndData, newIndicesPPU, DmaData_SPU::roundUpDMASize(newAllocatedSize));
365 return true;
366 }
367 return false;
368}
369
370
371
372
373void cellSpursJobQueueMain(CellSpursJobContext2 *pContext, CellSpursJob256 *pJob)
374{
375// CellSpursTaskId idTask = cellSpursGetTaskId();
376 unsigned int idSpu = cellSpursGetCurrentSpuId();
377
378 if(sc_verbose)
379 spu_print("CompressedTileStorage_compress [SPU#%u] start\n", idSpu);
380
381 g_pSpursJobContext = pContext;
382
383 uint32_t eaDataIn = pJob->workArea.userData[0];
384
385 CompressedTileStorage_compress_dataIn compressDataIn;
386 DmaData_SPU::getAndWait(&compressDataIn, eaDataIn, sizeof(CompressedTileStorage_compress_dataIn));
387 CCompressedTileStorage_compress c(compressDataIn);
388
389 compressDataIn.neededCompressed = c.compress(compressDataIn.upgradeBlock);
390 compressDataIn.newAllocatedSize = c.newAllocatedSize;
391
392 DmaData_SPU::putAndWait(&compressDataIn, eaDataIn, sizeof(CompressedTileStorage_compress_dataIn));
393
394 if(sc_verbose)
395 spu_print("CompressedTileStorage_compress [SPU#%u] exit\n", idSpu);
396}
397