16bit descriptor and variable temp field size, sign saving and reading

This commit is contained in:
Simon Robertshaw 2011-12-31 18:57:42 +00:00
parent 8a2be10598
commit b1aaa32116

View File

@ -86,7 +86,7 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
int partsDataLen, partsPosDataLen, fanDataLen, wallDataLen, finalDataLen, outputDataLen; int partsDataLen, partsPosDataLen, fanDataLen, wallDataLen, finalDataLen, outputDataLen;
int blockX, blockY, blockW, blockH, fullX, fullY, fullW, fullH; int blockX, blockY, blockW, blockH, fullX, fullY, fullW, fullH;
int x, y, i, wallDataFound = 0; int x, y, i, wallDataFound = 0;
int posCount; int posCount, signsCount;
//Get coords in blocks //Get coords in blocks
blockX = orig_x0/CELL; blockX = orig_x0/CELL;
@ -191,8 +191,8 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
//Copy parts data //Copy parts data
/* Field descriptor format: /* Field descriptor format:
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| vy | vx | dcololour | ctype | tmp[2] | tmp[1] | life[2] | life[1] | | vy | vx | dcololour | ctype | 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 life[2] means a second byte (for a 16 bit field) if life[1] is present
*/ */
partsData = malloc(NPART * (sizeof(particle)+1)); partsData = malloc(NPART * (sizeof(particle)+1));
@ -207,7 +207,7 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
//Loop while there is a pmap entry //Loop while there is a pmap entry
while (i) while (i)
{ {
unsigned char fieldDesc = 0; unsigned short fieldDesc = 0;
int fieldDescLoc = 0, tempTemp, vTemp; int fieldDescLoc = 0, tempTemp, vTemp;
//Turn pmap entry into a partsptr index //Turn pmap entry into a partsptr index
@ -216,22 +216,33 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
//Type (required) //Type (required)
partsData[partsDataLen++] = partsptr[i].type; partsData[partsDataLen++] = partsptr[i].type;
//Temperature (required), 2 bytes
tempTemp = partsptr[i].temp;
partsData[partsDataLen++] = tempTemp;
partsData[partsDataLen++] = tempTemp >> 8;
//Location of the field descriptor //Location of the field descriptor
fieldDescLoc = partsDataLen++; fieldDescLoc = partsDataLen++;
partsDataLen++;
//Extra Temperature (2nd byte optional, 1st required), 1 to 2 bytes
//Store temperature as an offset of 21C(294.15K) or go into a 16byte int and store the whole thing
if(fabs(partsptr[i].temp-294.15f)<127)
{
tempTemp = (partsptr[i].temp-294.15f);
partsData[partsDataLen++] = tempTemp;
}
else
{
fieldDesc |= 1;
tempTemp = partsptr[i].temp;
partsData[partsDataLen++] = tempTemp;
partsData[partsDataLen++] = tempTemp >> 8;
}
//Life (optional), 1 to 2 bytes //Life (optional), 1 to 2 bytes
if(partsptr[i].life) if(partsptr[i].life)
{ {
fieldDesc |= 1; fieldDesc |= 1 << 1;
partsData[partsDataLen++] = partsptr[i].life; partsData[partsDataLen++] = partsptr[i].life;
if(partsptr[i].life > 255) if(partsptr[i].life > 255)
{ {
fieldDesc |= 1 << 1; fieldDesc |= 1 << 2;
partsData[partsDataLen++] = partsptr[i].life >> 8; partsData[partsDataLen++] = partsptr[i].life >> 8;
} }
} }
@ -239,11 +250,11 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
//Tmp (optional), 1 to 2 bytes //Tmp (optional), 1 to 2 bytes
if(partsptr[i].tmp) if(partsptr[i].tmp)
{ {
fieldDesc |= 1 << 2; fieldDesc |= 1 << 3;
partsData[partsDataLen++] = partsptr[i].tmp; partsData[partsDataLen++] = partsptr[i].tmp;
if(partsptr[i].tmp > 255) if(partsptr[i].tmp > 255)
{ {
fieldDesc |= 1 << 3; fieldDesc |= 1 << 4;
partsData[partsDataLen++] = partsptr[i].tmp >> 8; partsData[partsDataLen++] = partsptr[i].tmp >> 8;
} }
} }
@ -251,14 +262,14 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
//Ctype (optional), 1 byte //Ctype (optional), 1 byte
if(partsptr[i].ctype) if(partsptr[i].ctype)
{ {
fieldDesc |= 1 << 4; fieldDesc |= 1 << 5;
partsData[partsDataLen++] = partsptr[i].ctype; partsData[partsDataLen++] = partsptr[i].ctype;
} }
//Dcolour (optional), 4 bytes //Dcolour (optional), 4 bytes
if(partsptr[i].dcolour && (partsptr[i].dcolour & 0xFF000000)) if(partsptr[i].dcolour && (partsptr[i].dcolour & 0xFF000000))
{ {
fieldDesc |= 1 << 5; fieldDesc |= 1 << 6;
partsData[partsDataLen++] = (partsptr[i].dcolour&0xFF000000)>>24; partsData[partsDataLen++] = (partsptr[i].dcolour&0xFF000000)>>24;
partsData[partsDataLen++] = (partsptr[i].dcolour&0x00FF0000)>>16; partsData[partsDataLen++] = (partsptr[i].dcolour&0x00FF0000)>>16;
partsData[partsDataLen++] = (partsptr[i].dcolour&0x0000FF00)>>8; partsData[partsDataLen++] = (partsptr[i].dcolour&0x0000FF00)>>8;
@ -268,7 +279,7 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
//VX (optional), 1 byte //VX (optional), 1 byte
if(fabs(partsptr[i].vx) > 0.001f) if(fabs(partsptr[i].vx) > 0.001f)
{ {
fieldDesc |= 1 << 6; fieldDesc |= 1 << 7;
vTemp = (int)(partsptr[i].vx*16.0f+127.5f); vTemp = (int)(partsptr[i].vx*16.0f+127.5f);
if (vTemp<0) vTemp=0; if (vTemp<0) vTemp=0;
if (vTemp>255) vTemp=255; if (vTemp>255) vTemp=255;
@ -278,7 +289,7 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
//VY (optional), 1 byte //VY (optional), 1 byte
if(fabs(partsptr[i].vy) > 0.001f) if(fabs(partsptr[i].vy) > 0.001f)
{ {
fieldDesc |= 1 << 7; fieldDesc |= 1 << 8;
vTemp = (int)(partsptr[i].vy*16.0f+127.5f); vTemp = (int)(partsptr[i].vy*16.0f+127.5f);
if (vTemp<0) vTemp=0; if (vTemp<0) vTemp=0;
if (vTemp>255) vTemp=255; if (vTemp>255) vTemp=255;
@ -287,6 +298,7 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
//Write the field descriptor; //Write the field descriptor;
partsData[fieldDescLoc] = fieldDesc; partsData[fieldDescLoc] = fieldDesc;
partsData[fieldDescLoc+1] = fieldDesc>>8;
//Get the pmap entry for the next particle in the same position //Get the pmap entry for the next particle in the same position
i = partsPosLink[i]; i = partsPosLink[i];
@ -314,6 +326,31 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
bson_append_binary(&b, "wallMap", BSON_BIN_USER, wallData, wallDataLen); bson_append_binary(&b, "wallMap", BSON_BIN_USER, wallData, wallDataLen);
if(fanData) if(fanData)
bson_append_binary(&b, "fanMap", BSON_BIN_USER, fanData, fanDataLen); bson_append_binary(&b, "fanMap", BSON_BIN_USER, fanData, fanDataLen);
signsCount = 0;
for(i = 0; i < MAXSIGNS; i++)
{
if(signs[i].text[0] && signs[i].x>=fullX && signs[i].x<=fullX+fullW && signs[i].y>=fullY && signs[i].y<=fullY+fullH)
{
signsCount++;
}
}
if(signsCount)
{
bson_append_start_array(&b, "signs");
for(i = 0; i < MAXSIGNS; i++)
{
if(signs[i].text[0] && signs[i].x>=fullX && signs[i].x<=fullX+fullW && signs[i].y>=fullY && signs[i].y<=fullY+fullH)
{
bson_append_start_object(&b, "sign");
bson_append_string(&b, "text", signs[i].text);
bson_append_int(&b, "justification", signs[i].ju);
bson_append_int(&b, "x", signs[i].x-fullX);
bson_append_int(&b, "y", signs[i].y-fullY);
bson_append_finish_object(&b);
}
}
}
bson_append_finish_array(&b);
bson_finish(&b); bson_finish(&b);
bson_print(&b); bson_print(&b);
@ -422,14 +459,77 @@ int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned c
return 1; return 1;
} }
if(replace)
{
//Remove everything
clear_sim();
}
bson b; bson b;
bson_iterator iter; bson_iterator iter;
bson_init_data(&b, bsonData); bson_init_data(&b, bsonData);
bson_iterator_init(&iter, &b); bson_iterator_init(&iter, &b);
while(bson_iterator_more(&iter)) while(bson_iterator_next(&iter))
{ {
bson_iterator_next(&iter); if(strcmp(bson_iterator_key(&iter), "signs")==0)
if(strcmp(bson_iterator_key(&iter), "parts")==0) {
if(bson_iterator_type(&iter)==BSON_ARRAY)
{
bson_iterator subiter;
bson_iterator_subiterator(&iter, &subiter);
while(bson_iterator_next(&subiter))
{
if(strcmp(bson_iterator_key(&subiter), "sign")==0)
{
if(bson_iterator_type(&subiter)==BSON_OBJECT)
{
bson_iterator signiter;
bson_iterator_subiterator(&subiter, &signiter);
//Find a free sign ID
for (i = 0; i < MAXSIGNS; i++)
if (!signs[i].text[0])
break;
//Stop reading signs if we have no free spaces
if(i >= MAXSIGNS)
break;
while(bson_iterator_next(&signiter))
{
if(strcmp(bson_iterator_key(&signiter), "text")==0 && bson_iterator_type(&signiter)==BSON_STRING)
{
strcpy(signs[i].text, bson_iterator_string(&signiter));
clean_text(signs[i].text, 158-14);
}
else if(strcmp(bson_iterator_key(&signiter), "justification")==0 && bson_iterator_type(&signiter)==BSON_INT)
{
signs[i].ju = bson_iterator_int(&signiter);
}
else if(strcmp(bson_iterator_key(&signiter), "x")==0 && bson_iterator_type(&signiter)==BSON_INT)
{
signs[i].x = bson_iterator_int(&signiter)+fullX;
}
else if(strcmp(bson_iterator_key(&signiter), "y")==0 && bson_iterator_type(&signiter)==BSON_INT)
{
signs[i].y = bson_iterator_int(&signiter)+fullY;
}
else
{
fprintf(stderr, "Unknown sign property %s\n", bson_iterator_key(&signiter));
}
}
}
else
{
fprintf(stderr, "Wrong type for \n", bson_iterator_key(&subiter));
}
}
}
}
else
{
fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter));
}
}
else if(strcmp(bson_iterator_key(&iter), "parts")==0)
{ {
if(bson_iterator_type(&iter)==BSON_BINDATA && ((unsigned char)bson_iterator_bin_type(&iter))==BSON_BIN_USER && (partsDataLen = bson_iterator_bin_len(&iter)) > 0) if(bson_iterator_type(&iter)==BSON_BINDATA && ((unsigned char)bson_iterator_bin_type(&iter))==BSON_BIN_USER && (partsDataLen = bson_iterator_bin_len(&iter)) > 0)
{ {
@ -541,12 +641,6 @@ int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned c
} }
} }
if(replace)
{
//Remove everything
clear_sim();
}
//Read wall and fan data //Read wall and fan data
if(wallData) if(wallData)
{ {
@ -580,7 +674,6 @@ int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned c
int newIndex = 0, fieldDescriptor, tempTemp; int newIndex = 0, fieldDescriptor, tempTemp;
int posCount, posTotal, partsPosDataIndex = 0; int posCount, posTotal, partsPosDataIndex = 0;
int saved_x, saved_y; int saved_x, saved_y;
puts("Have particle data");
if(fullW * fullH * 3 > partsPosDataLen) if(fullW * fullH * 3 > partsPosDataLen)
{ {
fprintf(stderr, "Not enough particle position data"); fprintf(stderr, "Not enough particle position data");
@ -614,12 +707,13 @@ int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned c
//Put the next posTotal particles at this position //Put the next posTotal particles at this position
for (posCount=0; posCount<posTotal; posCount++) for (posCount=0; posCount<posTotal; posCount++)
{ {
//i+3 because we have 4 bytes of required fields (type (1), temp (2), descriptor (1)) //i+3 because we have 4 bytes of required fields (type (1), descriptor (2), temp (1))
if (i+3 >= partsDataLen) if (i+3 >= partsDataLen)
goto fail; goto fail;
x = saved_x + fullX; x = saved_x + fullX;
y = saved_y + fullY; y = saved_y + fullY;
fieldDescriptor = partsData[i+3]; fieldDescriptor = partsData[i+1];
fieldDescriptor |= partsData[i+2] << 8;
if(x >= XRES || x < 0 || y >= YRES || y < 0) if(x >= XRES || x < 0 || y >= YRES || y < 0)
{ {
fprintf(stderr, "Out of range [%d]: %d %d, [%d, %d], [%d, %d]\n", i, x, y, (unsigned)partsData[i+1], (unsigned)partsData[i+2], (unsigned)partsData[i+3], (unsigned)partsData[i+4]); fprintf(stderr, "Out of range [%d]: %d %d, [%d, %d], [%d, %d]\n", i, x, y, (unsigned)partsData[i+1], (unsigned)partsData[i+2], (unsigned)partsData[i+3], (unsigned)partsData[i+4]);
@ -652,16 +746,30 @@ int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned c
partsptr[newIndex].type = partsData[i]; partsptr[newIndex].type = partsData[i];
partsptr[newIndex].x = x; partsptr[newIndex].x = x;
partsptr[newIndex].y = y; partsptr[newIndex].y = y;
partsptr[newIndex].temp = (partsData[i+1] | (partsData[i+2]<<8)); i+=3;
i+=4;
//Read temp
if(fieldDescriptor & 0x01)
{
//Full 16bit int
tempTemp = partsData[i++];
tempTemp |= (((unsigned)partsData[i++]) << 8);
partsptr[newIndex].temp = tempTemp;
}
else
{
//1 Byte room temp offset
tempTemp = (char)partsData[i++];
partsptr[newIndex].temp = tempTemp+294.15f;
}
//Read life //Read life
if(fieldDescriptor & 0x01) if(fieldDescriptor & 0x02)
{ {
if(i >= partsDataLen) goto fail; if(i >= partsDataLen) goto fail;
partsptr[newIndex].life = partsData[i++]; partsptr[newIndex].life = partsData[i++];
//Read 2nd byte //Read 2nd byte
if(fieldDescriptor & 0x02) if(fieldDescriptor & 0x04)
{ {
if(i >= partsDataLen) goto fail; if(i >= partsDataLen) goto fail;
partsptr[newIndex].life |= partsData[i++]; partsptr[newIndex].life |= partsData[i++];
@ -669,12 +777,12 @@ int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned c
} }
//Read tmp //Read tmp
if(fieldDescriptor & 0x04) if(fieldDescriptor & 0x08)
{ {
if(i >= partsDataLen) goto fail; if(i >= partsDataLen) goto fail;
partsptr[newIndex].tmp = partsData[i++]; partsptr[newIndex].tmp = partsData[i++];
//Read 2nd byte //Read 2nd byte
if(fieldDescriptor & 0x08) if(fieldDescriptor & 0x10)
{ {
if(i >= partsDataLen) goto fail; if(i >= partsDataLen) goto fail;
partsptr[newIndex].tmp |= partsData[i++]; partsptr[newIndex].tmp |= partsData[i++];
@ -682,31 +790,31 @@ int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned c
} }
//Read ctype //Read ctype
if(fieldDescriptor & 0x10) if(fieldDescriptor & 0x20)
{ {
if(i >= partsDataLen) goto fail; if(i >= partsDataLen) goto fail;
partsptr[newIndex].ctype = partsData[i++]; partsptr[newIndex].ctype = partsData[i++];
} }
//Read dcolour //Read dcolour
if(fieldDescriptor & 0x20) if(fieldDescriptor & 0x40)
{ {
if(i+3 >= partsDataLen) goto fail; if(i+3 >= partsDataLen) goto fail;
partsptr[newIndex].dcolour = partsData[i++]; partsptr[newIndex].dcolour = partsData[i++];
partsptr[newIndex].dcolour = partsData[i++]; partsptr[newIndex].dcolour |= partsData[i++]<<8;
partsptr[newIndex].dcolour = partsData[i++]; partsptr[newIndex].dcolour |= partsData[i++]<<16;
partsptr[newIndex].dcolour = partsData[i++]; partsptr[newIndex].dcolour |= partsData[i++]<<24;
} }
//Read vx //Read vx
if(fieldDescriptor & 0x40) if(fieldDescriptor & 0x80)
{ {
if(i >= partsDataLen) goto fail; if(i >= partsDataLen) goto fail;
partsptr[newIndex].vx = (partsData[i++]-127.0f)/16.0f; partsptr[newIndex].vx = (partsData[i++]-127.0f)/16.0f;
} }
//Read vy //Read vy
if(fieldDescriptor & 0x80) if(fieldDescriptor & 0x100)
{ {
if(i >= partsDataLen) goto fail; if(i >= partsDataLen) goto fail;
partsptr[newIndex].vy = (partsData[i++]-127.0f)/16.0f; partsptr[newIndex].vy = (partsData[i++]-127.0f)/16.0f;