21 Dec 11, 03:27AM
Hello.
I have been reading into the map file (.cgz) format. Using a combo of conoutf, and a hex reader, I have been deciphering the map file format and how it records data. I know there is two levels of compression, and am working with un-gzipped files.
In the data section, after the header, it records the cubes. My question stems from the compression. It uses 225 to signify that cube is the same as the cube before. How does it determine how many cubes are the same? For instance, as viewed in a hex viewer, this is the first two different kinds of cubes, however by my calculations, there should 519 "FF"s, however it obviously uses some kind of maths to reduce it down to 5.
The 09 isn't part of the next cube, so I think it must factor into the math. Can I get some hint to how it does this? I am not the best at C++, so that is hindering the process a little.
Here is some of the relevant parts of the code.
bool load_world (worldio.cpp):
void save_world (worldio.cpp)
I have been reading into the map file (.cgz) format. Using a combo of conoutf, and a hex reader, I have been deciphering the map file format and how it records data. I know there is two levels of compression, and am working with un-gzipped files.
In the data section, after the header, it records the cubes. My question stems from the compression. It uses 225 to signify that cube is the same as the cube before. How does it determine how many cubes are the same? For instance, as viewed in a hex viewer, this is the first two different kinds of cubes, however by my calculations, there should 519 "FF"s, however it obviously uses some kind of maths to reduce it down to 5.
[SELECT ALL] Code:
00 02 00 FF FF FF FF FF 09 04 00 10 02 03 04 00 02 00
The 09 isn't part of the next cube, so I think it must factor into the math. Can I get some hint to how it does this? I am not the best at C++, so that is hindering the process a little.
Here is some of the relevant parts of the code.
bool load_world (worldio.cpp):
[SELECT ALL] Code:
loopk(cubicsize)
{
char *c = mlayout + k;
sqr *s = &world[k];
int type = f ? f->getchar() : -1;
int n = 1;
switch(type)
{
case -1:
{
if(f)
{
conoutf("while reading map at %d: type %d out of range", k, type);
delete f;
f = NULL;
}
*c = 127;
s->type = SOLID;
s->ftex = DEFAULT_FLOOR;
s->ctex = DEFAULT_CEIL;
s->wtex = s->utex = DEFAULT_WALL;
s->tag = 0;
s->floor = 0;
s->ceil = 16;
s->vdelta = 0;
break;
}
case 255:
{
if(!t || (n = f->getchar()) < 0) { delete f; f = NULL; k--; continue; }
char tmp = *(c-1);
memset(c, tmp, n);
for(int i = 0; i<n; i++, k++) memcpy(&world[k], t, sizeof(sqr));
k--;
break;
}
case 254: // only in MAPVERSION<=2
{
if(!t) { delete f; f = NULL; k--; continue; }
*c = *(c-1);
memcpy(s, t, sizeof(sqr));
s->r = s->g = s->b = f->getchar();
f->getchar();
break;
}
case SOLID:
{
*c = 127;
s->type = SOLID;
s->wtex = f->getchar();
s->vdelta = f->getchar();
if(hdr.version<=2) { f->getchar(); f->getchar(); }
s->ftex = DEFAULT_FLOOR;
s->ctex = DEFAULT_CEIL;
s->utex = s->wtex;
s->tag = 0;
s->floor = 0;
s->ceil = 16;
break;
}
default:
{
if(type<0 || type>=MAXTYPE)
{
conoutf("while reading map at %d: type %d out of range", k, type);
delete f;
f = NULL;
k--;
continue;
}
s->type = type;
s->floor = f->getchar();
s->ceil = f->getchar();
if(s->floor>=s->ceil) s->floor = s->ceil-1; // for pre 12_13
diff = s->ceil - s->floor;
*c = s->floor; // FIXME
s->wtex = f->getchar();
s->ftex = f->getchar();
s->ctex = f->getchar();
if(hdr.version<=2) { f->getchar(); f->getchar(); }
s->vdelta = f->getchar();
s->utex = (hdr.version>=2) ? f->getchar() : s->wtex;
s->tag = (hdr.version>=5) ? f->getchar() : 0;
}
}
if ( type != SOLID && diff > 6 )
{
Ma += n;
Mv += diff * n;
}
s->defer = 0;
t = s;
texuse[s->wtex] = 1;
if(!SOLID(s)) texuse[s->utex] = texuse[s->ftex] = texuse[s->ctex] = 1;
}
void save_world (worldio.cpp)
[SELECT ALL] Code:
sqr *t = NULL;
int sc = 0;
#define spurge while(sc) { f->putchar(255); if(sc>255) { f->putchar(255); sc -= 255; } else { f->putchar(sc); sc = 0; } }
loopk(cubicsize)
{
sqr *s = &world[k];
#define c(f) (s->f==t->f)
// 4 types of blocks, to compress a bit:
// 255 (2): same as previous block + count
// 254 (3): same as previous, except light // deprecated
// SOLID (5)
// anything else (9)
if(SOLID(s))
{
if(t && c(type) && c(wtex) && c(vdelta))
{
sc++;
}
else
{
spurge;
f->putchar(s->type);
f->putchar(s->wtex);
f->putchar(s->vdelta);
}
}
else
{
if(t && c(type) && c(floor) && c(ceil) && c(ctex) && c(ftex) && c(utex) && c(wtex) && c(vdelta) && c(tag))
{
sc++;
}
else
{
spurge;
f->putchar(s->type);
f->putchar(s->floor);
f->putchar(s->ceil);
f->putchar(s->wtex);
f->putchar(s->ftex);
f->putchar(s->ctex);
f->putchar(s->vdelta);
f->putchar(s->utex);
f->putchar(s->tag);
}
}
t = s;
}
spurge;
delete f;
conoutf("wrote map file %s", cgzname);