/**
* Permet d'afficher le contenu d'un fichier snapshot CPC
* @author Thierry JOUIN
* @version 1.1
* @date 31/10/2001
*/

#include "CError.h"
#include "CCPCSnapshot.h"

#include "optionParser.h"

#include <vector>

struct SOption createSnapshotOption[]=
{
	{'i',"inSnapshot",0,1,1,"Load <$1> snapshot file"},
	{'l',"loadFileData",0,0,2,"Load <$1> file data at <$2> address in snapshot memory"},
	{'p',"putData",0,0,2,"Put <$1> byte at <$2> address in snapshot memory"},
	{'s',"setToken",0,0,2,"Set snapshot token <$1> to value <$2>\n\t\tUse <$1>:<val> to set array value\n\t\tex '-s CRTC_REG:6 20' : Set CRTC register 6 to 20"},
	{'x',"clearMemory",0,1,0,"Clear snapshot memory"},
	{'r',"romDeconnect",0,1,0,"Deconnect lower and upper rom"},
	{'e',"enableInterrupt",0,1,0,"Enable interrupt"},
	{'d',"disableInterrupt",0,1,0,"Disable interrupt"},
	{'c',"configFile",0,1,1,"Load a config file with createSnapshot option"},
	{'t',"tokenList",0,1,0,"Display setable snapshot token ID"},
	{0,NULL,0,0,0,NULL}
};

int main(int argc, char** argv)
{
	int i,o;

	std::cout << "createSnapshot (c) Ramlaid 2003" << std::endl << std::endl;

	struct SOptionOut *cmdOption=NULL;

	if (parseCommandLineOption(&argc,&argv,createSnapshotOption,&cmdOption) != NO_ERROR)
	{
		printf("%s\n\n",getErrorString());
		printUsage("createSnapshot <filename.sna>",
			"Create a Amstrad CPC snapshot <filename.sna>\nDefault snapshot : 6128, CRTC 0, rom deconnected, no interrupt, IM 1, SP = 0xc000, CRTC standard value",
			createSnapshotOption);
		exit(-1);
	}

	if ((o=optionIndex(cmdOption,'c')) != ERROR_UNKNOWN)
	{
		if (parseConfigFileOption(cmdOption[o].argv[0],&argc,&argv,createSnapshotOption,&cmdOption) != NO_ERROR)
		{
			printf("%s\n\n",getErrorString());
			printUsage("createSnapshot <filename.sna>",
				"Create a Amstrad CPC snapshot <filename.sna>\nDefault snapshot : 6128, CRTC 0, rom deconnected, no interrupt, CRTC standard value",
				createSnapshotOption);
			exit(-1);
		}
	}

	if (argc != 2)
	{
		printf("Must define output file\n");
		printUsage("createSnapshot <filename.sna>",
			"Create a Amstrad CPC snapshot <filename.sna>\nDefault snapshot : 6128, CRTC 0, rom deconnected, no interrupt, CRTC standard value",
			createSnapshotOption);
		exit(-1);
	}

	std::string filenameOut(argv[1]);
	CCPCSnapshot snapshot;

	// Looking for help display
	if (optionIndex(cmdOption,'t') != -1)
	{
		CCPCSnapshot::displayTokenHelp(std::cout);
		freeOptionOut(cmdOption);
		return 0;
	}

	// Looking for a -i arg
	try
	{
		if ((i = optionIndex(cmdOption,'i')) != -1)
		{
			snapshot.loadFromFile(cmdOption[i].argv[0]);
			std::cout << "Load input snapshot " << cmdOption[i].argv[0] << std::endl;
		}
		
		if (optionIndex(cmdOption,'x') != -1)
		{
			snapshot.clearMemory();
			std::cout << "Clear memory" << std::endl;
		}

		i=0;
		while (cmdOption[i].shortName != 0)
		{
			switch(cmdOption[i].shortName)
			{
			case 'l':
				{
					std::string filename = cmdOption[i].argv[0];
					int adr = strtol(cmdOption[i].argv[1],NULL,0);
					ASSERTMSG(errno != ERANGE, "Wrong value " << cmdOption[i].argv[1]);
					snapshot.loadDataFromFile(filename,adr);
					std::cout << "Load data " << filename << " at address #" << std::hex << adr << std::dec << std::endl;
					break;
				}
			case 'p':
				{
					int adr = strtol(cmdOption[i].argv[0],NULL,0);
					ASSERTMSG(errno != ERANGE, "Wrong value " << cmdOption[i].argv[0]);
					int val = strtol(cmdOption[i].argv[1],NULL,0);
					ASSERTMSG(errno != ERANGE, "Wrong value " << cmdOption[i].argv[1]);
					snapshot.putData(adr,val);
					std::cout << "Putting data #" << std::hex << val << " at address #" << adr << std::dec << std::endl;
					break;
				}
			case 's':
				{
					int val = strtol(cmdOption[i].argv[1],NULL,0);
					ASSERTMSG(errno != ERANGE, "Wrong value " << cmdOption[i].argv[1]);
					snapshot.setTokenValue(cmdOption[i].argv[0],val);
					std::cout << "Setting token " << cmdOption[i].argv[0] << " to " << val << std::endl;
					break;
				}
			case 'r':
				{
					snapshot.romDeconnect();
					std::cout << "Rom deconnection" << std::endl;
					break;
				}
			case 'd':
				{
					std::cout << "Interrupt disable" << std::endl;
					snapshot.disableInterrupt();
					break;
				}
			case 'e':
				{
					std::cout << "Interrupt enable" << std::endl;
					snapshot.enableInterrupt();
				}
			case 'c':
			case 'x':
			case 'i':
				{
					// Already done !
					break;
				}
			default :
				{
					std::cerr << "Unknow option ! " << cmdOption[i].shortName << std::endl;
					freeOptionOut(cmdOption);
					return -1;
				}
			}
			i++;
		}
		
		std::cout << "Saving " << filenameOut << std::endl;
		snapshot.saveToFile(filenameOut);
	}
	catch(CException &e)
	{
		std::cerr << e << std::endl;
		freeOptionOut(cmdOption);
		return -1;
	}

	freeOptionOut(cmdOption);
	return 0;
}
