diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj
index d426230e5d..2f4f995420 100644
--- a/projects/openrct2.vcxproj
+++ b/projects/openrct2.vcxproj
@@ -31,6 +31,7 @@
+
@@ -59,6 +60,7 @@
+
diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters
index 81179ea802..405b3f8f65 100644
--- a/projects/openrct2.vcxproj.filters
+++ b/projects/openrct2.vcxproj.filters
@@ -99,6 +99,9 @@
Header Files
+
+ Header Files
+
@@ -185,6 +188,9 @@
Source Files
+
+ Source Files
+
diff --git a/src/rct2.c b/src/rct2.c
index 88c59870fe..d3854e81af 100644
--- a/src/rct2.c
+++ b/src/rct2.c
@@ -25,13 +25,16 @@
#include
#include
#include "addresses.h"
+#include "climate.h"
#include "config.h"
+#include "date.h"
#include "game.h"
#include "gfx.h"
#include "intro.h"
#include "map.h"
#include "news_item.h"
#include "osinterface.h"
+#include "park.h"
#include "rct2.h"
#include "ride.h"
#include "scenario.h"
@@ -120,15 +123,13 @@ void rct2_init()
RCT2_CALLPROC_EBPSAFE(0x0068F083); // window guest list init vars a
RCT2_CALLPROC_EBPSAFE(0x006BD3A4);
map_init();
- RCT2_CALLPROC_EBPSAFE(0x00667132); // init_park();
+ park_init();
RCT2_CALLPROC_EBPSAFE(0x0066B5C0); // 0x0066B5C0 (part of 0x0066B3E8) screen_game_create_windows()
- RCT2_CALLPROC_EBPSAFE(0x006C4494); // init_date
- RCT2_CALLPROC_X(0x6C45ED, 0, 0, 0, 0, 0, 0, 0); // init_climate_and_date()
+ date_reset();
+ climate_reset(CLIMATE_COOL_AND_WET);
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
-
- // Window guest list init vars b
- RCT2_CALLPROC_EBPSAFE(0x0068F050);
+ RCT2_CALLPROC_EBPSAFE(0x0068F050); // window guest list init vars b
RCT2_CALLPROC_EBPSAFE(0x006BD39C);
title_load();
diff --git a/src/rct2.h b/src/rct2.h
index 4a2c86aa4a..5b083c9bd9 100644
--- a/src/rct2.h
+++ b/src/rct2.h
@@ -18,8 +18,8 @@
* along with this program. If not, see .
*****************************************************************************/
-#ifndef _SDL_RCT2_H_
-#define _SDL_RCT2_H_
+#ifndef _RCT2_H_
+#define _RCT2_H_
#include
#include
@@ -33,8 +33,14 @@ typedef unsigned short uint16;
typedef unsigned long uint32;
typedef unsigned long long uint64;
-#define rol32(x, shift) (((x) << (shift)) | ((x) >> (32 - (shift))))
-#define ror32(x, shift) (((x) >> (shift)) | ((x) << (32 - (shift))))
+#define rol8(x, shift) (((uint8)(x) << (shift)) | ((uint8)(x) >> (8 - (shift))))
+#define ror8(x, shift) (((uint8)(x) >> (shift)) | ((uint8)(x) << (8 - (shift))))
+#define rol16(x, shift) (((uint16)(x) << (shift)) | ((uint16)(x) >> (16 - (shift))))
+#define ror16(x, shift) (((uint16)(x) >> (shift)) | ((uint16)(x) << (16 - (shift))))
+#define rol32(x, shift) (((uint32)(x) << (shift)) | ((uint32)(x) >> (32 - (shift))))
+#define ror32(x, shift) (((uint32)(x) >> (shift)) | ((uint32)(x) << (32 - (shift))))
+#define rol64(x, shift) (((uint64)(x) << (shift)) | ((uint32)(x) >> (64 - (shift))))
+#define ror64(x, shift) (((uint64)(x) >> (shift)) | ((uint32)(x) << (64 - (shift))))
#define sgn(x) ((x > 0) ? 1 : ((x < 0) ? -1 : 0))
#define clamp(l, x, h) (min(h, max(l, x)))
diff --git a/src/sawyercoding.c b/src/sawyercoding.c
new file mode 100644
index 0000000000..f6efff4008
--- /dev/null
+++ b/src/sawyercoding.c
@@ -0,0 +1,146 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#include
+#include "addresses.h"
+#include "rct2.h"
+#include "sawyercoding.h"
+
+static int decode_chunk_rle(char *buffer, int length);
+static int decode_chunk_repeat(char *buffer, int length);
+static void decode_chunk_rotate(char *buffer, int length);
+
+/**
+ *
+ * rct2: 0x0067685F
+ * buffer (esi)
+ */
+int sawyercoding_read_chunk(HFILE hFile, uint8 *buffer)
+{
+ DWORD numBytesRead;
+ int i, code;
+
+ uint8 encoding;
+ uint32 length;
+
+ // Read chunk encoding and length
+ ReadFile(hFile, &encoding, 1, &numBytesRead, NULL);
+ ReadFile(hFile, &length, 4, &numBytesRead, NULL);
+
+ // Read chunk data
+ ReadFile(hFile, buffer, length, &numBytesRead, NULL);
+
+ // Decode chunk data
+ switch (encoding) {
+ case CHUNK_ENCODING_RLE:
+ length = decode_chunk_rle(buffer, length);
+ break;
+ case CHUNK_ENCODING_RLECOMPRESSED:
+ length = decode_chunk_rle(buffer, length);
+ length = decode_chunk_repeat(buffer, length);
+ break;
+ case CHUNK_ENCODING_ROTATE:
+ decode_chunk_rotate(buffer, length);
+ break;
+ }
+
+ // Set length
+ RCT2_GLOBAL(0x009E3828, uint32) = length;
+ return length;
+}
+
+/**
+ *
+ * rct2: 0x0067693A
+ */
+static int decode_chunk_rle(char *buffer, int length)
+{
+ int i, j, count;
+ uint8 *src, *dst, rleCodeByte;
+
+ // Backup buffer
+ src = malloc(length);
+ memcpy(src, buffer, length);
+ dst = buffer;
+
+ for (i = 0; i < length; i++) {
+ rleCodeByte = src[i];
+ if (rleCodeByte & 128) {
+ i++;
+ count = 1 - rleCodeByte + 256;
+ for (j = 0; j < count; j++)
+ *dst++ = src[i];
+ } else {
+ for (j = 0; j < rleCodeByte; j++)
+ *dst++ = src[++i];
+ }
+ }
+
+ // Free backup buffer
+ free(src);
+
+ // Return final size
+ return dst - buffer;
+}
+
+/**
+ *
+ * rct2: 0x006769F1
+ */
+static int decode_chunk_repeat(char *buffer, int length)
+{
+ int i, j, count;
+ uint8 *src, *dst, *copyOffset, rleCodeByte;
+
+ // Backup buffer
+ src = malloc(length);
+ memcpy(src, buffer, length);
+ dst = buffer;
+
+ for (i = 0; i < length; i++) {
+ if (src[i] == 0xFF) {
+ *dst++ = src[++i];
+ } else {
+ count = src[i] & 7;
+ copyOffset = dst + (int)(src[i] >> 3) - 32;
+ for (j = 0; j < count; j++)
+ *dst++ = *copyOffset++;
+ }
+ }
+
+ // Free backup buffer
+ free(src);
+
+ // Return final size
+ return dst - buffer;
+}
+
+/**
+ *
+ * rct2: 0x006768F4
+ */
+static void decode_chunk_rotate(char *buffer, int length)
+{
+ int i, code = 1;
+ for (i = 0; i < length; i++) {
+ buffer[i] = ror8(buffer[i], code);
+ code = (code + 2) % 8;
+ }
+}
\ No newline at end of file
diff --git a/src/sawyercoding.h b/src/sawyercoding.h
new file mode 100644
index 0000000000..52b893504c
--- /dev/null
+++ b/src/sawyercoding.h
@@ -0,0 +1,35 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#ifndef _SAWYERCODING_H_
+#define _SAWYERCODING_H_
+
+#include
+
+enum {
+ CHUNK_ENCODING_NONE,
+ CHUNK_ENCODING_RLE,
+ CHUNK_ENCODING_RLECOMPRESSED,
+ CHUNK_ENCODING_ROTATE
+};
+
+int sawyercoding_read_chunk(HFILE hFile, uint8 *buffer);
+
+#endif
\ No newline at end of file
diff --git a/src/scenario.c b/src/scenario.c
index 70cdfd5ef8..99e9ead251 100644
--- a/src/scenario.c
+++ b/src/scenario.c
@@ -23,6 +23,7 @@
#include
#include "addresses.h"
#include "rct2.h"
+#include "sawyercoding.h"
#include "scenario.h"
#include "strings.h"
@@ -237,6 +238,8 @@ static void scenario_scores_save()
}
}
+void sub_67685F(HFILE hFile, uint32 address);
+
/**
* Loads only the basic information from a scenario.
* rct2: 0x006761D6
@@ -250,9 +253,9 @@ static int scenario_load_basic(char *path)
FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
RCT2_GLOBAL(0x009E382C, HANDLE*) = hFile;
- RCT2_CALLPROC_X(0x0067685F, 0, 0, 0, 0, 0x009E34E4, 0, 0);
+ sawyercoding_read_chunk(hFile, 0x009E34E4);
if (RCT2_GLOBAL(0x009E34E4, uint8) == 1) {
- RCT2_CALLPROC_X(0x0067685F, 0, 0, 0, 0, 0x0141F570, 0, 0);
+ sawyercoding_read_chunk(hFile, 0x0141F570);
CloseHandle(hFile);
RCT2_GLOBAL(0x009AA00C, uint8) = 0;
if (RCT2_GLOBAL(0x0141F6F8, uint8) != 255) {
diff --git a/src/title.c b/src/title.c
index 71bae058c7..6b14e1daa0 100644
--- a/src/title.c
+++ b/src/title.c
@@ -19,13 +19,15 @@
*****************************************************************************/
#include "addresses.h"
+#include "date.h"
#include "game.h"
#include "gfx.h"
+#include "intro.h"
#include "map.h"
#include "news_item.h"
+#include "park.h"
#include "rct2.h"
#include "ride.h"
-#include "intro.h"
#include "viewport.h"
static void title_create_windows();
@@ -51,15 +53,15 @@ void title_load()
RCT2_CALLPROC_EBPSAFE(0x006C4209);
RCT2_CALLPROC_EBPSAFE(0x0069EB13);
ride_init_all();
- RCT2_CALLPROC_EBPSAFE(0x0068F083);
+ RCT2_CALLPROC_EBPSAFE(0x0068F083); // window_guest_list_init_vars_a
RCT2_CALLPROC_EBPSAFE(0x006BD3A4);
map_init();
- RCT2_CALLPROC_EBPSAFE(0x00667132);
- RCT2_CALLPROC_EBPSAFE(0x006C4494);
+ park_init();
+ date_reset();
RCT2_CALLPROC_X(0x006C45ED, 0, 0, 0, 0, 0, 0, 0);
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
- RCT2_CALLPROC_EBPSAFE(0x0068F050);
+ RCT2_CALLPROC_EBPSAFE(0x0068F050); // window_guest_list_init_vars_b
RCT2_CALLPROC_EBPSAFE(0x006BD39C);
RCT2_CALLPROC_EBPSAFE(0x0068AFFD);
RCT2_CALLPROC_EBPSAFE(0x0069EBE4);