the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1include "stdafx.h"
2#include "CompressedTileStorage_SPU.h"
3#ifdef SN_TARGET_PS3_SPU
4#include "..\Common\DmaData.h"
5#else
6#include "..\..\..\..\Minecraft.World\Tile.h"
7#include "..\..\..\..\Minecraft.World\TilePos.h"
8#include "..\..\..\..\Minecraft.World\LevelChunk.h"
9#endif
10
11#include <stdlib.h>
12
13#ifdef SN_TARGET_PS3_SPU
14TileCompressData_SPU::OutputData TileCompressData_SPU::m_OutputData;
15CompressedTileStorage_SPU* TileCompressData_SPU::m_pTileStorage;
16#endif
17
18// Note: See header for an overview of this class
19
20// int CompressedTileStorage::deleteQueueIndex;
21// XLockFreeStack <unsigned char> CompressedTileStorage::deleteQueue[3];
22//
23// CRITICAL_SECTION CompressedTileStorage::cs_write;
24
25CompressedTileStorage_SPU::CompressedTileStorage_SPU(unsigned char* data)
26{
27 indicesAndData = data;
28 allocatedSize = 0;
29}
30
31
32CompressedTileStorage_SPU::~CompressedTileStorage_SPU()
33{
34}
35
36// Get an index into the normal ordering of tiles for the java game, given a block index (0 to 511) and a tile index (0 to 63)
37inline int CompressedTileStorage_SPU::getIndex(int block, int tile)
38{
39 // bits for index into data is: xxxxzzzzyyyyyyy
40 // we want block(b) & tile(t) spread out as:
41 // from: ______bbbbbbbbb
42 // to: bb__bb__bbbbb__
43 //
44 // from: _________tttttt
45 // to: __tt__tt_____tt
46
47 int index = ( ( block & 0x180) << 6 ) | ( ( block & 0x060 ) << 4 ) | ( ( block & 0x01f ) << 2 );
48 index |= ( ( tile & 0x30 ) << 7) | ( ( tile & 0x0c ) << 5 ) | ( tile & 0x03 );
49
50 return index;
51}
52
53// Get the block and tile (reversing getIndex above) for a given x, y, z coordinate
54//
55// bits for index into data is: xxxxzzzzyyyyyyy
56// bbttbbttbbbbbtt
57//
58// so x is: ___________xxxx
59// and maps to this bit of b ______bb_______
60// and this bit of t _________tt____
61//
62// y is: ________yyyyyyy
63// and maps to this bit of b __________bbbbb
64// and this bit of t _____________tt
65//
66// and z is: ___________zzzz
67// and maps to this bit of b ________bb_____
68// and this bit of t ___________tt__
69//
70
71inline void CompressedTileStorage_SPU::getBlockAndTile(int *block, int *tile, int x, int y, int z)
72{
73 *block = ( ( x & 0x0c ) << 5 ) | ( ( z & 0x0c ) << 3 ) | ( y >> 2 );
74 *tile = ( ( x & 0x03 ) << 4 ) | ( ( z & 0x03 ) << 2 ) | ( y & 0x03 );
75}
76
77
78// Get an individual tile value
79int CompressedTileStorage_SPU::get(int x, int y, int z)
80{
81 if(y<0)
82 return 0;
83 if(!indicesAndData) return 0;
84
85 unsigned short *blockIndices = (unsigned short *)indicesAndData;
86 unsigned char *data = indicesAndData + 1024;
87
88 int block, tile;
89 getBlockAndTile( &block, &tile, x, y, z );
90 int indexType = blockIndices[block] & INDEX_TYPE_MASK;
91
92 if( indexType == INDEX_TYPE_0_OR_8_BIT )
93 {
94 if( blockIndices[block] & INDEX_TYPE_0_BIT_FLAG )
95 {
96 // 0 bit reads are easy - the value is packed in the index
97 return ( blockIndices[block] >> INDEX_TILE_SHIFT ) & INDEX_TILE_MASK;
98 }
99 else
100 {
101 // 8-bit reads are just directly read from the 64 long array of values stored for the block
102 unsigned char *packed = data + ( ( blockIndices[block] >> INDEX_OFFSET_SHIFT ) & INDEX_OFFSET_MASK );
103 return packed[tile];
104 }
105 }
106 else
107 {
108 int bitspertile = 1 << indexType; // will be 1, 2 or 4 (from index values of 0, 1, 2)
109 int tiletypecount = 1 << bitspertile; // will be 2, 4 or 16 (from index values of 0, 1, 2)
110 int tiletypemask = tiletypecount - 1; // will be 1, 3 or 15 (from index values of 0, 1, 2)
111 int indexshift = 3 - indexType; // will be 3, 2 or 1 (from index values of 0, 1, 2)
112 int indexmask_bits = 7 >> indexType; // will be 7, 3 or 1 (from index values of 0, 1, 2)
113 int indexmask_bytes = 62 >> indexshift; // will be 7, 15 or 31 (from index values of 0, 1, 2)
114
115 unsigned char *tile_types = data + ( ( blockIndices[block] >> INDEX_OFFSET_SHIFT ) & INDEX_OFFSET_MASK );
116 unsigned char *packed = tile_types + tiletypecount;
117 int idx = ( tile >> indexshift ) & indexmask_bytes;
118 int bit = ( tile & indexmask_bits ) * bitspertile;
119 return tile_types[( packed[idx] >> bit ) & tiletypemask];
120 }
121 return 0;
122}
123
124#ifdef SN_TARGET_PS3_SPU
125
126
127
128
129void TileCompressData_SPU::uncompressTiles(int x0, int z0, int x1, int z1, bool upper)
130{
131 int y0 = -2;
132 int y1 = 18;
133 for(int iY=y0;iY<y1;iY++)
134 {
135 if(validY(iY+m_y0, upper))
136 {
137 for(int iX=x0;iX<x1;iX++)
138 {
139 for(int iZ=z0;iZ<z1;iZ++)
140 {
141 int index = ((iX+2)*sc_size*sc_size) + ((iY+2)*sc_size) + (iZ+2);
142 int sectionX = (iX+m_x0) & 0xf;
143 int sectionY = (iY+m_y0);
144 if(upper)
145 sectionY -= 128;
146 int sectionZ = (iZ+m_z0) & 0xf;
147 m_OutputData.m_tileIds[index] = m_pTileStorage->get(sectionX, sectionY, sectionZ);
148 }
149 }
150 }
151 }
152}
153
154
155void TileCompressData_SPU::clearTiles(int x0, int z0, int x1, int z1, bool upper)
156{
157 int y0 = -2;
158 int y1 = 18;
159 for(int iY=y0;iY<y1;iY++)
160 {
161 if(validY((iY+m_y0), upper))
162 {
163 for(int iX=x0;iX<x1;iX++)
164 {
165 for(int iZ=z0;iZ<z1;iZ++)
166 {
167 int index = ((iX+2)*sc_size*sc_size) + ((iY+2)*sc_size) + (iZ+2);
168 m_OutputData.m_tileIds[index] = 0;
169 }
170 }
171 }
172 }
173}
174
175
176void TileCompressData_SPU::uncompressLights(int x0, int z0, int x1, int z1, bool upper, bool skyLight)
177{
178 int y0 = -2;
179 int y1 = 18;
180 for(int iY=y0;iY<y1;iY++)
181 {
182 if(validY(iY+m_y0, upper))
183 {
184 for(int iX=x0;iX<x1;iX++)
185 {
186 for(int iZ=z0;iZ<z1;iZ++)
187 {
188 int index = ((iX+2)*sc_size*sc_size) + ((iY+2)*sc_size) + (iZ+2);
189 int sectionX = (iX+m_x0) & 0xf;
190 int sectionY = (iY+m_y0);
191 if(upper)
192 sectionY -= 128;
193 int sectionZ = (iZ+m_z0) & 0xf;
194 if(skyLight)
195 {
196 m_OutputData.m_brightness[index] = m_pLightStorage->get(sectionX, sectionY, sectionZ);
197 }
198 else
199 {
200 m_OutputData.m_brightness[index] |= m_pLightStorage->get(sectionX, sectionY, sectionZ) << 4;
201 }
202 }
203 }
204 }
205 }
206}
207
208void TileCompressData_SPU::clearLights(int x0, int z0, int x1, int z1, bool upper, bool skyLight)
209{
210 int y0 = -2;
211 int y1 = 18;
212 for(int iY=y0;iY<y1;iY++)
213 {
214 if(validY((iY+m_y0), upper))
215 {
216 for(int iX=x0;iX<x1;iX++)
217 {
218 for(int iZ=z0;iZ<z1;iZ++)
219 {
220 int index = ((iX+2)*sc_size*sc_size) + ((iY+2)*sc_size) + (iZ+2);
221 if(skyLight)
222 m_OutputData.m_tileIds[index] &= 0xf0;
223 else
224 m_OutputData.m_tileIds[index] &= 0x0f;
225 }
226 }
227 }
228 }
229}
230
231void TileCompressData_SPU::uncompressData(int x0, int z0, int x1, int z1, bool upper)
232{
233 int y0 = -2;
234 int y1 = 18;
235 for(int iY=y0;iY<y1;iY++)
236 {
237 if(validY(iY+m_y0, upper))
238 {
239 for(int iX=x0;iX<x1;iX++)
240 {
241 for(int iZ=z0;iZ<z1;iZ++)
242 {
243 int index = ((iX+2)*sc_size*sc_size) + ((iY+2)*sc_size) + (iZ+2);
244 int sectionX = (iX+m_x0) & 0xf;
245 int sectionY = (iY+m_y0);
246 if(upper)
247 sectionY -= 128;
248 int sectionZ = (iZ+m_z0) & 0xf;
249 m_OutputData.m_data_flags[index] = m_pDataStorage->get(sectionX, sectionY, sectionZ);
250 }
251 }
252 }
253 }
254}
255
256void TileCompressData_SPU::clearData(int x0, int z0, int x1, int z1, bool upper)
257{
258 int y0 = -2;
259 int y1 = 18;
260 for(int iY=y0;iY<y1;iY++)
261 {
262 if(validY((iY+m_y0), upper))
263 {
264 for(int iX=x0;iX<x1;iX++)
265 {
266 for(int iZ=z0;iZ<z1;iZ++)
267 {
268 int index = ((iX+2)*sc_size*sc_size) + ((iY+2)*sc_size) + (iZ+2);
269 m_OutputData.m_data_flags[index] = 0;
270 }
271 }
272 }
273 }
274}
275
276
277void TileCompressData_SPU::dmaSparseStorage(int64_t dataAndSize, unsigned char* pDest)
278{
279 uint32_t loadFrom = (uint32_t)dataAndSize & 0x00000000ffffffffL;
280 unsigned int loadSize = (uint32_t)((dataAndSize >> 48)*128)+128;
281 DmaData_SPU::getAndWait(pDest, loadFrom, loadSize);
282}
283
284int padTo16(int size)
285{
286 if(size & 0x0f)
287 {
288 size &= ~0x0f;
289 size += 0x10;
290 }
291 return size;
292}
293void TileCompressData_SPU::loadAndUncompressLowerSection(int block, int x0, int z0, int x1, int z1)
294{
295
296 // tile IDs first
297 // ---------------------------
298 if(m_lowerBlocks[block] != NULL)
299 {
300 int dmaSize = padTo16(m_lowerBlocksSize[block]);
301 DmaData_SPU::getAndWait(m_pTileStorage->getDataPtr(), (uint32_t)m_lowerBlocks[block], dmaSize);
302// spu_print("Grabbed %d of data\n", m_lowerBlocksSize[block]);
303 uncompressTiles(x0, z0, x1, z1, false);
304 }
305 else
306 {
307 clearTiles(x0, z0, x1, z1, false);
308 }
309
310}
311
312void TileCompressData_SPU::loadAndUncompressUpperSection(int block, int x0, int z0, int x1, int z1)
313{
314 if(m_upperBlocks[block] != NULL)
315 {
316 int dmaSize = padTo16(m_upperBlocksSize[block]);
317 DmaData_SPU::getAndWait(m_pTileStorage->getDataPtr(), (uint32_t)m_upperBlocks[block], dmaSize);
318 uncompressTiles(x0, z0, x1, z1, true);
319 }
320 else
321 {
322 clearTiles(x0, z0, x1, z1, true);
323 }
324
325 // Sky Lights
326 // ---------------------------
327 if(m_upperSkyLight[block] != 0)
328 {
329 dmaSparseStorage(m_upperSkyLight[block], m_pLightStorage->getDataPtr());
330 uncompressLights(x0, z0, x1, z1, true, true);
331 }
332 else
333 {
334 clearLights(x0, z0, x1, z1, true, true);
335 }
336
337 // Block Lights
338 // ---------------------------
339 if(m_upperBlockLight[block] != 0)
340 {
341 dmaSparseStorage(m_upperBlockLight[block], m_pLightStorage->getDataPtr());
342 uncompressLights(x0, z0, x1, z1, true, false);
343 }
344 else
345 {
346 clearLights(x0, z0, x1, z1, true, false);
347 }
348
349 // Data
350 // ---------------------------
351 if(m_upperData[block] != 0)
352 {
353 dmaSparseStorage(m_upperData[block], m_pDataStorage->getDataPtr());
354 uncompressData(x0, z0, x1, z1, true);
355 }
356 else
357 {
358 clearData(x0, z0, x1, z1, true);
359 }
360}
361
362
363void TileCompressData_SPU::uncompress( uint32_t eaDataOut )
364{
365 unsigned char pScratchArea[33*1024];
366 int outDataSize = sc_size*sc_size*sc_size*3;
367 CompressedTileStorage_SPU ts(pScratchArea);
368 SparseLightStorage_SPU ls(pScratchArea);
369 SparseDataStorage_SPU ds(pScratchArea);
370
371 m_pTileStorage = &ts;
372 m_pLightStorage = &ls;
373 m_pDataStorage = &ds;
374
375 if(m_y0 <= 127)
376 {
377 loadAndUncompressLowerSection(0, -2,-2, 0,0);
378 loadAndUncompressLowerSection(1, -2,0, 0,16);
379 loadAndUncompressLowerSection(2, -2,16, 0,18);
380
381 loadAndUncompressLowerSection(3, 0,-2, 16,0);
382 loadAndUncompressLowerSection(4, 0,0, 16,16);
383 loadAndUncompressLowerSection(5, 0,16, 16,18);
384
385 loadAndUncompressLowerSection(6, 16,-2, 18,0);
386 loadAndUncompressLowerSection(7, 16,0, 18,16);
387 loadAndUncompressLowerSection(8, 16,16, 18,18);
388 }
389 if(m_y0 >= 128)
390 {
391 loadAndUncompressUpperSection(0, -2,-2, 0,0);
392 loadAndUncompressUpperSection(1, -2,0, 0,16);
393 loadAndUncompressUpperSection(2, -2,16, 0,18);
394
395 loadAndUncompressUpperSection(3, 0,-2, 16,0);
396 loadAndUncompressUpperSection(4, 0,0, 16,16);
397 loadAndUncompressUpperSection(5, 0,16, 16,18);
398
399 loadAndUncompressUpperSection(6, 16,-2, 18,0);
400 loadAndUncompressUpperSection(7, 16,0, 18,16);
401 loadAndUncompressUpperSection(8, 16,16, 18,18);
402 }
403
404// for(int i=0;i<20*20*20; i++)
405// {
406// m_OutputData.m_data_flags[i] = 0xEE;
407// m_OutputData.m_data_flags[i] = 0xEE;
408// m_OutputData.m_data_flags[i] = 0xEE;
409//
410// if(m_OutputData.m_data_flags[i] == 32)
411// {
412// spu_print("Help! 32 in flags\n");
413// }
414// }
415 DmaData_SPU::putAndWait(m_OutputData.m_tileIds, eaDataOut, outDataSize);
416}
417
418#else
419
420
421void TileCompressData_SPU::setForChunk( Region* region, int x0, int y0, int z0 )
422{
423 m_x0 = x0;
424 m_y0 = y0;
425 m_z0 = z0;
426
427 // we have to grab a 20x20x20 section, so we need 9 chunks in total, the centre chunk and all neighbours in x and z
428 int offsets[3] = {-2, 0, 18};
429 for(int i=0;i<3;i++)
430 {
431 for(int j=0; j<3;j++)
432 {
433 if(y0 <= 127)
434 {
435 LevelChunk* pLevelChunk = region->getLevelChunk(m_x0+offsets[i], 0, m_z0+offsets[j]);
436 if(pLevelChunk && !pLevelChunk->isEmpty())
437 {
438 m_lowerBlocks[i*3+j] = pLevelChunk->lowerBlocks->indicesAndData;
439 m_lowerBlocksSize[i*3+j] = pLevelChunk->lowerBlocks->allocatedSize;
440 m_lowerSkyLight[i*3+j] = pLevelChunk->lowerSkyLight->dataAndCount;
441 m_lowerBlockLight[i*3+j] = pLevelChunk->lowerBlockLight->dataAndCount;
442 m_lowerData[i*3+j] = pLevelChunk->lowerData->dataAndCount;
443 }
444 else
445 {
446 m_lowerBlocks[i*3+j] = NULL;
447 m_lowerBlocksSize[i*3+j] = 0;
448 m_lowerSkyLight[i*3+j] = 0;
449 m_lowerBlockLight[i*3+j] = 0;
450 m_lowerData[i*3+j] = 0;
451 }
452 }
453 if(y0 >= 128)
454 {
455 LevelChunk* pLevelChunk = region->getLevelChunk(m_x0+offsets[i], 128, m_z0+offsets[j]);
456 if(pLevelChunk && !pLevelChunk->isEmpty())
457 {
458 m_upperBlocks[i*3+j] = pLevelChunk->upperBlocks->indicesAndData;
459 m_upperBlocksSize[i*3+j] = pLevelChunk->upperBlocks->allocatedSize;
460 m_upperSkyLight[i*3+j] = pLevelChunk->upperSkyLight->dataAndCount;
461 m_upperBlockLight[i*3+j] = pLevelChunk->upperBlockLight->dataAndCount;
462 m_upperData[i*3+j] = pLevelChunk->upperData->dataAndCount;
463 }
464 else
465 {
466 m_upperBlocks[i*3+j] = NULL;
467 m_upperBlocksSize[i*3+j] = 0;
468 m_upperSkyLight[i*3+j] = 0;
469 m_upperBlockLight[i*3+j] = 0;
470 m_upperData[i*3+j] = 0;
471 }
472 }
473
474 }
475 }
476}
477
478
479
480#endif