Added save_track_file. Fixed bugs.

Encountered bug where incorrect tracks would be displayed if the loading process failed.
Added checksum validation to loading code.
Increased the max rle length to match rct2.
This commit is contained in:
Duncan Frost 2015-04-28 20:29:03 +01:00
parent 64374e5ac4
commit 66de066901
3 changed files with 75 additions and 7 deletions

View File

@ -508,7 +508,10 @@ rct_track_td6* load_track_design(const char *path)
// Validate the checksum
// Not the same checksum algorithm as scenarios and saved games
// sub_6770C1();
if (!sawyercoding_validate_track_checksum(fpBuffer, fpLength)){
log_error("Track checksum failed.");
return 0;
}
// Decode the track data
decoded = malloc(0x10000);
@ -1055,6 +1058,8 @@ rct_track_design *track_get_info(int index, uint8** preview)
if (!(loaded_track = load_track_design(track_path))) {
if (preview != NULL) *preview = NULL;
// Mark cache as empty.
RCT2_ADDRESS(RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE, uint32)[i] = 0;
log_error("Failed to load track: %s", trackDesignList + (index * 128));
return NULL;
}
@ -1790,6 +1795,33 @@ int ride_to_td6(uint8 rideIndex){
return tracked_ride_to_td6(rideIndex, track_design, track_elements);
}
/* rct2: 0x006771DC but not really its branched from that
* quite far.
*/
int save_track_to_file(rct_track_td6* track_design, char* path){
window_close_construction_windows();
uint8* track_file = malloc(0x8000);
int length = sawyercoding_encode_td6((char*)track_design, track_file, 0x609F);
FILE *file;
log_verbose("saving track %s", path);
file = fopen(path, "wb");
if (file == NULL) {
free(track_file);
log_error("Failed to save %s", path);
return 0;
}
fwrite(track_file, length, 1, file);
fclose(file);
free(track_file);
return 1;
}
/* rct2: 0x006D2804 & 0x006D264D */
int save_track_design(uint8 rideIndex){
rct_ride* ride = GET_RIDE(rideIndex);
@ -1859,10 +1891,7 @@ int save_track_design(uint8 rideIndex){
return 1;
}
// Until 0x006771DC is finished we required to copy the path name.
strcpy(RCT2_ADDRESS(0x141EF68, char), path);
// This is the function that actually saves the track to a file
RCT2_CALLPROC_EBPSAFE(0x006771DC);
save_track_to_file(RCT2_ADDRESS(0x009D8178, rct_track_td6), path);
ride_list_item item = { .type = 0xFC, .entry_index = 0 };
track_load_list(item);

View File

@ -225,6 +225,43 @@ int sawyercoding_decode_td6(char *src, char *dst, int length)
return decode_chunk_rle(src, dst, length - 4);
}
int sawyercoding_encode_td6(char* src, char* dst, int length){
int output_length = encode_chunk_rle(src, dst, length);
uint32 checksum = 0;
for (int i = 0; i < output_length; i++){
uint8 new_byte = ((checksum & 0xFF) + dst[i]) & 0xFF;
checksum = (checksum & 0xFFFFFF00) + new_byte;
checksum = rol32(checksum, 3);
}
checksum -= 0x1D4C1;
*((uint32*)&dst[output_length]) = checksum;
output_length += 4;
return output_length;
}
/* Based off of rct2: 0x006770C1 */
int sawyercoding_validate_track_checksum(char* src, int length){
uint32 file_checksum = *((uint32*)&src[length - 4]);
uint32 checksum = 0;
for (int i = 0; i < length - 4; i++){
uint8 new_byte = ((checksum & 0xFF) + src[i]) & 0xFF;
checksum = (checksum & 0xFFFFFF00) + new_byte;
checksum = rol32(checksum, 3);
}
if (checksum - 0x1D4C1 == file_checksum)
return 1; // .TD6
else if (checksum - 0x1A67C == file_checksum)
return 1; // .TD4
else if (checksum - 0x1A650 == file_checksum)
return 1; // .TD4
else
return 0;
}
#pragma region Decoding
/**
@ -318,14 +355,14 @@ static int encode_chunk_rle(char *src_buffer, char *dst_buffer, int length)
while (src < end_src - 1){
if ((count && *src == src[1]) || count > 120){
if ((count && *src == src[1]) || count > 125){
*dst++ = count - 1;
for (; count != 0; --count){
*dst++ = *src_norm_start++;
}
}
if (*src == src[1]){
for (; (count < 120) && ((src + count) < end_src); count++){
for (; (count < 125) && ((src + count) < end_src); count++){
if (*src != src[count]) break;
}
*dst++ = 257 - count;

View File

@ -55,6 +55,8 @@ int sawyercoding_decode_sv4(char *src, char *dst, int length);
int sawyercoding_decode_sc4(char *src, char *dst, int length);
int sawyercoding_encode_sv4(char *src, char *dst, int length);
int sawyercoding_decode_td6(char *src, char *dst, int length);
int sawyercoding_encode_td6(char* src, char* dst, int length);
int sawyercoding_validate_track_checksum(char* src, int length);
int sawyercoding_detect_file_type(char *src, int length);