View Single Post
Cataphract

JCF Member

Joined: Sep 2002

Posts: 24

Cataphract is doing well so far

Feb 15, 2007, 05:48 PM
Cataphract is offline
Reply With Quote
Somehow I got the idea the stream was immediately preceded by the sizes.

Anyhow, I've finished the program, now it's just a matter of rearranging it and compile as a dll to use with mIRC. Maybe then I'll start doing something more interesting with the level files.

I'm going to post the code for the completeness of this thread.
Thanks to those who replied.

j2linfo.h
Code:
typedef struct cstream {
	long 	compSize;
	long	uncompSize;
	char	*compData;
	char	*uncompData;
} cstream, *cstreamP;

int uncompressStream(cstreamP st);
cstreamP newStream(void);


typedef struct LEVLheader {
	char		magic[4];
	char		passwordHash[3];
	char		hideLevel;
	char		levelName[32];
	short		version;
	long		fileSize;
	long		CRC32;
	cstreamP	stream[4];
} LEVLheader, *LEVLheaderP;

LEVLheaderP newLEVLheader(void);
int populateLVLheader(LEVLheaderP head,FILE *f);

//debugging
void memdump(unsigned char* data,int interval);
j2linfo.c
Code:
#include <stdio.h>
#include <stdlib.h>
#include "zlib/zlib.h"

#include "j2linfo.h"

#define err(str)	fwrite(str "\n", 1, strlen(str)+2, stderr)

void *chkmal(void *ptr) {
	if (ptr == NULL) { err("Could not allocate memory"); exit(2); };
	return ptr;
}
void memdump(unsigned char* data,int interval) {
	int i = -1;
	while (++i < interval) {
	  printf(" %X ",(unsigned int) (*(data+i)));
	}
	printf("\n");
}

int uncompressStream(cstreamP st) {
	long ucs = st->uncompSize;
	long resuncomp; //to hold the result of uncompress

	if (st->compData == NULL) return 1;
	if (st->uncompData != NULL) free(st->uncompData);
	st->uncompData = malloc(st->uncompSize);
	if (st->uncompData == NULL) return 2;
	
	printf("About to call uncompress:\n"
	  "size of compressed data: %i\n"
	  "size of uncompressed data: %i\n\n",st->compSize,st->uncompSize
	);
	
	resuncomp = uncompress(st->uncompData, &ucs, st->compData, st->compSize);
	
	if (resuncomp != Z_OK)  return 3;
	if (ucs != st->uncompSize) return 4;
	
	return 0;
}
cstreamP newStream(void) {
	cstreamP		ret;
	ret = malloc(sizeof *ret);
	if (ret == NULL) return NULL;
	memset(ret,0,sizeof *ret);
	return ret;
}
LEVLheaderP newLEVLheader(void) {
	LEVLheaderP		ret;
	ret = malloc(sizeof *ret);	
	if (ret == NULL) return NULL;
	memset(ret,0,sizeof *ret);
	return ret;
}

int populateLVLheader(LEVLheaderP head,FILE *f) {
  if (fread(head->magic,4, 1, f) == 0) {
	perror("Could not read the magic string of the LEVL header");
	return 1;
  }
  if (fread(head->passwordHash,3, 1, f) == 0) {
	perror("Could not read the password hash string of the LEVL header");
	return 1;
  }
  if (fread(&head->hideLevel,1, 1, f) == 0) {
	perror("Could not read the hide level byte of the LEVL header");
	return 1;
  }
  if (fread(head->levelName,32, 1, f) == 0) {
	perror("Could not read the level name of the LEVL header");
	return 1;
  }
  if (fread(&head->version,2, 1, f) == 0) {
	perror("Could not read the version out of the LEVL header");
	return 1;
  }
  if (fread(&head->fileSize,4, 1, f) == 0) {
	perror("Could not read the file size out of the LEVL header");
	return 1;
  }
  if (fread(&head->CRC32,4, 1, f) == 0) {
	perror("Could not read the checksum of the LEVL header");
	return 1;
  }
  return 0;
}

int main(int argc, char **argv) {
  FILE *file;
  char *inputstream,*outputstream;
  LEVLheaderP head;
  int i;
  char outname[50] = "";
  char gendata[19+32*6];
  
  head = chkmal(newLEVLheader());
  
  if (argc < 2) { err("Give the file as a second argument."); return 1; }
  
  if ((file = fopen(argv[1],"rb")) == NULL) { perror("Could not open the file for reading"); return 1; }
  
  if (fseek(file, (long int) 180, SEEK_SET) != 0) {
	perror("Error setting the position for reading");
	return 1;
  }
  
  //Read header. I will not read into the struct as that is not portable
  if (populateLVLheader(head,file) != 0) return 1;
  
  if (memcmp(head->magic, "LEVL", 4) != 0) {
	err("This does not appear to be a valid Jazz2 level file.");
	return 1;
  }
  
  i = -1; while (i++ < 3) {
	head->stream[i] = newStream();
	
	if (head->stream[i] == NULL) exit(1);
	if (fread(&(head->stream[i]->compSize), sizeof(long), 1, file) == 0) {
		perror("Could not read the compressed size of a stream");
		return 1;
	}
	if (fread(&(head->stream[i]->uncompSize), sizeof(long), 1, file) == 0) {
		perror("Could not read the uncompressed size of a stream");
		return 1;
	}
  }
  
  i = -1; while (i++ < 3) {
    head->stream[i]->compData = chkmal(malloc(head->stream[i]->compSize));
    head->stream[i]->uncompData = chkmal(malloc(head->stream[i]->uncompSize));
	  
    if (fread(head->stream[i]->compData, 1, head->stream[i]->compSize, file) == 0) {
		perror("Could not read the compressed data some stream");
		return 1;
    }
	if (uncompressStream(head->stream[i]) != 0) {
		err("Error uncompressing stream.");
		return 1;
	};
  }
  
  if (fclose(file) != 0)  { perror("Error closing the file"); return 1; }
  
  i = -1; while (i++ < 3) {
    sprintf(outname,"t:\\j\\out%i.txt",i+1);
	
    printf(
	  "Written: %u bytes\n",
	  fwrite(head->stream[i]->uncompData,
	  1,
	  head->stream[i]->uncompSize,
	  fopen(outname,"wb"))
	);
  }
  
  if (head->stream[0]->uncompSize < 19+32*6) {
	err("Bad stream 1"); return 1;
  }
  else memcpy(gendata,head->stream[0]->uncompData,19+32*6);
  
  //make sure the strings are always null-terminated
  i = 0; while (i++ < 6) { *(gendata+19+32*i-1) = '\x00'; }

  printf(
	"\nLEVEL INFORMATION\n"
	"Level name: %s\n"
	"Tileset: %s\n"
	"Bonus Level: %s\n"
	"Next Level: %s\n"
	"SecretLevel: %s\n"
	"MusicFile: %s\n",
	gendata+19,gendata+19+32*1,gendata+19+32*2,
	gendata+19+32*3,gendata+19+32*4,gendata+19+32*5
  );
  
  return 0;
}