101 lines
3.5 KiB
C++
101 lines
3.5 KiB
C++
// SeparateX.cpp : Defines the entry point for the console application.
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
|
|
FILE *input_file_f, *output_file_f;
|
|
unsigned char *buffer, *relay_buffer;
|
|
unsigned long bytes_read;
|
|
int i, size, offset;
|
|
char *output_pathA, *input_pathA;
|
|
|
|
/* _tmain takes an XBox .mcr file and reads all the compressed chunk blocks into individual files.
|
|
* The method also copies the 4 KB "last updated" header of the .mcr file into a new file called header_output.txt.
|
|
* This header_output.txt will be used by later programs when assembling the final PC .mcr file.
|
|
|
|
* _tmain expects two command line arguments:
|
|
* argv[0]: Path to the .mcr file from which the data will be read.
|
|
* argv[1]: Path to the directory into which the files should be output.
|
|
*/
|
|
int _tmain(int argc, _TCHAR* argv[])
|
|
{
|
|
|
|
// Allocate memory for buffer and offsets and sizes
|
|
buffer = new unsigned char[4096];
|
|
relay_buffer = new unsigned char[4096];
|
|
input_pathA = new char[200];
|
|
output_pathA = new char[200];
|
|
|
|
// Open the file and read in the first 4096.
|
|
sprintf(input_pathA, "%ls", argv[1]);
|
|
input_file_f = fopen(input_pathA, "rb");
|
|
bytes_read = fread(buffer, sizeof(char), 4096, input_file_f);
|
|
|
|
// Create the header_output.txt file and write out two blocks: the offset block and last updated block.
|
|
// The offset block will be overwritten by a later program.
|
|
output_file_f = fopen("header_output.txt", "wb");
|
|
bytes_read = fread(relay_buffer, sizeof(char), 4096, input_file_f);
|
|
fwrite(buffer, sizeof(char), 4096, output_file_f);
|
|
fwrite(relay_buffer, sizeof(char), 4096, output_file_f);
|
|
fclose(output_file_f);
|
|
|
|
// Now loop through the 1024 chunk entries
|
|
for (i = 0; i < 4096; i += 4)
|
|
{
|
|
|
|
// Grab offset and size for each
|
|
offset = buffer[i] * 65536 + buffer[i + 1] * 256 + buffer[i + 2];
|
|
size = buffer[i + 3];
|
|
|
|
// If the offset is zero, we do nothing more; this chunk has no associated data.
|
|
if (offset != 0)
|
|
{
|
|
|
|
// Create an output file for this chunk
|
|
sprintf(output_pathA, "%ls\\%d.dat", argv[2], i / 4);
|
|
output_file_f = fopen(output_pathA, "wb");
|
|
|
|
// Move the input file pointer to the location of the chunk
|
|
// The first four bytes are the length of the data; store that first.
|
|
fseek(input_file_f, 4096 * offset, SEEK_SET);
|
|
fread(relay_buffer, sizeof(char), 4, input_file_f);
|
|
offset = ((relay_buffer[1] << 16) + (relay_buffer[2] << 8) + relay_buffer[3]) % 4096;
|
|
|
|
// Relay the input immediately to the output file in 4KB chunks
|
|
for (int x = 1; x < size; x ++)
|
|
{
|
|
|
|
// Try to read the next segment.
|
|
bytes_read = fread(relay_buffer, sizeof(char), 4096, input_file_f);
|
|
if (bytes_read != 4096) printf("Warning: could not read sector %d for chunk %d.\n", x, i / 4);
|
|
bytes_read = fwrite(relay_buffer, sizeof(char), 4096, output_file_f);
|
|
if (bytes_read != 4096) printf("Warning: could not write sector %d for chunk %d.\n", x, i / 4);
|
|
|
|
}
|
|
|
|
// Read the final segment without its trailing zeros.
|
|
bytes_read = fread(relay_buffer, sizeof(char), offset, input_file_f);
|
|
if (bytes_read != offset) printf("Warning: could not read final sector for chunk %d.\n", i / 4);
|
|
|
|
// Write the final segment to the file and close the handle.
|
|
fwrite(relay_buffer, sizeof(char), bytes_read, output_file_f);
|
|
if (bytes_read != offset) printf("Warning: could not write final sector for chunk %d.\n", i / 4);
|
|
fclose(output_file_f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(output_file_f);
|
|
|
|
// Clear memory
|
|
delete [4096] buffer;
|
|
delete [200] input_pathA;
|
|
delete [200] output_pathA;
|
|
delete [4096] relay_buffer;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|