mirror of https://github.com/OpenRCT2/OpenRCT2.git
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:
parent
64374e5ac4
commit
66de066901
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue