Extract image from .xsp files

This code allows you to extract and save .xsp file images to bmp’s, this type of file was used by XstBasic2 a game programming language.

xst2

#include <stdio.h>
#include <stdlib.h>

//bmp has no transparency so this should be a neutral colour that a paint program could change to transparent
//bit out was used as it is the easiest format to write!
#define transparencycolour 0xff /*this is the same as 255(0-255 = 256 = 16*16 = 0xff = 0x16*16) f hexadecimal = 16*/

typedef unsigned short int WORD; /*WORD is a 16 bits integer*/

unsigned char xsp_palette[768];

unsigned char *BMPimage = NULL; /*char pointer to a file image*/

//simple bitmap saving procedure I found on-line (then modified)
void saveBmp2(int w, int h, unsigned char *img, int wh) {

	int i;
	FILE *f;

	char fname[64];
	// 54 is the bmpfileheader + bmpinfoheader and 3 is bmppad
	int filesize = 54 + 3 * w * h;  //w is your image width, h is image height, both int
	
	unsigned char bmpfileheader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0};
	unsigned char bmpinfoheader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0};
	unsigned char bmppad[3] = {0,0,0};

	bmpfileheader[ 2] = (unsigned char)(filesize    );
	bmpfileheader[ 3] = (unsigned char)(filesize>> 8);
	bmpfileheader[ 4] = (unsigned char)(filesize>>16);
	bmpfileheader[ 5] = (unsigned char)(filesize>>24);

	bmpinfoheader[ 4] = (unsigned char)(       w    );
	bmpinfoheader[ 5] = (unsigned char)(       w>> 8);
	bmpinfoheader[ 6] = (unsigned char)(       w>>16);
	bmpinfoheader[ 7] = (unsigned char)(       w>>24);
	bmpinfoheader[ 8] = (unsigned char)(       h    );
	bmpinfoheader[ 9] = (unsigned char)(       h>> 8);
	bmpinfoheader[10] = (unsigned char)(       h>>16);
	bmpinfoheader[11] = (unsigned char)(       h>>24);

	sprintf(fname,"img%d.bmp",wh);

	f = fopen(fname,"wb");
	fwrite(bmpfileheader,1,sizeof(bmpfileheader),f);
	fwrite(bmpinfoheader,1,sizeof(bmpinfoheader),f);
	for(i=0; i<h; i++)
	{
	    fwrite(img+(w*(h-i-1)*3),3,w,f);
	    fwrite(bmppad,1,(4-(w*3)%4)%4,f);
	}
	fclose(f);
}


//main program, all the action happens here. change "bi_gfxs.xsp" to whatever file you want to access (or use argv and call with parameters)
int main(int argc, char *argv[])
{
	int c,k,amount,x,y,icx,icy,ysize;
	int r,g,b;
	unsigned long image_size;
	FILE *input;

	/*grab parameters*/ 
	if(argc < 2 ) {
		printf("Must input a parameter (filename)");
		return -1;
	} 
	
	input=fopen(argv[1],"rb");

	printf(argv[1]);
	
	if(!input){ printf("Cannot open file"); return -1; }

	//check id
	k=fgetc(input);
	if(k!=0x66){ printf("Not a XSP file"); fclose(input); return -1; }
	
	//read the palette
	fseek(input,-769,SEEK_END);
	for(c=0;c<768;c++)xsp_palette[c]=fgetc(input);
	
	//read the image amount 0 is the 0x66 id from xsp files
	fseek(input,1,SEEK_SET);
	amount=fgetc(input); amount+=fgetc(input)*0x100;
	printf("Amount of sprites = %d\n",amount);
	
	//loop for all images
	for(c=0;c<amount;c++)
	{
		x = fgetc(input); x+=fgetc(input)*0x100;
		y = fgetc(input); y+=fgetc(input)*0x100;
		printf("Sprite %d: size %d x %d\n",c+1,x,y);

		
		//allocate the memory for the image
		image_size=((x+1)*3)*(y+1);
 		BMPimage = (unsigned char *)malloc(image_size + 5);

		ysize=(x*3);

		//read the image
		for(icy=0; icy<y; icy++)
			for(icx=0; icx<x; icx++) {
				//get the pixel
				k=fgetc(input);
				//get its colour
				r=xsp_palette[k*3]*3;
				g=xsp_palette[(k*3)+1]*3;
				b=xsp_palette[(k*3)+2]*3;

				//unless transparent
				if(k==0){r=g=b=transparencycolour; }

				//add it to the bitmap (BGR format)
				BMPimage[(icx*3)+(icy*ysize)]=b;
				BMPimage[((icx*3)+1)+(icy*ysize)]=g;
				BMPimage[((icx*3)+2)+(icy*ysize)]=r;
			}
		//save the bitmap	
		saveBmp2(x,y,BMPimage,c + 1);

		//free the bitmap
		if(BMPimage)free(BMPimage);
		BMPimage=NULL;
	}

	printf("Operation complete");
	fclose(input);    
	return 0;
}

xst2Bmp
xst2Bmp
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s