Jump to content
  • Advertisement
Sign in to follow this  
Plasmarobo

ogzstream failures

This topic is 2896 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Alright, so some of you may have heard of the popular game Minecraft.
The map files use a named-binary-tag format that is gzipped with zlib.
I'm a windows programmer and a C++ programmer, so naturally I am working with the self-built zlib using gzstream. My problem is that it doesn't work.

The code compiles beautifully, but even when fed a known valid gz file (tested via 7zip), it returns a true bad() call. I've tried every file path combination I can think of, relative, absolute, drive-root, and I simply cannot get this thing to work.

I could use some help on this one, I'll post my code, but really, I need a starting point. Others on the internet have had similar problems, but as far as I know gzstream support is limited, and most people seem to be programming in straight-up C.

So here are the files in this order:

<MCmapper.h>
<MCmapper.cpp>
<nbtdef.h>
<nbtdef.cpp>
#ifndef _MCMAPPER_H_
#define _MCMAPPER_H_
//#include <wx/dir.h>
#include "nbtdef.h"
//#include <string>


//DATA MAPPINGS

enum blocks{
air = 0,
stone,
grass,
dirt,
cobble,
board,
sapling,
bedrock,
water1,
water2,
lava1,
lava2,
sand,
shale,
gold,
iron,
coal,
wood,
leaf,
sponge,
glass,
c_r, c_o, c_y, c_l, c_g, c_ag, c_cy, c_b, c_p, c_in, c_vi, c_ma, c_pi, c_bl, c_gr, c_w,
f_y, f_r,
m_b, m_r,
gold_b,
iron_b,
dstep,
step,
brick,
tnt,
shelf,
moss,
obsidian,
torch,
fire,
mod,
stair_w,
chest,
wire,
diamond,
diamond_b,
workbench,
crops,
soil,
furnace,
furnace_b,
sign,
door,
ladder,
rail,
stairs_s,
sign_w,
lever,
plate_s,
door_i,
redstone,
redstone_g,
torch_r,
torch_r_o,
button,
snow,
ice,
snow_b,
cactus,
clay,
reed,
phonograph,
fence,
pumpkin,
netherstone,
slow,
lightstone,
portal,
jac_o_lantern
};


class CHUNK{
protected:
int x;
int z;
short blocks[16][16][128]; //X, Z, Y
public:
CHUNK();

};

void EnumerateChunks(std::string filename);

#endif



// MCmapper.cpp : Defines the entry point for the console application.
//#
#include <wx/dir.h>
#include <wx/filefn.h>
#include <wx/arrstr.h>
#include "MCmapper.h"
void EnumerateChunks(std::string fname, wxArrayString &files, size_t &sz){
wxDir dir(wxGetCwd());
if(!dir.IsOpened()){
return;
}
//Enumerate files in directory
wxString filename(fname.c_str(), wxConvUTF8);
if(!dir.Open(filename))
return;
sz = dir.GetAllFiles(filename,&files);
//We now have every chunk file in the string array. We need to open each file
//read the chunk data and build the surface array
//for(int i = 0; i < sz-2; i++){
// std::cout << std::string(files.mb_str()) << std::endl;
//}
//char a;
//std::cin >> a;

}

void NBTDUMP(wxString file, size_t sz, std::string fileout){
//READ THE FILE WITH AN NBT FILE
char buf[1024];//MAX 1024 length
strcpy(buf,(const char*) file.mb_str(wxConvUTF8));
std::string str(buf);
nbt_file f;
//f.ReadFile(buf);
f.ReadFile(buf);
std::ofstream files;
files.open(fileout.c_str());
if(files.is_open()){
//Begin dump
std::string str;
for(std::vector<nbt_tag>::iterator iter = f.Begin(); iter != f.End(); ++iter){
//For every tag, print it's string
//files << TypeToString(iter->GetType()) << std::endl;
switch (iter->GetType())
{
case nbt_type::TAG_END:
str = "TAG_END";
break;

case nbt_type::TAG_BYTE:
str = "TAG_BYTE";
break;

case nbt_type::TAG_SHORT:
str = "TAG_SHORT";
break;

case nbt_type::TAG_INT:
str = "TAG_INT";
break;

case nbt_type::TAG_LONG:
str = "TAG_LONG";
break;

case nbt_type::TAG_FLOAT:
str = "TAG_FLOAT";
break;

case nbt_type::TAG_DOUBLE:
str = "TAG_DOUBLE";
break;

case nbt_type::TAG_BYTE_ARRAY:
str = "TAG_BYTE_ARRAY";
break;

case nbt_type::TAG_STRING:
str = "TAG_STRING";
break;

case nbt_type::TAG_LIST:
str = "TAG_LIST";
break;

case nbt_type::TAG_COMPOUND:
str = "TAG_COMPOUND";
break;

default:
str = "TAG_Unknown";
break;
}
files << str << std::endl;
}
files.close();

}

}

void ExtractChunk(wxArrayString files, size_t sz, CHUNK** data){



};


int main(int argc, char* argv[])
{
wxArrayString files;
size_t s;
EnumerateChunks("world",files, s);
NBTDUMP(files[0],s,"dump.txt");
return 0;
}




#ifndef NBTDEF_H_
#define NBTDEF_H_
#include <cstdint>
//#define ZLIB_WINAPI
#include "gzstream.h"

#include <string>
#include <list>
#include <vector>
//#include "endianness.h"

#define L_ENDIAN 0
#define B_ENDIAN 1

int get_endianness();

uint64_t swpd(double d);
double uswpd(uint64_t d);

float swapf(float);
double swapd(double);
void swaps(uint16_t *x);
void swapi(uint32_t *x);
void swapl(uint64_t *x);

enum nbt_status
{
NBT_OK = 0,
NBT_ERR = -1,
NBT_EMEM = -2,
NBT_EGZ = -3

};

enum nbt_type
{
TAG_END = 0, /* No name, no payload */
TAG_BYTE = 1, /* char, 8 bits, signed */
TAG_SHORT = 2, /* short, 16 bits, signed */
TAG_INT = 3, /* long, 32 bits, signed */
TAG_LONG = 4, /* long long, 64 bits, signed */
TAG_FLOAT = 5, /* float, 32 bits, signed */
TAG_DOUBLE = 6, /* double, 64 bits, signed */
TAG_BYTE_ARRAY = 7, /* char *, 8 bits, unsigned, TAG_INT length */
TAG_STRING = 8, /* char *, 8 bits, signed, TAG_SHORT length */
TAG_LIST = 9, /* X *, X bits, TAG_INT length, no names inside */
TAG_COMPOUND = 10 /* nbt_tag * */

};
//std::string TypeToString(nbt_type t);

class nbt_tag
{
protected:
//THIS IS A TEMPLATE
nbt_type type; /* Type of the value */
std::string name; /* tag name */
void *value;
public:
nbt_tag();
nbt_tag(nbt_type t);
nbt_tag(nbt_type t, std::string n, void *v);
nbt_tag(const nbt_tag &rhs);
~nbt_tag();
void* GetValue();
nbt_type GetType();
void SetType(nbt_type t);
void SetName(std::string n);
std::string GetName();
void SetValue(void *v);
void SwapEndian();
};

class nbt_byte_array
{
protected:
int32_t length;
unsigned char *content;
public:
nbt_byte_array();
nbt_byte_array(int32_t l, unsigned char *c);
nbt_byte_array(const nbt_byte_array &rhs);
~nbt_byte_array();
int32_t Size();
unsigned char *Get();
};
template <typename T>
int nbt_read_tag(igzstream &fs, nbt_tag &t);


class nbt_file{
protected:
int _Read(igzstream &fs, char &t, nbt_tag &tg);
std::vector<nbt_tag> tags;
public:
nbt_file();
nbt_file(const nbt_file &rhs);
nbt_file(std::vector<nbt_tag> t);
~nbt_file();
void ReadFile(igzstream &fs);
void ReadFile(std::string filename);
void ReadFile(const char* filename);
nbt_tag First();
std::vector<nbt_tag>::iterator Begin() {return tags.begin();}
std::vector<nbt_tag>::iterator End() {return tags.end();}
void WriteFile(std::string filename);
void AddTag(nbt_tag t, int index);
};









#endif NBTDEF_H_



#include <cstdint>
#include "gzstream.h"

#include "nbtdef.h"
//#include "endianness.h"
#include <string>

nbt_tag::nbt_tag(nbt_type t) {type = t; name = ""; value = NULL;}
nbt_tag::nbt_tag(){type = nbt_type::TAG_END; name = ""; value = NULL;}
nbt_tag::nbt_tag(nbt_type t, std::string n, void *v){type = t; name = n; value = v;}
nbt_tag::nbt_tag(const nbt_tag &rhs){type = rhs.type; name = rhs.name; delete value; memcpy(value,rhs.value,sizeof(rhs.value));}
nbt_tag::~nbt_tag(){delete value;}
void* nbt_tag::GetValue(){return value;}
nbt_type nbt_tag::GetType(){return type;}
void nbt_tag::SetValue(void *v){delete value; memcpy(value, v, sizeof(v));}
void nbt_tag::SetType(nbt_type t){type = t;}
void nbt_tag::SetName(std::string n){name= n;}
void nbt_tag::SwapEndian(){
switch(type){
case TAG_END:
break;
case TAG_BYTE:
break;
case TAG_SHORT:
if(get_endianness() == L_ENDIAN)
swaps((uint16_t*)value);
break;
case TAG_INT:
if(get_endianness() == L_ENDIAN)
swapi((uint32_t*)value);
break;
case TAG_LONG:
if(get_endianness() == L_ENDIAN)
swapl((uint64_t*)value);
break;
case TAG_FLOAT:
if(get_endianness() == L_ENDIAN)
swapf(*((float*)value));
break;
case TAG_DOUBLE:
if(get_endianness() == L_ENDIAN)
swapd(*((double*)value));
break;
case TAG_BYTE_ARRAY:
break;




}
}

nbt_byte_array::nbt_byte_array(){content = NULL; length = 0;}
nbt_byte_array::nbt_byte_array(int32_t l, unsigned char *c){length = l; delete content; memcpy(content, c, l);}
nbt_byte_array::nbt_byte_array(const nbt_byte_array &rhs){length = rhs.length; delete content; memcpy(content, rhs.content, length);}
nbt_byte_array::~nbt_byte_array(){delete content;}
int32_t nbt_byte_array::Size(){return length;}
unsigned char *nbt_byte_array::Get(){return content;}

nbt_file::nbt_file(){}
nbt_file::nbt_file(const nbt_file &rhs){
tags = rhs.tags;
}
nbt_file::nbt_file(std::vector<nbt_tag> t){
tags = t;
}
nbt_file::~nbt_file(){}

int read_name(igzstream &fs, nbt_tag &t){
char *buffer;
int16_t len;
fs.read((char*)&len, sizeof(len));
if(get_endianness() == L_ENDIAN)
swaps((uint16_t *)&len);
buffer = new char[len];
fs.read(buffer, len);
std::string str(buffer);
delete [] buffer;
buffer = NULL;
t.SetName(str);
return 0;
}

template <typename T>
int nbt_read(igzstream &fs, nbt_tag &t){
t.SetValue((void*)(new T));
read_name(fs, t);
fs.read((char*)t.GetValue(), sizeof(T));
return 1;
}

void nbt_file::ReadFile(igzstream &fs){
char t = nbt_type::TAG_END;
int i = 0;
fs.read((char*)&i, t);
nbt_tag tg;
while(_Read(fs, t, tg)){
tags.push_back(tg);
}
tags.push_back(tg);
}
int nbt_file::_Read(igzstream &fs, char &t, nbt_tag &tg){
fs.read(&t, 1);

tg.SetType((nbt_type) t);

switch (t)
{
case TAG_END:
return 0;
break;

case TAG_BYTE:
nbt_read<char>(fs,tg);
break;

case TAG_SHORT:
nbt_read<int16_t>(fs, tg);

break;

case TAG_INT:
nbt_read<int32_t>(fs,tg);
break;

case TAG_LONG:
nbt_read<int64_t>(fs, tg);

break;

case TAG_FLOAT:
nbt_read<float>(fs, tg);

break;

case TAG_DOUBLE:
nbt_read<double>(fs, tg);
break;

case TAG_STRING:
{ /* to make it shut up about the variable declaration */
//This function uses a lot of hackery, we assign the std::string varaible rather than a char array
//because the nbt_tag destructor does not expect an array pointer
read_name(fs, tg);
char *buffer;
// std::string *str = new std::string;
int16_t len;
fs.read((char*)&len, sizeof(len));
if(get_endianness() == L_ENDIAN)
swaps((uint16_t *)&len);
buffer = new char[len];
fs.read(buffer, len);
std::string *str = new std::string(buffer);
delete [] buffer;
buffer = NULL;
tg.SetValue(str);
}
break;

case TAG_BYTE_ARRAY:
{
read_name(fs, tg);
std::list<unsigned char> *lst = new std::list<unsigned char>;
unsigned char *buffer;
//int32_t len = nbt_read_byte_array(nbt, &bytestring);
int32_t len;
fs.read((char*)&len, sizeof(len));
if(get_endianness() == L_ENDIAN)
swapi((uint32_t *)&len);
buffer = new unsigned char[len];
fs.read((char*)buffer, len);
for(int i = 0; i < len; ++i)
lst->push_back(buffer);
tg.SetValue(lst);
delete [] buffer;
buffer = NULL;
}
break;

case TAG_LIST:
{
read_name(fs, tg);
std::list<nbt_tag> *lst = new std::list<nbt_tag>;
char type;
int32_t len;
fs.read(&type,1); //All tags share a type in a list
fs.read((char*)&len, sizeof(len)); //Length of tag seqeuence
for(int i = 0; i < len; ++i){
lst->push_back(nbt_tag());
_Read(fs, type, lst->back());
}
tg.SetValue(lst);
}
break;

case TAG_COMPOUND:
{
//Series of tags of different types
//Create a vector and read in types to the vector until the next TAG END
read_name(fs, tg);
std::list<nbt_tag> *lst = new std::list<nbt_tag>;
char type;
do{
fs.read(&type,1);
lst->push_back(nbt_tag());
} while(_Read(fs, t,lst->back())==1);
}
break;
}
return 1;
}

void nbt_file::ReadFile(std::string filename){
igzstream fs;
fs.open(filename.c_str(),std::ios::binary | std::ios::in | std::ios::app);
if(fs.good())
ReadFile(fs);
}
void nbt_file::ReadFile(const char* filename){
igzstream fs;
fs.open(filename, std::ios::binary | std::ios::in | std::ios::app);
if(!fs.bad())
ReadFile(fs);
fs.close();
}

nbt_tag nbt_file::First(){
return tags.front();
}
void nbt_file::WriteFile(std::string filename){} // Don't worry about this for now
void nbt_file::AddTag(nbt_tag t, int index){} // Don't worry about this for now


int get_endianness()
{
union
{
uint32_t i;
char c[4];
} t = { 0x01020304 };

return t.c[0] == 1;
}

uint64_t swpd(double d)
{
int i;

uint64_t res;
unsigned char *dest = (unsigned char *)&res;
unsigned char *src = (unsigned char *)&d;

for (i = 0; i < 8; ++i)
dest = src[7 - i];

return res;
}

double uswpd(uint64_t d)
{
int i;

double res;
unsigned char *src = (unsigned char *)&res;
unsigned char *dest = (unsigned char *)&d;

for (i = 0; i < 8; ++i)
dest = src[7 - i];

return res;
}

float swapf(float fx)
{
float rv;

char *ftc = (char *)&fx;
char *rtf = (char *)&rv;

rtf[0] = ftc[3];
rtf[1] = ftc[2];
rtf[2] = ftc[1];
rtf[3] = ftc[0];

return rv;
}

double swapd(double dx)
{
double rv;

char *ftc = (char *)&dx;
char *rtv = (char *)&rv;

rtv[0] = ftc[7];
rtv[1] = ftc[6];
rtv[2] = ftc[5];
rtv[3] = ftc[4];
rtv[4] = ftc[3];
rtv[5] = ftc[2];
rtv[6] = ftc[1];
rtv[7] = ftc[0];

return rv;
}

void swaps(uint16_t *x)
{
*x = (*x >> 8) | (*x << 8);
}

void swapi(uint32_t *x)
{
*x = (*x >> 24) |
((*x<<8) & 0x00FF0000) |
((*x>>8) & 0x0000FF00) |
(*x << 24);
}

void swapl(uint64_t *x)
{
*x = (*x>>56) |
((*x<<40) & 0x00FF000000000000ULL) |
((*x<<24) & 0x0000FF0000000000ULL) |
((*x<<8) & 0x000000FF00000000ULL) |
((*x>>8) & 0x00000000FF000000ULL) |
((*x>>24) & 0x0000000000FF0000ULL) |
((*x>>40) & 0x000000000000FF00ULL) |
(*x<<56);
}



They depend on zlib and gzstream right now, and some of my code is trail-test hardcoding. Anyway, I'm going to go beat my head against a brick wall (attempt to debug) for a while.

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!