mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-06 06:32:56 +01:00
use SDL_RWops for save games
This commit is contained in:
@@ -90,11 +90,8 @@ bool Source_Sample::LoadWAV(const char* filename)
|
||||
{
|
||||
log_verbose("Source_Sample::LoadWAV(%s)", filename);
|
||||
|
||||
utf8 utf8filename[512];
|
||||
win1252_to_utf8(utf8filename, filename, sizeof(utf8filename));
|
||||
|
||||
Unload();
|
||||
SDL_RWops* rw = SDL_RWFromFile(utf8filename, "rb");
|
||||
SDL_RWops* rw = platform_sdl_rwfromfile(filename, "rb");
|
||||
if (rw == NULL) {
|
||||
log_verbose("Error loading %s", filename);
|
||||
return false;
|
||||
@@ -122,11 +119,8 @@ bool Source_Sample::LoadCSS1(const char* filename, unsigned int offset)
|
||||
{
|
||||
log_verbose("Source_Sample::LoadCSS1(%s, %d)", filename, offset);
|
||||
|
||||
utf8 utf8filename[512];
|
||||
win1252_to_utf8(utf8filename, filename, sizeof(utf8filename));
|
||||
|
||||
Unload();
|
||||
SDL_RWops* rw = SDL_RWFromFile(utf8filename, "rb");
|
||||
SDL_RWops* rw = platform_sdl_rwfromfile(filename, "rb");
|
||||
if (rw == NULL) {
|
||||
log_verbose("Unable to load %s", filename);
|
||||
return false;
|
||||
@@ -854,10 +848,7 @@ void* Mixer_Play_Music(int pathid, int loop, int streaming)
|
||||
if (streaming) {
|
||||
const char* filename = get_file_path(pathid);
|
||||
|
||||
utf8 utf8filename[512];
|
||||
win1252_to_utf8(utf8filename, filename, sizeof(utf8filename));
|
||||
|
||||
SDL_RWops* rw = SDL_RWFromFile(utf8filename, "rb");
|
||||
SDL_RWops* rw = platform_sdl_rwfromfile(filename, "rb");
|
||||
if (rw == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
40
src/editor.c
40
src/editor.c
@@ -339,16 +339,16 @@ static int editor_load_landscape_from_sc4(const char *path)
|
||||
static int editor_read_s6(const char *path)
|
||||
{
|
||||
int i, j;
|
||||
FILE *file;
|
||||
SDL_RWops* rw;
|
||||
rct_s6_header *s6Header = (rct_s6_header*)0x009E34E4;
|
||||
rct_s6_info *s6Info = (rct_s6_info*)0x0141F570;
|
||||
|
||||
log_verbose("loading landscape, %s", path);
|
||||
|
||||
file = fopen(path, "rb");
|
||||
if (file != NULL) {
|
||||
if (!sawyercoding_validate_checksum(file)) {
|
||||
fclose(file);
|
||||
rw = platform_sdl_rwfromfile(path, "rb");
|
||||
if (rw != NULL) {
|
||||
if (!sawyercoding_validate_checksum(rw)) {
|
||||
SDL_RWclose(rw);
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
|
||||
|
||||
@@ -357,10 +357,10 @@ static int editor_read_s6(const char *path)
|
||||
}
|
||||
|
||||
// Read first chunk
|
||||
sawyercoding_read_chunk(file, (uint8*)s6Header);
|
||||
sawyercoding_read_chunk(rw, (uint8*)s6Header);
|
||||
if (s6Header->type == S6_TYPE_SCENARIO) {
|
||||
// Read second chunk
|
||||
sawyercoding_read_chunk(file, (uint8*)s6Info);
|
||||
sawyercoding_read_chunk(rw, (uint8*)s6Info);
|
||||
|
||||
if (s6Info->var_000 == 255)
|
||||
s6Info->var_000 = 1;
|
||||
@@ -374,50 +374,50 @@ static int editor_read_s6(const char *path)
|
||||
if (s6Header->num_packed_objects > 0) {
|
||||
j = 0;
|
||||
for (i = 0; i < s6Header->num_packed_objects; i++)
|
||||
j += object_load_packed(file);
|
||||
j += object_load_packed(rw);
|
||||
if (j > 0)
|
||||
object_list_load();
|
||||
}
|
||||
|
||||
uint8 load_success = object_read_and_load_entries(file);
|
||||
uint8 load_success = object_read_and_load_entries(rw);
|
||||
|
||||
// Read flags (16 bytes). Loads:
|
||||
// RCT2_ADDRESS_CURRENT_MONTH_YEAR
|
||||
// RCT2_ADDRESS_CURRENT_MONTH_TICKS
|
||||
// RCT2_ADDRESS_SCENARIO_TICKS
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_CURRENT_MONTH_YEAR);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_MONTH_YEAR);
|
||||
|
||||
// Read map elements
|
||||
memset((void*)RCT2_ADDRESS_MAP_ELEMENTS, 0, MAX_MAP_ELEMENTS * sizeof(rct_map_element));
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_MAP_ELEMENTS);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_MAP_ELEMENTS);
|
||||
|
||||
// Read game data, including sprites
|
||||
sawyercoding_read_chunk(file, (uint8*)0x010E63B8);
|
||||
sawyercoding_read_chunk(rw, (uint8*)0x010E63B8);
|
||||
|
||||
if (s6Header->type == S6_TYPE_SCENARIO) {
|
||||
// Read number of guests in park and something else
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_GUESTS_IN_PARK);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_GUESTS_IN_PARK);
|
||||
|
||||
// Read ?
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_LAST_GUESTS_IN_PARK);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_LAST_GUESTS_IN_PARK);
|
||||
|
||||
// Read park rating
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_CURRENT_PARK_RATING);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_PARK_RATING);
|
||||
|
||||
// Read ?
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_ACTIVE_RESEARCH_TYPES);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_ACTIVE_RESEARCH_TYPES);
|
||||
|
||||
// Read ?
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_CURRENT_EXPENDITURE);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_EXPENDITURE);
|
||||
|
||||
// Read ?
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_CURRENT_PARK_VALUE);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_PARK_VALUE);
|
||||
|
||||
// Read more game data, including research items and rides
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_COMPLETED_COMPANY_VALUE);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_COMPLETED_COMPANY_VALUE);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
SDL_RWclose(rw);
|
||||
if (!load_success){
|
||||
log_error("failed to load all entries.");
|
||||
set_load_objects_fail_reason();
|
||||
|
||||
91
src/game.c
91
src/game.c
@@ -593,32 +593,12 @@ static void load_landscape()
|
||||
*
|
||||
* rct2: 0x00675E1B
|
||||
*/
|
||||
int game_load_sv6(const char *path)
|
||||
int game_load_sv6(SDL_RWops* rw)
|
||||
{
|
||||
FILE *file;
|
||||
int i, j;
|
||||
|
||||
log_verbose("loading saved game, %s", path);
|
||||
|
||||
strcpy((char*)0x0141EF68, path);
|
||||
strcpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, path);
|
||||
|
||||
strcpy(gScenarioSaveName, path_get_filename(path));
|
||||
path_remove_extension(gScenarioSaveName);
|
||||
|
||||
file = fopen(path, "rb");
|
||||
if (file == NULL) {
|
||||
log_error("unable to open %s", path);
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!sawyercoding_validate_checksum(file)) {
|
||||
fclose(file);
|
||||
|
||||
log_error("invalid checksum, %s", path);
|
||||
if (!sawyercoding_validate_checksum(rw)) {
|
||||
log_error("invalid checksum");
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
|
||||
@@ -629,31 +609,29 @@ int game_load_sv6(const char *path)
|
||||
rct_s6_info *s6Info = (rct_s6_info*)0x0141F570;
|
||||
|
||||
// Read first chunk
|
||||
sawyercoding_read_chunk(file, (uint8*)s6Header);
|
||||
sawyercoding_read_chunk(rw, (uint8*)s6Header);
|
||||
if (s6Header->type == S6_TYPE_SAVEDGAME) {
|
||||
// Read packed objects
|
||||
if (s6Header->num_packed_objects > 0) {
|
||||
j = 0;
|
||||
for (i = 0; i < s6Header->num_packed_objects; i++)
|
||||
j += object_load_packed(file);
|
||||
j += object_load_packed(rw);
|
||||
if (j > 0)
|
||||
object_list_load();
|
||||
}
|
||||
}
|
||||
|
||||
uint8 load_success = object_read_and_load_entries(file);
|
||||
uint8 load_success = object_read_and_load_entries(rw);
|
||||
|
||||
// Read flags (16 bytes)
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_CURRENT_MONTH_YEAR);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_MONTH_YEAR);
|
||||
|
||||
// Read map elements
|
||||
memset((void*)RCT2_ADDRESS_MAP_ELEMENTS, 0, MAX_MAP_ELEMENTS * sizeof(rct_map_element));
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_MAP_ELEMENTS);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_MAP_ELEMENTS);
|
||||
|
||||
// Read game data, including sprites
|
||||
sawyercoding_read_chunk(file, (uint8*)0x010E63B8);
|
||||
|
||||
fclose(file);
|
||||
sawyercoding_read_chunk(rw, (uint8*)0x010E63B8);
|
||||
|
||||
if (!load_success){
|
||||
set_load_objects_fail_reason();
|
||||
@@ -683,12 +661,30 @@ int game_load_save(const char *path)
|
||||
{
|
||||
rct_window *mainWindow;
|
||||
|
||||
if (!game_load_sv6(path)) {
|
||||
title_load();
|
||||
rct2_endupdate();
|
||||
log_verbose("loading saved game, %s", path);
|
||||
|
||||
strcpy((char*)0x0141EF68, path);
|
||||
strcpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, path);
|
||||
|
||||
strcpy(gScenarioSaveName, path_get_filename(path));
|
||||
path_remove_extension(gScenarioSaveName);
|
||||
|
||||
SDL_RWops* rw = platform_sdl_rwfromfile(path, "rb");
|
||||
if (rw == NULL) {
|
||||
log_error("unable to open %s", path);
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!game_load_sv6(rw)) {
|
||||
title_load();
|
||||
rct2_endupdate();
|
||||
SDL_RWclose(rw);
|
||||
return 0;
|
||||
}
|
||||
SDL_RWclose(rw);
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_PLAYING;
|
||||
viewport_init_all();
|
||||
game_create_windows();
|
||||
@@ -803,7 +799,7 @@ static int show_save_game_dialog(char *resultPath)
|
||||
return result;
|
||||
}
|
||||
|
||||
char save_game()
|
||||
int save_game()
|
||||
{
|
||||
window_loadsave_open(LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME, gScenarioSaveName);
|
||||
return 0;
|
||||
@@ -818,13 +814,17 @@ char save_game()
|
||||
// Ensure path has .SV6 extension
|
||||
path_set_extension(path, ".SV6");
|
||||
|
||||
if (scenario_save(path, gConfigGeneral.save_plugin_data ? 1 : 0)) {
|
||||
game_do_command(0, 1047, 0, -1, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
|
||||
gfx_invalidate_screen();
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
SDL_RWops* rw = platform_sdl_rwfromfile(path, "wb+");
|
||||
if (rw != NULL) {
|
||||
int success = scenario_save(rw, gConfigGeneral.save_plugin_data ? 1 : 0);
|
||||
SDL_RWclose(rw);
|
||||
if (success) {
|
||||
game_do_command(0, 1047, 0, -1, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
|
||||
gfx_invalidate_screen();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void game_autosave()
|
||||
@@ -834,7 +834,14 @@ void game_autosave()
|
||||
platform_get_user_directory(path, "save");
|
||||
strcat(path, "autosave.sv6");
|
||||
|
||||
scenario_save(path, 0x80000000);
|
||||
strcpy(gScenarioSaveName, path_get_filename(path));
|
||||
path_remove_extension(gScenarioSaveName);
|
||||
|
||||
SDL_RWops* rw = platform_sdl_rwfromfile(path, "wb+");
|
||||
if (rw != NULL) {
|
||||
scenario_save(rw, 0x80000000);
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define _GAME_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
enum GAME_COMMAND {
|
||||
GAME_COMMAND_SET_RIDE_APPEARANCE,
|
||||
@@ -107,11 +108,11 @@ void game_increase_game_speed();
|
||||
void game_reduce_game_speed();
|
||||
|
||||
void game_load_or_quit_no_save_prompt();
|
||||
int game_load_sv6(const char *path);
|
||||
int game_load_sv6(SDL_RWops* rw);
|
||||
int game_load_save(const char *path);
|
||||
void game_pause_toggle(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void pause_toggle();
|
||||
char save_game();
|
||||
int save_game();
|
||||
void rct2_exit();
|
||||
void rct2_exit_reason(rct_string_id title, rct_string_id body);
|
||||
void game_autosave();
|
||||
|
||||
48
src/object.c
48
src/object.c
@@ -55,19 +55,19 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi
|
||||
uint8 objectType;
|
||||
rct_object_entry openedEntry;
|
||||
char path[260];
|
||||
FILE *file;
|
||||
SDL_RWops* rw;
|
||||
|
||||
subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), (char*)installedObject + 16);
|
||||
|
||||
log_verbose("loading object, %s", path);
|
||||
|
||||
file = fopen(path, "rb");
|
||||
if (file == NULL)
|
||||
rw = platform_sdl_rwfromfile(path, "rb");
|
||||
if (rw == NULL)
|
||||
return 0;
|
||||
|
||||
fread(&openedEntry, sizeof(rct_object_entry), 1, file);
|
||||
SDL_RWread(rw, &openedEntry, sizeof(rct_object_entry), 1);
|
||||
if (!object_entry_compare(&openedEntry, entry)) {
|
||||
fclose(file);
|
||||
SDL_RWclose(rw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -82,14 +82,14 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi
|
||||
|
||||
if (*chunkSize == 0xFFFFFFFF) {
|
||||
chunk = rct2_malloc(0x600000);
|
||||
*chunkSize = sawyercoding_read_chunk(file, chunk);
|
||||
*chunkSize = sawyercoding_read_chunk(rw, chunk);
|
||||
chunk = rct2_realloc(chunk, *chunkSize);
|
||||
}
|
||||
else {
|
||||
chunk = rct2_malloc(*chunkSize);
|
||||
*chunkSize = sawyercoding_read_chunk(file, chunk);
|
||||
*chunkSize = sawyercoding_read_chunk(rw, chunk);
|
||||
}
|
||||
fclose(file);
|
||||
SDL_RWclose(rw);
|
||||
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ int object_load(int groupIndex, rct_object_entry *entry, int* chunkSize)
|
||||
* ebx : file
|
||||
* ebp : entry
|
||||
*/
|
||||
int write_object_file(FILE *file, rct_object_entry* entry){
|
||||
int write_object_file(SDL_RWops *rw, rct_object_entry* entry){
|
||||
uint8 entryGroupIndex = 0, type = 0;
|
||||
uint8* chunk = 0;
|
||||
|
||||
@@ -201,7 +201,7 @@ int write_object_file(FILE *file, rct_object_entry* entry){
|
||||
chunkHeader.length = installed_entry->chunk_size;
|
||||
|
||||
size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry), chunk, chunkHeader);
|
||||
fwrite(dst_buffer, 1, size_dst, file);
|
||||
SDL_RWwrite(rw, dst_buffer, 1, size_dst);
|
||||
|
||||
free(dst_buffer);
|
||||
return 1;
|
||||
@@ -211,16 +211,16 @@ int write_object_file(FILE *file, rct_object_entry* entry){
|
||||
*
|
||||
* rct2: 0x006AA2B7
|
||||
*/
|
||||
int object_load_packed(FILE *file)
|
||||
int object_load_packed(SDL_RWops* rw)
|
||||
{
|
||||
object_unload_all();
|
||||
|
||||
rct_object_entry entry;
|
||||
|
||||
fread(&entry, 16, 1, file);
|
||||
SDL_RWread(rw, &entry, 16, 1);
|
||||
|
||||
uint8* chunk = rct2_malloc(0x600000);
|
||||
uint32 chunkSize = sawyercoding_read_chunk(file, chunk);
|
||||
uint32 chunkSize = sawyercoding_read_chunk(rw, chunk);
|
||||
chunk = rct2_realloc(chunk, chunkSize);
|
||||
|
||||
if (chunk == NULL){
|
||||
@@ -315,11 +315,11 @@ int object_load_packed(FILE *file)
|
||||
}
|
||||
|
||||
// Actually write the object to the file
|
||||
FILE* obj_file = fopen(path, "wb");
|
||||
if (obj_file){
|
||||
uint8 result = write_object_file(obj_file, &entry);
|
||||
SDL_RWops* rw_out = platform_sdl_rwfromfile(path, "wb");
|
||||
if (rw_out != NULL){
|
||||
uint8 result = write_object_file(rw_out, &entry);
|
||||
|
||||
fclose(obj_file);
|
||||
SDL_RWclose(rw_out);
|
||||
object_unload_all();
|
||||
|
||||
return result;
|
||||
@@ -1514,9 +1514,9 @@ int object_get_scenario_text(rct_object_entry *entry)
|
||||
subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath);
|
||||
|
||||
rct_object_entry openedEntry;
|
||||
FILE *file = fopen(path, "rb");
|
||||
if (file != NULL) {
|
||||
fread(&openedEntry, sizeof(rct_object_entry), 1, file);
|
||||
SDL_RWops* rw = platform_sdl_rwfromfile(path, "rb");
|
||||
if (rw != NULL) {
|
||||
SDL_RWread(rw, &openedEntry, sizeof(rct_object_entry), 1);
|
||||
if (object_entry_compare(&openedEntry, entry)) {
|
||||
|
||||
// Skip over the object entry
|
||||
@@ -1530,14 +1530,14 @@ int object_get_scenario_text(rct_object_entry *entry)
|
||||
char *chunk;
|
||||
if (chunkSize == 0xFFFFFFFF) {
|
||||
chunk = malloc(0x600000);
|
||||
chunkSize = sawyercoding_read_chunk(file, chunk);
|
||||
chunkSize = sawyercoding_read_chunk(rw, chunk);
|
||||
chunk = realloc(chunk, chunkSize);
|
||||
}
|
||||
else {
|
||||
chunk = malloc(chunkSize);
|
||||
sawyercoding_read_chunk(file, chunk);
|
||||
sawyercoding_read_chunk(rw, chunk);
|
||||
}
|
||||
fclose(file);
|
||||
SDL_RWclose(rw);
|
||||
|
||||
// Calculate and check checksum
|
||||
if (object_calculate_checksum(&openedEntry, chunk, chunkSize) != openedEntry.checksum) {
|
||||
@@ -1578,7 +1578,7 @@ int object_get_scenario_text(rct_object_entry *entry)
|
||||
return 1;
|
||||
}
|
||||
log_error("Opened object didn't match.");
|
||||
fclose(file);
|
||||
SDL_RWclose(rw);
|
||||
return 0;
|
||||
}
|
||||
log_error("File failed to open.");
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define _OBJECT_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
// First 0xF of rct_object_entry->flags
|
||||
typedef enum{
|
||||
@@ -94,8 +95,8 @@ extern rct_object_entry_group object_entry_groups[];
|
||||
int object_load_entry(const char *path, rct_object_entry *outEntry);
|
||||
void object_list_load();
|
||||
void set_load_objects_fail_reason();
|
||||
int object_read_and_load_entries(FILE *file);
|
||||
int object_load_packed(FILE *file);
|
||||
int object_read_and_load_entries(SDL_RWops* rw);
|
||||
int object_load_packed(SDL_RWops* rw);
|
||||
void object_unload_all();
|
||||
|
||||
int check_object_entry(rct_object_entry *entry);
|
||||
@@ -109,7 +110,7 @@ int object_entry_compare(const rct_object_entry *a, const rct_object_entry *b);
|
||||
int object_calculate_checksum(const rct_object_entry *entry, const char *data, int dataLength);
|
||||
int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp);
|
||||
rct_object_entry *object_get_next(rct_object_entry *entry);
|
||||
int write_object_file(FILE *file, rct_object_entry* entry);
|
||||
int write_object_file(SDL_RWops* rw, rct_object_entry* entry);
|
||||
void reset_loaded_objects();
|
||||
int find_object_in_entry_group(rct_object_entry* entry, uint8* entry_type, uint8* entry_index);
|
||||
void object_create_identifier_name(uint8* string_buffer, rct_object_entry* object);
|
||||
|
||||
@@ -518,7 +518,7 @@ void set_load_objects_fail_reason(){
|
||||
*
|
||||
* rct2: 0x006AA0C6
|
||||
*/
|
||||
int object_read_and_load_entries(FILE *file)
|
||||
int object_read_and_load_entries(SDL_RWops* rw)
|
||||
{
|
||||
object_unload_all();
|
||||
|
||||
@@ -529,7 +529,7 @@ int object_read_and_load_entries(FILE *file)
|
||||
|
||||
// Read all the object entries
|
||||
entries = malloc(OBJECT_ENTRY_COUNT * sizeof(rct_object_entry));
|
||||
sawyercoding_read_chunk(file, (uint8*)entries);
|
||||
sawyercoding_read_chunk(rw, (uint8*)entries);
|
||||
|
||||
uint8 load_fail = 0;
|
||||
// Load each object
|
||||
|
||||
@@ -82,6 +82,7 @@ void platform_process_messages();
|
||||
int platform_scancode_to_rct_keycode(int sdl_key);
|
||||
void platform_start_text_input(char* buffer, int max_length);
|
||||
void platform_stop_text_input();
|
||||
SDL_RWops* platform_sdl_rwfromfile(const char* filename, const char* mode);
|
||||
|
||||
// Platform specific definitions
|
||||
char platform_get_path_separator();
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "../interface/keyboard_shortcut.h"
|
||||
#include "../interface/window.h"
|
||||
#include "../input.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../openrct2.h"
|
||||
#include "platform.h"
|
||||
|
||||
@@ -605,6 +606,13 @@ void platform_stop_text_input()
|
||||
gTextInput = NULL;
|
||||
}
|
||||
|
||||
SDL_RWops* platform_sdl_rwfromfile(const char* filename, const char* mode)
|
||||
{
|
||||
utf8 utf8filename[512];
|
||||
win1252_to_utf8(utf8filename, filename, sizeof(utf8filename));
|
||||
return SDL_RWFromFile(utf8filename, mode);
|
||||
}
|
||||
|
||||
static void platform_unload_cursors()
|
||||
{
|
||||
for (int i = 0; i < CURSOR_COUNT; i++)
|
||||
|
||||
125
src/scenario.c
125
src/scenario.c
@@ -58,18 +58,18 @@ static void scenario_objective_check();
|
||||
*/
|
||||
int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info)
|
||||
{
|
||||
FILE *file;
|
||||
SDL_RWops* rw;
|
||||
|
||||
log_verbose("loading scenario details, %s", path);
|
||||
|
||||
file = fopen(path, "rb");
|
||||
if (file != NULL) {
|
||||
rw = platform_sdl_rwfromfile(path, "rb");
|
||||
if (rw != NULL) {
|
||||
// Read first chunk
|
||||
sawyercoding_read_chunk(file, (uint8*)header);
|
||||
sawyercoding_read_chunk(rw, (uint8*)header);
|
||||
if (header->type == S6_TYPE_SCENARIO) {
|
||||
// Read second chunk
|
||||
sawyercoding_read_chunk(file, (uint8*)info);
|
||||
fclose(file);
|
||||
sawyercoding_read_chunk(rw, (uint8*)info);
|
||||
SDL_RWclose(rw);
|
||||
RCT2_GLOBAL(0x009AA00C, uint8) = 0;
|
||||
|
||||
// Checks for a scenario string object (possibly for localisation)
|
||||
@@ -84,7 +84,7 @@ int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *in
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
fclose(file);
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
|
||||
log_error("invalid scenario, %s", path);
|
||||
@@ -102,15 +102,15 @@ int scenario_load(const char *path)
|
||||
{
|
||||
log_verbose("loading scenario, %s", path);
|
||||
|
||||
FILE *file;
|
||||
SDL_RWops* rw;
|
||||
int i, j;
|
||||
rct_s6_header *s6Header = (rct_s6_header*)0x009E34E4;
|
||||
rct_s6_info *s6Info = (rct_s6_info*)0x0141F570;
|
||||
|
||||
file = fopen(path, "rb");
|
||||
if (file != NULL) {
|
||||
if (!sawyercoding_validate_checksum(file)) {
|
||||
fclose(file);
|
||||
rw = platform_sdl_rwfromfile(path, "rb");
|
||||
if (rw != NULL) {
|
||||
if (!sawyercoding_validate_checksum(rw)) {
|
||||
SDL_RWclose(rw);
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = STR_FILE_CONTAINS_INVALID_DATA;
|
||||
|
||||
@@ -119,57 +119,57 @@ int scenario_load(const char *path)
|
||||
}
|
||||
|
||||
// Read first chunk
|
||||
sawyercoding_read_chunk(file, (uint8*)s6Header);
|
||||
sawyercoding_read_chunk(rw, (uint8*)s6Header);
|
||||
if (s6Header->type == S6_TYPE_SCENARIO) {
|
||||
// Read second chunk
|
||||
sawyercoding_read_chunk(file, (uint8*)s6Info);
|
||||
sawyercoding_read_chunk(rw, (uint8*)s6Info);
|
||||
|
||||
// Read packed objects
|
||||
if (s6Header->num_packed_objects > 0) {
|
||||
j = 0;
|
||||
for (i = 0; i < s6Header->num_packed_objects; i++)
|
||||
j += object_load_packed(file);
|
||||
j += object_load_packed(rw);
|
||||
if (j > 0)
|
||||
object_list_load();
|
||||
}
|
||||
|
||||
uint8 load_success = object_read_and_load_entries(file);
|
||||
uint8 load_success = object_read_and_load_entries(rw);
|
||||
|
||||
// Read flags (16 bytes). Loads:
|
||||
// RCT2_ADDRESS_CURRENT_MONTH_YEAR
|
||||
// RCT2_ADDRESS_CURRENT_MONTH_TICKS
|
||||
// RCT2_ADDRESS_SCENARIO_TICKS
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_CURRENT_MONTH_YEAR);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_MONTH_YEAR);
|
||||
|
||||
// Read map elements
|
||||
memset((void*)RCT2_ADDRESS_MAP_ELEMENTS, 0, MAX_MAP_ELEMENTS * sizeof(rct_map_element));
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_MAP_ELEMENTS);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_MAP_ELEMENTS);
|
||||
|
||||
// Read game data, including sprites
|
||||
sawyercoding_read_chunk(file, (uint8*)0x010E63B8);
|
||||
sawyercoding_read_chunk(rw, (uint8*)0x010E63B8);
|
||||
|
||||
// Read number of guests in park and something else
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_GUESTS_IN_PARK);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_GUESTS_IN_PARK);
|
||||
|
||||
// Read ?
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_LAST_GUESTS_IN_PARK);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_LAST_GUESTS_IN_PARK);
|
||||
|
||||
// Read park rating
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_CURRENT_PARK_RATING);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_PARK_RATING);
|
||||
|
||||
// Read ?
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_ACTIVE_RESEARCH_TYPES);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_ACTIVE_RESEARCH_TYPES);
|
||||
|
||||
// Read ?
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_CURRENT_EXPENDITURE);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_EXPENDITURE);
|
||||
|
||||
// Read ?
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_CURRENT_PARK_VALUE);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_PARK_VALUE);
|
||||
|
||||
// Read more game data, including research items and rides
|
||||
sawyercoding_read_chunk(file, (uint8*)RCT2_ADDRESS_COMPLETED_COMPANY_VALUE);
|
||||
sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_COMPLETED_COMPANY_VALUE);
|
||||
|
||||
fclose(file);
|
||||
SDL_RWclose(rw);
|
||||
if (!load_success){
|
||||
log_error("failed to load all entries.");
|
||||
set_load_objects_fail_reason();
|
||||
@@ -183,7 +183,7 @@ int scenario_load(const char *path)
|
||||
return 1;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
|
||||
log_error("failed to find scenario file.");
|
||||
@@ -745,7 +745,7 @@ int scenario_get_num_packed_objects_to_write()
|
||||
*
|
||||
* rct2: 0x006AA26E
|
||||
*/
|
||||
int scenario_write_packed_objects(FILE *file)
|
||||
int scenario_write_packed_objects(SDL_RWops* rw)
|
||||
{
|
||||
int i;
|
||||
rct_object_entry_extended *entry = (rct_object_entry_extended*)0x00F3F03C;
|
||||
@@ -753,7 +753,7 @@ int scenario_write_packed_objects(FILE *file)
|
||||
if (RCT2_ADDRESS(0x009ACFA4, uint32)[i] == 0xFFFFFFFF || (entry->flags & 0xF0))
|
||||
continue;
|
||||
|
||||
if (!write_object_file(file, (rct_object_entry*)entry))
|
||||
if (!write_object_file(rw, (rct_object_entry*)entry))
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -878,21 +878,16 @@ static scenario_fix_ghosts(rct_s6_data *s6)
|
||||
* rct2: 0x006754F5
|
||||
* @param flags bit 0: pack objects, 1: save as scenario
|
||||
*/
|
||||
int scenario_save(char *path, int flags)
|
||||
int scenario_save(SDL_RWops* rw, int flags)
|
||||
{
|
||||
rct_window *w;
|
||||
rct_viewport *viewport;
|
||||
int viewX, viewY, viewZoom, viewRotation;
|
||||
|
||||
if (strcmp(path_get_filename(path), "autosave.sv6")) {
|
||||
strcpy(gScenarioSaveName, path_get_filename(path));
|
||||
path_remove_extension(gScenarioSaveName);
|
||||
}
|
||||
|
||||
if (flags & 2)
|
||||
log_verbose("saving scenario, %s", path);
|
||||
log_verbose("saving scenario");
|
||||
else
|
||||
log_verbose("saving game, %s", path);
|
||||
log_verbose("saving game");
|
||||
|
||||
|
||||
if (!(flags & 0x80000000))
|
||||
@@ -949,7 +944,7 @@ int scenario_save(char *path, int flags)
|
||||
memcpy(&s6->dword_010E63B8, (void*)0x010E63B8, 0x2E8570);
|
||||
|
||||
scenario_fix_ghosts(s6);
|
||||
scenario_save_s6(path, s6);
|
||||
scenario_save_s6(rw, s6);
|
||||
|
||||
free(s6);
|
||||
|
||||
@@ -961,25 +956,17 @@ int scenario_save(char *path, int flags)
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool scenario_save_s6(char *path, rct_s6_data *s6)
|
||||
bool scenario_save_s6(SDL_RWops* rw, rct_s6_data *s6)
|
||||
{
|
||||
FILE *file;
|
||||
char *buffer;
|
||||
sawyercoding_chunk_header chunkHeader;
|
||||
int encodedLength;
|
||||
long fileSize;
|
||||
uint32 checksum;
|
||||
|
||||
file = fopen(path, "wb+");
|
||||
if (file == NULL) {
|
||||
log_error("Unable to write to %s", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer = malloc(0x600000);
|
||||
if (buffer == NULL) {
|
||||
log_error("Unable to allocate enough space for a write buffer.");
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -987,21 +974,20 @@ bool scenario_save_s6(char *path, rct_s6_data *s6)
|
||||
chunkHeader.encoding = CHUNK_ENCODING_ROTATE;
|
||||
chunkHeader.length = sizeof(rct_s6_header);
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->header, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
|
||||
// 1: Write scenario info chunk
|
||||
if (s6->header.type == S6_TYPE_SCENARIO) {
|
||||
chunkHeader.encoding = CHUNK_ENCODING_ROTATE;
|
||||
chunkHeader.length = sizeof(rct_s6_info);
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->info, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
}
|
||||
|
||||
// 2: Write packed objects
|
||||
if (s6->header.num_packed_objects > 0) {
|
||||
if (!scenario_write_packed_objects(file)) {
|
||||
if (!scenario_write_packed_objects(rw)) {
|
||||
free(buffer);
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1010,92 +996,91 @@ bool scenario_save_s6(char *path, rct_s6_data *s6)
|
||||
chunkHeader.encoding = CHUNK_ENCODING_ROTATE;
|
||||
chunkHeader.length = 721 * sizeof(rct_object_entry);
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)s6->objects, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
|
||||
// 4: Misc fields (data, rand...) chunk
|
||||
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
|
||||
chunkHeader.length = 16;
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->elapsed_months, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
|
||||
// 5: Map elements + sprites and other fields chunk
|
||||
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
|
||||
chunkHeader.length = 0x180000;
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)s6->map_elements, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
|
||||
if (s6->header.type == S6_TYPE_SCENARIO) {
|
||||
// 6:
|
||||
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
|
||||
chunkHeader.length = 0x27104C;
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->dword_010E63B8, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
|
||||
// 7:
|
||||
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
|
||||
chunkHeader.length = 4;
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->guests_in_park, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
|
||||
// 8:
|
||||
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
|
||||
chunkHeader.length = 8;
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->last_guests_in_park, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
|
||||
// 9:
|
||||
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
|
||||
chunkHeader.length = 2;
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->park_rating, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
|
||||
// 10:
|
||||
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
|
||||
chunkHeader.length = 1082;
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->active_research_types, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
|
||||
// 11:
|
||||
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
|
||||
chunkHeader.length = 16;
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->current_expenditure, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
|
||||
// 12:
|
||||
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
|
||||
chunkHeader.length = 4;
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->park_value, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
|
||||
// 13:
|
||||
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
|
||||
chunkHeader.length = 0x761E8;
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->completed_company_value, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
} else {
|
||||
// 6: Everything else...
|
||||
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
|
||||
chunkHeader.length = 0x2E8570;
|
||||
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->dword_010E63B8, chunkHeader);
|
||||
fwrite(buffer, encodedLength, 1, file);
|
||||
SDL_RWwrite(rw, buffer, encodedLength, 1);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
// Determine number of bytes written
|
||||
fileSize = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
fileSize = (long)SDL_RWtell(rw);
|
||||
SDL_RWseek(rw, 0, RW_SEEK_SET);
|
||||
|
||||
// Read all written bytes back into a single buffer
|
||||
buffer = malloc(fileSize);
|
||||
fread(buffer, fileSize, 1, file);
|
||||
SDL_RWread(rw, buffer, fileSize, 1);
|
||||
checksum = sawyercoding_calculate_checksum(buffer, fileSize);
|
||||
free(buffer);
|
||||
|
||||
// Append the checksum
|
||||
fseek(file, fileSize, SEEK_SET);
|
||||
fwrite(&checksum, sizeof(uint32), 1, file);
|
||||
fclose(file);
|
||||
SDL_RWseek(rw, fileSize, RW_SEEK_SET);
|
||||
SDL_RWwrite(rw, &checksum, sizeof(uint32), 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -425,8 +425,8 @@ void scenario_update();
|
||||
unsigned int scenario_rand();
|
||||
unsigned int scenario_rand_max(unsigned int max);
|
||||
int scenario_prepare_for_save();
|
||||
int scenario_save(char *path, int flags);
|
||||
bool scenario_save_s6(char *path, rct_s6_data *s6);
|
||||
int scenario_save(SDL_RWops* rw, int flags);
|
||||
bool scenario_save_s6(SDL_RWops* rw, rct_s6_data *s6);
|
||||
void scenario_set_filename(const char *value);
|
||||
void scenario_failure();
|
||||
void scenario_success();
|
||||
|
||||
12
src/title.c
12
src/title.c
@@ -168,9 +168,15 @@ static int title_load_park(const char *path)
|
||||
rct_window* w;
|
||||
int successfulLoad;
|
||||
|
||||
successfulLoad = _strcmpi(path_get_extension(path), ".sv6") == 0 ?
|
||||
game_load_sv6(path) :
|
||||
scenario_load(path);
|
||||
if (_strcmpi(path_get_extension(path), ".sv6") == 0) {
|
||||
SDL_RWops* rw = platform_sdl_rwfromfile(path, "rb");
|
||||
if (rw != NULL) {
|
||||
successfulLoad = game_load_sv6(rw);
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
} else {
|
||||
successfulLoad = scenario_load(path);
|
||||
}
|
||||
|
||||
if (!successfulLoad)
|
||||
return 0;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../addresses.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "sawyercoding.h"
|
||||
|
||||
static int decode_chunk_rle(uint8* src_buffer, uint8* dst_buffer, int length);
|
||||
@@ -42,24 +43,24 @@ uint32 sawyercoding_calculate_checksum(uint8* buffer, uint32 length)
|
||||
*
|
||||
* rct2: 0x00676FD2
|
||||
*/
|
||||
int sawyercoding_validate_checksum(FILE *file)
|
||||
int sawyercoding_validate_checksum(SDL_RWops* rw)
|
||||
{
|
||||
uint32 i, checksum, fileChecksum, dataSize, bufferSize;
|
||||
uint8 buffer[1024];
|
||||
|
||||
// Get data size
|
||||
fseek(file, 0, SEEK_END);
|
||||
dataSize = ftell(file);
|
||||
SDL_RWseek(rw, 0, RW_SEEK_END);
|
||||
dataSize = (uint32)SDL_RWtell(rw);
|
||||
if (dataSize < 8)
|
||||
return 0;
|
||||
dataSize -= 4;
|
||||
|
||||
// Calculate checksum
|
||||
fseek(file, 0, SEEK_SET);
|
||||
SDL_RWseek(rw, 0, RW_SEEK_SET);
|
||||
checksum = 0;
|
||||
do {
|
||||
bufferSize = min(dataSize, 1024);
|
||||
if (fread(buffer, bufferSize, 1, file) != 1)
|
||||
if (SDL_RWread(rw, buffer, bufferSize, 1) != 1)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < bufferSize; i++)
|
||||
@@ -68,11 +69,11 @@ int sawyercoding_validate_checksum(FILE *file)
|
||||
} while (dataSize != 0);
|
||||
|
||||
// Read file checksum
|
||||
if (fread(&fileChecksum, sizeof(fileChecksum), 1, file) != 1)
|
||||
if (SDL_RWread(rw, &fileChecksum, sizeof(fileChecksum), 1) != 1)
|
||||
return 0;
|
||||
|
||||
// Reset file position
|
||||
fseek(file, 0, SEEK_SET);
|
||||
SDL_RWseek(rw, 0, RW_SEEK_SET);
|
||||
|
||||
// Validate
|
||||
return checksum == fileChecksum;
|
||||
@@ -83,12 +84,12 @@ int sawyercoding_validate_checksum(FILE *file)
|
||||
* rct2: 0x0067685F
|
||||
* buffer (esi)
|
||||
*/
|
||||
int sawyercoding_read_chunk(FILE *file, uint8 *buffer)
|
||||
int sawyercoding_read_chunk(SDL_RWops* rw, uint8 *buffer)
|
||||
{
|
||||
sawyercoding_chunk_header chunkHeader;
|
||||
|
||||
// Read chunk header
|
||||
if (fread(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file) != 1) {
|
||||
if (SDL_RWread(rw, &chunkHeader, sizeof(sawyercoding_chunk_header), 1) != 1) {
|
||||
log_error("Unable to read chunk header!");
|
||||
return -1;
|
||||
}
|
||||
@@ -96,7 +97,7 @@ int sawyercoding_read_chunk(FILE *file, uint8 *buffer)
|
||||
uint8* src_buffer = malloc(chunkHeader.length);
|
||||
|
||||
// Read chunk data
|
||||
if (fread(src_buffer, chunkHeader.length, 1, file) != 1) {
|
||||
if (SDL_RWread(rw, src_buffer, chunkHeader.length, 1) != 1) {
|
||||
free(src_buffer);
|
||||
log_error("Unable to read chunk data!");
|
||||
return -1;
|
||||
|
||||
@@ -47,9 +47,9 @@ enum {
|
||||
FILE_TYPE_SC4 = (2 << 2)
|
||||
};
|
||||
|
||||
int sawyercoding_validate_checksum(FILE *file);
|
||||
int sawyercoding_validate_checksum(SDL_RWops* rw);
|
||||
uint32 sawyercoding_calculate_checksum(uint8* buffer, uint32 length);
|
||||
int sawyercoding_read_chunk(FILE *file, uint8 *buffer);
|
||||
int sawyercoding_read_chunk(SDL_RWops* rw, uint8 *buffer);
|
||||
int sawyercoding_write_chunk_buffer(uint8 *dst_file, uint8* buffer, sawyercoding_chunk_header chunkHeader);
|
||||
int sawyercoding_decode_sv4(char *src, char *dst, int length);
|
||||
int sawyercoding_decode_sc4(char *src, char *dst, int length);
|
||||
|
||||
@@ -377,7 +377,11 @@ void window_editor_bottom_toolbar_jump_forward_to_save_scenario()
|
||||
// Save the scenario
|
||||
parkFlagsBackup = RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32);
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_18;
|
||||
success = scenario_save(path, gConfigGeneral.save_plugin_data ? 3 : 2);
|
||||
SDL_RWops* rw = platform_sdl_rwfromfile(path, "wb+");
|
||||
if (rw != NULL) {
|
||||
success = scenario_save(rw, gConfigGeneral.save_plugin_data ? 3 : 2);
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) = parkFlagsBackup;
|
||||
|
||||
if (success) {
|
||||
|
||||
@@ -724,6 +724,7 @@ static void window_loadsave_populate_list(int includeNewItem, bool browsable, co
|
||||
|
||||
static void window_loadsave_select(rct_window *w, const char *path)
|
||||
{
|
||||
SDL_RWops* rw;
|
||||
switch (_loadsaveType) {
|
||||
case (LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME) :
|
||||
if (gLoadSaveTitleSequenceSave) {
|
||||
@@ -752,13 +753,19 @@ static void window_loadsave_select(rct_window *w, const char *path)
|
||||
}
|
||||
break;
|
||||
case (LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME) :
|
||||
if (scenario_save((char*)path, gConfigGeneral.save_plugin_data ? 1 : 0)) {
|
||||
window_close(w);
|
||||
rw = platform_sdl_rwfromfile(path, "wb+");
|
||||
if (rw != NULL) {
|
||||
int success = scenario_save(rw, gConfigGeneral.save_plugin_data ? 1 : 0);
|
||||
SDL_RWclose(rw);
|
||||
if (success) {
|
||||
window_close(w);
|
||||
|
||||
game_do_command(0, 1047, 0, -1, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
|
||||
gfx_invalidate_screen();
|
||||
}
|
||||
else {
|
||||
game_do_command(0, 1047, 0, -1, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
|
||||
gfx_invalidate_screen();
|
||||
} else {
|
||||
window_error_open(STR_SAVE_GAME, 1047);
|
||||
}
|
||||
} else {
|
||||
window_error_open(STR_SAVE_GAME, 1047);
|
||||
}
|
||||
break;
|
||||
@@ -774,11 +781,17 @@ static void window_loadsave_select(rct_window *w, const char *path)
|
||||
}
|
||||
break;
|
||||
case (LOADSAVETYPE_SAVE | LOADSAVETYPE_LANDSCAPE) :
|
||||
if (scenario_save((char*)path, gConfigGeneral.save_plugin_data ? 3 : 2)) {
|
||||
window_close(w);
|
||||
gfx_invalidate_screen();
|
||||
}
|
||||
else {
|
||||
rw = platform_sdl_rwfromfile(path, "wb+");
|
||||
if (rw != NULL) {
|
||||
int success = scenario_save(rw, gConfigGeneral.save_plugin_data ? 3 : 2);
|
||||
SDL_RWclose(rw);
|
||||
if (success) {
|
||||
window_close(w);
|
||||
gfx_invalidate_screen();
|
||||
} else {
|
||||
window_error_open(STR_SAVE_LANDSCAPE, 1049);
|
||||
}
|
||||
} else {
|
||||
window_error_open(STR_SAVE_LANDSCAPE, 1049);
|
||||
}
|
||||
break;
|
||||
@@ -788,14 +801,18 @@ static void window_loadsave_select(rct_window *w, const char *path)
|
||||
int parkFlagsBackup = RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32);
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_18;
|
||||
s6Info->var_000 = 255;
|
||||
int success = scenario_save((char*)path, gConfigGeneral.save_plugin_data ? 3 : 2);
|
||||
rw = platform_sdl_rwfromfile(path, "wb+");
|
||||
int success = 0;
|
||||
if (rw != NULL) {
|
||||
success = scenario_save(rw, gConfigGeneral.save_plugin_data ? 3 : 2);
|
||||
SDL_RWclose(rw);
|
||||
}
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) = parkFlagsBackup;
|
||||
|
||||
if (success) {
|
||||
window_close(w);
|
||||
title_load();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
window_error_open(STR_SAVE_SCENARIO, STR_SCENARIO_SAVE_FAILED);
|
||||
s6Info->var_000 = 4;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user