From b4b4a90f006c4c84d11a7017c2c454c1692c7b24 Mon Sep 17 00:00:00 2001 From: Simon Robertshaw Date: Fri, 30 Dec 2011 19:48:11 +0000 Subject: [PATCH] Almost finished new save format, just signs and thumbnail rendering needed --- includes/graphics.h | 2 - includes/save.h | 6 + src/graphics.c | 192 ------------------- src/save.c | 438 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 429 insertions(+), 209 deletions(-) diff --git a/includes/graphics.h b/includes/graphics.h index 957c16073..dde1c9c6a 100644 --- a/includes/graphics.h +++ b/includes/graphics.h @@ -215,8 +215,6 @@ void dim_copy_pers(pixel *dst, pixel *src); void render_zoom(pixel *img); -pixel *prerender_save(void *save, int size, int *width, int *height); - int render_thumb(void *thumb, int size, int bzip2, pixel *vid_buf, int px, int py, int scl); void render_cursor(pixel *vid, int x, int y, int t, int rx, int ry); diff --git a/includes/save.h b/includes/save.h index 3b4cc7cf2..a9645a07b 100644 --- a/includes/save.h +++ b/includes/save.h @@ -3,15 +3,21 @@ void *build_thumb(int *size, int bzip2); +pixel *prerender_save(void *save, int size, int *width, int *height); + void *build_save(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h, unsigned char bmap[YRES/CELL][XRES/CELL], float vx[YRES/CELL][XRES/CELL], float vy[YRES/CELL][XRES/CELL], float pv[YRES/CELL][XRES/CELL], float fvx[YRES/CELL][XRES/CELL], float fvy[YRES/CELL][XRES/CELL], sign signs[MAXSIGNS], void* partsptr); int parse_save(void *save, int size, int replace, int x0, int y0, unsigned char bmap[YRES/CELL][XRES/CELL], float vx[YRES/CELL][XRES/CELL], float vy[YRES/CELL][XRES/CELL], float pv[YRES/CELL][XRES/CELL], float fvx[YRES/CELL][XRES/CELL], float fvy[YRES/CELL][XRES/CELL], sign signs[MAXSIGNS], void* partsptr, unsigned pmap[YRES][XRES]); +pixel *prerender_save_OPS(void *save, int size, int *width, int *height); + void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h, unsigned char bmap[YRES/CELL][XRES/CELL], float vx[YRES/CELL][XRES/CELL], float vy[YRES/CELL][XRES/CELL], float pv[YRES/CELL][XRES/CELL], float fvx[YRES/CELL][XRES/CELL], float fvy[YRES/CELL][XRES/CELL], sign signs[MAXSIGNS], void* partsptr); int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned char bmap[YRES/CELL][XRES/CELL], float vx[YRES/CELL][XRES/CELL], float vy[YRES/CELL][XRES/CELL], float pv[YRES/CELL][XRES/CELL], float fvx[YRES/CELL][XRES/CELL], float fvy[YRES/CELL][XRES/CELL], sign signs[MAXSIGNS], void* partsptr, unsigned pmap[YRES][XRES]); //Old save parsers, readers +pixel *prerender_save_PSv(void *save, int size, int *width, int *height); + void *build_save_PSv(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h, unsigned char bmap[YRES/CELL][XRES/CELL], float fvx[YRES/CELL][XRES/CELL], float fvy[YRES/CELL][XRES/CELL], sign signs[MAXSIGNS], void* partsptr); int parse_save_PSv(void *save, int size, int replace, int x0, int y0, unsigned char bmap[YRES/CELL][XRES/CELL], float fvx[YRES/CELL][XRES/CELL], float fvy[YRES/CELL][XRES/CELL], sign signs[MAXSIGNS], void* partsptr, unsigned pmap[YRES][XRES]); diff --git a/src/graphics.c b/src/graphics.c index 3a2c85c0b..aa72139b7 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -3485,198 +3485,6 @@ void render_zoom(pixel *img) //draws the zoom box #endif } -//gets the thumbnail preview for stamps -pixel *prerender_save(void *save, int size, int *width, int *height) -{ - unsigned char *d,*c=save; - int i,j,k,x,y,rx,ry,p=0; - int bw,bh,w,h,new_format = 0; - pixel *fb; - - if (size<16) - return NULL; - if (!(c[2]==0x43 && c[1]==0x75 && c[0]==0x66) && !(c[2]==0x76 && c[1]==0x53 && c[0]==0x50)) - return NULL; - if (c[2]==0x43 && c[1]==0x75 && c[0]==0x66) { - new_format = 1; - } - if (c[4]>SAVE_VERSION) - return NULL; - - bw = c[6]; - bh = c[7]; - w = bw*CELL; - h = bh*CELL; - - if (c[5]!=CELL) - return NULL; - - i = (unsigned)c[8]; - i |= ((unsigned)c[9])<<8; - i |= ((unsigned)c[10])<<16; - i |= ((unsigned)c[11])<<24; - d = malloc(i); - if (!d) - return NULL; - fb = calloc(w*h, PIXELSIZE); - if (!fb) - { - free(d); - return NULL; - } - - if (BZ2_bzBuffToBuffDecompress((char *)d, (unsigned *)&i, (char *)(c+12), size-12, 0, 0)) - goto corrupt; - size = i; - - if (size < bw*bh) - goto corrupt; - - k = 0; - for (y=0; y>1)&1; i>1)&1; i>1)&1; i>1)&1; i>1)&1; i>1)&1; i=size) - goto corrupt; - - for (y=0; y= size) - goto corrupt; - j=d[p++]; - if (j0) - { - if (j==PT_STKM || j==PT_STKM2 || j==PT_FIGH) - { - pixel lc, hc=PIXRGB(255, 224, 178); - if (j==PT_STKM || j==PT_FIGH) lc = PIXRGB(255, 255, 255); - else lc = PIXRGB(100, 100, 255); - //only need to check upper bound of y coord - lower bounds and x SAVE_VERSION) + { + return NULL; + } + + //Incompatible cell size + if(inputData[5] > CELL) + { + return NULL; + } + + //Too large/off screen + if(blockW > XRES/CELL || blockH > YRES/CELL) + { + return NULL; + } + *height = fullH; + *width = fullW; + + //Todo: Read and draw particles + + return malloc((fullH * fullW) * sizeof(pixel)); +} + void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h, unsigned char bmap[YRES/CELL][XRES/CELL], float vx[YRES/CELL][XRES/CELL], float vy[YRES/CELL][XRES/CELL], float pv[YRES/CELL][XRES/CELL], float fvx[YRES/CELL][XRES/CELL], float fvy[YRES/CELL][XRES/CELL], sign signs[MAXSIGNS], void* o_partsptr) { particle *partsptr = o_partsptr; @@ -50,17 +101,21 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h //Copy fan and wall data wallData = malloc(blockW*blockH); wallDataLen = blockW*blockH; - fanData = malloc(blockW*blockH); + fanData = malloc((blockW*blockH)*2); fanDataLen = 0; for(x = blockX; x < blockX+blockW; x++) { for(y = blockY; y < blockY+blockH; y++) { - wallData[y*blockW+x] = bmap[y][x]; + wallData[(y-blockY)*blockW+(x-blockX)] = bmap[y][x]; if(bmap[y][x] && !wallDataFound) wallDataFound = 1; if(bmap[y][x]==WL_FAN || bmap[y][x]==4) { + i = (int)(fvx[y][x]*64.0f+127.5f); + if (i<0) i=0; + if (i>255) i=255; + fanData[fanDataLen++] = i; i = (int)(fvy[y][x]*64.0f+127.5f); if (i<0) i=0; if (i>255) i=255; @@ -91,9 +146,9 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h { if(parts[i].type) { - x = (int)(parts[i].x+0.5f); - y = (int)(parts[i].y+0.5f); - if(x >= fullX && x <= fullX+fullW && y >= fullY && y <= fullY+fullH) + x = (int)(parts[i].x+0.5f)-fullX; + y = (int)(parts[i].y+0.5f)-fullY; + if(x >= 0 && x <= fullW && y >= 0 && y <= fullH) { unsigned char fieldDesc = 0; int fieldDescLoc = 0, tempTemp, vTemp; @@ -104,7 +159,6 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h //X and Y coord (required), 2 bytes each partsData[partsDataLen++] = x; partsData[partsDataLen++] = x >> 8; - printf("Saved: %d, %d", (char)x, (char)(x>>8)); partsData[partsDataLen++] = y; partsData[partsDataLen++] = y >> 8; @@ -182,16 +236,19 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h } } } + if(!partsDataLen) + { + free(partsData); + partsData = NULL; + } bson b; bson_init(&b); - /* These fields are in the "outer" header, don't bother saving here - bson_append_int(&b, "majorVersion", SAVE_VERSION); - bson_append_int(&b, "xRes", fullW); - bson_append_int(&b, "yRes", fullH); - bson_append_int(&b, "cellSize", CELL);*/ - //Save stuff like gravity, heat, blah states - bson_append_int(&b, "partsDataBytes", partsDataLen); //For debugging, remove eventually + bson_append_bool(&b, "legacyEnable", legacy_enable); + bson_append_bool(&b, "gravityEnable", ngrav_enable); + bson_append_bool(&b, "paused", sys_pause); + bson_append_int(&b, "gravityMode", gravityMode); + bson_append_int(&b, "airMode", airMode); if(partsData) bson_append_binary(&b, "parts", BSON_BIN_USER, partsData, partsDataLen); if(wallData) @@ -247,8 +304,42 @@ int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned c particle *partsptr = o_partsptr; unsigned char * inputData = save, *bsonData = NULL, *partsData = NULL, *fanData = NULL, *wallData = NULL; int inputDataLen = size, bsonDataLen = 0, partsDataLen, fanDataLen, wallDataLen; - int i, freeIndicesCount, x, y, returnCode = 0; + int i, freeIndicesCount, x, y, returnCode = 0, j; int *freeIndices = NULL; + int blockX, blockY, blockW, blockH, fullX, fullY, fullW, fullH; + + //Block sizes + blockX = x0/CELL; + blockY = y0/CELL; + blockW = inputData[6]; + blockH = inputData[7]; + + //Full size, normalised + fullX = blockX*CELL; + fullY = blockY*CELL; + fullW = blockW*CELL; + fullH = blockH*CELL; + + //From newer version + if(inputData[4] > SAVE_VERSION) + { + fprintf(stderr, "Save from newer version"); + return 2; + } + + //Incompatible cell size + if(inputData[5] > CELL) + { + fprintf(stderr, "Cell size mismatch"); + return 1; + } + + //Too large/off screen + if(blockX+blockW > XRES/CELL || blockY+blockH > YRES/CELL) + { + fprintf(stderr, "Save too large"); + return 1; + } bsonDataLen = ((unsigned)inputData[8]); bsonDataLen |= ((unsigned)inputData[9]) << 8; @@ -263,7 +354,10 @@ int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned c } if (BZ2_bzBuffToBuffDecompress(bsonData, &bsonDataLen, inputData+12, inputDataLen-12, 0, 0)) + { + fprintf(stderr, "Unable to decompress"); return 1; + } bson b; bson_iterator iter; @@ -283,6 +377,127 @@ int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned c fprintf(stderr, "Invalid datatype of particle data: %d[%d] %d[%d] %d[%d]\n", bson_iterator_type(&iter), bson_iterator_type(&iter)==BSON_BINDATA, (unsigned char)bson_iterator_bin_type(&iter), ((unsigned char)bson_iterator_bin_type(&iter))==BSON_BIN_USER, bson_iterator_bin_len(&iter), bson_iterator_bin_len(&iter)>0); } } + else if(strcmp(bson_iterator_key(&iter), "wallMap")==0) + { + if(bson_iterator_type(&iter)==BSON_BINDATA && ((unsigned char)bson_iterator_bin_type(&iter))==BSON_BIN_USER && (wallDataLen = bson_iterator_bin_len(&iter)) > 0) + { + wallData = bson_iterator_bin_data(&iter); + } + else + { + fprintf(stderr, "Invalid datatype of wall data: %d[%d] %d[%d] %d[%d]\n", bson_iterator_type(&iter), bson_iterator_type(&iter)==BSON_BINDATA, (unsigned char)bson_iterator_bin_type(&iter), ((unsigned char)bson_iterator_bin_type(&iter))==BSON_BIN_USER, bson_iterator_bin_len(&iter), bson_iterator_bin_len(&iter)>0); + } + } + else if(strcmp(bson_iterator_key(&iter), "fanMap")==0) + { + if(bson_iterator_type(&iter)==BSON_BINDATA && ((unsigned char)bson_iterator_bin_type(&iter))==BSON_BIN_USER && (fanDataLen = bson_iterator_bin_len(&iter)) > 0) + { + fanData = bson_iterator_bin_data(&iter); + } + else + { + fprintf(stderr, "Invalid datatype of fan data: %d[%d] %d[%d] %d[%d]\n", bson_iterator_type(&iter), bson_iterator_type(&iter)==BSON_BINDATA, (unsigned char)bson_iterator_bin_type(&iter), ((unsigned char)bson_iterator_bin_type(&iter))==BSON_BIN_USER, bson_iterator_bin_len(&iter), bson_iterator_bin_len(&iter)>0); + } + } + else if(strcmp(bson_iterator_key(&iter), "legacyEnable")==0 && replace) + { + if(bson_iterator_type(&iter)==BSON_BOOL) + { + legacy_enable = ((int)bson_iterator_bool(&iter))?1:0; + } + else + { + fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter)); + } + } + else if(strcmp(bson_iterator_key(&iter), "gravityEnable")==0 && replace) + { + if(bson_iterator_type(&iter)==BSON_BOOL) + { + int tempGrav = ngrav_enable; + tempGrav = ((int)bson_iterator_bool(&iter))?1:0; +#ifndef RENDERER + //Change the gravity state + if(ngrav_enable != tempGrav) + { + if(tempGrav) + start_grav_async(); + else + stop_grav_async(); + } +#endif + } + else + { + fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter)); + } + } + else if(strcmp(bson_iterator_key(&iter), "paused")==0 && !sys_pause) + { + if(bson_iterator_type(&iter)==BSON_BOOL) + { + sys_pause = ((int)bson_iterator_bool(&iter))?1:0; + } + else + { + fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter)); + } + } + else if(strcmp(bson_iterator_key(&iter), "gravityMode")==0 && replace) + { + if(bson_iterator_type(&iter)==BSON_INT) + { + gravityMode = bson_iterator_int(&iter); + } + else + { + fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter)); + } + } + else if(strcmp(bson_iterator_key(&iter), "airMode")==0 && replace) + { + if(bson_iterator_type(&iter)==BSON_INT) + { + airMode = bson_iterator_int(&iter); + } + else + { + fprintf(stderr, "Wrong type for %s\n", bson_iterator_key(&iter)); + } + } + } + + if(replace) + { + //Remove everything + clear_sim(); + } + + //Read wall and fan data + if(wallData) + { + j = 0; + if(blockW * blockH > wallDataLen) + { + fprintf(stderr, "Not enough wall data"); + goto fail; + } + for(x = 0; x < blockW; x++) + { + for(y = 0; y < blockH; y++) + { + bmap[blockY+y][blockX+x] = wallData[y*blockW+x]; + if((bmap[blockY+y][blockX+x]==WL_FAN || bmap[blockY+y][blockX+x]==4) && fanData) + { + if(j+1 >= fanDataLen) + { + fprintf(stderr, "Not enough fan data"); + } + fvx[blockY+y][blockX+x] = (fanData[j++]-127.0f)/64.0f; + fvy[blockY+y][blockX+x] = (fanData[j++]-127.0f)/64.0f; + } + } + } } //Read particle data @@ -311,6 +526,8 @@ int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned c { x = partsData[i+1] | (((unsigned)partsData[i+2])<<8); y = partsData[i+3] | (((unsigned)partsData[i+4])<<8); + x += fullX; + y += fullY; fieldDescriptor = partsData[i+7]; if(x >= XRES || x < 0 || y >= YRES || y < 0) { @@ -416,7 +633,198 @@ fin: return returnCode; } -//the old saving function +//Old saving +pixel *prerender_save_PSv(void *save, int size, int *width, int *height) +{ + unsigned char *d,*c=save; + int i,j,k,x,y,rx,ry,p=0; + int bw,bh,w,h,new_format = 0; + pixel *fb; + + if (size<16) + return NULL; + if (!(c[2]==0x43 && c[1]==0x75 && c[0]==0x66) && !(c[2]==0x76 && c[1]==0x53 && c[0]==0x50)) + return NULL; + if (c[2]==0x43 && c[1]==0x75 && c[0]==0x66) { + new_format = 1; + } + if (c[4]>SAVE_VERSION) + return NULL; + + bw = c[6]; + bh = c[7]; + w = bw*CELL; + h = bh*CELL; + + if (c[5]!=CELL) + return NULL; + + i = (unsigned)c[8]; + i |= ((unsigned)c[9])<<8; + i |= ((unsigned)c[10])<<16; + i |= ((unsigned)c[11])<<24; + d = malloc(i); + if (!d) + return NULL; + fb = calloc(w*h, PIXELSIZE); + if (!fb) + { + free(d); + return NULL; + } + + if (BZ2_bzBuffToBuffDecompress((char *)d, (unsigned *)&i, (char *)(c+12), size-12, 0, 0)) + goto corrupt; + size = i; + + if (size < bw*bh) + goto corrupt; + + k = 0; + for (y=0; y>1)&1; i>1)&1; i>1)&1; i>1)&1; i>1)&1; i>1)&1; i=size) + goto corrupt; + + for (y=0; y= size) + goto corrupt; + j=d[p++]; + if (j0) + { + if (j==PT_STKM || j==PT_STKM2 || j==PT_FIGH) + { + pixel lc, hc=PIXRGB(255, 224, 178); + if (j==PT_STKM || j==PT_FIGH) lc = PIXRGB(255, 255, 255); + else lc = PIXRGB(100, 100, 255); + //only need to check upper bound of y coord - lower bounds and x