// ------------------------------------------
// NTRQ2NSF
// Command-line tool to export NSF from NTRQ
// ------------------------------------------
//
// V1.3 made for larger NTRQ V1.7 ROM
//

#include <stdio.h>
#include <string.h>
#define nsfHeaderSize 128
#define ntrqDataSize 0x2000
#define ntrqnsfBinarySize (0x8000 + nsfHeaderSize)
#define ntrqDataOffset (ntrqDataSize + nsfHeaderSize)

#define ntrqDPCMAddress 0x1C910
//#define ntrqDPCMAddress 0xC910

#define NSFDPCMAddress 0x4980

#define NSFDPCMLength (0x20000 - ntrqDPCMAddress)
//#define NSFDPCMLength (0x10000 - ntrqDPCMAddress)

#define songNameOffset 14
#define composerNameOffset songNameOffset+32
#define copyrightNameOffset composerNameOffset+32

int getFileSize (FILE *file)
{
	int size;
	fseek(file, 0, SEEK_END);
	size = ftell(file);
	fseek(file, 0, SEEK_SET);
	return size;
}

int writeField (int offset, char *fieldString, char *buf)
{
	int len = strlen(fieldString);
	char *a = '\0';
	if (len > 31) {
		strncpy (fieldString+31, a, 1);
		len = 32;	
	}
	//printf("%s %d\n", fieldString, len);
	sprintf(buf+offset, "%s", fieldString);
	return 0;
}

int main (int argc, const char * argv[]) {

	FILE *ntrqBinary;
	FILE *ntrqSave;
	FILE *nsf;
	FILE *ntrqROM;
	
	char buffer[ntrqnsfBinarySize];
	char ntrqBinaryName[] = "NTRQNSF.BIN";
	
	//printf("%s\n%d\n", argv[1], (unsigned int)strlen(argv[1]));
	
	if (argc < 6) {
		printf("\n");
		printf("NTRQ2NSF V1.3: Convert NTRQ .sav file to NSF\n\n");
		printf("Usage : NTRQ2NSF <ntrq.sav> <output.nsf> <NSF name> <composer name> <copyright name>\n\n");
		printf("- The file NTRQNSF.BIN is required. It is included with NTRQ.\n- Your .SAV file must be uncompressed (8192 bytes in size).\n");
		printf("- Some emulators use compressed .SAV files and these are not compatible with NTRQ2NSF.\n");
		printf("- The resulting .NSF will contain all 8 songs contained in the .SAV file, even some of them are empty.\n");
		printf("- the last three parameters, <NSF name>, <composer> and <copyright> get written into the NSF header.\n\n");
		return 0;
	}
	
	const char *inputName = argv[1];
	const char *outputName = argv[2];
	const char *songName = argv[3];
	const char *composerName = argv[4];
	const char *copyrightName = argv[5];
		
	// Read base binary file into buffer	
	if ((ntrqBinary = fopen (ntrqBinaryName,"rb"))!=0)
	{
		if (getFileSize(ntrqBinary)!=ntrqnsfBinarySize)
		{
			printf("\nError, NTRQNSF.BIN is invalid or corrupted.\n\n");
			fclose(ntrqBinary);
			return 0;
		}
		fread(buffer, 1, sizeof(buffer), ntrqBinary);
		fclose(ntrqBinary);
	} else {
		printf("\nError, could not open NTRQNSF.BIN\n\n");
		return 0;
	}
	
	// Attempt to patch binary using .sav file
	if ((ntrqSave = fopen (inputName, "rb"))!=0)
	{
		// If .sav not 8192 bytes, .sav file probably compressed
		if (getFileSize(ntrqSave)!=ntrqDataSize)
		{
			printf("\nError, it seems that your .SAV file is compressed. Please unzip it and re-run NTRQ2NSF\n\n");
			fclose(ntrqSave);
			return 0;
		} else {
			fread (buffer+(ntrqDataOffset), 1, ntrqDataSize, ntrqSave);
			fclose(ntrqSave);
		}
	} else {
		printf("\nError, could not find specified .SAV file.\n\n");
		fclose(ntrqSave);
		return 0;
	}
	
	//Clear song, composer and copyright text fields
	memset (buffer+songNameOffset, '\0', 32);
	memset (buffer+composerNameOffset, '\0', 32);
	memset (buffer+copyrightNameOffset, '\0', 32);
	
	//Write songname, composer and copyright fields
	writeField (songNameOffset, (char *)songName, buffer);
	writeField (composerNameOffset, (char *)composerName, buffer);
	writeField (copyrightNameOffset, (char *)copyrightName, buffer);

	// Grab samples from current NTRQ ROM
	if ((ntrqROM = fopen ("ntrq.nes", "rb"))==0)
	{
		printf("\nError, could not find NTRQ ROM - it's required for patching current sample set into NSF.\n\n");
		fclose(ntrqROM);
		return 0;
	} else
	{
		// Read samples from NTRQ ROM, patch into NSF
		fseek (ntrqROM, ntrqDPCMAddress, SEEK_SET);
		//fread (buffer+(NSFDPCMAddress), 1, NSFDPCMLength, ntrqROM);
		fread (buffer+(NSFDPCMAddress), 1, NSFDPCMLength-1, ntrqROM);
		fclose (ntrqROM);
	}
	
	// Attempt to write output file
	if ((nsf = fopen (outputName, "wb"))!=0)
	{
		fwrite(buffer, 1, sizeof(buffer), nsf);
		fclose(nsf);
		printf("\nSuccessfully written NSF file, %s\n\n", outputName);		
	
	} else {
		printf("\nError creating output file.\n\n");
		fclose(nsf);
	}
	
	return 0;
}
