Esempio n. 1
0
bool vtElevLayer::ImportFromFile(const wxString &strFileName,
	bool progress_callback(int), vtElevError *err)
{
	// Avoid trouble with '.' and ',' in Europe - all the file readers assume
	//  the default "C" locale.
	ScopedLocale normal_numbers(LC_NUMERIC, "C");

	wxString strExt = strFileName.AfterLast('.');
	vtString fname = (const char *) strFileName.mb_str(wxConvUTF8);

	VTLOG("ImportFromFile '%s'\n", (const char *) fname);

	if (!strExt.CmpNoCase(_T("gz")))
	{
		// ignore .gz, look at extension under it
		wxString dropped = strFileName.Left(strFileName.Len()-3);
		strExt = dropped.AfterLast('.');
	}

	if (!strExt.CmpNoCase(_T("bz2")))
	{
		// ignore .bz2, look at extension under it
		wxString dropped = strFileName.Left(strFileName.Len()-4);
		strExt = dropped.AfterLast('.');
	}

	// The first character in the file is useful for telling which format
	// the file really is.
	FILE *fp = vtFileOpen(fname, "rb");
	char first = fgetc(fp);
	fclose(fp);

	bool success = false;

	if (!strExt.CmpNoCase(_T("dxf")))
	{
		m_pTin = new vtTin2d;
		success = m_pTin->ReadDXF(fname, progress_callback);
	}
	else
	if (!strFileName.Right(6).CmpNoCase(_T("xy.adf")))
	{
		m_pTin = new vtTin2d;
		success = m_pTin->ReadADF(fname, progress_callback);
	}
	else
	if (!strFileName.Right(4).CmpNoCase(_T(".tin")))
	{
		m_pTin = new vtTin2d;
		success = m_pTin->ReadGMS(fname, progress_callback);
	}
	else
	if (!strFileName.Right(4).CmpNoCase(_T(".ply")))
	{
		m_pTin = new vtTin2d;
		success = m_pTin->ReadPLY(fname, progress_callback);
	}
	else
	{
		if (m_pGrid == NULL)
			m_pGrid = new vtElevationGrid;
	}

	if (!strExt.CmpNoCase(_T("3tx")))
	{
		success = m_pGrid->LoadFrom3TX(fname, progress_callback);
	}
	else if (!strExt.CmpNoCase(_T("dem")))
	{
		// If there is a .hdr file in the same place, it is most likely
		//  a GTOPO30/SRTM30 file
		vtString hdr_fname = ChangeFileExtension(fname, ".hdr");
		if (vtFileExists(hdr_fname))
			success = m_pGrid->LoadFromGTOPO30(hdr_fname, progress_callback);
		else
		{
			if (first == '*')
				success = m_pGrid->LoadFromMicroDEM(fname, progress_callback);
			else
				success = m_pGrid->LoadFromDEM(fname, progress_callback, err);
		}
	}
	else if (!strExt.CmpNoCase(_T("asc")))
	{
		success = m_pGrid->LoadFromASC(fname, progress_callback);
		// vtElevationGrid does have its own ASC reader, but use GDAL instead
//		success = m_pGrid->LoadWithGDAL(strFileName.mb_str(wxConvUTF8), progress_callback, err);
	}
	else if (!strExt.CmpNoCase(_T("bil")))
	{
		success = m_pGrid->LoadWithGDAL(fname, progress_callback, err);
	}
	else if (!strExt.CmpNoCase(_T("mem")))
	{
		success = m_pGrid->LoadWithGDAL(fname, progress_callback, err);
	}
	else if (!strExt.CmpNoCase(_T("ter")))
	{
		success = m_pGrid->LoadFromTerragen(fname, progress_callback);
	}
	else if (!strExt.CmpNoCase(_T("cdf")))
	{
		success = m_pGrid->LoadWithGDAL(fname, progress_callback, err);
	}
	else if (!strExt.CmpNoCase(_T("hdr")))
	{
		success = m_pGrid->LoadFromGTOPO30(fname, progress_callback);
		if (!success)
			success = m_pGrid->LoadFromGLOBE(fname, progress_callback);
	}
	else if (!strExt.CmpNoCase(_T("dte")) ||
			!strExt.CmpNoCase(_T("dt0")) ||
			!strExt.CmpNoCase(_T("dt1")) ||
			!strExt.CmpNoCase(_T("dt2")))
	{
		success = m_pGrid->LoadFromDTED(fname, progress_callback);
	}
	else if (!strExt.Left(3).CmpNoCase(_T("pgm")))
	{
		success = m_pGrid->LoadFromPGM(fname, progress_callback);
	}
	else if (!strExt.CmpNoCase(_T("grd")))
	{
		// might by CDF, might be Surfer GRD
		if (first == 'D')
		{
			VTLOG("First character is 'D', attempting load as a Surfer Grid file.\n");
			success = m_pGrid->LoadFromGRD(fname, progress_callback);
		}
		else
		{
			VTLOG("First character is not 'D', attempting load as a netCDF file.\n");
			success = m_pGrid->LoadWithGDAL(fname, progress_callback, err);
		}
		if (!success)
		{
			VTLOG("Didn't load successfully, attempting load with GDAL.\n");
			// Might be 'Arc Binary Grid', try GDAL
			success = m_pGrid->LoadWithGDAL(fname, progress_callback, err);
		}
	}
	else if (!strFileName.Right(8).CmpNoCase(_T("catd.ddf")) ||
			!strExt.Left(3).CmpNoCase(_T("tif")) ||
			!strExt.Left(3).CmpNoCase(_T("png")) ||
			!strExt.Left(3).CmpNoCase(_T("img")) ||
			!strExt.CmpNoCase(_T("adf")))
	{
		if (m_pGrid)
			success = m_pGrid->LoadWithGDAL(fname, progress_callback, err);
	}
	else if (!strExt.CmpNoCase(_T("raw")))
	{
		RawDlg dlg(NULL, -1, _("Raw Elevation File"));

		dlg.m_iBytes = 2;
		dlg.m_iWidth = 100;
		dlg.m_iHeight = 100;
		dlg.m_fVUnits = 1.0f;
		dlg.m_fSpacing = 30.0f;
		dlg.m_bBigEndian = false;
		dlg.m_extents.SetToZero();
		g_bld->GetProjection(dlg.m_original);

		if (dlg.ShowModal() == wxID_OK)
		{
			success = m_pGrid->LoadFromRAW(fname, dlg.m_iWidth,
					dlg.m_iHeight, dlg.m_iBytes, dlg.m_fVUnits, dlg.m_bBigEndian,
					progress_callback);
		}
		if (success)
		{
			m_pGrid->SetEarthExtents(dlg.m_extents);
			m_pGrid->SetProjection(dlg.m_proj);
		}
	}
	else if (!strExt.CmpNoCase(_T("ntf")))
	{
		success = m_pGrid->LoadFromNTF5(fname, progress_callback);
	}
	else if (!strExt.CmpNoCase(_T("txt")) ||
		!strExt.CmpNoCase(_T("xyz")))
	{
		success = m_pGrid->LoadFromXYZ(fname, progress_callback);
	}
	else if (!strExt.CmpNoCase(_T("hgt")))
	{
		success = m_pGrid->LoadFromHGT(fname, progress_callback);
	}
	else if (!strExt.Left(2).CmpNoCase(_T("db")))
	{
		success = ImportFromDB(fname, progress_callback);
	}
	if (!success)
		return false;

	vtProjection *pProj;
	if (m_pGrid)
		pProj = &m_pGrid->GetProjection();
	else
		pProj = &m_pTin->m_proj;

	// We should ask for a CRS before asking for extents
	if (!g_bld->ConfirmValidCRS(pProj))
	{
		if (err)
		{
			err->type = vtElevError::CANCELLED;
			err->message = "Cancelled";
		}
		return false;
	}

	if (m_pGrid != NULL)
	{
		if (m_pGrid->GetEarthExtents().IsEmpty())
		{
			// No extents.
			wxString msg = _("File lacks geographic location (extents). Would you like to specify extents?\n Yes - specify extents\n No - use some default values\n");
			int res = wxMessageBox(msg, _("Elevation Import"), wxYES_NO | wxCANCEL);
			if (res == wxYES)
			{
				DRECT ext;
				ext.SetToZero();
				ExtentDlg dlg(NULL, -1, _("Elevation Grid Extents"));
				dlg.SetArea(ext, (pProj->IsGeographic() != 0));
				if (dlg.ShowModal() == wxID_OK)
					m_pGrid->SetEarthExtents(dlg.m_area);
				else
					return false;
			}
			if (res == wxNO)
			{
				// Just make up some fake extents, assuming a regular even grid
				int xsize, ysize;
				m_pGrid->GetDimensions(xsize, ysize);

				DRECT ext;
				ext.left = ext.bottom = 0;
				if (pProj->IsGeographic())
				{
					ext.right = xsize * (1.0/3600);	// arc second
					ext.top = ysize * (1.0/3600);
				}
				else
				{
					ext.right = xsize * 10;	// 10 linear units (meters, feet..)
					ext.top = ysize * 10;
				}
				m_pGrid->SetEarthExtents(ext);
			}
			if (res == wxCANCEL)
			{
				if (err)
				{
					err->type = vtElevError::CANCELLED;
					err->message = "Cancelled";
				}
				return false;
			}
		}
		m_pGrid->SetupLocalCS(1.0f);
	}
	return true;
}
Esempio n. 2
0
int main(int argc, char *argv[])
{
        bool dumpBin        = false;
        bool dumpElf        = false;
        bool listInfo        = false;
        bool convertBin        = false;
        bool convertElf        = false;
        unsigned int loadAddress = 0, entryPoint = 0;
        
        // print title
        printf("%s\n", title);
        
        // process args
        if(argc == 2)
        {
                // if no options given, list info on dol file
                listInfo = true;
        }
        else if(argc >= 3)
        {
                // check case-insensitively for options
                if(     strcasecmp("-e", argv[1]) == 0)
                        dumpElf                = true;
                else if(strcasecmp("-b", argv[1]) == 0)
                        dumpBin                = true;
                else if(strcasecmp("-i", argv[1]) == 0)
                        listInfo        = true;
                else if(strcasecmp("-c", argv[1]) == 0)
                {
                        convertBin        = true;
                        if (argc == 5)
                        {
                            loadAddress       = strtoul(argv[3], (char **)NULL, 16);
                            entryPoint        = strtoul(argv[4], (char **)NULL, 16);
                        }
                        else if(argc == 3)
                        {
                            loadAddress = 0x80003100u;
                            entryPoint = 0x80003100u;
                        }
                        else
                        {
                            printf("%s\n", usage);
                            return 1;
                        }
                        

                }
                else if(strcasecmp("-d", argv[1]) == 0)
                        convertElf        = true;
                else
                {
                        // usage error
                        printf("%s\n", usage);
                        return 1;
                }
        }
        else
        {
                // usage error
                printf("%s\n", usage);
                return 1;
        }
        
        // open/create dol file
        char filename[256];
        strcpy(filename, argv[2]);
        DolFile dolFile;
        if(convertBin || convertElf)
        {
                char dolFilename[256];
                strcpy(dolFilename, filename);
                ChangeFileExtension(dolFilename, "dol");
                
                if(!dolFile.create(dolFilename))
                {
                        printf("Error creating %s!\n", dolFilename);
                        return 2;
                }
        }
        else
        {
                if(!dolFile.open(filename))
                {
                        printf("Error opening %s!\n", filename);
                        return 2;
                }
        }
        
        bool ret = true;
        // list info on dol file
        if(listInfo)
                ret = listDolInfo(dolFile);
        // dump to binary file
        else if(dumpBin)
                ret = dumpDolToBinaryFile(dolFile);
        // dump to elf file
        else if(dumpElf)
                ret = dumpDolToElfFile(dolFile);
        // convert binary file to dol
        else if(convertBin)
                ret = convertBinaryFileToDol(dolFile, filename, loadAddress, entryPoint);
        // convert elf file to dol
        else if(convertElf)
                ret = convertElfFileToDol(dolFile, filename);
        
        // close dol file
        dolFile.close();
        
        // return ok if finished ok
        if(ret)
                return 0;
        return 666;
}
Esempio n. 3
0
// dump dol file to a binary file
// 
// args:        dol file object
// returns:        true if successful
bool dumpDolToBinaryFile(const DolFile& dolFile)
{
        unsigned int i;
        
        // get binary filename
        char binFilename[256];
        strcpy(binFilename, dolFile.getFilename());
        ChangeFileExtension(binFilename, "bin");
        
        // open binary output file
        FILE* bin_fd = 0;
        bin_fd = fopen(binFilename, "w+b");
        if(bin_fd == 0)
        {
                printf("Error creating %s!\n", binFilename);
                return false;
        }
        
        // get load address and entry point
        unsigned int loadAddress = dolFile.getLowestAddress();
        unsigned int entryPoint  = dolFile.getEntryPoint();
        // check if load address is same as entry point
        if(loadAddress != entryPoint)
        {
                // if load address is different to exec address,
                // it could cause problems in binary format
                
                // check if there is space before the load address
                // to put in a jump to the entry point
                if(loadAddress >= 0x80003100 + 4)
                {
                        // insert jump to entry point before code
                        unsigned int jump = TEST_CHANGE_ENDIAN_32BIT(MY_ENDIAN == LITTLE_ENDIAN, 0x48000000 | (entryPoint - (loadAddress - 4)) );
                        fwrite(&jump, 1, 4, bin_fd);
                        // update load address and entry point
                        loadAddress -= 4;
                        entryPoint = loadAddress;
                }
        }
        
        // dump text bits first
        for(i=0; i<dolFile.getMaxNumTextSections(); i++)
        {
                if(dolFile.isTextSectionValid(i))
                {
                        unsigned int address= dolFile.getTextAddress(i);
                        //unsigned int offset = dolFile.getTextOffset(i);
                        //unsigned int size        = dolFile.getTextSize(i);
                        
                        // make sure binary file is big enough to contain correct section offset
                        unsigned char zero = 0;
                        fseek(bin_fd, 0, SEEK_END);
                        // if its not big enough, buffer file with 0 till its big enough
                        while((unsigned int)ftell(bin_fd) < (address-loadAddress))
                                fwrite(&zero, 1, 1, bin_fd);
                        
                        // goto section offset in binary file
                        if(fseek(bin_fd, address-loadAddress, SEEK_SET) != 0)
                                printf("Error seeking to TEXT section %d in binary file\n", i);
                        
                        // write section to binary file
                        if(dolFile.extractTextSection(i, bin_fd) == ERROR_RETURN)
                                printf("Error writing TEXT section %d in binary file\n", i);
                }
        }
        
        // then dump data bits
        for(i=0; i<dolFile.getMaxNumDataSections(); i++)
        {
                if(dolFile.isDataSectionValid(i))
                {
                        unsigned int address= dolFile.getDataAddress(i);
                        //unsigned int offset = dolFile.getDataOffset(i);
                        //unsigned int size        = dolFile.getDataSize(i);
                        
                        // make sure binary file is big enough to contain correct section offset
                        unsigned char zero = 0;
                        fseek(bin_fd, 0, SEEK_END);
                        // if its not big enough, buffer file with 0 till its big enough
                        while((unsigned int)ftell(bin_fd) < (address-loadAddress))
                                fwrite(&zero, 1, 1, bin_fd);
                        
                        // goto section offset in binary file
                        if(fseek(bin_fd, address-loadAddress, SEEK_SET) != 0)
                                printf("Error seeking to DATA section %d in binary file\n", i);
                        
                        // write section to binary file
                        if(dolFile.extractDataSection(i, bin_fd) == ERROR_RETURN)
                                printf("Error writing DATA section %d in binary file\n", i);
                }
        }
        
        // last attempt to make the entry point the same as the load address
        // this checks if there are nops at the load address that we can then overwrite
        // (ive decided to leave it out for now incase those nops are 'required' somehow...
/*        if(loadAddress != entryPoint)
        {
                int instr = 0;
                fseek(bin_fd, 0, SEEK_SET);
                fread(&instr, 4, 1, bin_fd);
                if(SET_ENDIAN_32BIT(instr) == NOP)
                {
                        // insert jump to entry point before code
                        unsigned int jump = TEST_CHANGE_ENDIAN_32BIT(MY_ENDIAN == LITTLE_ENDIAN, (x48000000 | (entryPoint - (loadAddress - 4)));
                        fseek(bin_fd, 0, SEEK_SET);
                        fwrite(&jump, 1, 4, bin_fd);
                        // update entry point
                        entryPoint = loadAddress;
                }
        }
*/        
        // close file and finish up
        fclose(bin_fd);
        printf(        "\nDumped %s to %s\n"
                        "Load Address: 0x%08X\n"
                        "Entry point:  0x%08X\n"
                        , dolFile.getFilename(), binFilename, loadAddress, entryPoint);
        
        return true;
}
Esempio n. 4
0
// dump dol file to an elf file
// 
// args:        dol file object
// returns:        true if successful
bool dumpDolToElfFile(const DolFile& dolFile)
{
        // work out filename to use for elf file
        char elfFilename[256];
        strcpy(elfFilename, dolFile.getFilename());
        ChangeFileExtension(elfFilename, "elf");
        
        // create elf output file
        ElfFile elfFile;
        if(!elfFile.create(elfFilename, ELFDATA2MSB))
                return false;
        
        // set elf file as PPC
        elfFile.setMachineType(EM_PPC);
        
        // set entry point in elf file
        elfFile.setEntryPoint(dolFile.getEntryPoint());
        
        // create a temp file to store section data during copy
        FILE* temp_fd = fopen("~temp.tmp", "w+b");
        if(temp_fd == 0)
        {
                elfFile.close();
                return false;
        }
        char name[32];
        
        // add dol text sections to elf file
        for(u32 i=0; i<dolFile.getNumTextSections(); i++)
        {
                // get section data from dol file
                fseek(temp_fd, 0, SEEK_SET);
                dolFile.extractTextSection(i, temp_fd);
                sprintf(name, ".text%d", i);
                // add section data to elf file
                fseek(temp_fd, 0, SEEK_SET);
                elfFile.addSection(temp_fd, dolFile.getTextAddress(i), dolFile.getTextSize(i),
                        name, SHT_PROGBITS, SHF_ALLOC|SHF_EXECINSTR, 32);
                
                // add a program header for the section just added
                // the section just added, was added as the last section
//                u32 offset = elfFile.getSectionOffset(elfFile.getNumSections() - 1);
//                elfFile.addProgramHeader(dolFile.getTextAddress(i), dolFile.getTextSize(i), offset, PT_LOAD, PF_EXEC|PF_READ, 32);
        }
        // add dol data sections to elf file
        for(u32    i=0; i<dolFile.getNumDataSections(); i++)
        {
                // get section data from dol file
                fseek(temp_fd, 0, SEEK_SET);
                dolFile.extractDataSection(i, temp_fd);
                sprintf(name, ".data%d", i);
                // add section data to elf file
                fseek(temp_fd, 0, SEEK_SET);
                elfFile.addSection(temp_fd, dolFile.getDataAddress(i), dolFile.getDataSize(i),
                        name, SHT_PROGBITS, SHF_ALLOC|SHF_WRITE, 32);
                
                // add a program header for the section just added
                // the section just added, was added as the last section
//                u32 offset = elfFile.getSectionOffset(elfFile.getNumSections() - 1);
//                elfFile.addProgramHeader(dolFile.getDataAddress(i), dolFile.getDataSize(i), offset, PT_LOAD, PF_WRITE|PF_READ, 32);
        }
        
        // add bss section to elf file
        elfFile.addSectionHeader(dolFile.getBssAddress(), dolFile.getBssSize(),
                ".bss", 0, SHT_NOBITS, SHF_WRITE|SHF_ALLOC, 1);
        // add a program header for the section just added
        // the section just added, was added as the last section
//        u32 index = elfFile.getNumSections() - 1;
//        elfFile.addProgramHeader(elfFile.getSectionAddress(index), elfFile.getSectionSize(index), elfFile.getSectionOffset(index), PT_LOAD, PF_WRITE|PF_READ, 32);
        
        // finish up
        fclose(temp_fd);
        remove("~temp.tmp");
        elfFile.close();
        printf(        "\nConverted %s to to %s\n", dolFile.getFilename(), elfFilename);
        return true;
}
Esempio n. 5
0
// Main entry point
int _tmain(int argc, _TCHAR* argv[])
{
	// Add command line alias'
	cl.AddAlias(L"h", L"?");
	cl.AddAlias(L"help", L"?");
	cl.AddAlias(L"x", L"extract");
	cl.AddAlias(L"o", L"out");

	// Parse command line
	cl.Parse(GetCommandLine(), true);

	// Display logo...
	if (!cl.GetSwitch(L"nologo"))
	{
		wprintf(L"Structured Ini File Compiler v1.1\nCopyright (C) 2007 Topten Software.  All Rights Reserved\n\n");
	}

	// Display help
	if (cl.GetSwitch(L"?"))
	{
		cl.BuildHelp(L"nologo", L"Suppress display of copyright and version info", NULL, clOptional);
		cl.BuildHelp(L"?|h|help", L"Display help information", NULL, clOptional);
		cl.BuildHelp(L"i", L"Include path", L"path", clMulti|clValue|clOptional);
		cl.BuildHelp(L"x|extract", L"Extract (decompile)", NULL, clOptional);
		cl.BuildHelp(L"unicode", L"Decompile to unicode", NULL, clOptional);
		cl.BuildHelp(L"flat", L"Decompile to flat", NULL, clOptional);
		cl.BuildHelp(L"o|out", L"Output File", NULL, clOptional);
		cl.BuildHelp(L"InputFile", L"File to be processed", NULL, clPlaced);
		cl.BuildHelp(L"crcstamp", L"CRC Stamp Module", NULL, clOptional);
		cl.BuildHelp(L"crcverify", L"Check Module CRC Stamp", NULL, clOptional);
		wprintf(cl.GetHelp(L"Sinic"));
		return 7;
	}

	// Get input value
	CUniString strInputFile;
	cl.GetPlacedValue(0, L"InputFile", strInputFile);
	strInputFile=QualifyPath(strInputFile);

	if (cl.GetSwitch(L"crcverify"))
	{
		if (!DoesFileExist(strInputFile))
		{
			wprintf(L"Verifying %s... file doesn't exist, ignoring\n", strInputFile);
			return 0;
		}
		else
		{
			if (!CheckModuleCRC(strInputFile))
			{
				CheckModuleCRCWithErrors(strInputFile);
				wprintf(L"************************************************************\n");
				wprintf(L" Verifying %s... FAILED\n", strInputFile);
				wprintf(L"************************************************************\n");
				return 7;
			}
			else
			{
				wprintf(L"Verifying %s... OK\n", strInputFile);
				return 0;
			}
		}
	}

	// Module CRC Stamp?
	if (cl.GetSwitch(L"crcstamp"))
	{
		// Work out output file
		CUniString strOutputFile;
		cl.GetValue(L"out", strOutputFile);
		if (strOutputFile.IsEmpty())
			strOutputFile=strInputFile;

		// Error handling...
		cl.CheckNoUnknownArgs();
		if (cl.HasError())
		{
			wprintf(cl.GetErrorMessage());
			wprintf(L"\n\n");
			return 7;
		}

		// Open file for read/write
		FILE* pFile;
		if (_wfopen_s(&pFile, strInputFile, L"rb")!=0)
		{
			wprintf(L"Error: Can't open file '%s'\n", strInputFile);
			return 7;
		}

		// Get file size
		fseek(pFile, 0, SEEK_END);
		DWORD dwLength=ftell(pFile);
		fseek(pFile, 0, SEEK_SET);

		// Check has length
		if (dwLength==0)
		{
			fclose(pFile);
			wprintf(L"Error: Zero length file\n");
			return 7;
		}

		// Load file into memory
		LPBYTE pFileData=(LPBYTE)malloc(dwLength);

		// Read data
		if (fread(pFileData, dwLength, 1, pFile)!=1)
		{
			free(pFileData);
			fclose(pFile);
			wprintf(L"Error: Error reading file\n");
			return 7;
		}

		// Close the file
		fclose(pFile);

		if (CountCRCControlBlocks(pFileData, dwLength)>1)
			{
			free(pFileData);
			fclose(pFile);
			wprintf(L"Error: File contains multiple CRC Control blocks!\n");
			return 7;
			}
			

		// Locate CRC Control block
		CRCCONTROLBLOCK* pCRCBlock=LocateCRCControlBlock(pFileData, dwLength);
		if (!pCRCBlock)
		{
			free(pFileData);
			fclose(pFile);
			wprintf(L"Error: File doesn't contain CRC Control block!\n");
			return 7;
		}

		wprintf(L"CRC Control Block located at offset: 0x%.8x\n", reinterpret_cast<LPBYTE>(pCRCBlock)-pFileData);

		// Calculate the CRC upto start of control block
		pCRCBlock->dwCRC=CalculateModuleCRC(pFileData, dwLength, pCRCBlock);
		pCRCBlock->dwModuleLength=dwLength;

		wprintf(L"Module length: 0x%.8x\n", dwLength);
		wprintf(L"CRC: 0x%.8x\n", pCRCBlock->dwCRC);
				
		pFile=NULL;
		if (_wfopen_s(&pFile, strOutputFile, L"wb")!=0)
		{
			wprintf(L"Error: Can't open output file '%s'\n", strOutputFile);
			return 7;
		}

		if (!CheckModuleCRC(pFileData, dwLength))
		{
			wprintf(L"Error: double check failed\n");
			return 7;
		}

		// Write CRC stamped
		fwrite(pFileData, dwLength, 1, pFile);

		// Clean up
		free(pFileData);

		fclose(pFile);

		if (!CheckModuleCRC(strOutputFile))
		{
			CheckModuleCRCWithErrors(strOutputFile);
			return 7;
		}

		wprintf(L"CRC Stamped %s - OK\n\n", strOutputFile);
		return 0;
	}


	// Compile or decompile
	bool bDecompile=cl.GetSwitch(L"extract");
	bool bUnicode=cl.GetSwitch(L"unicode");
	bool bFlat=cl.GetSwitch(L"flat");

	// Get output file
	CUniString strOutputFile;
	cl.GetValue(L"out", strOutputFile);
	if (strOutputFile.IsEmpty())
	{
		strOutputFile=ChangeFileExtension(strInputFile.IsEmpty() ? L"" : strInputFile, bDecompile ? L"sini" : L"bini");
	}
	strOutputFile=QualifyPath(strOutputFile);


	// Setup file content provider with include paths
	CFileContentProvider fp;
	CVector<CUniString> vecIncludePaths;
	cl.GetMultiValue(L"i", vecIncludePaths);
	for (int i=0; i<vecIncludePaths.GetSize(); i++)
	{
		CUniString str=QualifyPath(vecIncludePaths[i]);
		fp.AddIncludePath(str);
	}

	// Get defines
	CVector<CUniString> vecDefines;
	cl.GetMultiValue(L"d", vecDefines);

	// Error handling...
	cl.CheckNoUnknownArgs();
	if (cl.HasError())
	{
		wprintf(cl.GetErrorMessage());
		wprintf(L"\n\n");
		return 7;
	}

	if (!bDecompile)
	{
		// Load the input file
		CProfileFile file;
		for (int i=0; i<vecDefines.GetSize(); i++)
		{
			CUniString strName, strValue;
			SplitString(vecDefines[i], L"=", strName, strValue);
			wprintf(L"#define %s %s\n", strName, strValue);
			file.Define(strName, strValue);
		}

		if (!file.Load(strInputFile, &fp))
		{
			HRESULT hr=HRESULT_FROM_WIN32(GetLastError());
			wprintf(file.GetParseError());
			return 7;
		}

		// Extract encryption key
		DWORD dwEncryptionKey=0;
		CProfileSection* pSection=file.FindSection(L"Sinic");
		if (pSection)
		{
			// Save the key
			dwEncryptionKey=pSection->GetIntValue(L"EncryptionKey", 0);

			// Remove the "sinic" section
			file.Remove(pSection);
		}

		// Create output file
		CFileStream OutStream;
		if (!OutStream.Create(strOutputFile))
		{
			HRESULT hr=HRESULT_FROM_WIN32(GetLastError());
			wprintf(L"Failed to create '%s' - %s (0x%.8x)\n\n", strOutputFile, FormatError(hr), hr);
			return 7;
		}

		// Save as binary file
		HRESULT hr;
		if (dwEncryptionKey)
		{
			CAutoPtr<IStream, SRefCounted> spEncStream;
			CreateCryptorStream(&OutStream, CCryptorKey(dwEncryptionKey), &spEncStream);
			hr=SaveBinaryProfile(file, spEncStream);
		}
		else
		{
			hr=SaveBinaryProfile(file, &OutStream);
		}
		OutStream.Close();
		if (FAILED(hr))
		{
			HRESULT hr=HRESULT_FROM_WIN32(GetLastError());
			wprintf(L"Failed to save '%s' - %s (0x%.8x)\n\n", strOutputFile, FormatError(hr), hr);
			DeleteFile(strOutputFile);
			return 7;
		}
	}
	else
	{
		// Open stream
		CFileStream InStream;
		if (!InStream.Open(strInputFile))
		{
			HRESULT hr=HRESULT_FROM_WIN32(GetLastError());
			wprintf(L"Failed to open '%s' - %s (0x%.8x)\n\n", strInputFile, FormatError(hr), hr);
			return 7;
		}

		// Load profile
		CProfileFile file;
		HRESULT hr=LoadBinaryProfile(file, &InStream);
		if (FAILED(hr))
		{
			if (hr!=E_UNEXPECTED)
			{
				wprintf(L"Failed to load '%s' - %s (0x%.8x)\n\n", strInputFile, FormatError(hr), hr);
				return 7;
			}
			else
			{
				wprintf(L"Failed to load '%s' - not a binary profile file\n\n", strInputFile);
				return 7;
			}
		}

		// Save as heirarchial
		if (!file.Save(strOutputFile, bUnicode, !bFlat))
		{
			HRESULT hr=HRESULT_FROM_WIN32(GetLastError());
			wprintf(L"Failed to save '%s' - %s (0x%.8x)\n\n", strInputFile, FormatError(hr), hr);
			return 7;
		}
	}

	wprintf(L"%s - OK\n\n", strOutputFile);

	return 0;
}