Dev Apps - Public Source Dump

Information and updates for all other projects by Black Omen Productions (besides Shadow Empires): Namely Codename: MetalStorm, Anti-Balance, Ultimate Fixer and all versions of XyRAX

Moderators: Nefarius, Joel, Doombreed-x, Vendanna

Post Reply

0
No votes
 
Total votes: 0

User avatar
Nefarius
Retired Admin
Cherub
Posts: 11607
Joined: Sat Jun 15, 2002 8:13 pm
Location: Where the blood forever rains
Contact:

Hand-picked

Dev Apps - Public Source Dump

Post by Nefarius » Thu Dec 13, 2007 5:12 am

The things posted in this topic are free for anyone to repurpose for private / learning (if you release a tool based on something dumped here please let us know however). These are sources for various little apps created during development to automate mundane tasks. Not everything will end up here, but this should grow quite a bit over time (or it may stay small, who knows :P)


Alter color palette of *.GIF files (for D1/Infinity graphics) so that brightness and contrast fit into D2 - kudos to Paul Siramy for indirectly giving me the idea to write this.

Notes: units.dat = D2 unit palette, palshift.dat = color shift with fixup for brightness / contrast (made in Paintshop Pro and converted via PalAnalyzer).

Sample (open both at the same time):
http://img145.imageshack.us/img145/5410/a1pw8.gif - before adjustment
http://img145.imageshack.us/img145/5608 ... gedvh1.gif - after adjustment

Code: Select all

#include <cstdio>
#include <cstdlib>
#include <cstring>

#pragma pack(1)

struct RgbColor
{
	unsigned char r;
	unsigned char g;
	unsigned char b;
};

struct Palette
{
	RgbColor color[256];
};

#pragma pack()

int __cdecl main(int argc, char** argv)
{
	if (argc != 2)
	{
		printf("CORRECT USAGE: <FILENAME>");
		return 0;
	}

	FILE* fpal = fopen("units.dat","rb");
	if (fpal == 0)
	{
		printf("COULDN'T OPEN UNITS.DAT");
		return 0;
	}

	Palette unit_pal;
	fread(unit_pal.color,1,256*3,fpal);
	fclose(fpal);

	FILE* shift = fopen("palshift.dat","rb");
	if (shift == 0)
	{
		printf("COULDN'T OPEN PALSHIFT.DAT");
		return 0;
	}

	unsigned char palshift[256];
	fread(palshift,1,256,shift);
	fclose(shift);

	char* file_name = argv[1];

	FILE* file = fopen(file_name,"rb");
	if (file == 0)
	{
		printf("FILE DOESN'T EXIST OR CANNOT BE OPENED");
		return 0;
	}

	fseek(file,0,SEEK_END);
	int size = ftell(file);
	rewind(file);

	if (size <= 0)
	{
		printf("INVALID FILE SIZE!");
		return 0;
	}

	unsigned char* buffer = (unsigned char*)malloc(size);
	if (buffer == 0)
	{
		printf("COULDN'T ALLOCATE BUFFER");
		fclose(file);
		return 0;
	}

	size = fread(buffer,1,size,file);
	fclose(file);

	char type[7];
	memcpy(type,buffer,7);
	type[6] = 0;

	if (strcmp(type,"GIF89a") != 0)
	{
		free(buffer);
		printf("WRONG FILE FORMAT, PLEASE USE GIF 89A");
		return 0;
	}

	if ((buffer[10] & 1) == 0)
	{
		free(buffer);
		printf("PLEASE USE A GIF FILE WITH A GLOBAL PALETTE");
		return 0;
	}

	if ((buffer[10] & 128) == 0)
	{
		free(buffer);
		printf("PLEASE USE A GIF FILE WITH A 8-BIT PALETTE");
		return 0;
	}

	Palette* palette = (Palette*)(buffer + 13);
	int trans = buffer[11];
	for (int i = 0; i < 256; i++)
	{
		int idx = palshift[i];
		if (i != trans)
		{
			int r = unit_pal.color[idx].b;
			int g = unit_pal.color[idx].g;
			int b = unit_pal.color[idx].r;

			palette->color[i].r = r;
			palette->color[i].g = g;
			palette->color[i].b = b;
		}
	}

	char* f = file_name;
	while(*f != 0)
	{
		if (*f == '.') {
			*f = 0;
			break;
		}

		f++;
	}

	char new_name[256];
	sprintf(new_name,"RECALIBRATED_%s.gif",file_name);

	FILE* out = fopen(new_name,"wb");
	if (out != 0)
	{
		fwrite(buffer,1,size,out);
		fclose(out);
	}

	free(buffer);
	return 0;
}

A modified version of the above ;)

Code: Select all

#pragma comment(linker,"/FILEALIGN:512")
#include <cstdio>
#include <cstdlib>
#include <cstring>

#pragma pack(1)

struct RgbColor
{
	unsigned char r;
	unsigned char g;
	unsigned char b;
};

struct Palette
{
	RgbColor color[256];
};

#pragma pack()

int __cdecl main(int argc, char** argv)
{
	if (argc != 5)
	{
		printf("CORRECT USAGE: <FILENAME>");
		return 0;
	}

	FILE* fpal = fopen("units.dat","rb");
	if (fpal == 0)
	{
		printf("COULDN'T OPEN UNITS.DAT");
		return 0;
	}

	int nPal = atoi(argv[3]);
	Palette unit_pal;
	fread(unit_pal.color,1,256*3,fpal);
	fclose(fpal);

	FILE* shift = fopen(argv[4],"rb");
	if (shift == 0)
	{
		printf("COULDN'T OPEN PALSHIFT.DAT");
		return 0;
	}

	unsigned char* palshift = (unsigned char*)malloc(nPal*256);
	if (palshift == 0)
	{
		printf("COULDN'T ALLOCATE BUFFER");
		return 0;
	}

	fread(palshift,1,nPal*256,shift);
	fclose(shift);

	char* file_name = argv[1];

	FILE* file = fopen(file_name,"rb");
	if (file == 0)
	{
		free(palshift);
		printf("FILE DOESN'T EXIST OR CANNOT BE OPENED");
		return 0;
	}

	fseek(file,0,SEEK_END);
	int size = ftell(file);
	rewind(file);

	if (size <= 0)
	{
		free(palshift);
		printf("INVALID FILE SIZE!");
		return 0;
	}

	unsigned char* buffer = (unsigned char*)malloc(size);
	if (buffer == 0)
	{
		free(palshift);
		printf("COULDN'T ALLOCATE BUFFER");
		fclose(file);
		return 0;
	}

	size = fread(buffer,1,size,file);
	fclose(file);

	char type[7];
	memcpy(type,buffer,7);
	type[6] = 0;

	if (strcmp(type,"GIF89a") != 0)
	{
		free(palshift);
		free(buffer);
		printf("WRONG FILE FORMAT, PLEASE USE GIF 89A");
		return 0;
	}

	if ((buffer[10] & 1) == 0)
	{
		free(palshift);
		free(buffer);
		printf("PLEASE USE A GIF FILE WITH A GLOBAL PALETTE");
		return 0;
	}

	if ((buffer[10] & 128) == 0)
	{
		free(palshift);
		free(buffer);
		printf("PLEASE USE A GIF FILE WITH A 8-BIT PALETTE");
		return 0;
	}

	int offset = atoi(argv[2]) * 256;
	Palette* palette = (Palette*)(buffer + 13);
	int trans = buffer[11];
	for (int i = 0; i < 256; i++)
	{
		int idx = palshift[offset+i];
		if (i != trans)
		{
			int r = unit_pal.color[idx].b;
			int g = unit_pal.color[idx].g;
			int b = unit_pal.color[idx].r;

			palette->color[i].r = r;
			palette->color[i].g = g;
			palette->color[i].b = b;
		}
	}

	char* f = file_name;
	while(*f != 0)
	{
		if (*f == '.') {
			*f = 0;
			break;
		}

		f++;
	}

	char new_name[256];
	sprintf(new_name,"%s_changed.gif",file_name);

	FILE* out = fopen(new_name,"wb");
	if (out != 0)
	{
		fwrite(buffer,1,size,out);
		fclose(out);
	}

	free(palshift);
	free(buffer);
	return 0;
}
Last edited by Nefarius on Sun Dec 23, 2007 7:59 am, edited 3 times in total.
''(...) The game can basically be considered unhackable. '' - Blizzard Entertainment (30th May 2000)
Black Omen Productions | MetalStorm: Progress Report | Screenshots

User avatar
Nefarius
Retired Admin
Cherub
Posts: 11607
Joined: Sat Jun 15, 2002 8:13 pm
Location: Where the blood forever rains
Contact:

Hand-picked

Re: Dev Apps - Public Source Dump

Post by Nefarius » Thu Feb 07, 2008 9:48 pm

PCX -> DC6 Multi Batch conversion with support for transparency, animation, offsets, no limit on frame count, frame size (etc)
Conversion code itself based on dc6con (Paul's modified version, not the original by Ryan Smith), the rest is new code.

Code: Select all

#include <WINDOWS.H>
#include <CSTDARG>
#include <CSTDIO>
#include <CMATH>

// ###################### STRUCTS ######################
struct FileList
{
	char* filename;
	FileList* next;
};

#pragma pack(1)

struct CellOffset;

struct BatchConvertToDC6Args
{
	size_t structsize;
	bool transparent;
	int directions;
	char background;
	CellOffset* offsets;
};

struct PcxHeader
{
	BYTE manufacturer;
	BYTE version;
	BYTE encoding;
	BYTE bits_per_pixel;
	WORD left;
	WORD top;
	WORD width;
	WORD height;
	WORD vres;
	WORD hres;
	BYTE palette[48];
	BYTE reserved;
	BYTE color_planes;
	WORD bytes_per_line;
	WORD palette_type;
	BYTE filler[58];
};

struct PcxFile
{
	PcxHeader* head;
	BYTE* pixels;
	DWORD size;
};

struct CellHeader
{
	DWORD version;
	DWORD unknown1;
	DWORD unknown2;
	DWORD filler;
	DWORD dir_count;
	DWORD frame_count;
};

struct CellFrame
{
	DWORD flip;
	DWORD width;
	DWORD height;
	long x_offset;
	long y_offset;
	DWORD unknown;
	DWORD next_frame_offset;
	DWORD frame_size;
};

struct CellFile;

struct CellFrameList
{
	CellFrame* frame;
	BYTE* pixels;
	DWORD size;
	CellFrameList* next;
	DWORD offset;
	CellFile* parent;
};

struct CellOffset
{
	long x_offset;
	long y_offset;
};

struct CellFile
{
	CellHeader* head;
	CellFrameList* framehead;
	CellFrameList* frametail;
	DWORD frame_count;
	DWORD dir_count;
	DWORD width;
	DWORD height;
	bool transparent;
	char filler;
};

#pragma pack()

// ###################### TYPEDEFS ####################
typedef int (__fastcall* FileListCycler)(FileList*, void*);

// ##################### PROTOTYPES ####################
void cleanup();

// ###################### GLOBALS ######################
static void* heap = 0;
static FileList* filehead = 0;
static FileList* filetail = 0;
static const DWORD pcxheadsize = sizeof(PcxHeader);









void __cdecl error(char* format, ...)
{
	va_list args;
	va_start(args, format);
	char buffer[500];
	memset(buffer, 0, sizeof(buffer));
	_vsnprintf(buffer, sizeof(buffer) - 1, format, args);
	char message[1000];
	memset(message, 0, sizeof(message));
	_snprintf(message, sizeof(message) - 1, "Error: %s", buffer);
	MessageBox(0, message, "Fatal Error", MB_OK | MB_ICONERROR);
	cleanup();
	void* process = GetCurrentProcess();
	TerminateProcess(process, -1);
}

void InitHeap(int megs)
{
	int size = megs << 20;
	if (size <= 0)
		error("HEAP CREATION FAILURE, HEAPSIZE: %u", size);

	heap = HeapCreate(0, size, 0);
	if (heap == 0)
		error("HEAP CREATION FAILURE");
}

bool KillHeap()
{
	if (heap == 0)
		return false;

	return (HeapDestroy(heap) != 0);
}

void* __fastcall silentalloc(int size, int count = 0)
{
	if (heap == 0)
		return 0;

	if (count != 0)
		size *= count;

	if (size <= 0)
		return 0;

	return HeapAlloc(heap, HEAP_ZERO_MEMORY, size);
}

void* __fastcall alloc(int size, int count = 0)
{
	if (heap == 0)
		error("MEMORY ALLOCATION FAILURE, INVALID HEAP");

	if (count != 0)
		size *= count;

	if (size <= 0)
		error("MEMORY ALLOCATION FAILURE, MEMSIZE: %u", size);

	void* mem = HeapAlloc(heap, HEAP_ZERO_MEMORY, size);
	if (mem == 0)
		error("MEMORY ALLOCATION FAILURE");

	return mem;
}

void __fastcall clear(void* mem)
{
	if (mem == 0 || heap == 0)
		return;

	HeapFree(heap, 0, mem);
}

bool __fastcall getext(char* filename, int size, char** ext)
{
	if (filename == 0 || ext == 0 || size <= 0)
		return false;

	*ext = 0;
	for (int i = size; i >= 0; i--)
	{
		if (filename[i] == '.')
		{
			int offset = i + 1;
			if (offset >= size)
				return false;

			*ext = filename + offset;
			return true;
		}
	}

	return false;
}

bool __fastcall swapext(char* filename, char* ext, int size)
{
	if (filename == 0 || ext == 0 || size <= 0)
		return false;

	char* oldext = 0;
	int extlen = lstrlen(ext);
	if (getext(filename,size,&oldext) == 0)
		return false;

	int oldlen = lstrlen(oldext);
	if (oldlen < extlen)
		return false;

	*oldext = 0;
	lstrcat(filename,ext);
	return true;
}

void DeleteFileList()
{
	FileList* file = filehead;
	filetail = 0;
	filehead = 0;

	while (file != 0)
	{
		FileList* next = file->next;
		file->next = 0;

		if (file->filename != 0)
		{
			clear(file->filename);
			file->filename = 0;
		}

		clear(file);
		file = next;
	}
}

void CreateFileNode(char* path)
{
	if (path == 0)
		return;

	int length = lstrlen(path);
	if (length <= 0)
		return;

	char* buff = (char*)alloc(sizeof(char), length + 1);
	lstrcpy(buff, path);

	FileList* node = (FileList*)alloc(sizeof(FileList));
	if (filehead == 0)
		filehead = node;

	if (filetail != 0)
		filetail->next = node;

	node->filename = buff;
	filetail = node;
}

int CreateFileList(char* filter)
{
	WIN32_FIND_DATA fd;
	memset(&fd, 0, sizeof(fd));

	char buffer[MAX_PATH];
	memset(buffer, 0, sizeof(buffer));
	GetCurrentDirectory(sizeof(buffer) - 1, buffer);

	char search[MAX_PATH];
	_snprintf(search, sizeof(search) - 1, "%s\\*.%s", buffer, filter);

	int files = 0;
	void* find = FindFirstFile(search, &fd);
	if (find == 0)
		error("FAILED OPENING SEARCH HANDLE");

	do {

		char* filename = fd.cFileName;
		if (filename != 0)
		{
			int length = lstrlen(filename);
			if (length > 0)
			{
				char* ext = 0;
				if (getext(filename, length, &ext) != false)
				{
					if (lstrcmpi(ext, filter) == 0)
					{
						CreateFileNode(filename);
						files++;
					}
				}
			}
		}

	} while (FindNextFile(find, &fd) != 0);

	FindClose(find);
	return files;
}

size_t __fastcall TellSize(FILE* buff)
{
	if (buff == 0)
		return 0;

	fseek(buff, 0, SEEK_END);
	size_t size = ftell(buff);
	rewind(buff);

	return size;
}

PcxFile* ReadPCX(char* filename, char filler)
{
	if (filename == 0)
		return 0;

	FILE* buff = fopen(filename, "rb");
	if (buff == 0)
		return 0;

	int size = TellSize(buff);
	if (size <= 0)
	{
		fclose(buff);
		return 0;
	}

	PcxFile* pcxfile = (PcxFile*)silentalloc(sizeof(PcxFile));
	if (pcxfile == 0)
	{
		fclose(buff);
		return 0;
	}

	PcxHeader* pcxhead = (PcxHeader*)silentalloc(sizeof(PcxHeader));
	if (pcxhead == 0)
	{
		clear(pcxfile);
		fclose(buff);
		return 0;
	}

	int bytes_read = fread(pcxhead, 1, pcxheadsize, buff);
	if (bytes_read != pcxheadsize)
	{
		clear(pcxfile);
		clear(pcxhead);
		fclose(buff);
		return 0;
	}

	size -= bytes_read;
	if (size <= 0)
	{
		clear(pcxfile);
		clear(pcxhead);
		fclose(buff);
		return 0;
	}

	BYTE* pixels = (BYTE*)silentalloc(size);
	if (pixels == 0)
	{
		clear(pcxfile);
		clear(pcxhead);
		fclose(buff);
		return 0;
	}

	memset(pixels, filler, size);
	bytes_read = fread(pixels, 1, size, buff);
	if (bytes_read != size)
	{
		clear(pixels);
		clear(pcxfile);
		clear(pcxhead);
		fclose(buff);
		return 0;
	}

	pcxfile->head = pcxhead;
	pcxfile->pixels = pixels;
	pcxfile->size = bytes_read;
	fclose(buff);
	return pcxfile;
}

void DeletePCX(PcxFile* pcxfile)
{
	if (pcxfile == 0)
		return;
	if (pcxfile->head != 0)
		clear(pcxfile->head);
	pcxfile->head = 0;
	if (pcxfile->pixels != 0)
		clear(pcxfile->pixels);
	pcxfile->pixels = 0;
	clear(pcxfile);
}

bool ValidatePCX(PcxFile* pcxfile)
{
	if (pcxfile == 0)
		return false;

	if (pcxfile->head == 0)
		return false;

	if (pcxfile->pixels == 0 || pcxfile->size == 0)
		return false;

	if (pcxfile->head->manufacturer != 10)
		return false;

	if (pcxfile->head->version != 5)
		return false;

	if (pcxfile->head->encoding != 1)
		return false;

	if (pcxfile->head->bits_per_pixel != 8)
		return false;

	return true;
}

bool DecodePCX(PcxFile* pcxfile)
{
	if (ValidatePCX(pcxfile) == false)
		return false;

	int size = (pcxfile->head->width + 1) * (pcxfile->head->height + 1);
	if (size <= 0)
		return false;

	BYTE* buff = (BYTE*)silentalloc(size);
	if (buff == 0)
		return false;

	BYTE* in		= pcxfile->pixels;
	BYTE* out		= buff;
	int out_size	= size;
	int in_size		= pcxfile->size;
	
	for (int y = 0; y <= pcxfile->head->height; y++)
	{
		int x = 0;
		while (x <= pcxfile->head->width)
		{
			BYTE pixel = *in;
			if (--in_size < 0)			// buffer overflow prevention
			{
				clear(buff);
				return false;
			}
			in++;

			int runlength = 1;
			if ((pixel & 192) == 192)
			{
				runlength = pixel & 63;

				pixel = *in;
				if (--in_size < 0)		// buffer overflow prevention
				{
					clear(buff);
					return false;
				}
				in++;
			}

			while (runlength-- > 0)
			{
				*out = pixel;
				if (--out_size < 0)		// buffer overflow prevention
				{
					clear(buff);
					return false;
				}
				out++;

				x++;
			}
		}
	}

	clear(pcxfile->pixels);
	pcxfile->pixels = buff;
	pcxfile->size = size;
	pcxfile->head->width++;
	pcxfile->head->height++;
	return true;
}

/*
void PixelToASCII(char* filename, BYTE* pixels, int size, int rows)
{
	if (filename == 0 || pixels == 0 || size <= 0)
		return;

	int len = lstrlen(filename);
	if (len <= 0)
		return;

	char* newname = (char*)alloc(len+1);
	if (newname == 0)
		return;

	lstrcpy(newname, filename);
	if (swapext(newname, "txt", len) == false)
	{
		clear(newname);
		return;
	}

	FILE* outfile = fopen(newname, "w");
	if (outfile == 0)
	{
		clear(newname);
		return;
	}

	int row = 0;
	for (int i = 0; i < size; i++)
	{
		char pixel = pixels[i];
		if (pixel != 0) {
			pixel = '#';
		} else {
			pixel = '.';
		}
		fprintf(outfile,"%c",pixel);
		row++;
		if (row >= rows)
		{
			row = 0;
			fprintf(outfile,"\n");
		}
	}

	fclose(outfile);
	clear(newname);
}

// USAGE: OutputTXT(filename, pixels, size, width);

*/

long __fastcall GetDC6FrameCount(long width, long height)
{
	double dwidth = (double)width;
	double dheight = (double)height;
	double dframes = ceil(dwidth / 256) * ceil(dheight / 256);
	return (long)dframes;
}

void DeleteDC6(CellFile* cellfile)
{
	if (cellfile == 0)
		return;

	if (cellfile->head != 0)
		clear(cellfile->head);
	cellfile->head = 0;

	CellFrameList* frame = cellfile->framehead;
	cellfile->framehead = 0;
	cellfile->frametail = 0;
	while (frame != 0)
	{
		CellFrameList* next = frame->next;
		frame->next = 0;
		if (frame->frame != 0)
			clear(frame->frame);
		frame->frame = 0;
		frame->parent = 0;
		clear(frame);
		frame = next;
	}

	clear(cellfile);
}

bool AddDC6Frame(CellFile* file, long width, long height, BYTE* pixels)
{
	if (file == 0 || width <= 0 || height <= 0 || pixels == 0)
		return false;

	CellFrameList* cellframe = (CellFrameList*)silentalloc(sizeof(CellFrameList));
	if (cellframe == 0)
		return false;

	if (file->framehead == 0)
		file->framehead = cellframe;

	if (file->frametail != 0)
		file->frametail->next = cellframe;

	cellframe->parent = file;
	file->frametail = cellframe;
	long frame_size = width * height;
	if (frame_size <= 0)
		return 0;

	cellframe->pixels = pixels;
	cellframe->size = frame_size;

	CellFrame* framehead = (CellFrame*)silentalloc(sizeof(CellFrame));
	if (framehead == 0)
		return false;

	framehead->flip = 0;
	framehead->width = width;
	framehead->height = height;
	framehead->unknown = 0;
	framehead->x_offset = 0;
	framehead->y_offset = 0;
	framehead->next_frame_offset = 0;
	framehead->frame_size = 0;
	cellframe->frame = framehead;
	file->frame_count++;
	return true;
}

CellFile* CreateDC6File(BYTE* pixels, DWORD size, long width, long height, bool transparent, char fillcolor, int directions, CellOffset* offsets)
{
	if (pixels == 0 || size == 0)
		return 0;

	if (width <= 0 || height <= 0 || directions < 1 || directions > 64)
		return 0;
		
	CellFile* cellfile = (CellFile*)silentalloc(sizeof(CellFile));
	if (cellfile == 0)
		return 0;

	CellHeader* cellhead = (CellHeader*)silentalloc(sizeof(CellHeader));
	cellfile->head = cellhead;
	cellfile->height = height;
	cellfile->width = width;
	cellfile->transparent = transparent;
	cellfile->filler = fillcolor;
	cellfile->dir_count = directions;

	if (cellhead == 0)
	{
		DeleteDC6(cellfile);
		return 0;
	}

	long frames = GetDC6FrameCount(width, height);
	if (frames <= 0 || frames % directions != 0)
	{
		DeleteDC6(cellfile);
		return 0;
	}

	cellhead->version = 6;
	cellhead->unknown1 = 1;
	cellhead->unknown2 = 0;
	cellhead->filler = 0xEEEEEEEE;
	cellhead->dir_count = directions;
	cellhead->frame_count = frames / directions;

	for (int y = 0; y < height; y += 256)
	{
		int x = 0;
		while (x < width)
		{
			long frame_x = (width - x > 256) ? 256 : width - x;
			long frame_y = (height - y > 256) ? 256 : height - y;
			DWORD offset = x + (y * width);

			BYTE* frame_px = pixels + offset;
			long frame_size = size - offset;
			if (frame_size <= 0)
			{
				DeleteDC6(cellfile);
				return 0;
			}

			if (AddDC6Frame(cellfile, frame_x, frame_y, frame_px) == false)
			{
				DeleteDC6(cellfile);
				return 0;
			}

			x += 256;
		}
	}

	if (offsets != 0)
	{
		DWORD this_dir = 0;
		DWORD this_frame = 0;
		CellFrameList* frame = cellfile->framehead;
		while (frame != 0)
		{
			frame->frame->x_offset = offsets[this_dir].x_offset;
			frame->frame->y_offset = offsets[this_dir].y_offset;
			frame = frame->next;
			if (frame == 0)
				break;

			this_frame++;
			if (this_frame >= cellfile->head->frame_count)
			{
				this_dir++;
				if (this_dir >= cellfile->head->dir_count)
				{
					DeleteDC6(cellfile);
					return 0;
				}

				this_frame = 0;
			}
		}
	}

	return cellfile;
}

bool ValidateDC6(CellFile* file)
{
	if (file == 0)
		return false;

	if (file->width == 0 || file->height == 0)
		return false;

	if (file->frame_count <= 0)
		return false;

	if (file->framehead == 0)
		return false;

	if (file->frametail == 0)
		return false;

	CellHeader* head = file->head;
	if (head == 0)
		return false;

	if (head->dir_count <= 0 || head->frame_count <= 0)
		return false;

	if (head->version != 6)
		return false;

	CellFrameList* frame = file->framehead;
	DWORD frames = 0;
	while (frame != 0)
	{
		if (frame->parent == 0)
			return false;

		if (frame->pixels == 0)
			return false;

		if (frame->size <= 0)
			return false;

		CellFrame* framehead = frame->frame;
		if (framehead == 0)
			return false;

		if (framehead->width <= 0 || framehead->height <= 0)
			return false;

		frame = frame->next;
		frames++;
	}

	if (frames != head->frame_count * head->dir_count)
		return false;

	if (frames != file->frame_count)
		return false;

	return true;
}

bool write_data(FILE* file, size_t size, DWORD data)
{
	if (file != 0)
	{
		void* data_ptr = &
		DWORD written = fwrite(data_ptr, 1, size, file);
		if (written != size)
		{
			fclose(file);
			return false;
		}

		return true;
	}

	return false;
}

bool WriteDC6Head(CellHeader* head, FILE* file)
{
	if (file == 0)
		return false;

	if (head == 0 )
	{
		fclose(file);
		return false;
	}

	DWORD written = fwrite(head, 1, sizeof(CellHeader), file);
	if (written != sizeof(CellHeader))
	{
		fclose(file);
		return false;
	}

	return true;
}

bool WriteDC6Pixels(FILE* file, BYTE* data, long width, long height, long rowbytes, bool transparent, char filler)
{
	if (file == 0)
		return false;

	if (data == 0 || width <= 0 || height <= 0)
	{
		fclose(file);
		return false;
	}

	long line = height - 1;
	long pixels = 0;

	BYTE* in = data + (rowbytes * line);
	while (line >= 0)
	{
		while (pixels < width)
		{
			long pwidth = width - pixels;
			if (pwidth > 127)
				pwidth = 127;

			if (transparent == true)
			{
				if (*in == filler)
				{
					int count = 0;
					BYTE* test = in;

					for (int i = pixels; i < width; i++)
					{
						if (*test != filler)
							break;

						count++;
						test++;
					}

					if ((count + pixels) == width)
					{
						pixels += count;
						in += count;
						continue;
					}

					if (count > 127)
						count = 127;

					pixels += count;
					in += count;
					fputc(count + 128, file);
					continue;
				}
					else
				{
					for (int i = 0; i < pwidth; i++)
					{
						if (in[i] == filler)
						{
							pwidth = i;
							break;
						}
					}
				}
			}

			fputc(pwidth, file);
			for (int i = 0; i < pwidth; i++)
			{
				fputc(*in++, file);
				pixels++;
			}
		}

		pixels = 0;
		line--;
		fputc(128, file);
		in = data + (rowbytes * line);
	}


	return true;
}

bool WriteDC6Frame(CellFrameList* frame, FILE* file, DWORD ptr_offset)
{
	if (file == 0)
		return false;

	if (frame == 0 || ptr_offset == 0)
	{
		fclose(file);
		return false;
	}

	CellFrame* head = frame->frame;
	if (head == 0)
	{
		fclose(file);
		return false;
	}

	DWORD frame_pos = ftell(file);
	fseek(file, ptr_offset, SEEK_SET);
	if (write_data(file, 4, frame_pos) == false)
		return false;

	fseek(file, frame_pos, SEEK_SET);

	DWORD written = fwrite(head, 1, sizeof(CellFrame), file);
	if (written != sizeof(CellFrame))
	{
		fclose(file);
		return false;
	}

	DWORD last_pos = ftell(file) - 8;
	
	CellFile* cellfile = frame->parent;
	if (cellfile == 0)
	{
		fclose(file);
		return false;
	}

	if (WriteDC6Pixels(file, frame->pixels, head->width, head->height, cellfile->width, cellfile->transparent, cellfile->filler) == false)
		return false;

	frame_pos = ftell(file);
	fseek(file, last_pos, SEEK_SET);

	if (write_data(file, 4, frame_pos + 3) == false)
		return false; 
	
	if (write_data(file, 4, frame_pos - last_pos - 8) == false)
		return false;

	fseek(file, frame_pos, SEEK_SET);
	for (int i = 0; i < 3; i++)
		fputc(0xEE, file);

	return true;
}

bool WriteDC6File(CellFile* file, char* filename)
{
	if (filename == 0)
		return false;

	if (ValidateDC6(file) == false)
		return false;

	int len = lstrlen(filename);
	if (len <= 0)
		return false;

	char* newname = (char*)silentalloc(len+1);
	if (newname == 0)
		return false;

	lstrcpy(newname, filename);
	if (swapext(newname, "dc6", len) == false)
	{
		clear(newname);
		return false;
	}

	FILE* outfile = fopen(newname, "wb");
	clear(newname);
	if (outfile == 0)
		return false;

	if (WriteDC6Head(file->head, outfile) == false)
		return false;

	DWORD refoffset = ftell(outfile);
	for (int i = 0; i < (int)file->frame_count; i++)
	{
		if (write_data(outfile, 4, 0) == false)
			return false;
	}

	DWORD frame_idx = 0;
	CellFrameList* frame = file->framehead;
	while (frame != 0)
	{
		if (WriteDC6Frame(frame, outfile, frame_idx * 4 + refoffset) == false)
			return false;

		frame_idx++;
		frame = frame->next;
	}

	fclose(outfile);
	return true;
}

int __fastcall BatchConvertToDC6(FileList* file, void* arg)
{
	if (file == 0 || file->filename == 0 || arg == 0)
		return 0;

	BatchConvertToDC6Args* args = (BatchConvertToDC6Args*)arg;
	if (args->structsize != sizeof(BatchConvertToDC6Args))
		return 0;

	PcxFile* pcxfile = ReadPCX(file->filename, args->background);
	if (pcxfile == 0)
		return 0;

	int ret = (DecodePCX(pcxfile) != false) ? 1 : 0;
	if (ret == 1)
	{
		CellFile* cellfile = CreateDC6File(pcxfile->pixels, pcxfile->size, pcxfile->head->width, pcxfile->head->height, args->transparent, args->background, args->directions, args->offsets);
		if (cellfile == 0) {
			ret = 0;
		} else {
			WriteDC6File(cellfile, file->filename);
			DeleteDC6(cellfile);
		}
	}

	DeletePCX(pcxfile);
	return ret;
}

int ProcessFileList(FileListCycler fpListFunc, void* args)
{
	if (IsBadCodePtr((FARPROC)fpListFunc) != 0)
		error("INVALID FUNCTION POINTER");

	int count = 0;
	FileList* file = filehead;

	while (file != 0)
	{
		FileList* next = file->next;
		count += fpListFunc(file, args);
		file = next;
	}

	return count;
}

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* szCmdLine, int nShowCmd)
{
	InitHeap(16);


	// test data, add GUI is next step
	CreateFileList("pcx");
	BatchConvertToDC6Args args;
	args.structsize = sizeof(BatchConvertToDC6Args);
	args.transparent = true;
	args.directions = 4;
	args.background = 0;
	CellOffset offsets[4];
	offsets[0].x_offset = -100;
	offsets[0].y_offset = 200;
	offsets[1].x_offset = -100;
	offsets[1].y_offset = 200;
	offsets[2].x_offset = -100;
	offsets[2].y_offset = 200;
	offsets[3].x_offset = -100;
	offsets[3].y_offset = 200;
	args.offsets = offsets;
	ProcessFileList(BatchConvertToDC6, &args);
	

	cleanup();
	return 0;
}

void cleanup()
{
	DeleteFileList();
	KillHeap();
}
Last edited by Nefarius on Thu Feb 07, 2008 9:54 pm, edited 1 time in total.
''(...) The game can basically be considered unhackable. '' - Blizzard Entertainment (30th May 2000)
Black Omen Productions | MetalStorm: Progress Report | Screenshots

User avatar
Nefarius
Retired Admin
Cherub
Posts: 11607
Joined: Sat Jun 15, 2002 8:13 pm
Location: Where the blood forever rains
Contact:

Hand-picked

Re: Dev Apps - Public Source Dump

Post by Nefarius » Mon Feb 18, 2008 4:38 am

Source Statistics Tool

This outputs a formatted list of the size of a project in BYTES and LINES, there are many tools out there that do this, but I didn't particularly like any so I made this here.

Code: Select all

#define WIN32_LEAN_AND_MEAN
#include <WINDOWS.H>
#include <CSTDIO>

/*

	the concept of this application is to map out all source files involved in a certain project
	and all of its subdirectories and generate a structured file with information about line count
	as well as total line count for the entire project, I realize there are existing programs
	to do the same, but they are either too sophisticated, too target specific or are not freeware
	from what I've seen so far, this should just be a very simple program
	Source (c) 2008 - /\/epharius

*/

struct FileNode
{
	char* name;
	FileNode* next;
};

struct FolderNode
{
	char* name;
	bool searched;
	FolderNode* next;
};

struct NodeList
{
	void* head;
	void* tail;
	long count;
};

static int longest = 0;
static NodeList* folders = 0;
static NodeList* files = 0;
static void* heap = 0;

void ErrorMessage(char* expression, char* file, long line, unsigned long address)
{
	char buffer[3500];
	wsprintf(buffer, "ERROR: %s\nFILE: %s, LINE: #%u\nLOCATION: 0x%08X", expression, file, line, address);
	MessageBox(0, buffer, "ASSERTION FAILED", MB_OK | MB_ICONEXCLAMATION);
	TerminateProcess(GetCurrentProcess(), -1);
}

__declspec (naked) unsigned long GetAddress()
{
	__asm
	{
		mov eax,[esp]
		retn
	}
}

#define ASSERT(e) if (e == 0) { ErrorMessage(#e, __FILE__, __LINE__, GetAddress()); }

void InitHeap(long megs)
{
	megs <<= 20;
	heap = HeapCreate(0, megs, 0);
	ASSERT(heap)
}

void KillHeap()
{
	HeapDestroy(heap);
}

void* alloc(size_t size)
{
	void* mem = HeapAlloc(heap, HEAP_ZERO_MEMORY, size);
	ASSERT(mem)
	return mem;
}

void flush(void* mem)
{
	HeapFree(heap, 0, mem);
}

void AddFolderNode(char* base, char* name)
{
	char* path = 0;

	if (name != 0)
	{
		int length = lstrlen(base) + lstrlen(name) + 10;
		path = (char*)alloc(length);
		wsprintf(path, "%s\\%s", base, name);
	}
		else
	{
		int length = lstrlen(base) + 10;
		path = (char*)alloc(length);
		lstrcpy(path, base);
	}

	if (folders == 0)
		folders = (NodeList*)alloc(sizeof(NodeList));
	
	FolderNode* obj = (FolderNode*)alloc(sizeof(FolderNode));
	obj->name = path;
	obj->searched = false;
	obj->next = 0;

	if (name == 0)
		obj->searched = true;

	if (folders->head == 0)
		folders->head = obj;
	
	if (folders->tail != 0)
	{
		FolderNode* tail = (FolderNode*)folders->tail;
		tail->next = obj;
	}

	folders->tail = obj;
	folders->count++;
}

void ClearFolderList()
{
	if (folders == 0)
		return;

	FolderNode* node = (FolderNode*)folders->head;
	while (node != 0)
	{
		FolderNode* next = node->next;
		if (node->name != 0)
			flush(node->name);
		flush(node);
		node = next;
	}

	flush(folders);
	folders = 0;
}

char* DupeString(char* string)
{
	int length = lstrlen(string);
	char* temp = (char*)alloc(length + 1);
	lstrcpy(temp, string);
	return temp;
}

bool GoodFolder(char* current, char* folder)
{
	if (lstrlen(folder) <= 0)
		return false;

	if (lstrcmpi(current, folder) == 0)
		return false;

	if (lstrcmpi(folder, ".") == 0 || lstrcmpi(folder, "..") == 0)
		return false;

	AddFolderNode(current, folder);
	return true;
}

void MakeFolderList()
{
	char* current = (char*)alloc(MAX_PATH + 1);
	GetCurrentDirectory(MAX_PATH, current);
	AddFolderNode(current, 0);

	while (true)
	{
		char* pattern = (char*)alloc(lstrlen(current) + 10);
		lstrcpy(pattern, current);
		lstrcat(pattern, "\\*");

		WIN32_FIND_DATA w32;
		memset(&w32, 0, sizeof(w32));

		void* search = FindFirstFile(pattern, &w32);
		ASSERT(search)

		do {

			if (w32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
				GoodFolder(current, w32.cFileName);

		} while (FindNextFile(search, &w32) != 0);

		FindClose(search);

		if (folders == 0)
			break;

		flush(pattern);
		pattern = 0;

		flush(current);
		current = 0;

		FolderNode* node = (FolderNode*)folders->head;
		while (node != 0)
		{
			if (node->searched == false)
			{
				current = DupeString(node->name);
				node->searched = true;
				break;
			}

			node = node->next;
		}

		if (current == 0)
			break;
	}
}

bool HasChar(char* name, char c)
{
	int length = lstrlen(name);
	for (int i = 0; i < length; i++)
	{
		if (name[i] == c)
			return true;
	}

	return false;
}

void AddFileNode(char* ext, char* path, char* name)
{
	if (HasChar(name, '*') == true)
		return;
	
	if (HasChar(name, '.') == false)
		return;

	char* buffer = (char*)alloc(lstrlen(path) + lstrlen(name) + 10);
	wsprintf(buffer, "%s\\%s", path, name);

	if (files == 0)
		files = (NodeList*)alloc(sizeof(NodeList));

	FileNode* obj = (FileNode*)alloc(sizeof(FileNode));
	if (files->head == 0)
		files->head = obj;

	if (files->tail != 0)
	{
		FileNode* tail = (FileNode*)files->tail;
		tail->next = obj;
	}

	files->tail = obj;
	files->count++;
	obj->next = 0;
	obj->name = buffer;

	int length = lstrlen(buffer);
	if (length > longest)
		longest = length;
}

void ClearFileList()
{
	if (files == 0)
		return;

	FileNode* node = (FileNode*)files->head;
	while (node != 0)
	{
		FileNode* next = node->next;
		if (node->name != 0)
			flush(node->name);

		flush(node);
		node = next;
	}

	flush(files);
	files = 0;
}

void ProcessFolder(char* dir, char** exts, int count)
{
	for (int i = 0; i < count; i++)
	{
		char* ext = exts[i];
		char* path = (char*)alloc(lstrlen(dir) + lstrlen(ext) + 10);
		wsprintf(path, "%s\\*.%s", dir, ext);

		WIN32_FIND_DATA w32;
		memset(&w32, 0, sizeof(w32));

		void* search = FindFirstFile(path, &w32);
		ASSERT(search)

		do {
			AddFileNode(ext, dir, w32.cFileName);
		} while (FindNextFile(search, &w32) != 0);

		FindClose(search);
		flush(path);
	}
}

void MakeFileList(char** exts, int count)
{
	if (folders == 0)
		return;

	FolderNode* node = (FolderNode*)folders->head;
	while (node != 0)
	{
		ProcessFolder(node->name, exts, count);
		node = node->next;
	}
}

void GetData(char* filename, unsigned long* lines,unsigned long* size)
{
	*lines = 0;
	*size = 0;

	FILE* in = fopen(filename, "rb");
	if (in == 0)
		return;

	fseek(in, 0, SEEK_END);
	*size = ftell(in);
	rewind(in);

	if (*size == 0)
	{
		fclose(in);
		return;
	}

	char* buffer = (char*)alloc(*size);
	long buffsize = fread(buffer, 1, *size, in);
	fclose(in);
	if (buffsize <= 0)
	{
		flush(buffer);
		return;
	}

	for (long i = 0; i < buffsize; i++)
	{
		if (buffer[i] == '\n')
			*lines += 1;
	}

	flush(buffer);
}

void AddFileToText(FILE* out, char* file, unsigned long lines, unsigned long size)
{
	int length = lstrlen(file);
	fprintf(out, "%s", file);

	while (length < longest + 10)
	{
		fprintf(out, "%s", " ");
		length++;
	}

	fprintf(out, "LINES: %8u, SIZE: %8u BYTES\n", lines, size);
}

void OutputList(char* filename)
{
	if (files == 0)
		return;

	FILE* out = fopen(filename, "w");
	ASSERT(out)

	unsigned long totalsize = 0;
	unsigned long totallines = 0;
	FileNode* file = (FileNode*)files->head;
	while (file != 0)
	{
		unsigned long lines;
		unsigned long size;
		GetData(file->name, &lines, &size);
		AddFileToText(out, file->name, lines, size);

		file = file->next;
		totalsize += size;
		totallines += lines;
	}

	fprintf(out, "\nTOTAL LINES: %8u\nTOTAL SIZE:  %8u BYTES", totallines, totalsize);

	fclose(out);
}

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* szCmdLine, int nShowCmd)
{
	InitHeap(30);
	MakeFolderList();

	char* exts[] = {"c", "cpp", "h", "hxx", "cxx", "hpp", "def", "rc"};
	int count = sizeof(exts) / sizeof(char*);
	MakeFileList(exts, count);
	OutputList("out.txt");

	ClearFileList();
	ClearFolderList();
	KillHeap();
	return 0;
}
''(...) The game can basically be considered unhackable. '' - Blizzard Entertainment (30th May 2000)
Black Omen Productions | MetalStorm: Progress Report | Screenshots

User avatar
Nefarius
Retired Admin
Cherub
Posts: 11607
Joined: Sat Jun 15, 2002 8:13 pm
Location: Where the blood forever rains
Contact:

Hand-picked

Re: Dev Apps - Public Source Dump

Post by Nefarius » Mon Aug 04, 2008 4:52 pm

Modified version of Purge (the old one you can download from the filecenter if its still there), that is more efficient etc.

Code: Select all

#include <CSTDIO>
#include <CSTRING>
#include <CSTDLIB>

struct Hash
{
	char* text;
	Hash* next;
};

typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;

#define HASH_SIZE 2048
#define HASH_BYTES sizeof(Hash*) * HASH_SIZE

static BYTE gHashBytes[ 256 ] =
{
	// this is from the key schedule of AES
	// couldn't be bothered to generate something for this

	0x8D, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
	0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A, 0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39,
	0x72, 0xE4, 0xD3, 0xBD, 0x61, 0xC2, 0x9F, 0x25, 0x4A, 0x94, 0x33, 0x66, 0xCC, 0x83, 0x1D, 0x3A,
	0x74, 0xE8, 0xCB, 0x8D, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36, 0x6C, 0xD8,
	0xAB, 0x4D, 0x9A, 0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A, 0xD4, 0xB3, 0x7D, 0xFA, 0xEF,
	0xC5, 0x91, 0x39, 0x72, 0xE4, 0xD3, 0xBD, 0x61, 0xC2, 0x9F, 0x25, 0x4A, 0x94, 0x33, 0x66, 0xCC,
	0x83, 0x1D, 0x3A, 0x74, 0xE8, 0xCB, 0x8D, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B,
	0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A, 0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A, 0xD4, 0xB3,
	0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39, 0x72, 0xE4, 0xD3, 0xBD, 0x61, 0xC2, 0x9F, 0x25, 0x4A, 0x94,
	0x33, 0x66, 0xCC, 0x83, 0x1D, 0x3A, 0x74, 0xE8, 0xCB, 0x8D, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
	0x40, 0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A, 0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35,
	0x6A, 0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39, 0x72, 0xE4, 0xD3, 0xBD, 0x61, 0xC2, 0x9F,
	0x25, 0x4A, 0x94, 0x33, 0x66, 0xCC, 0x83, 0x1D, 0x3A, 0x74, 0xE8, 0xCB, 0x8D, 0x01, 0x02, 0x04,
	0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A, 0x2F, 0x5E, 0xBC, 0x63,
	0xC6, 0x97, 0x35, 0x6A, 0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39, 0x72, 0xE4, 0xD3, 0xBD,
	0x61, 0xC2, 0x9F, 0x25, 0x4A, 0x94, 0x33, 0x66, 0xCC, 0x83, 0x1D, 0x3A, 0x74, 0xE8, 0xCB, 0x00,
};

DWORD PURGE_MakeHash(char* szText, size_t iSize)
{
	char* buf = szText;
	char* end = buf + iSize - 1;

	DWORD dwHash = 0;
	DWORD i = 0;

	while (buf < end)
	{
		if (i > 32)
		{
			i = 0;
		}

		*buf = tolower(*buf);

		dwHash = (_rotl(dwHash + (gHashBytes[ *buf % 256 ] << i), i) >> i) ^ _rotr(dwHash, i);
	
		++i;
		buf++;
	}

	*end = 0;

	return ((((dwHash >> 8) ^ dwHash) >> 16) ^ (dwHash >> 8) ^ dwHash) & (HASH_SIZE - 1);
}

static Hash** gHashTable = NULL;
static int gTotalObjects = 0;

void PURGE_FlushTable()
{
	gTotalObjects = 0;

	if (gHashTable == NULL)
	{
		return;
	}

	for (int i = 0; i < HASH_SIZE; i++)
	{
		Hash* pHash = gHashTable[i];

		while (pHash)
		{
			Hash* pNext = pHash->next;

			if (pHash->text)
			{
				free(pHash->text);
			}

			free(pHash);

			pHash = pNext;
		}
	}

	free(gHashTable);

	gHashTable = NULL;
}

static char gReadBuffer[ 16384 ];

int PURGE_OutputFile(FILE* pFile)
{
	if (pFile == NULL)
	{
		return -1;
	}

	if (gHashTable == NULL)
	{
		return -2;
	}

	for (int i = 0; i < HASH_SIZE; i++)
	{
		Hash* pHash = gHashTable[i];

		while (pHash)
		{
			if (pHash->text)
			{
				fprintf(pFile, "%s\n", pHash->text);
			}

			pHash = pHash->next;
		}
	}

	return 0;
}

int PURGE_ProcessFile(FILE* pFile)
{
	PURGE_FlushTable();

	if (pFile == NULL)
	{
		return -1;
	}

	gHashTable = (Hash **)malloc( HASH_BYTES );

	if (gHashTable == NULL)
	{
		return -2;
	}

	memset(gHashTable, 0, HASH_BYTES);

	while (fgets(gReadBuffer, 16384, pFile))
	{
		int iSize = strlen(gReadBuffer);

		if (iSize <= 0)
		{
			continue;
		}

		Hash* pHash = (Hash *)malloc(sizeof(Hash));

		if (pHash == NULL)
		{
			continue;
		}

		DWORD dwHash = PURGE_MakeHash(gReadBuffer, iSize);

		pHash->text = NULL;
		pHash->next = gHashTable[ dwHash ];

		gHashTable[ dwHash ] = pHash;

		char* szText = (char *)malloc(iSize + 1);
		
		if (szText == NULL)
		{
			continue;
		}

		strcpy(szText, gReadBuffer);

		pHash->text = szText;

		gTotalObjects++;
	}

	printf("file contains %u object(s)\n", gTotalObjects);

	int iDupes = 0;
	printf("scanning hash table for duplicates\n");

	for (int i = 0; i < HASH_SIZE; i++)
	{
		Hash* pHash = gHashTable[i];

		while (pHash)
		{
			if (pHash->text)
			{
				Hash* pCheckHash = pHash->next;

				while (pCheckHash != NULL)
				{
					if (pCheckHash->text)
					{
						if (!strcmp(pCheckHash->text, pHash->text))
						{
							printf("duplicate %s found\n", pHash->text);
							free(pCheckHash->text);
							pCheckHash->text = NULL;
							iDupes++;
						}
					}

					pCheckHash = pCheckHash->next;
				}
			}

			pHash = pHash->next;
		}
	}

	printf("%d duplicate(s) found\n", iDupes);

	return 0;
}

int PURGE_IsValidFile(char* szFileName)
{
	if (szFileName == NULL)
	{
		return 0;
	}

	int iSize = strlen(szFileName);

	if (iSize < 5)
	{
		return 0;
	}

	char* buf = szFileName + iSize - 4;

	if (strcmpi(buf, ".txt"))
	{
		return 0;
	}

	buf = szFileName;
	char* end = szFileName + iSize - 1;

	while (buf < end)
	{
		*buf = tolower(*buf);
		buf++;
	}

	return 1;
}

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		return 0;
	}

	for (int i = 1; i < argc; i++)
	{
		char* szFileName = argv[i];

		if (!PURGE_IsValidFile(szFileName))
		{
			continue;
		}

		FILE* pFile = fopen(szFileName, "r");

		printf("processing file %s\n", szFileName);

		int iError;

		if ((iError = PURGE_ProcessFile(pFile)))
		{
			printf("read error %d encountered\n", iError);
			fclose(pFile);
			continue;
		}

		fclose(pFile);

		pFile = fopen(szFileName, "w");

		if ((iError = PURGE_OutputFile(pFile)))
		{
			printf("write error %d encountered\n", iError);
		}

		fclose(pFile);
	}

	PURGE_FlushTable();

	return 0;
}
Last edited by Nefarius on Mon Aug 04, 2008 4:57 pm, edited 1 time in total.
''(...) The game can basically be considered unhackable. '' - Blizzard Entertainment (30th May 2000)
Black Omen Productions | MetalStorm: Progress Report | Screenshots

User avatar
Nefarius
Retired Admin
Cherub
Posts: 11607
Joined: Sat Jun 15, 2002 8:13 pm
Location: Where the blood forever rains
Contact:

Hand-picked

Re: Dev Apps - Public Source Dump

Post by Nefarius » Thu Aug 21, 2008 2:22 am

New ExpGen, should fix the problems some people had with "spaces".

Code: Select all

#include <CSTDIO>
#include <CSTDLIB>
#include <CMATH>

void makefile(FILE* file, long levels, long decay, long start)
{
	if (levels <= 1)
	{
		printf("error: maximum level cannot be %d\n", levels);
		return;
	}

	if (decay < 0 || decay > 32)
	{
		printf("error: decay rate must be between 0 and 32, defaulting to 0\n");
		decay = 0;
	}

	if (start < 1 || start > levels)
	{
		printf("error: start of decay cannot be %d\n, defaulting to 1", start);
		start = 1;
	}

	fprintf(file, "Level\tAmazon\tSorceress\tNecromancer\tPaladin\tBarbarian\tDruid\tAssassin\tExpRatio\n");
	fprintf(file, "MaxLvl\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", levels, levels, levels, levels, levels, levels, levels, decay);

	decay = 1 << decay;

	fprintf(file, "0\t0\t0\t0\t0\t0\t0\t0\t%d\n", decay);

	double fstart = start;
	double maxlvl = levels;
	double fdecay = decay;

	for (int i = 1; i <= levels; i++)
	{
		double lvl = i;
		double exp = (4294967295.0 - (lvl * 256.0)) * pow(lvl / maxlvl, 4) + (lvl * 256.0);

		double s = lvl - fstart;

		s = (s <= 0.0) ? 0.0 : s;

		double rate = fdecay - fdecay / ( maxlvl - fstart ) * s;
		rate = (rate <= 1.0) ? 1.0 : rate;

		unsigned long _exp = (unsigned long)exp;
		unsigned long _rate = (unsigned long)rate;

		fprintf(file, "%d\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\n", i, _exp, _exp, _exp, _exp, _exp, _exp, _exp, _rate);
	}
}

int main(int argc, char* argv[])
{
	if (argc < 5)
	{
		printf("correct usage is expgen.exe <FILENAME> <MAX LEVEL> <DECAY> <DECAY START>\n");
		return 0;
	}

	FILE* file = fopen(argv[1], "w");

	if (file == NULL)
	{
		printf("error: cannot open %s for writing\n", argv[1]);
		return 0;
	}

	long levels			= atol(argv[2]);
	long decay			= atol(argv[3]);
	long decay_start	= atol(argv[4]);

	makefile(file, levels, decay, decay_start);

	fclose(file);

	return 0;
}
Last edited by Nefarius on Thu Aug 21, 2008 2:31 am, edited 1 time in total.
''(...) The game can basically be considered unhackable. '' - Blizzard Entertainment (30th May 2000)
Black Omen Productions | MetalStorm: Progress Report | Screenshots

User avatar
Nefarius
Retired Admin
Cherub
Posts: 11607
Joined: Sat Jun 15, 2002 8:13 pm
Location: Where the blood forever rains
Contact:

Hand-picked

Re: Dev Apps - Public Source Dump

Post by Nefarius » Tue Sep 16, 2008 9:23 pm

Convert TrueType font to 16x16 BMP to use with Paul's old font tool for converting to DC6 (this is entirely useless unless you change the code though, to support other character sizes). Stores TEXTMETRIC and ABC data for the font in a *.sov file. Based in part on some code I found on the net.

Code: Select all

#include <WINDOWS.H>
#include <CSTDIO>
#include <CSTDARG>
#include "RESOURCE.H"

#define ARRSIZE(arr) sizeof(arr) / sizeof(arr[0])

int __cdecl ShowMessage(HWND hwnd, char* title, UINT options, char* format, ...)
{
	va_list args;
	va_start(args, format);

	char msg[ 1024 ];
	memset(msg, 0, ARRSIZE(msg));
	_vsnprintf(msg, ARRSIZE(msg), format, args);

	return MessageBox(hwnd, msg, title, options);
}

void KillProcess(UINT exit)
{
	TerminateProcess(GetCurrentProcess(), exit);
}

void ShowError(char* event, char* file, int line)
{
	ShowMessage(NULL, "ASSERTION FAILURE", MB_OK, "EXPRESSION: %s\nFILE: %s, #%u", event, file, line);
	KillProcess(-1);
}

void ShowErrorEx(char* msg, BOOL fatal)
{
	ShowMessage(NULL, "RANDOM ERROR", MB_OK, msg);

	if (fatal)
	{
		KillProcess(-1);
	}
}

#define ASSERT(expr) if (!(expr)) ShowError(#expr, __FILE__, __LINE__);
#define ERRAR(msg) ShowErrorEx(msg, 1)
#define WARN(msg) ShowErrorEx(msg, 0)

static HFONT font = NULL;
static HINSTANCE inst = NULL;
static char iniPath[ 1024 ];
static char fontName[ 1024 ];
static DWORD fontFlags = 0;
static int fontSize = 0;

enum EFONTSTYLE
{
	EFONTSTYLE_NONE = 0,
	EFONTSTYLE_BOLD = 1,
	EFONTSTYLE_ITALICS = 2,
	EFONTSTYLE_UNDERLINED = 4,
	EFONTSTYLE_STRIKEOUT = 8,
};

void LoadConfig(char* filename)
{
	memset(iniPath, 0, ARRSIZE(iniPath));

	char buffer[ 1024 ];
	GetCurrentDirectory(ARRSIZE(buffer), buffer);

	_snprintf(iniPath, ARRSIZE(iniPath), "%s\\%s.ini", buffer, filename);

	FILE* file = fopen(iniPath, "rb");

	if (!file)
	{
		ERRAR("wtf, where did you idiots put my {filtered} ini file");
	}

	fclose(file);

	fontSize = GetPrivateProfileInt(filename, "fontSize", 0, iniPath);

	char fontStyle[ 48 ];

	GetPrivateProfileString(filename, "fontStyle", "", fontStyle, ARRSIZE(fontStyle), iniPath);

	char* buf = fontStyle;
	BYTE b;

	do
	{
		b = tolower(*buf++);
		DWORD flags;

		switch (b)
		{
			case 'b':	flags = EFONTSTYLE_BOLD;		break;
			case 'i':	flags = EFONTSTYLE_ITALICS;		break;
			case 'u':	flags = EFONTSTYLE_UNDERLINED;	break;
			case 's':	flags = EFONTSTYLE_STRIKEOUT;	break;
			default:	flags = EFONTSTYLE_NONE;		break;
		}

		fontFlags |= flags;

	} while(b);

	GetPrivateProfileString(filename, "fontName", "", fontName, ARRSIZE(fontName), iniPath);
}

void SaveFontInfo(char* filename, TEXTMETRIC* txtinfo, ABC* charinfo)
{
	FILE* out = fopen(filename, "wb");
	ASSERT(out);

	fwrite(txtinfo, 1, sizeof(TEXTMETRIC), out);
	fwrite(charinfo, 1, sizeof(ABC) * 256, out);

	fclose(out);
}

void SaveScreen(HWND hwnd, HDC hdc, char* filename, int w, int h)
{
	FILE* out = fopen(filename, "wb");
	ASSERT(out);

	BITMAPFILEHEADER head;
	BITMAPINFOHEADER info;

	head.bfType = 0x4D42;
	head.bfSize	= 0;
	head.bfReserved1 = 0;
	head.bfReserved2 = 0;
	head.bfOffBits = sizeof(head) + sizeof(info);

	info.biSize = sizeof(info);
	info.biWidth = w;
	info.biHeight = h;
	info.biPlanes = 1;
	info.biBitCount = 24;
	info.biCompression = BI_RGB;
	info.biSizeImage = 0;
	info.biXPelsPerMeter = 0;
	info.biYPelsPerMeter = 0;
	info.biClrUsed = 0;
	info.biClrImportant = 0;

	fwrite(&head, 1, sizeof(head), out);
	fwrite(&info, 1, sizeof(info), out);

	BITMAPINFO nfo;
	nfo.bmiHeader = info;

	HDC memdc = CreateCompatibleDC(hdc);
	ASSERT(memdc);

	BYTE* block = NULL;

	HBITMAP bmp = CreateDIBSection(hdc, &nfo, DIB_RGB_COLORS, (void**)&block, NULL, 0);
	ASSERT(bmp);

	SelectObject(memdc, bmp);

	BitBlt(memdc, 0, 0, w, h, hdc, 0, 0, SRCCOPY);

	DeleteDC(memdc);

	size_t bytes = (((24 * w + 31) & (~31)) / 8) * h;

	fwrite(block, 1, bytes, out);

	DeleteObject(bmp);

	fclose(out);
}

LRESULT __stdcall WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	switch (msg)
	{
		case WM_DESTROY:

			PostQuitMessage(WM_QUIT);

		break;

		default:

			return DefWindowProc(hwnd, msg, wparam, lparam);

	}

	return 0;
}

void SaveFont(HWND hwnd)
{
	HDC hdc = GetDC(hwnd);
	ASSERT(hdc);

	SelectObject(hdc, font);

	TEXTMETRIC txtinfo;
	GetTextMetrics(hdc, &txtinfo);

	ABC abc[256];
	GetCharABCWidths(hdc, 0, 255, abc);

	RECT rect;
	GetClientRect(hwnd, &rect);
	FillRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));

	SetBkColor(hdc, 0x000000);
	SetTextColor(hdc, 0xFFFFFF);

	unsigned char c;
	int left, top, bottom;

	for (int y = 0; y < 16; y++)
	{
		top = y * txtinfo.tmHeight;
		bottom = top + txtinfo.tmHeight;

		for (int x = 0; x < 16; x++)
		{
			left = x * txtinfo.tmMaxCharWidth;

			c = (unsigned char)(y * 16 + x);

			TextOut(hdc, left - abc[c].abcA, top, (const char*)&c, 1);

			left += abc[c].abcB;
			left += abc[c].abcC;
		}
	}

	char filename[ 1024 ];
	_snprintf(filename, ARRSIZE(filename), "%s%d.bmp", fontName, fontSize);

	SaveScreen(hwnd, hdc, filename, 16 * txtinfo.tmMaxCharWidth, 16 * txtinfo.tmHeight);

	_snprintf(filename, ARRSIZE(filename), "%s%d.sov", fontName, fontSize);
	SaveFontInfo(filename, &txtinfo, abc);

	ReleaseDC(hwnd, hdc);
}

void InitWindow(HINSTANCE instance)
{
	inst = instance;

	WNDCLASSEX args;

	args.cbSize			= sizeof(args);
	args.style			= CS_OWNDC|CS_VREDRAW|CS_HREDRAW;
	args.lpfnWndProc	= WndProc;
	args.cbClsExtra		= 0;
	args.cbWndExtra		= 0;
	args.hInstance		= instance;
	args.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
	args.hCursor		= LoadCursor(NULL, IDC_ARROW);
	args.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
	args.hIconSm		= LoadIcon(NULL, IDI_APPLICATION);
	args.lpszClassName	= "wndClassEx";
	args.lpszMenuName	= NULL;

	RegisterClassEx(&args);

	HWND hwnd = CreateWindowEx
	(
		WS_EX_OVERLAPPEDWINDOW,
		"wndClassEx",
		"FontRender",
		WS_OVERLAPPEDWINDOW|WS_VISIBLE,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		800,
		600,
		NULL,
		NULL,
		instance,
		NULL
	);

	SaveFont(hwnd);

	MSG msg;

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
}

void LoadFont()
{
	font = CreateFont
	(
		-fontSize,
		0,
		0,
		0,
		(fontFlags & EFONTSTYLE_BOLD) ? FW_BOLD : FW_NORMAL,
		(fontFlags & EFONTSTYLE_ITALICS) ? 1 : 0,
		(fontFlags & EFONTSTYLE_UNDERLINED) ? 1 : 0,
		(fontFlags & EFONTSTYLE_STRIKEOUT) ? 1 : 0,
		ANSI_CHARSET,
		OUT_DEFAULT_PRECIS,
		CLIP_DEFAULT_PRECIS,
		DRAFT_QUALITY,
		DEFAULT_PITCH|FF_DONTCARE,
		fontName
	);

	ASSERT(font);
}

void DeleteFont()
{
	if (font)
	{
		DeleteObject(font);
	}
}

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* szCmdLine, int nShowCmd)
{
	LoadConfig("FontRender");
	LoadFont();
	InitWindow(hInstance);
	DeleteFont();

	return 0;
}
Last edited by Nefarius on Tue Sep 16, 2008 9:25 pm, edited 1 time in total.
''(...) The game can basically be considered unhackable. '' - Blizzard Entertainment (30th May 2000)
Black Omen Productions | MetalStorm: Progress Report | Screenshots

User avatar
Nefarius
Retired Admin
Cherub
Posts: 11607
Joined: Sat Jun 15, 2002 8:13 pm
Location: Where the blood forever rains
Contact:

Hand-picked

Re: Dev Apps - Public Source Dump

Post by Nefarius » Sun Jun 07, 2009 2:05 pm

Small app that was recently updated to revive HC chars ( and convert between SC and HC and vice versa), we're not using this anymore due to the different file format but may be useful to some people dunno.

EDIT: :P forgot to increment version #, oh my...

Code: Select all

#include <WINDOWS.H>
#include <CSTDLIB>
#include <CSTDIO>
#include "RESOURCE.H"

static const char gszDefault[] = "Please load a file by clicking the <OPEN> button";
char gszPath[ MAX_PATH ];
HANDLE ghHeap = NULL;
BYTE* ghFile = NULL;
size_t giSize = NULL;

#define GET( buffer, type, offset ) *( ( type* )( (( BYTE *)( buffer )) + offset ) )
#define SET( buffer, type, offset, value ) *( ( type* )( (( BYTE *)( buffer )) + offset ) ) = type( value )

void __fastcall SetFileFlag(BYTE* hFile, size_t iSize, DWORD dwFlag, BOOL bSet)
{
	if ( hFile && iSize >= 0x28 )
	{
		DWORD dwMask = GET( hFile, DWORD, 0x24 );

		if ( bSet )
		{
			dwMask |= dwFlag;
		}
			else
		{
			dwMask &= ~dwFlag;
		}

		SET( hFile, DWORD, 0x24, dwMask );
	}
}

void __fastcall CheckSum(BYTE* hFile, size_t iSize)
{
	if ( hFile && iSize >= 0x10 )
	{
		SET( hFile, DWORD, 0x0C, 0 );

		DWORD dwSum = 0;

		BYTE* hBeg = hFile;
		BYTE* hEnd = hBeg + iSize;

		do
		{
			dwSum = _rotl( dwSum, 1 ) + *hBeg++;

		} while ( hBeg < hEnd );

		SET( hFile, DWORD, 0x0C, dwSum );
	}
}

void __fastcall SaveFile(HWND hWindow, BOOL bAsk)
{
	if ( !ghFile )
	{
		return;
	}

	if ( bAsk )
	{
		if ( MessageBox( hWindow, "Would you like to save the current file?", "HcTool v1.01", MB_YESNO ) != IDYES )
		{
			return;
		}
	}

	CheckSum( ghFile, giSize );

	FILE* hFile = fopen( gszPath, "wb" );

	do
	{
		if ( hFile == NULL )
		{
			break;
		}

		fwrite( ghFile, 1, giSize, hFile );

	} while ( false );

	if ( hFile )
	{
		fclose( hFile );
	}
}

void __fastcall SetText(HWND hWindow, const char* szMessage = NULL)
{
	if ( szMessage == NULL )
	{
		szMessage = gszDefault;
	}

	SetDlgItemText( hWindow, IDC_STATIC_TEXT, szMessage );
}

void __fastcall CloseFile(HWND hWindow)
{
	if ( ghFile )
	{
		HeapFree( ghHeap, 0, ghFile );
	}

	ghFile = NULL;
	giSize = 0;

	memset( gszPath, 0, sizeof(gszPath) );

	if ( hWindow )
	{
		SetText( hWindow );
	}
}

BYTE* __fastcall GetFile(HWND hWindow, size_t* pSize)
{
	OPENFILENAME ofn;
	memset( &ofn, 0, sizeof(ofn) );

	ofn.lStructSize			= sizeof(ofn);
	ofn.nMaxFile			= MAX_PATH;
	ofn.lpstrFile			= gszPath;
	ofn.lpstrFilter			= "Diablo II Save Games\0*.D2S\0";
	ofn.nFilterIndex		= 1;
	ofn.Flags				= OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;
	ofn.hwndOwner			= hWindow;

	FILE* hFile = NULL;
	BYTE* hFileBuffer = NULL;
	size_t iSize = 0;

	do
	{
		if ( !GetOpenFileName( &ofn ) )
		{
			break;
		}

		hFile = fopen( gszPath, "rb" );

		if ( hFile == NULL )
		{
			break;
		}

		fseek( hFile, 0, SEEK_END );
		iSize = ftell( hFile );
		rewind( hFile );

		if ( !iSize )
		{
			break;
		}

		hFileBuffer = (BYTE *)HeapAlloc( ghHeap, HEAP_ZERO_MEMORY, iSize );

		if ( hFileBuffer == NULL )
		{
			break;
		}

		size_t iReadSize = fread( hFileBuffer, 1, iSize, hFile );

		if ( iReadSize != iSize )
		{
			HeapFree( ghHeap, 0, hFileBuffer );

			hFileBuffer = NULL;

			break;
		}

		if ( hWindow )
		{
			SetText( hWindow, gszPath );
		}

	} while ( false );

	if ( hFile )
	{
		fclose( hFile );
	}

	*pSize = iSize;

	return hFileBuffer;
}

int __stdcall HcToolDialogProc(
									HWND hWindow,
									unsigned int eMessage,
									unsigned int nParams,
									long nMsg
								)
{
	if ( eMessage == WM_CLOSE )
	{
		SaveFile( hWindow, 1 );

		CloseFile( hWindow );

		EndDialog( hWindow, 0 );

		return 1;
	}
		else if ( eMessage == WM_COMMAND )
	{
		switch ( LOWORD( nParams ) )
		{
			case IDOPEN:
			{
				SaveFile( hWindow, 1 );

				CloseFile( hWindow );

				size_t iSize;
				BYTE* hFile = GetFile( hWindow, &iSize );	
			
				if ( hFile )
				{
					ghFile = hFile;
					giSize = iSize;
				}

				break;
			}

			case IDSAVE:
			{
				SaveFile( hWindow, 0 );

				CloseFile( hWindow );

				break;
			}

			case IDREVIVE:
			{
				SetFileFlag( ghFile, giSize, 8, 0 );

				break;
			}

			case IDSOFTCORE:
			{
				SetFileFlag( ghFile, giSize, 4, 0 );

				break;
			}

			case IDHARDCORE:
			{
				SetFileFlag( ghFile, giSize, 4, 1 );
				SetFileFlag( ghFile, giSize, 8, 0 );

				break;
			}
		}

		return 1;
	}
		else if ( eMessage == WM_INITDIALOG )
	{
		SetText( hWindow );

		HICON hIcon = LoadIcon( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_ICON ) );

		SendMessage(

			hWindow,
			WM_SETICON,
			ICON_SMALL,
			long( hIcon )
		);

		SendMessage(

			hWindow,
			WM_SETICON,
			ICON_BIG,
			long( hIcon )
		);

		return 1;
	}
	
	return 0;
}

int __stdcall WinMain(
						HINSTANCE hInstance,
						HINSTANCE hPrevInstance,
						char* szCmdLine,
						int nShowCmd
					)
{

	ghHeap = GetProcessHeap();
	
	if ( ghHeap == NULL )
	{
		return 1;
	}

	DialogBox( hInstance, MAKEINTRESOURCE(IDD_HCTOOL), NULL, HcToolDialogProc );

	CloseFile( NULL );

	return 0;
}
Last edited by Nefarius on Sun Jun 07, 2009 2:14 pm, edited 1 time in total.
''(...) The game can basically be considered unhackable. '' - Blizzard Entertainment (30th May 2000)
Black Omen Productions | MetalStorm: Progress Report | Screenshots

User avatar
Nefarius
Retired Admin
Cherub
Posts: 11607
Joined: Sat Jun 15, 2002 8:13 pm
Location: Where the blood forever rains
Contact:

Hand-picked

Re: Dev Apps - Public Source Dump

Post by Nefarius » Sun Jan 24, 2010 6:09 pm

CellBBox - automatically calcs bounding box for COF from DCC frame size, parses an entire token/wclass/armtype combo

Code: Select all

#define WIN32_LEAN_AND_MEAN
#include <WINDOWS.H>
#include <CSTDIO>
#include <CMATH>

#include "dccinfo.h"

// uses a version of Paul Siramy's dccinfo that I modified

__inline int GetIniValue( char* ptBuffer, size_t iSize, const char* ptKeyName, const char* ptFileName, int nTokenSize )
{
	memset( ptBuffer, 0, iSize );

	return ( GetPrivateProfileString( "Sprite", ptKeyName, "", ptBuffer, iSize, ptFileName ) == DWORD( nTokenSize ) );
}

__inline BOOL GetCellPX( int& x, int& y, int &h, const char* ptFileName )
{
	x = GetPrivateProfileInt( "Size", "x", 0, ptFileName );
	y = GetPrivateProfileInt( "Size", "y", 0, ptFileName );
	h = GetPrivateProfileInt( "Size", "h", 0, ptFileName );

	return ( x > 0 && x > 0 && h > 0 );
}

const char* gptModes[21] =
{
	"DT", "NU", "WL", "GH",
	"A1", "A2", "BL", "SC", 
	"S1", "S2", "S3", "S4", 
	"S5", "DD", "RN", "ON", 
	"OP", "TN", "TW", "TH", 
	"KK"
};

void PatchCOF(
					int x, int y, int w, int h,
					const char* ptToken,
					const char* ptMode,
					const char* ptWeapClass
				)
{
	char szPath[ 1024 ];

	_snprintf( szPath, 1024, ".\\%s\\COF\\%s%s%s.cof", ptToken, ptToken, ptMode, ptWeapClass );

	FILE* ptFile = fopen( szPath, "rb+" );	

	if ( ptFile )
	{
		fseek( ptFile, 0x08, SEEK_SET );

		fwrite( &x, 1, sizeof(int), ptFile );
		fwrite( &w, 1, sizeof(int), ptFile );
		fwrite( &y, 1, sizeof(int), ptFile );
		fwrite( &h, 1, sizeof(int), ptFile );

		fclose( ptFile );
	}
}

FILE* GetCELL(
					const char* ptToken,
					const char* ptComponent,
					const char* ptArmType,
					const char* ptMode,
					const char* ptWeapClass
				)
{
	char szPath[ 1024 ];

	_snprintf( szPath, 1024, ".\\%s\\%s\\%s%s%s%s%s.dcc", ptToken, ptComponent, ptToken, ptComponent, ptArmType, ptMode, ptWeapClass );

	FILE* ptFile = fopen( szPath, "rb" );

	if ( ptFile )
	{
		printf( "Loading: %s\n", szPath ); 
	}

	return ptFile;
}

int __cdecl main( int argc, char* argv[] )
{
	char szFileName[ 1024 ];
	memset( szFileName, 0, 1024 );

	const char* ptFileName = "sprite.ini";

	if ( argc > 1 )
	{
		ptFileName = argv[1];
	}

	_snprintf( szFileName, 1024, ".\\%s", ptFileName );

	FILE* ptFile = fopen( szFileName, "r" );

	if ( ptFile == NULL )
	{
		printf( "ini file %s doesn't exist\n", szFileName );

		return 0;
	}

	fclose( ptFile );

	char szToken[16];

	if ( !GetIniValue( szToken, 16, "Token", szFileName, 2 ) )
	{
		printf( "%s is not a valid token\n", szToken );

		return 0;
	}

	char szArmor[16];

	if ( !GetIniValue( szArmor, 16, "ArmType", szFileName, 3 ) )
	{
		printf( "%s is not a valid armtype\n", szArmor );

		return 0;
	}

	char szComponent[16];

	if ( !GetIniValue( szComponent, 16, "Component", szFileName, 2 ) )
	{
		printf( "%s is not a valid component\n", szComponent );

		return 0;
	}

	char szWeapon[16];

	if ( !GetIniValue( szWeapon, 16, "WeapClass", szFileName, 3 ) )
	{
		printf( "%s is not a valid weapclass\n", szWeapon );

		return 0;
	}

	for ( int i = 0; i < 21; i++ )
	{
		FILE* ptCell = GetCELL( szToken, szComponent, szArmor, gptModes[i], szWeapon );

		if ( ptCell )
		{
			DCC_FILE_S* ptCellFile =  dcc_get_in_mem( ptCell );

			if ( ptCellFile )
			{
				int x = 512;
				int y = 512;
				int w = -512;
				int h = -512;

				for ( int d = 0; d < ptCellFile->dcc_info.directions; d++ )
				{
					int dx = ptCellFile->dir_info[d].box.xmin;
					int dy = ptCellFile->dir_info[d].box.ymin;
					int dw = ptCellFile->dir_info[d].box.xmax;
					int dh = ptCellFile->dir_info[d].box.ymax;

					if ( dx < x )
					{
						x = dx;
					}

					if ( dy < y )
					{
						y = dy;
					}

					if ( dw > w )
					{
						w = dw;
					}

					if ( dh > h )
					{
						h = dh;
					}
				}

				int xMax, yMax, hMax;

				if ( GetCellPX( xMax, yMax, hMax, szFileName ) )
				{
					x = ( x * xMax ) / 100;
					y = ( y * yMax ) / 100;
					h = ( h * hMax ) / 100;
					w = ( w * xMax ) / 100;
				}

				printf( "\t\t x: %d, y: %d, w: %d, h: %d\n", x, y, w, h );

				PatchCOF( x, y, w, h, szToken, gptModes[i], szWeapon );

				dcc_my_exit( ptCellFile );
			}

			fclose( ptCell );
		}
	}

	return 1;
}
''(...) The game can basically be considered unhackable. '' - Blizzard Entertainment (30th May 2000)
Black Omen Productions | MetalStorm: Progress Report | Screenshots

User avatar
Nefarius
Retired Admin
Cherub
Posts: 11607
Joined: Sat Jun 15, 2002 8:13 pm
Location: Where the blood forever rains
Contact:

Hand-picked

Re: Dev Apps - Public Source Dump

Post by Nefarius » Fri May 28, 2010 2:55 pm

A small utility to append/inject/replace palettes from the item colorshift tables.

Code: Select all

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <io.h>

typedef unsigned long		dword;
typedef unsigned short	word;
typedef unsigned char		byte;

void error( const char* msg, dword line )
{
	printf( "%s (#%u)\n", msg, line );
}

#define BUILD_TABLES	0
#define ASSERT(e)		if ( !( e ) ) { error( #e, __LINE__ ); exit( -1 ); }

inline void* malloc_s( size_t size )
{
	void* buffer = malloc( size );
	
	ASSERT( buffer );
	
	memset( buffer, 0, size );
	
	return buffer;
}

inline void free_s( void* buffer )
{
	if ( buffer )
	{
		free( buffer );
	}
}

const char* palette_filenames[] =
{
	"brown",
	"gold",
	"grey",
	"grey2",
	"greybrown",
	"invgrey",
	"invgrey2",
	"invgreybrown",
	
	NULL
};

void close_output( FILE* file )
{
	if ( file )
	{
		fclose( file );
	}
}

void write_output( FILE* file, void* buffer, size_t size )
{
	ASSERT( file );
	ASSERT( buffer );
	ASSERT( fwrite( buffer, 1, size, file ) == size );
}

FILE* open_output( const char* filename, const char* extension )
{
	char name[ 1024 ];
	
	strncpy( name, "./output/", 1024 );
	
	strncat( name, filename, 1024 );
	
	if ( extension )
	{
		strncat( name, extension, 1024 );
	}
	
	printf( "opening: %s\n", name );
	
	FILE* file = fopen( name, "wb" );
	ASSERT( file );
	
	return file;
}

void savefile( void* buffer, const char* filename, const char* extension, size_t size )
{
	char name[ 1024 ];
	
	strncpy( name, filename, 1024 );
	
	if ( extension )
	{
		strncat( name, extension, 1024 );
	}
	
	printf( "opening: %s\n", name );
	
	FILE* file = fopen( name, "wb" );
	ASSERT( file );	
	
	ASSERT( fwrite( buffer, 1, size, file ) == size );
	
	fclose( file );
}

byte* getfile( const char* filename, const char* extension, size_t& count )
{
	char name[ 1024 ];
	
	strncpy( name, filename, 1024 );
	
	if ( extension )
	{
		strncat( name, extension, 1024 );
	}
	
	printf( "opening: %s\n", name );
	
	FILE* file = fopen( name, "rb" );
	ASSERT( file );
	
	size_t size =  _filelength( _fileno( file ) );
	
	ASSERT( ( ( size & 255 ) == 0 ) && ( ( count = ( size >> 8 ) ) > 0 ) );
	
	byte* buffer = ( byte* )malloc_s( size );
	
	ASSERT( fread( buffer, 1, size, file ) == size );
	
	fclose( file );
	
	return buffer;
}

int __cdecl main( int argc, char* argv[] )
{
	#if ( BUILD_TABLES )
	
		const char** filename_iter = palette_filenames;
	
		const char* filename;
		
		while ( ( filename = *filename_iter++ ) )
		{
			size_t count;
			
			byte* file = getfile( filename, ".dat", count );
			
			byte* table = ( byte* )malloc_s( 256 );
			
			size_t j = 0;
			
			while ( j < count )
			{
				size_t i = 0;
				
				byte* read_pt = &file[ j << 8 ];
				
				do
				{
					if ( read_pt[i] != i )
					{
						table[i] = 1;
					}
				
					i++;
				
				} while ( i < 256 );
				
				j++;
			}
			
			savefile( table, filename, ".tbl", 256 ); 
			
			free_s( table );
			free_s( file );
		}
	
	#else
	
		if ( argc < 2 )
		{
			printf( "please supply a source file\n" );
			
			return 1;
		}
		
		const char* palshift = argv[1];
		
		size_t count;
		
		byte* source = getfile( palshift, NULL, count );
		
		bool append		= true;
		bool inject		= false;
		
		size_t pos = 0;
		
		if ( argc > 2 )
		{
			append = false;
			
			int posi = atoi( argv[2] );
			
			if ( posi < 0 )
			{
				inject = true;
			}

			pos = abs( posi );
		}
		
		const char** filename_iter = palette_filenames;
	
		const char* filename;
		
		while ( ( filename = *filename_iter++ ) )
		{
			size_t pal_count;
			size_t ignore;
			
			byte* file = getfile( filename, ".tbl", ignore );
			byte* dest = getfile( filename, ".dat", pal_count );
			
			FILE* outputf = open_output( filename, ".dat" );
			
			byte palette[ 256 ];
			
			size_t sub_pos = ( ( append || pos > pal_count ) ? pal_count : pos );
			
			size_t i = 0;
			
			// write the palettes that come before our new palette(s)
			
			while ( i < sub_pos )
			{
				write_output( outputf, &dest[ i << 8 ], 256 );
				
				i++;
			}
			
			// now we write our new palettes
			
			size_t j = 0;
			
			while ( j < count )
			{
				size_t k = 0;
				
				byte* read_pt = &source[ j << 8 ];
				
				do
				{
					byte c = k;
					
					if ( file[k] )
					{
						c = read_pt[k];
					}
		
					palette[k] = c;
				
					k++;
				
				} while ( k < 256 );
				
				write_output( outputf, palette, 256 );
				
				j++;
			}
			
			if ( !inject )
			{
				i += j;
			}
			
			// lastly, write whatever remains to be written
			
			while ( i < pal_count )
			{
				write_output( outputf, &dest[ i << 8 ], 256 );
				
				i++;
			}
			
			close_output( outputf );
			
			free_s( file );
			free_s( dest );
		}		
		
		free_s( source );
	
	#endif
	
	return 0;
}
''(...) The game can basically be considered unhackable. '' - Blizzard Entertainment (30th May 2000)
Black Omen Productions | MetalStorm: Progress Report | Screenshots

Post Reply

Return to “Mods by Nefarius”