mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-19 14:41:29 +02:00
This commit is contained in:
@@ -45,8 +45,8 @@
|
||||
#define BUILD_NUM 350
|
||||
#mesondefine SNAPSHOT_ID
|
||||
#mesondefine MOD_ID
|
||||
#define FUTURE_SAVE_VERSION 96
|
||||
#define FUTURE_MINOR_VERSION 2
|
||||
#define FUTURE_SAVE_VERSION 97
|
||||
#define FUTURE_MINOR_VERSION 0
|
||||
|
||||
#if !(defined(SNAPSHOT) || defined(BETA) || defined(DEBUG) || MOD_ID > 0)
|
||||
#undef FUTURE_SAVE_VERSION
|
||||
|
@@ -1024,7 +1024,7 @@ void GameSave::readOPS(char * data, int dataLength)
|
||||
//Read particle data
|
||||
if (partsData && partsPosData)
|
||||
{
|
||||
int newIndex = 0, fieldDescriptor, tempTemp;
|
||||
int newIndex = 0, tempTemp;
|
||||
int posCount, posTotal, partsPosDataIndex = 0;
|
||||
if (fullW * fullH * 3 > partsPosDataLen)
|
||||
throw ParseException(ParseException::Corrupt, "Not enough particle position data");
|
||||
@@ -1052,8 +1052,8 @@ void GameSave::readOPS(char * data, int dataLength)
|
||||
throw ParseException(ParseException::Corrupt, "Ran past particle data buffer");
|
||||
x = saved_x + fullX;
|
||||
y = saved_y + fullY;
|
||||
fieldDescriptor = partsData[i+1];
|
||||
fieldDescriptor |= partsData[i+2] << 8;
|
||||
unsigned int fieldDescriptor = (unsigned int)(partsData[i+1]);
|
||||
fieldDescriptor |= (unsigned int)(partsData[i+2]) << 8;
|
||||
if (x >= fullW || y >= fullH)
|
||||
throw ParseException(ParseException::Corrupt, "Particle out of range");
|
||||
|
||||
@@ -1092,6 +1092,14 @@ void GameSave::readOPS(char * data, int dataLength)
|
||||
particles[newIndex].temp = tempTemp+294.15f;
|
||||
}
|
||||
|
||||
// fieldDesc3
|
||||
if (fieldDescriptor & 0x8000)
|
||||
{
|
||||
if (i >= partsDataLen)
|
||||
throw ParseException(ParseException::Corrupt, "Ran past particle data buffer while loading third byte of field descriptor");
|
||||
fieldDescriptor |= (unsigned int)(partsData[i++]) << 16;
|
||||
}
|
||||
|
||||
//Read life
|
||||
if(fieldDescriptor & 0x02)
|
||||
{
|
||||
@@ -1194,13 +1202,28 @@ void GameSave::readOPS(char * data, int dataLength)
|
||||
{
|
||||
if (i+3 >= partsDataLen)
|
||||
throw ParseException(ParseException::Corrupt, "Ran past particle data buffer while loading tmp3 and tmp4");
|
||||
if (fieldDescriptor & 0x10000 && i+7 >= partsDataLen)
|
||||
throw ParseException(ParseException::Corrupt, "Ran past particle data buffer while loading high halves of tmp3 and tmp4");
|
||||
unsigned int tmp34;
|
||||
tmp34 = (unsigned int)partsData[i++];
|
||||
tmp34 |= (unsigned int)partsData[i++] << 8;
|
||||
particles[newIndex].tmp3 = tmp34;
|
||||
tmp34 = (unsigned int)partsData[i++];
|
||||
tmp34 |= (unsigned int)partsData[i++] << 8;
|
||||
particles[newIndex].tmp4 = tmp34;
|
||||
tmp34 = (unsigned int)partsData[i + 0];
|
||||
tmp34 |= (unsigned int)partsData[i + 1] << 8;
|
||||
if (fieldDescriptor & 0x10000)
|
||||
{
|
||||
tmp34 |= (unsigned int)partsData[i + 4] << 16;
|
||||
tmp34 |= (unsigned int)partsData[i + 5] << 24;
|
||||
}
|
||||
particles[newIndex].tmp3 = int(tmp34);
|
||||
tmp34 = (unsigned int)partsData[i + 2];
|
||||
tmp34 |= (unsigned int)partsData[i + 3] << 8;
|
||||
if (fieldDescriptor & 0x10000)
|
||||
{
|
||||
tmp34 |= (unsigned int)partsData[i + 6] << 16;
|
||||
tmp34 |= (unsigned int)partsData[i + 7] << 24;
|
||||
}
|
||||
particles[newIndex].tmp4 = int(tmp34);
|
||||
i += 4;
|
||||
if (fieldDescriptor & 0x10000)
|
||||
i += 4;
|
||||
}
|
||||
|
||||
//Particle specific parsing:
|
||||
@@ -2186,14 +2209,21 @@ char * GameSave::serialiseOPS(unsigned int & dataLength)
|
||||
}
|
||||
|
||||
//Copy parts data
|
||||
/* Field descriptor format:
|
||||
| 0 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
| RESERVED | type[2] | tmp3 and tmp4 | tmp[3+4] | tmp2[2] | tmp2 | ctype[2] | vy | vx | decorations | ctype[1] | tmp[2] | tmp[1] | life[2] | life[1] | temp dbl len |
|
||||
/* Field descriptor [1+2] format:
|
||||
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
| fieldDesc3 | type[2] | tmp3/4[1+2] | tmp[3+4] | tmp2[2] | tmp2 | ctype[2] | vy | vx | decorations | ctype[1] | tmp[2] | tmp[1] | life[2] | life[1] | temp dbl len |
|
||||
life[2] means a second byte (for a 16 bit field) if life[1] is present
|
||||
fieldDesc3 means Field descriptor [3] exists
|
||||
Field descriptor [3] format:
|
||||
| 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
|
||||
| RESERVED | FREE | FREE | FREE | FREE | FREE | FREE | tmp3/4[3+4] |
|
||||
last bit is reserved. If necessary, use it to signify that fieldDescriptor will have another byte
|
||||
That way, if we ever need a 17th bit, we won't have to change the save format
|
||||
That way, if we ever need a 25th bit, we won't have to change the save format
|
||||
*/
|
||||
auto partsData = std::unique_ptr<unsigned char[]>(new unsigned char[NPART * (sizeof(Particle)+1)]);
|
||||
|
||||
// Allocate enough space to store all Particles and 3 bytes on top of that per Particle, for the field descriptors.
|
||||
// In practice, a Particle will never need as much space in the save as in memory; this is just an upper bound to simplify allocation.
|
||||
auto partsData = std::unique_ptr<unsigned char[]>(new unsigned char[NPART * (sizeof(Particle)+3)]);
|
||||
unsigned int partsDataLen = 0;
|
||||
auto partsSaveIndex = std::unique_ptr<unsigned[]>(new unsigned[NPART]);
|
||||
unsigned int partsCount = 0;
|
||||
@@ -2210,8 +2240,8 @@ char * GameSave::serialiseOPS(unsigned int & dataLength)
|
||||
//Loop while there is a pmap entry
|
||||
while (i)
|
||||
{
|
||||
unsigned short fieldDesc = 0;
|
||||
int fieldDescLoc = 0, tempTemp, vTemp;
|
||||
unsigned int fieldDesc = 0;
|
||||
int tempTemp, vTemp;
|
||||
|
||||
//Turn pmap entry into a particles index
|
||||
i = i>>8;
|
||||
@@ -2223,9 +2253,22 @@ char * GameSave::serialiseOPS(unsigned int & dataLength)
|
||||
partsData[partsDataLen++] = particles[i].type;
|
||||
|
||||
//Location of the field descriptor
|
||||
fieldDescLoc = partsDataLen++;
|
||||
int fieldDesc3Loc;
|
||||
int fieldDescLoc = partsDataLen++;
|
||||
partsDataLen++;
|
||||
|
||||
auto tmp3 = (unsigned int)(particles[i].tmp3);
|
||||
auto tmp4 = (unsigned int)(particles[i].tmp4);
|
||||
if ((tmp3 || tmp4) && (!PressureInTmp3(particles[i].type) || hasPressure))
|
||||
{
|
||||
fieldDesc |= 1 << 13;
|
||||
if ((tmp3 >> 16) || (tmp4 >> 16))
|
||||
{
|
||||
fieldDesc |= 1 << 15;
|
||||
fieldDesc |= 1 << 16;
|
||||
}
|
||||
}
|
||||
|
||||
// Extra type byte if necessary
|
||||
if (particles[i].type & 0xFF00)
|
||||
{
|
||||
@@ -2249,6 +2292,12 @@ char * GameSave::serialiseOPS(unsigned int & dataLength)
|
||||
partsData[partsDataLen++] = tempTemp >> 8;
|
||||
}
|
||||
|
||||
if (fieldDesc & (1 << 15))
|
||||
{
|
||||
RESTRICTVERSION(97, 0);
|
||||
fieldDesc3Loc = partsDataLen++;
|
||||
}
|
||||
|
||||
//Life (optional), 1 to 2 bytes
|
||||
if(particles[i].life)
|
||||
{
|
||||
@@ -2341,20 +2390,28 @@ char * GameSave::serialiseOPS(unsigned int & dataLength)
|
||||
}
|
||||
|
||||
//tmp3 and tmp4, 4 bytes
|
||||
if ((particles[i].tmp3 || particles[i].tmp4) && (!PressureInTmp3(particles[i].type) || hasPressure))
|
||||
if (fieldDesc & (1 << 13))
|
||||
{
|
||||
auto tmp3 = (unsigned int)(particles[i].tmp3);
|
||||
auto tmp4 = (unsigned int)(particles[i].tmp4);
|
||||
fieldDesc |= 1 << 13;
|
||||
partsData[partsDataLen++] = tmp3 ;
|
||||
partsData[partsDataLen++] = tmp3 >> 8;
|
||||
partsData[partsDataLen++] = tmp4 ;
|
||||
partsData[partsDataLen++] = tmp4 >> 8;
|
||||
if (fieldDesc & (1 << 16))
|
||||
{
|
||||
partsData[partsDataLen++] = tmp3 >> 16;
|
||||
partsData[partsDataLen++] = tmp3 >> 24;
|
||||
partsData[partsDataLen++] = tmp4 >> 16;
|
||||
partsData[partsDataLen++] = tmp4 >> 24;
|
||||
}
|
||||
}
|
||||
|
||||
//Write the field descriptor
|
||||
partsData[fieldDescLoc] = fieldDesc;
|
||||
partsData[fieldDescLoc+1] = fieldDesc>>8;
|
||||
if (fieldDesc & (1 << 15))
|
||||
{
|
||||
partsData[fieldDesc3Loc] = fieldDesc>>16;
|
||||
}
|
||||
|
||||
if (particles[i].type == PT_SOAP)
|
||||
soapCount++;
|
||||
|
Reference in New Issue
Block a user