the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 397 lines 14 kB view raw
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