145 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <fstream>
 | 
						|
#include <sstream>
 | 
						|
 | 
						|
#include "../../memory.h"
 | 
						|
 | 
						|
 | 
						|
#define GT1TOROM_MAJOR_VERSION "0.2"
 | 
						|
#define GT1TOROM_MINOR_VERSION "0"
 | 
						|
#define GT1TOROM_VERSION_STR "gt1torom v" GT1TOROM_MAJOR_VERSION "." GT1TOROM_MINOR_VERSION
 | 
						|
 | 
						|
#define GT1_MAX_SIZE (1<<16)
 | 
						|
 | 
						|
#define TRAMPOLINE_START 0x00FB
 | 
						|
 | 
						|
 | 
						|
uint8_t _gt1[GT1_MAX_SIZE];
 | 
						|
 | 
						|
 | 
						|
bool writeRomDataWithTrampoline(const std::string& outputFilename0, const std::string& outputFilename1, std::ofstream& outfile0, std::ofstream& outfile1, uint16_t& startAddress, uint16_t size, bool _default)
 | 
						|
{
 | 
						|
    uint16_t trampolineOffset = 0x0000;
 | 
						|
    for(uint16_t i=0; i<size; i++)
 | 
						|
    {
 | 
						|
        uint16_t address = startAddress + i + trampolineOffset;
 | 
						|
 | 
						|
        // Write ROM trampoline
 | 
						|
        if(LO_BYTE(address) == TRAMPOLINE_START)
 | 
						|
        {
 | 
						|
            static uint8_t trampolineOpcode[]  = {0xFE, 0xFC, 0x14, 0xE0, 0xC2};
 | 
						|
            static uint8_t trampolineOperand[] = {0x00, 0xFD, 0x04, 0x65, 0x18};
 | 
						|
 | 
						|
            for(int j=0; j<int(sizeof(trampolineOpcode)); j++)
 | 
						|
            {
 | 
						|
                outfile0.write((char *)&trampolineOpcode[j], 1);
 | 
						|
                if(outfile0.bad() || outfile0.fail())
 | 
						|
                {
 | 
						|
                    fprintf(stderr, "gt1torom : write error at address %04x in file '%s'\n", address + j, outputFilename0.c_str());
 | 
						|
                    return false;
 | 
						|
                }
 | 
						|
 | 
						|
                outfile1.write((char *)&trampolineOperand[j], 1);
 | 
						|
                if(outfile1.bad() || outfile1.fail())
 | 
						|
                {
 | 
						|
                    fprintf(stderr, "gt1torom : write error at address %04x in file '%s'\n", address + j, outputFilename1.c_str());
 | 
						|
                    return false;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            trampolineOffset += sizeof(trampolineOpcode);
 | 
						|
        }
 | 
						|
        
 | 
						|
        // Don't write default data after last trampoline
 | 
						|
        if(LO_BYTE(address) != TRAMPOLINE_START  ||  !_default)
 | 
						|
        {
 | 
						|
            static char nativeLoad[2] = {0x00, 0x00};
 | 
						|
            outfile0.write(&nativeLoad[0], 1);
 | 
						|
            if(outfile0.bad() || outfile0.fail())
 | 
						|
            {
 | 
						|
                fprintf(stderr, "gt1torom : write error at address %04x in file '%s'\n", startAddress + i, outputFilename0.c_str());
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
 | 
						|
            if (_default)
 | 
						|
                outfile1.write(&nativeLoad[1], 1);
 | 
						|
            else
 | 
						|
                outfile1.write((char *)&_gt1[i], 1);
 | 
						|
            if(outfile1.bad() || outfile1.fail())
 | 
						|
            {
 | 
						|
                fprintf(stderr, "gt1torom : write error at address %04x in file '%s'\n", startAddress + i, outputFilename1.c_str());
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    startAddress += size + trampolineOffset;
 | 
						|
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int main(int argc, char* argv[])
 | 
						|
{
 | 
						|
    if(argc != 4)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "%s\n", GT1TOROM_VERSION_STR);
 | 
						|
        fprintf(stderr, "Usage:   gt1torom <input filename> <output filename> <uint16_t start address in hex>\n");
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    std::string inputFilename = std::string(argv[1]);
 | 
						|
    if(inputFilename.find(".gt1") == inputFilename.npos  &&  inputFilename.find(".GT1") == inputFilename.npos)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "Wrong file extension in %s : must be '.gt1'\n", inputFilename.c_str());
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    // Check for gt1 file
 | 
						|
    std::ifstream gt1file(inputFilename, std::ios::binary | std::ios::in);
 | 
						|
    if(!gt1file.is_open())
 | 
						|
    {
 | 
						|
        fprintf(stderr, "gt1torom : couldn't open %s GT1 file.\n", inputFilename.c_str());
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    // Load gt1 file
 | 
						|
    gt1file.read((char *)_gt1, GT1_MAX_SIZE);
 | 
						|
    if(gt1file.bad())
 | 
						|
    {
 | 
						|
        fprintf(stderr, "gt1torom : failed to read %s GT1 file.\n", inputFilename.c_str());
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    uint16_t gt1Size = uint16_t(gt1file.gcount());
 | 
						|
 | 
						|
    std::string outputFilename0 = std::string(argv[2]) + "_ti";
 | 
						|
    std::ofstream outfile0(outputFilename0, std::ios::binary | std::ios::out);
 | 
						|
    if(!outfile0.is_open())
 | 
						|
    {
 | 
						|
        fprintf(stderr, "gt1torom : failed to open '%s'\n", outputFilename0.c_str());
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    std::string outputFilename1 = std::string(argv[2]) + "_td";
 | 
						|
    std::ofstream outfile1(outputFilename1, std::ios::binary | std::ios::out);
 | 
						|
    if(!outfile1.is_open())
 | 
						|
    {
 | 
						|
        fprintf(stderr, "gt1torom : failed to open '%s'\n", outputFilename1.c_str());
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    // Handles hex numbers
 | 
						|
    uint16_t startAddress = 0x0000;
 | 
						|
    std::stringstream ss;
 | 
						|
    ss << std::hex << argv[3];
 | 
						|
    ss >> startAddress;
 | 
						|
 | 
						|
    if(!writeRomDataWithTrampoline(outputFilename0, outputFilename1, outfile0, outfile1, startAddress, gt1Size, false)) return 1;
 | 
						|
    if(!writeRomDataWithTrampoline(outputFilename0, outputFilename1, outfile0, outfile1, startAddress, TRAMPOLINE_START + 1 - LO_BYTE(startAddress), true)) return 1;
 | 
						|
 | 
						|
    fprintf(stderr, "%s success : next available address : 0x%04X\n", GT1TOROM_VERSION_STR, startAddress - 1);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 |