This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
MineConvert/Xbox to Anvil/source/ReconstructP.cpp
Keith @ Killa Network edeb684560 Added XBox support
2015-11-05 18:54:13 +11:00

136 lines
4.1 KiB
C++

// ReconstructP.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <string.h>
FILE *header_file_f, *output_file_f, *input_file_f;
char *input_pathA, *output_pathA, a = 2;
unsigned char *buffer, *nbuffer, *blbuffer;
unsigned long bytes_read, len, p_len;
int offset;
/* Flips an integer from Big Endian to Little Endian or vice versa. Return value is the processed integer.
* Minecraft files, both PC and XBox, expect integers in Big Endian.
* _input_int: The integer to flip.
*/
int EndianFlip(int _input_int)
{
int retval;
unsigned char *_input_ptr = (unsigned char *)&_input_int;
unsigned char *_p_retval = (unsigned char *)&retval;
for (int _i = 0; _i < 4; _i ++)
{
_p_retval[3 - _i] = _input_ptr[_i];
}
return retval;
}
/* _tmain takes a directory full of compressed PC-format chunk files and assembles them into a PC-format .mcr file.
* _tmain expects the "LastUpdated" header block to be present in a file called "header_output.txt".
* _tmain expects two command line arguments:
* argv[1]: Path to the directory containing the PC chunk files.
* argv[2]: Path to the new .mcr file to create.
*/
int _tmain(int argc, _TCHAR* argv[])
{
buffer = new unsigned char[8192];
nbuffer = new unsigned char[409600];
blbuffer = new unsigned char[5];
output_pathA = new char[200];
input_pathA = new char[200];
for (int i = 0; i < 4096; i ++) buffer[i] = 0;
// Get the paths set up
sprintf(output_pathA, "%ls", argv[2]);
sprintf(input_pathA, "%ls", argv[1]);
p_len = strlen(input_pathA);
// Open the header file for reading
header_file_f = fopen("header_output.txt", "r+b");
// Create the final file; prepare to write the chunks by advancing the pointer to 8 KB.
output_file_f = fopen(output_pathA, "wb");
fwrite(buffer, sizeof(char), 8192, output_file_f);
offset = 2;
// Loop through reading in the compressed files
for (int i = 0; i < 1024; i ++)
{
// Get file path
sprintf(input_pathA + p_len, "\\%d.dat\0", i);
// Open the file for reading
input_file_f = fopen(input_pathA, "rb");
if (input_file_f != NULL)
{
// Read all the compressed PC data from the file
fseek(input_file_f, 0L, SEEK_END);
len = ftell(input_file_f);
rewind(input_file_f);
bytes_read = fread(nbuffer, sizeof(char), len, input_file_f);
if (len != bytes_read) printf("Warning: read for compressed file %d may have failed.\n", i);
// This gets the number of 4 KB chunks that this block will span in the final file
// If the chunk would span an exact multiple of 4096 bytes, by Minecraft convention the next chunk must be left blank.
bytes_read = (bytes_read + 5) / 4096 + ((bytes_read / 5) % 4096 == 0 ? 0 : 1);
// Write the size of this chunk to the header file
*(int *)blbuffer = EndianFlip(offset);
blbuffer[4] = bytes_read;
offset += bytes_read;
fwrite(blbuffer + 1, sizeof(char), 4, header_file_f);
// Grab the length of the chunk in bytes and write the entire chunk to the file
bytes_read = EndianFlip(len + 1);
fwrite(&bytes_read, sizeof(char), 4, output_file_f);
fwrite(&a, sizeof(char), 1, output_file_f);
bytes_read = fwrite(nbuffer, sizeof(char), len, output_file_f);
if (bytes_read != len) printf("Warning: write for compressed file %d may have failed. Conversion may be incomplete.\n", i);
// Now we need to pad to 4096 bytes by writing out zeroes
len = 4096 - ((bytes_read + 5) % 4096);
fwrite(buffer, sizeof(char), len, output_file_f);
fclose(input_file_f);
}
else
{
// If opening the file failed, we write blank bytes to the header file to indicate the chunk is not present.
bytes_read = 0;
fwrite(&bytes_read, sizeof(char), 4, header_file_f);
}
}
// Finally write the contents of the header_file.txt to the beginning of the .mcr file.
rewind(header_file_f);
rewind(output_file_f);
fread(buffer, sizeof(char), 8192, header_file_f);
fwrite(buffer, sizeof(char), 8192, output_file_f);
// Close files
fclose(header_file_f);
fclose(output_file_f);
delete [8192] buffer;
delete [409600] nbuffer;
delete [5] blbuffer;
delete [200] output_pathA;
delete [200] input_pathA;
return 0;
}