//**************************************************************************
//**
//** SLaunch.cpp : SLaunch
//**$Revise Date: 01/17/06
//**$Author: SVillarreal
//**$Description: Main DLL code
//**
//**************************************************************************
#include "stdafx.h"
#include <objbase.h>
#include <string.h>
#include <stdio.h>

#define ASCII_SLASH 47
#define ASCII_BACKSLASH 92
typedef unsigned char byte;

//configuration structure
typedef struct
{
	char exePath[256];
	char iwadPath[256];
	char pwadPath[256];
	char sehPath[256];
	char basePath[256];
}	filePathConfig_t;

typedef struct
{
	byte fast;
	byte respawn;
	byte noMonsters;
	int turbo;
	byte noSfx;
	byte noSnd;
	byte noMus;
	byte noVoc;
	short level;
	short difficulty;
	short resolution;
	byte useDogs;
	short numDogs;
	byte fullscreen;
	byte enableWarp;
}	config_t;

static const char* parameters[12] = {

	"-fastmonsters ",
	"-respawn ",
	"-nomonsters ",
	"-turbo ",
	"-nosfx ",
	"-nosound ",
	"-nomusic ",
	"-novoice ",
	"-dogs ",
	"-warp",
	"-width ",
	"-height ",
};

//file class
class fileHandle
{
	public:
		fileHandle();
		~fileHandle();
		config_t *mainConfig;
		config_t readConfig;
		filePathConfig_t mainPath;
		writeFile(char* path);
		loadFile(char* path);
		processFilePath(char* exe, char* iwad, char* pwad, char* seh, char* base);
		processCall();
		char pSet[1056];
		stripFileName(char* name);
	private:
		stripFileExt(char* file);
		int cfgNext(int pos);
};

//constructor
fileHandle::fileHandle()
{
}

//deconstructor
fileHandle::~fileHandle()
{
}

fileHandle::stripFileExt(char *file)
{
	char *search;

	search = file + strlen(file) - 1;
	while(*search != ASCII_SLASH && *search != ASCII_BACKSLASH
		&& search != file)
	{
		if(*search == '.')
		{
			*search = '\0';
			return -1;
		}
		search--;
	}
	return 1;
}

fileHandle::stripFileName (char *name)
{
	char *search;

	search = name+strlen(name)-1;
	while(search != name)
	{
		if(*search == 92 || *search == 47)
		{
			search++;
			*search = '\0';
			return -1;
		}
		search--;
	}
	return 1;
}

//write configuration file
fileHandle::writeFile(char* path)
{
	char* filePath = "";
	stripFileExt(path);
	sprintf(filePath, "%s.cfg", path);
	FILE* f = fopen(filePath, "wb");
	fwrite(&mainPath, sizeof(filePathConfig_t), 1, f);
	fwrite(mainConfig, sizeof(config_t), 1, f);
	fclose(f);
}

//load configuration file
fileHandle::loadFile(char* path)
{
	FILE* f = fopen(path, "rb");
	fread(&mainPath, sizeof(filePathConfig_t), 1, f);
	fread(&readConfig, sizeof(config_t), 1, f);
	fclose(f);
}

fileHandle::processFilePath(char* exe, char* iwad, char* pwad, char* seh, char* base)
{
	strncpy(mainPath.exePath, exe, sizeof(mainPath.exePath));
	strncpy(mainPath.iwadPath, iwad, sizeof(mainPath.iwadPath));
	strncpy(mainPath.pwadPath, pwad, sizeof(mainPath.pwadPath));
	strncpy(mainPath.sehPath, seh, sizeof(mainPath.sehPath));
	strncpy(mainPath.basePath, base, sizeof(mainPath.basePath));
}

int fileHandle::cfgNext(int pos)
{
	switch(pos)
	{
		case 0:
			return mainConfig->fast;
			break;
		case 1:
			return mainConfig->respawn;
			break;
		case 2:
			return mainConfig->noMonsters;
			break;
		case 3:
			return mainConfig->turbo;
			break;
		case 4:
			return mainConfig->noSfx;
			break;
		case 5:
			return mainConfig->noSnd;
			break;
		case 6:
			return mainConfig->noMus;
			break;
		case 7:
			return mainConfig->noVoc;
			break;
		case 8:
			return mainConfig->useDogs;
			break;
		case 9:
			return mainConfig->enableWarp;
			break;
	}
	return 0;
}

fileHandle::processCall(void)
{
	int i;
	char tempChr[32];
	sprintf(pSet, "%s -iwad %s -file %s -seh %s ", mainPath.exePath, mainPath.iwadPath,
		mainPath.pwadPath, mainPath.sehPath);
	//process optional parameters
	for(i = 0; i < 10; i++)
	{
		if(cfgNext(i))
		{
			strcat(pSet, parameters[i]);
			if(!strcmp(parameters[i], "-turbo "))
			{
				sprintf(tempChr, "%i ", mainConfig->turbo);
				strcat(pSet, tempChr);
			}
			if(!strcmp(parameters[i], "-dogs "))
			{
				sprintf(tempChr, "%i ", mainConfig->numDogs + 1);
				strcat(pSet, tempChr);
			}
			if(!strcmp(parameters[i], "-warp"))
			{
				sprintf(tempChr, " %i -skill %i ", mainConfig->level + 1,
					mainConfig->difficulty + 1);
				strcat(pSet, tempChr);
			}
		}
	}
	//set screenmode
	switch(mainConfig->fullscreen)
	{
		case 0:
			sprintf(tempChr, "-nofullscreen ");
			break;
		case 1:
			sprintf(tempChr, "-fullscreen ");
			break;
	}
	strcat(pSet, tempChr);

	//set resolution
	switch(mainConfig->resolution)
	{
		case 0:
			sprintf(tempChr, "-width 320 -height 240 ");
			break;
		case 1:
			sprintf(tempChr, "-width 640 -height 480 ");
			break;
		case 2:
			sprintf(tempChr, "-width 800 -height 600 ");
			break;
		case 3:
			sprintf(tempChr, "-width 1024 -height 768 ");
			break;
	}
	strcat(pSet, tempChr);
}

fileHandle mainFile;

void APIENTRY DoFile(char* path, config_t* cfg, char* exe, char* iwad, char* pwad,
					 char* seh, char* base)
{
	mainFile.mainConfig = cfg;
	mainFile.processFilePath(exe, iwad, pwad, seh, base);
	mainFile.writeFile(path);
}

void APIENTRY DoGameCall(config_t* cfg, char* exe, char* iwad, char* pwad,
						 char* seh, char* base)
{
	mainFile.mainConfig = cfg;
	mainFile.processFilePath(exe, iwad, pwad, seh, base);
	mainFile.processCall();
	getenv(base);
	system(mainFile.pSet);	//			:-(
}

config_t APIENTRY DoFileLoad(char* path)
{
	mainFile.loadFile(path);
	return mainFile.readConfig;
}

void APIENTRY DoPathLoad(char* pathStr, short slot)
{
	char type[256];
	switch(slot)
	{
		case 0:
			strncpy(type, mainFile.mainPath.exePath, 256);
			break;
		case 1:
			strncpy(type, mainFile.mainPath.iwadPath, 256);
			break;
		case 2:
			strncpy(type, mainFile.mainPath.pwadPath, 256);
			break;
		case 3:
			strncpy(type, mainFile.mainPath.sehPath, 256);
			break;
		case 4:
			strncpy(type, mainFile.mainPath.basePath, 256);
			break;
	}
	strncpy(pathStr, type, 256);
}

void APIENTRY StripFileName(char* path)
{
	mainFile.stripFileName(path);
}

BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    return TRUE;
}
