clang-format tests

This commit is contained in:
clang-format 2018-06-22 22:29:03 +02:00 committed by Hielke Morsink
parent 4d38475f12
commit 42fa1b0f63
46 changed files with 2530 additions and 2138 deletions

View File

@ -10,11 +10,11 @@
#include "Addresses.h"
#if defined(__GNUC__)
#ifdef __clang__
#define DISABLE_OPT __attribute__((noinline,optnone))
#else
#define DISABLE_OPT __attribute__((noinline,optimize("O0")))
#endif // __clang__
#ifdef __clang__
#define DISABLE_OPT __attribute__((noinline, optnone))
#else
#define DISABLE_OPT __attribute__((noinline, optimize("O0")))
#endif // __clang__
#else
#define DISABLE_OPT
#endif // defined(__GNUC__)
@ -23,12 +23,13 @@
// When switching to original code, stack frame pointer is modified and prevents breakpad from providing stack trace.
volatile int32_t _originalAddress = 0;
int32_t DISABLE_OPT RCT2_CALLPROC_X(int32_t address, int32_t _eax, int32_t _ebx, int32_t _ecx, int32_t _edx, int32_t _esi, int32_t _edi, int32_t _ebp)
int32_t DISABLE_OPT RCT2_CALLPROC_X(
int32_t address, int32_t _eax, int32_t _ebx, int32_t _ecx, int32_t _edx, int32_t _esi, int32_t _edi, int32_t _ebp)
{
int32_t result = 0;
_originalAddress = address;
#if defined(PLATFORM_X86) && !defined(NO_RCT2)
#ifdef _MSC_VER
#ifdef _MSC_VER
__asm {
push ebp
push address
@ -43,11 +44,11 @@ int32_t DISABLE_OPT RCT2_CALLPROC_X(int32_t address, int32_t _eax, int32_t _ebx,
lahf
pop ebp
pop ebp
/* Load result with flags */
/* Load result with flags */
mov result, eax
}
#else
__asm__ volatile ( "\
#else
__asm__ volatile("\
\n\
push %%ebx \n\
push %%ebp \n\
@ -66,11 +67,19 @@ int32_t DISABLE_OPT RCT2_CALLPROC_X(int32_t address, int32_t _eax, int32_t _ebx,
pop %%ebx \n\
/* Load result with flags */ \n\
mov %%eax, %[result] \n\
" : [address] "+m" (address), [eax] "+m" (_eax), [ebx] "+m" (_ebx), [ecx] "+m" (_ecx), [edx] "+m" (_edx), [esi] "+m" (_esi), [edi] "+m" (_edi), [ebp] "+m" (_ebp), [result] "+m" (result)
:
: "eax","ecx","edx","esi","edi","memory"
);
#endif
"
: [address] "+m"(address),
[eax] "+m"(_eax),
[ebx] "+m"(_ebx),
[ecx] "+m"(_ecx),
[edx] "+m"(_edx),
[esi] "+m"(_esi),
[edi] "+m"(_edi),
[ebp] "+m"(_ebp),
[result] "+m"(result)
:
: "eax", "ecx", "edx", "esi", "edi", "memory");
#endif
#endif // PLATFORM_X86
_originalAddress = 0;
// lahf only modifies ah, zero out the rest

View File

@ -13,19 +13,19 @@
#include <openrct2/common.h>
#ifdef USE_MMAP
#if defined(PLATFORM_64BIT)
#define GOOD_PLACE_FOR_DATA_SEGMENT ((uintptr_t)0x200000000)
#elif defined(PLATFORM_32BIT)
#define GOOD_PLACE_FOR_DATA_SEGMENT ((uintptr_t)0x09000000)
#else
#error "Unknown platform"
#endif
#if defined(PLATFORM_64BIT)
#define GOOD_PLACE_FOR_DATA_SEGMENT ((uintptr_t)0x200000000)
#elif defined(PLATFORM_32BIT)
#define GOOD_PLACE_FOR_DATA_SEGMENT ((uintptr_t)0x09000000)
#else
#define GOOD_PLACE_FOR_DATA_SEGMENT ((uintptr_t)0x8a4000)
#error "Unknown platform"
#endif
#else
#define GOOD_PLACE_FOR_DATA_SEGMENT ((uintptr_t)0x8a4000)
#endif
#define RCT2_ADDRESS(address, type) ((type*)(GOOD_PLACE_FOR_DATA_SEGMENT - 0x8a4000 + (address)))
#define RCT2_GLOBAL(address, type) (*((type*)(GOOD_PLACE_FOR_DATA_SEGMENT - 0x8a4000 + (address))))
#define RCT2_ADDRESS(address, type) ((type*)(GOOD_PLACE_FOR_DATA_SEGMENT - 0x8a4000 + (address)))
#define RCT2_GLOBAL(address, type) (*((type*)(GOOD_PLACE_FOR_DATA_SEGMENT - 0x8a4000 + (address))))
/**
* Returns the flags register
@ -39,8 +39,7 @@
* P = Parity flag
* All other bits are undefined.
*/
int32_t RCT2_CALLPROC_X(int32_t address, int32_t _eax, int32_t _ebx, int32_t _ecx, int32_t _edx, int32_t _esi, int32_t _edi, int32_t _ebp);
int32_t RCT2_CALLPROC_X(
int32_t address, int32_t _eax, int32_t _ebx, int32_t _ecx, int32_t _edx, int32_t _esi, int32_t _edi, int32_t _ebp);
#endif

View File

@ -20,9 +20,9 @@
#include <openrct2/world/Sprite.h>
#include <openrct2/world/Surface.h>
#define gRideEntries RCT2_ADDRESS(0x009ACFA4, rct_ride_entry *)
#define gTileElementTilePointers RCT2_ADDRESS(0x013CE9A4, rct_tile_element *)
rct_sprite *sprite_list = RCT2_ADDRESS(0x010E63BC, rct_sprite);
#define gRideEntries RCT2_ADDRESS(0x009ACFA4, rct_ride_entry*)
#define gTileElementTilePointers RCT2_ADDRESS(0x013CE9A4, rct_tile_element*)
rct_sprite* sprite_list = RCT2_ADDRESS(0x010E63BC, rct_sprite);
Ride gRideList[MAX_RIDES];
int16_t gMapSizeUnits;
@ -36,52 +36,37 @@ uint32_t gCurrentViewportFlags;
uint32_t gScenarioTicks;
uint8_t gCurrentRotation;
const CoordsXY CoordsDirectionDelta[] = {
{ -32, 0 },
{ 0, +32 },
{ +32, 0 },
{ 0, -32 },
{ -32, +32 },
{ +32, +32 },
{ +32, -32 },
{ -32, -32 }
};
const CoordsXY CoordsDirectionDelta[]
= { { -32, 0 }, { 0, +32 }, { +32, 0 }, { 0, -32 }, { -32, +32 }, { +32, +32 }, { +32, -32 }, { -32, -32 } };
const TileCoordsXY TileDirectionDelta[] = {
{ -1, 0 },
{ 0, +1 },
{ +1, 0 },
{ 0, -1 },
{ -1, +1 },
{ +1, +1 },
{ +1, -1 },
{ -1, -1 }
};
const TileCoordsXY TileDirectionDelta[]
= { { -1, 0 }, { 0, +1 }, { +1, 0 }, { 0, -1 }, { -1, +1 }, { +1, +1 }, { +1, -1 }, { -1, -1 } };
TileCoordsXYZD ride_get_entrance_location(const Ride * ride, const int32_t stationIndex);
TileCoordsXYZD ride_get_exit_location(const Ride * ride, const int32_t stationIndex);
TileCoordsXYZD ride_get_entrance_location(const Ride* ride, const int32_t stationIndex);
TileCoordsXYZD ride_get_exit_location(const Ride* ride, const int32_t stationIndex);
uint8_t get_current_rotation() {
uint8_t get_current_rotation()
{
return gCurrentRotation & 3;
}
const uint32_t construction_markers[] = {
COLOUR_DARK_GREEN << 19 | COLOUR_GREY << 24 | IMAGE_TYPE_REMAP, // White
2 << 19 | 0b110000 << 19 | IMAGE_TYPE_TRANSPARENT, // Translucent
2 << 19 | 0b110000 << 19 | IMAGE_TYPE_TRANSPARENT, // Translucent
};
int object_entry_group_counts[] = {
128, // rides
252, // small scenery
128, // large scenery
128, // walls
32, // banners
16, // paths
15, // path bits
19, // scenery sets
1, // park entrance
1, // water
1 // scenario text
128, // rides
252, // small scenery
128, // large scenery
128, // walls
32, // banners
16, // paths
15, // path bits
19, // scenery sets
1, // park entrance
1, // water
1 // scenario text
};
GeneralConfiguration gConfigGeneral;
@ -92,24 +77,42 @@ LocationXY16 gMapSelectPositionB;
LocationXYZ16 gMapSelectArrowPosition;
uint8_t gMapSelectArrowDirection;
void entrance_paint(paint_session * session, uint8_t direction, int height, const rct_tile_element * tile_element) {}
void banner_paint(paint_session * session, uint8_t direction, int height, const rct_tile_element * tile_element) {}
void surface_paint(paint_session * session, uint8_t direction, uint16_t height, const rct_tile_element * tileElement) {}
void path_paint(paint_session * session, uint16_t height, const rct_tile_element * tileElement) {}
void scenery_paint(paint_session * session, uint8_t direction, int height, const rct_tile_element * tileElement) {}
void fence_paint(paint_session * session, uint8_t direction, int height, const rct_tile_element * tileElement) {}
void large_scenery_paint(paint_session * session, uint8_t direction, uint16_t height, const rct_tile_element * tileElement) {}
void entrance_paint(paint_session* session, uint8_t direction, int height, const rct_tile_element* tile_element)
{
}
void banner_paint(paint_session* session, uint8_t direction, int height, const rct_tile_element* tile_element)
{
}
void surface_paint(paint_session* session, uint8_t direction, uint16_t height, const rct_tile_element* tileElement)
{
}
void path_paint(paint_session* session, uint16_t height, const rct_tile_element* tileElement)
{
}
void scenery_paint(paint_session* session, uint8_t direction, int height, const rct_tile_element* tileElement)
{
}
void fence_paint(paint_session* session, uint8_t direction, int height, const rct_tile_element* tileElement)
{
}
void large_scenery_paint(paint_session* session, uint8_t direction, uint16_t height, const rct_tile_element* tileElement)
{
}
Ride *get_ride(int index) {
if (index < 0 || index >= MAX_RIDES) {
Ride* get_ride(int index)
{
if (index < 0 || index >= MAX_RIDES)
{
log_error("invalid index %d for ride", index);
return nullptr;
}
return &gRideList[index];
}
rct_ride_entry *get_ride_entry(int index) {
if (index < 0 || index >= object_entry_group_counts[OBJECT_TYPE_RIDE]) {
rct_ride_entry* get_ride_entry(int index)
{
if (index < 0 || index >= object_entry_group_counts[OBJECT_TYPE_RIDE])
{
log_error("invalid index %d for ride type", index);
return nullptr;
}
@ -117,15 +120,18 @@ rct_ride_entry *get_ride_entry(int index) {
return gRideEntries[index];
}
rct_ride_entry *get_ride_entry_by_ride(Ride *ride) {
rct_ride_entry * type = get_ride_entry(ride->subtype);
if (type == nullptr) {
rct_ride_entry* get_ride_entry_by_ride(Ride* ride)
{
rct_ride_entry* type = get_ride_entry(ride->subtype);
if (type == nullptr)
{
log_error("Invalid ride subtype for ride");
}
return type;
}
rct_sprite *get_sprite(size_t sprite_idx) {
rct_sprite* get_sprite(size_t sprite_idx)
{
assert(sprite_idx < MAX_SPRITES);
return &sprite_list[sprite_idx];
}
@ -140,49 +146,54 @@ uint8_t rct_tile_element::GetType() const
return this->type & TILE_ELEMENT_TYPE_MASK;
}
int tile_element_get_direction(const rct_tile_element *element) {
int tile_element_get_direction(const rct_tile_element* element)
{
return element->type & TILE_ELEMENT_DIRECTION_MASK;
}
int tile_element_get_direction_with_offset(const rct_tile_element *element, uint8_t offset) {
int tile_element_get_direction_with_offset(const rct_tile_element* element, uint8_t offset)
{
return ((element->type & TILE_ELEMENT_DIRECTION_MASK) + offset) & TILE_ELEMENT_DIRECTION_MASK;
}
rct_tile_element *map_get_first_element_at(int x, int y) {
if (x < 0 || y < 0 || x > 255 || y > 255) {
rct_tile_element* map_get_first_element_at(int x, int y)
{
if (x < 0 || y < 0 || x > 255 || y > 255)
{
log_error("Trying to access element outside of range");
return nullptr;
}
return gTileElementTilePointers[x + y * 256];
}
int tile_element_get_station(const rct_tile_element * tileElement) {
int tile_element_get_station(const rct_tile_element* tileElement)
{
return (tileElement->properties.track.sequence & MAP_ELEM_TRACK_SEQUENCE_STATION_INDEX_MASK) >> 4;
}
void tile_element_set_station(rct_tile_element * tileElement, uint32_t stationIndex)
void tile_element_set_station(rct_tile_element* tileElement, uint32_t stationIndex)
{
tileElement->properties.track.sequence &= ~MAP_ELEM_TRACK_SEQUENCE_STATION_INDEX_MASK;
tileElement->properties.track.sequence |= (stationIndex << 4);
}
int32_t tile_element_get_track_sequence(const rct_tile_element * tileElement)
int32_t tile_element_get_track_sequence(const rct_tile_element* tileElement)
{
return tileElement->properties.track.sequence & MAP_ELEM_TRACK_SEQUENCE_SEQUENCE_MASK;
}
void tile_element_set_track_sequence(rct_tile_element * tileElement, int trackSequence)
void tile_element_set_track_sequence(rct_tile_element* tileElement, int trackSequence)
{
tileElement->properties.track.sequence &= ~MAP_ELEM_TRACK_SEQUENCE_SEQUENCE_MASK;
tileElement->properties.track.sequence |= (trackSequence & MAP_ELEM_TRACK_SEQUENCE_SEQUENCE_MASK);
}
bool tile_element_get_green_light(const rct_tile_element * tileElement)
bool tile_element_get_green_light(const rct_tile_element* tileElement)
{
return (tileElement->properties.track.sequence & MAP_ELEM_TRACK_SEQUENCE_GREEN_LIGHT) != 0;
}
void tile_element_set_green_light(rct_tile_element * tileElement, bool greenLight)
void tile_element_set_green_light(rct_tile_element* tileElement, bool greenLight)
{
tileElement->properties.track.sequence &= ~MAP_ELEM_TRACK_SEQUENCE_GREEN_LIGHT;
if (greenLight)
@ -191,28 +202,28 @@ void tile_element_set_green_light(rct_tile_element * tileElement, bool greenLigh
}
}
int tile_element_get_brake_booster_speed(const rct_tile_element *tileElement)
int tile_element_get_brake_booster_speed(const rct_tile_element* tileElement)
{
return (tileElement->properties.track.sequence >> 4) << 1;
}
void tile_element_set_brake_booster_speed(rct_tile_element *tileElement, int speed)
void tile_element_set_brake_booster_speed(rct_tile_element* tileElement, int speed)
{
tileElement->properties.track.sequence = tile_element_get_track_sequence(tileElement) | ((speed >> 1) << 4);
}
bool tile_element_is_taking_photo(const rct_tile_element * tileElement)
bool tile_element_is_taking_photo(const rct_tile_element* tileElement)
{
return (tileElement->properties.track.sequence & MAP_ELEM_TRACK_SEQUENCE_TAKING_PHOTO_MASK) != 0;
}
void tile_element_set_onride_photo_timeout(rct_tile_element * tileElement)
void tile_element_set_onride_photo_timeout(rct_tile_element* tileElement)
{
tileElement->properties.track.sequence &= MAP_ELEM_TRACK_SEQUENCE_SEQUENCE_MASK;
tileElement->properties.track.sequence |= (3 << 4);
}
void tile_element_decrement_onride_photo_timout(rct_tile_element * tileElement)
void tile_element_decrement_onride_photo_timout(rct_tile_element* tileElement)
{
// We should only touch the upper 4 bits, avoid underflow into the lower 4.
if (tileElement->properties.track.sequence & MAP_ELEM_TRACK_SEQUENCE_TAKING_PHOTO_MASK)
@ -221,7 +232,7 @@ void tile_element_decrement_onride_photo_timout(rct_tile_element * tileElement)
}
}
int32_t surface_get_water_height(const rct_tile_element * tileElement)
int32_t surface_get_water_height(const rct_tile_element* tileElement)
{
return tileElement->properties.surface.terrain & TILE_ELEMENT_SURFACE_WATER_HEIGHT_MASK;
}
@ -236,22 +247,22 @@ int16_t get_height_marker_offset()
return 0;
}
bool track_element_is_lift_hill(const rct_tile_element *trackElement)
bool track_element_is_lift_hill(const rct_tile_element* trackElement)
{
return trackElement->type & 0x80;
}
bool track_element_is_cable_lift(const rct_tile_element *trackElement)
bool track_element_is_cable_lift(const rct_tile_element* trackElement)
{
return trackElement->properties.track.colour & TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT;
}
bool track_element_is_inverted(const rct_tile_element *trackElement)
bool track_element_is_inverted(const rct_tile_element* trackElement)
{
return trackElement->properties.track.colour & TRACK_ELEMENT_COLOUR_FLAG_INVERTED;
}
void track_element_set_inverted(rct_tile_element * tileElement, bool inverted)
void track_element_set_inverted(rct_tile_element* tileElement, bool inverted)
{
if (inverted)
{
@ -268,52 +279,52 @@ bool is_csg_loaded()
return false;
}
uint8_t track_element_get_colour_scheme(const rct_tile_element * tileElement)
uint8_t track_element_get_colour_scheme(const rct_tile_element* tileElement)
{
return tileElement->properties.track.colour & 0x3;
}
uint16_t track_element_get_maze_entry(const rct_tile_element * tileElement)
uint16_t track_element_get_maze_entry(const rct_tile_element* tileElement)
{
return tileElement->properties.track.maze_entry;
}
uint8_t track_element_get_ride_index(const rct_tile_element * tileElement)
uint8_t track_element_get_ride_index(const rct_tile_element* tileElement)
{
return tileElement->properties.track.ride_index;
}
void track_element_set_ride_index(rct_tile_element * tileElement, uint8_t rideIndex)
void track_element_set_ride_index(rct_tile_element* tileElement, uint8_t rideIndex)
{
tileElement->properties.track.ride_index = rideIndex;
}
uint8_t track_element_get_type(const rct_tile_element * tileElement)
uint8_t track_element_get_type(const rct_tile_element* tileElement)
{
return tileElement->properties.track.type;
}
void track_element_set_type(rct_tile_element * tileElement, uint8_t type)
void track_element_set_type(rct_tile_element* tileElement, uint8_t type)
{
tileElement->properties.track.type = type;
}
void track_element_set_cable_lift(rct_tile_element * trackElement)
void track_element_set_cable_lift(rct_tile_element* trackElement)
{
trackElement->properties.track.colour |= TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT;
}
void track_element_clear_cable_lift(rct_tile_element * trackElement)
void track_element_clear_cable_lift(rct_tile_element* trackElement)
{
trackElement->properties.track.colour &= ~TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT;
}
TileCoordsXYZD ride_get_entrance_location(const Ride * ride, const int32_t stationIndex)
TileCoordsXYZD ride_get_entrance_location(const Ride* ride, const int32_t stationIndex)
{
return ride->entrances[stationIndex];
}
TileCoordsXYZD ride_get_exit_location(const Ride * ride, const int32_t stationIndex)
TileCoordsXYZD ride_get_exit_location(const Ride* ride, const int32_t stationIndex)
{
return ride->exits[stationIndex];
}

View File

@ -364,262 +364,18 @@ const_utf8string TrackNames[256] = {
};
const_utf8string FlatTrackNames[256] = {
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"1x4_A",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"2x2",
"4x4",
"",
"",
"",
"",
"1x5",
"",
"1x1_A",
"1x4_B",
"",
"1x1_B",
"1x4_C",
"3x3",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "1x4_A", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"2x2", "4x4", "", "", "", "", "1x5", "", "1x1_A", "1x4_B", "", "1x1_B", "1x4_C", "3x3", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
};
const_utf8string TrackElemNames[] = {
@ -975,261 +731,259 @@ const_utf8string RideCodeNames[RIDE_TYPE_COUNT] = {
"lim_launched_rc",
};
const_utf8string TrackCodeNames[256] = {
"flat",
"end_station",
"begin_station",
"middle_station",
"25_deg_up",
"60_deg_up",
"flat_to_25_deg_up",
"25_deg_up_to_60_deg_up",
"60_deg_up_to_25_deg_up",
"25_deg_up_to_flat",
"25_deg_down",
"60_deg_down",
"flat_to_25_deg_down",
"25_deg_down_to_60_deg_down",
"60_deg_down_to_25_deg_down",
"25_deg_down_to_flat",
"left_quarter_turn_5",
"right_quarter_turn_5",
"flat_to_left_bank",
"flat_to_right_bank",
"left_bank_to_flat",
"right_bank_to_flat",
"banked_left_quarter_turn_5",
"banked_right_quarter_turn_5",
"left_bank_to_25_deg_up",
"right_bank_to_25_deg_up",
"25_deg_up_to_left_bank",
"25_deg_up_to_right_bank",
"left_bank_to_25_deg_down",
"right_bank_to_25_deg_down",
"25_deg_down_to_left_bank",
"25_deg_down_to_right_bank",
"left_bank",
"right_bank",
"left_quarter_turn_5_25_deg_up",
"right_quarter_turn_5_25_deg_up",
"left_quarter_turn_5_25_deg_down",
"right_quarter_turn_5_25_deg_down",
"s_bend_left",
"s_bend_right",
"left_vertical_loop",
"right_vertical_loop",
"left_quarter_turn_3",
"right_quarter_turn_3",
"left_quarter_turn_3_bank",
"right_quarter_turn_3_bank",
"left_quarter_turn_3_25_deg_up",
"right_quarter_turn_3_25_deg_up",
"left_quarter_turn_3_25_deg_down",
"right_quarter_turn_3_25_deg_down",
"left_quarter_turn_1",
"right_quarter_turn_1",
"left_twist_down_to_up",
"right_twist_down_to_up",
"left_twist_up_to_down",
"right_twist_up_to_down",
"half_loop_up",
"half_loop_down",
"left_corkscrew_up",
"right_corkscrew_up",
"left_corkscrew_down",
"right_corkscrew_down",
"flat_to_60_deg_up",
"60_deg_up_to_flat",
"flat_to_60_deg_down",
"60_deg_down_to_flat",
"tower_base",
"tower_section",
"flat_covered",
"25_deg_up_covered",
"60_deg_up_covered",
"flat_to_25_deg_up_covered",
"25_deg_up_to_60_deg_up_covered",
"60_deg_up_to_25_deg_up_covered",
"25_deg_up_to_flat_covered",
"25_deg_down_covered",
"60_deg_down_covered",
"flat_to_25_deg_down_covered",
"25_deg_down_to_60_deg_down_covered",
"60_deg_down_to_25_deg_down_covered",
"25_deg_down_to_flat_covered",
"left_quarter_turn_5_covered",
"right_quarter_turn_5_covered",
"s_bend_left_covered",
"s_bend_right_covered",
"left_quarter_turn_3_covered",
"right_quarter_turn_3_covered",
"left_half_banked_helix_up_small",
"right_half_banked_helix_up_small",
"left_half_banked_helix_down_small",
"right_half_banked_helix_down_small",
"left_half_banked_helix_up_large",
"right_half_banked_helix_up_large",
"left_half_banked_helix_down_large",
"right_half_banked_helix_down_large",
"left_quarter_turn_1_60_deg_up",
"right_quarter_turn_1_60_deg_up",
"left_quarter_turn_1_60_deg_down",
"right_quarter_turn_1_60_deg_down",
"brakes",
"rotation_control_toggle",
"inverted_90_deg_up_to_flat_quarter_loop_maze",
"left_quarter_banked_helix_large_up",
"right_quarter_banked_helix_large_up",
"left_quarter_banked_helix_large_down",
"right_quarter_banked_helix_large_down",
"left_quarter_helix_large_up",
"right_quarter_helix_large_up",
"left_quarter_helix_large_down",
"right_quarter_helix_large_down",
"25_deg_up_left_banked",
"25_deg_up_right_banked",
"waterfall",
"rapids",
"on_ride_photo",
"25_deg_down_left_banked",
"25_deg_down_right_banked",
"water_splash",
"flat_to_60_deg_up_long_base",
"60_deg_up_to_flat_long_base",
"whirlpool",
"flat_to_60_deg_down_long_base",
"60_deg_up_to_flat_long_base122",
"cable_lift_hill",
"reverse_freefall_slope",
"reverse_freefall_vertical",
"90_deg_up",
"90_deg_down",
"60_deg_up_to_90_deg_up",
"90_deg_down_to_60_deg_down",
"90_deg_up_to_60_deg_up",
"60_deg_down_to_90_deg_down",
"brake_for_drop",
"left_eighth_to_diag",
"right_eighth_to_diag",
"left_eighth_to_orthogonal",
"right_eighth_to_orthogonal",
"left_eighth_bank_to_diag",
"right_eighth_bank_to_diag",
"left_eighth_bank_to_orthogonal",
"right_eighth_bank_to_orthogonal",
"diag_flat",
"diag_25_deg_up",
"diag_60_deg_up",
"diag_flat_to_25_deg_up",
"diag_25_deg_up_to_60_deg_up",
"diag_60_deg_up_to_25_deg_up",
"diag_25_deg_up_to_flat",
"diag_25_deg_down",
"diag_60_deg_down",
"diag_flat_to_25_deg_down",
"diag_25_deg_down_to_60_deg_down",
"diag_60_deg_down_to_25_deg_down",
"diag_25_deg_down_to_flat",
"diag_flat_to_60_deg_up",
"diag_60_deg_up_to_flat",
"diag_flat_to_60_deg_down",
"diag_60_deg_down_to_flat",
"diag_flat_to_left_bank",
"diag_flat_to_right_bank",
"diag_left_bank_to_flat",
"diag_right_bank_to_flat",
"diag_left_bank_to_25_deg_up",
"diag_right_bank_to_25_deg_up",
"diag_25_deg_up_to_left_bank",
"diag_25_deg_up_to_right_bank",
"diag_left_bank_to_25_deg_down",
"diag_right_bank_to_25_deg_down",
"diag_25_deg_down_to_left_bank",
"diag_25_deg_down_to_right_bank",
"diag_left_bank",
"diag_right_bank",
"log_flume_reverser",
"spinning_tunnel",
"left_barrel_roll_up_to_down",
"right_barrel_roll_up_to_down",
"left_barrel_roll_down_to_up",
"right_barrel_roll_down_to_up",
"left_bank_to_left_quarter_turn_3_25_deg_up",
"right_bank_to_right_quarter_turn_3_25_deg_up",
"left_quarter_turn_3_25_deg_down_to_left_bank",
"right_quarter_turn_3_25_deg_down_to_right_bank",
"powered_lift",
"left_large_half_loop_up",
"right_large_half_loop_up",
"right_large_half_loop_down",
"left_large_half_loop_down",
"left_flyer_twist_up",
"right_flyer_twist_up",
"left_flyer_twist_down",
"right_flyer_twist_down",
"flyer_half_loop_up",
"flyer_half_loop_down",
"left_flyer_corkscrew_up",
"right_flyer_corkscrew_up",
"left_flyer_corkscrew_down",
"right_flyer_corkscrew_down",
"heartline_transfer_up",
"heartline_transfer_down",
"left_heartline_roll",
"right_heartline_roll",
"mini_golf_hole_a",
"mini_golf_hole_b",
"mini_golf_hole_c",
"mini_golf_hole_d",
"mini_golf_hole_e",
"multidim_inverted_flat_to_90_deg_quarter_loop_down",
"90_deg_to_inverted_flat_quarter_loop_up",
"inverted_flat_to_90_deg_quarter_loop_down",
"left_curved_lift_hill",
"right_curved_lift_hill",
"left_reverser",
"right_reverser",
"air_thrust_top_cap",
"air_thrust_vertical_down",
"air_thrust_vertical_down_to_level",
"block_brakes",
"left_banked_quarter_turn_3_25_deg_up",
"right_banked_quarter_turn_3_25_deg_up",
"left_banked_quarter_turn_3_25_deg_down",
"right_banked_quarter_turn_3_25_deg_down",
"left_banked_quarter_turn_5_25_deg_up",
"right_banked_quarter_turn_5_25_deg_up",
"left_banked_quarter_turn_5_25_deg_down",
"right_banked_quarter_turn_5_25_deg_down",
"25_deg_up_to_left_banked_25_deg_up",
"25_deg_up_to_right_banked_25_deg_up",
"left_banked_25_deg_up_to_25_deg_up",
"right_banked_25_deg_up_to_25_deg_up",
"25_deg_down_to_left_banked_25_deg_down",
"25_deg_down_to_right_banked_25_deg_down",
"left_banked_25_deg_down_to_25_deg_down",
"right_banked_25_deg_down_to_25_deg_down",
"left_banked_flat_to_left_banked_25_deg_up",
"right_banked_flat_to_right_banked_25_deg_up",
"left_banked_25_deg_up_to_left_banked_flat",
"right_banked_25_deg_up_to_right_banked_flat",
"left_banked_flat_to_left_banked_25_deg_down",
"right_banked_flat_to_right_banked_25_deg_down",
"left_banked_25_deg_down_to_left_banked_flat",
"right_banked_25_deg_down_to_right_banked_flat",
"flat_to_left_banked_25_deg_up",
"flat_to_right_banked_25_deg_up",
"left_banked_25_deg_up_to_flat",
"right_banked_25_deg_up_to_flat",
"flat_to_left_banked_25_deg_down",
"flat_to_right_banked_25_deg_down",
"left_banked_25_deg_down_to_flat",
"right_banked_25_deg_down_to_flat",
"left_quarter_turn_1_90_deg_up",
"right_quarter_turn_1_90_deg_up",
"left_quarter_turn_1_90_deg_down",
"right_quarter_turn_1_90_deg_down",
"multidim_90_deg_up_to_inverted_flat_quarter_loop",
"multidim_flat_to_90_deg_down_quarter_loop",
"elem_255"
};
const_utf8string TrackCodeNames[256] = { "flat",
"end_station",
"begin_station",
"middle_station",
"25_deg_up",
"60_deg_up",
"flat_to_25_deg_up",
"25_deg_up_to_60_deg_up",
"60_deg_up_to_25_deg_up",
"25_deg_up_to_flat",
"25_deg_down",
"60_deg_down",
"flat_to_25_deg_down",
"25_deg_down_to_60_deg_down",
"60_deg_down_to_25_deg_down",
"25_deg_down_to_flat",
"left_quarter_turn_5",
"right_quarter_turn_5",
"flat_to_left_bank",
"flat_to_right_bank",
"left_bank_to_flat",
"right_bank_to_flat",
"banked_left_quarter_turn_5",
"banked_right_quarter_turn_5",
"left_bank_to_25_deg_up",
"right_bank_to_25_deg_up",
"25_deg_up_to_left_bank",
"25_deg_up_to_right_bank",
"left_bank_to_25_deg_down",
"right_bank_to_25_deg_down",
"25_deg_down_to_left_bank",
"25_deg_down_to_right_bank",
"left_bank",
"right_bank",
"left_quarter_turn_5_25_deg_up",
"right_quarter_turn_5_25_deg_up",
"left_quarter_turn_5_25_deg_down",
"right_quarter_turn_5_25_deg_down",
"s_bend_left",
"s_bend_right",
"left_vertical_loop",
"right_vertical_loop",
"left_quarter_turn_3",
"right_quarter_turn_3",
"left_quarter_turn_3_bank",
"right_quarter_turn_3_bank",
"left_quarter_turn_3_25_deg_up",
"right_quarter_turn_3_25_deg_up",
"left_quarter_turn_3_25_deg_down",
"right_quarter_turn_3_25_deg_down",
"left_quarter_turn_1",
"right_quarter_turn_1",
"left_twist_down_to_up",
"right_twist_down_to_up",
"left_twist_up_to_down",
"right_twist_up_to_down",
"half_loop_up",
"half_loop_down",
"left_corkscrew_up",
"right_corkscrew_up",
"left_corkscrew_down",
"right_corkscrew_down",
"flat_to_60_deg_up",
"60_deg_up_to_flat",
"flat_to_60_deg_down",
"60_deg_down_to_flat",
"tower_base",
"tower_section",
"flat_covered",
"25_deg_up_covered",
"60_deg_up_covered",
"flat_to_25_deg_up_covered",
"25_deg_up_to_60_deg_up_covered",
"60_deg_up_to_25_deg_up_covered",
"25_deg_up_to_flat_covered",
"25_deg_down_covered",
"60_deg_down_covered",
"flat_to_25_deg_down_covered",
"25_deg_down_to_60_deg_down_covered",
"60_deg_down_to_25_deg_down_covered",
"25_deg_down_to_flat_covered",
"left_quarter_turn_5_covered",
"right_quarter_turn_5_covered",
"s_bend_left_covered",
"s_bend_right_covered",
"left_quarter_turn_3_covered",
"right_quarter_turn_3_covered",
"left_half_banked_helix_up_small",
"right_half_banked_helix_up_small",
"left_half_banked_helix_down_small",
"right_half_banked_helix_down_small",
"left_half_banked_helix_up_large",
"right_half_banked_helix_up_large",
"left_half_banked_helix_down_large",
"right_half_banked_helix_down_large",
"left_quarter_turn_1_60_deg_up",
"right_quarter_turn_1_60_deg_up",
"left_quarter_turn_1_60_deg_down",
"right_quarter_turn_1_60_deg_down",
"brakes",
"rotation_control_toggle",
"inverted_90_deg_up_to_flat_quarter_loop_maze",
"left_quarter_banked_helix_large_up",
"right_quarter_banked_helix_large_up",
"left_quarter_banked_helix_large_down",
"right_quarter_banked_helix_large_down",
"left_quarter_helix_large_up",
"right_quarter_helix_large_up",
"left_quarter_helix_large_down",
"right_quarter_helix_large_down",
"25_deg_up_left_banked",
"25_deg_up_right_banked",
"waterfall",
"rapids",
"on_ride_photo",
"25_deg_down_left_banked",
"25_deg_down_right_banked",
"water_splash",
"flat_to_60_deg_up_long_base",
"60_deg_up_to_flat_long_base",
"whirlpool",
"flat_to_60_deg_down_long_base",
"60_deg_up_to_flat_long_base122",
"cable_lift_hill",
"reverse_freefall_slope",
"reverse_freefall_vertical",
"90_deg_up",
"90_deg_down",
"60_deg_up_to_90_deg_up",
"90_deg_down_to_60_deg_down",
"90_deg_up_to_60_deg_up",
"60_deg_down_to_90_deg_down",
"brake_for_drop",
"left_eighth_to_diag",
"right_eighth_to_diag",
"left_eighth_to_orthogonal",
"right_eighth_to_orthogonal",
"left_eighth_bank_to_diag",
"right_eighth_bank_to_diag",
"left_eighth_bank_to_orthogonal",
"right_eighth_bank_to_orthogonal",
"diag_flat",
"diag_25_deg_up",
"diag_60_deg_up",
"diag_flat_to_25_deg_up",
"diag_25_deg_up_to_60_deg_up",
"diag_60_deg_up_to_25_deg_up",
"diag_25_deg_up_to_flat",
"diag_25_deg_down",
"diag_60_deg_down",
"diag_flat_to_25_deg_down",
"diag_25_deg_down_to_60_deg_down",
"diag_60_deg_down_to_25_deg_down",
"diag_25_deg_down_to_flat",
"diag_flat_to_60_deg_up",
"diag_60_deg_up_to_flat",
"diag_flat_to_60_deg_down",
"diag_60_deg_down_to_flat",
"diag_flat_to_left_bank",
"diag_flat_to_right_bank",
"diag_left_bank_to_flat",
"diag_right_bank_to_flat",
"diag_left_bank_to_25_deg_up",
"diag_right_bank_to_25_deg_up",
"diag_25_deg_up_to_left_bank",
"diag_25_deg_up_to_right_bank",
"diag_left_bank_to_25_deg_down",
"diag_right_bank_to_25_deg_down",
"diag_25_deg_down_to_left_bank",
"diag_25_deg_down_to_right_bank",
"diag_left_bank",
"diag_right_bank",
"log_flume_reverser",
"spinning_tunnel",
"left_barrel_roll_up_to_down",
"right_barrel_roll_up_to_down",
"left_barrel_roll_down_to_up",
"right_barrel_roll_down_to_up",
"left_bank_to_left_quarter_turn_3_25_deg_up",
"right_bank_to_right_quarter_turn_3_25_deg_up",
"left_quarter_turn_3_25_deg_down_to_left_bank",
"right_quarter_turn_3_25_deg_down_to_right_bank",
"powered_lift",
"left_large_half_loop_up",
"right_large_half_loop_up",
"right_large_half_loop_down",
"left_large_half_loop_down",
"left_flyer_twist_up",
"right_flyer_twist_up",
"left_flyer_twist_down",
"right_flyer_twist_down",
"flyer_half_loop_up",
"flyer_half_loop_down",
"left_flyer_corkscrew_up",
"right_flyer_corkscrew_up",
"left_flyer_corkscrew_down",
"right_flyer_corkscrew_down",
"heartline_transfer_up",
"heartline_transfer_down",
"left_heartline_roll",
"right_heartline_roll",
"mini_golf_hole_a",
"mini_golf_hole_b",
"mini_golf_hole_c",
"mini_golf_hole_d",
"mini_golf_hole_e",
"multidim_inverted_flat_to_90_deg_quarter_loop_down",
"90_deg_to_inverted_flat_quarter_loop_up",
"inverted_flat_to_90_deg_quarter_loop_down",
"left_curved_lift_hill",
"right_curved_lift_hill",
"left_reverser",
"right_reverser",
"air_thrust_top_cap",
"air_thrust_vertical_down",
"air_thrust_vertical_down_to_level",
"block_brakes",
"left_banked_quarter_turn_3_25_deg_up",
"right_banked_quarter_turn_3_25_deg_up",
"left_banked_quarter_turn_3_25_deg_down",
"right_banked_quarter_turn_3_25_deg_down",
"left_banked_quarter_turn_5_25_deg_up",
"right_banked_quarter_turn_5_25_deg_up",
"left_banked_quarter_turn_5_25_deg_down",
"right_banked_quarter_turn_5_25_deg_down",
"25_deg_up_to_left_banked_25_deg_up",
"25_deg_up_to_right_banked_25_deg_up",
"left_banked_25_deg_up_to_25_deg_up",
"right_banked_25_deg_up_to_25_deg_up",
"25_deg_down_to_left_banked_25_deg_down",
"25_deg_down_to_right_banked_25_deg_down",
"left_banked_25_deg_down_to_25_deg_down",
"right_banked_25_deg_down_to_25_deg_down",
"left_banked_flat_to_left_banked_25_deg_up",
"right_banked_flat_to_right_banked_25_deg_up",
"left_banked_25_deg_up_to_left_banked_flat",
"right_banked_25_deg_up_to_right_banked_flat",
"left_banked_flat_to_left_banked_25_deg_down",
"right_banked_flat_to_right_banked_25_deg_down",
"left_banked_25_deg_down_to_left_banked_flat",
"right_banked_25_deg_down_to_right_banked_flat",
"flat_to_left_banked_25_deg_up",
"flat_to_right_banked_25_deg_up",
"left_banked_25_deg_up_to_flat",
"right_banked_25_deg_up_to_flat",
"flat_to_left_banked_25_deg_down",
"flat_to_right_banked_25_deg_down",
"left_banked_25_deg_down_to_flat",
"right_banked_25_deg_down_to_flat",
"left_quarter_turn_1_90_deg_up",
"right_quarter_turn_1_90_deg_up",
"left_quarter_turn_1_90_deg_down",
"right_quarter_turn_1_90_deg_down",
"multidim_90_deg_up_to_inverted_flat_quarter_loop",
"multidim_flat_to_90_deg_down_quarter_loop",
"elem_255" };

View File

@ -13,7 +13,6 @@
#include <openrct2/common.h>
#include <openrct2/ride/Ride.h>
extern const utf8string RideNames[RIDE_TYPE_COUNT];
extern const utf8string TrackNames[256];
extern const utf8string FlatTrackNames[256];

View File

@ -11,29 +11,34 @@
#include <openrct2/sprites.h>
enum SpriteGroup {
enum SpriteGroup
{
SPRITEGROUP_NONE,
SPRITEGROUP_FENCE_METAL_A, // 14568
SPRITEGROUP_FENCE_METAL_B, // 14990
SPRITEGROUP_FENCE_METAL_A, // 14568
SPRITEGROUP_FENCE_METAL_B, // 14990
SPRITEGROUP_FENCE_SPIRAL_SLIDE, // 20564
SPRITEGROUP_FLOOR_CORK, // 22134
SPRITEGROUP_FENCE_ROPE, // 22138
SPRITEGROUP_FLOOR_CORK, // 22134
SPRITEGROUP_FENCE_ROPE, // 22138
};
static void canonicalizeFunctionCall(function_call *call);
static void canonicalizeFunctionCall(function_call* call);
static SpriteGroup getSpriteGroup(uint16_t spriteIndex);
bool FunctionCall::AssertsEquals(std::vector<function_call> expected, std::vector<function_call> actual) {
if (expected.size() != actual.size()) {
bool FunctionCall::AssertsEquals(std::vector<function_call> expected, std::vector<function_call> actual)
{
if (expected.size() != actual.size())
{
return false;
}
for (size_t i = 0; i < expected.size(); i++) {
for (size_t i = 0; i < expected.size(); i++)
{
function_call expectedCall = expected[i];
function_call actualCall = actual[i];
if (!AssertsEquals(expectedCall, actualCall)) {
if (!AssertsEquals(expectedCall, actualCall))
{
return false;
}
}
@ -41,100 +46,139 @@ bool FunctionCall::AssertsEquals(std::vector<function_call> expected, std::vecto
return true;
}
bool FunctionCall::AssertsEquals(function_call expected, function_call actual) {
bool FunctionCall::AssertsEquals(function_call expected, function_call actual)
{
canonicalizeFunctionCall(&actual);
canonicalizeFunctionCall(&expected);
if (expected.function != actual.function) {
if (expected.function != actual.function)
{
return false;
}
uint8_t function = expected.function;
if (function == SUPPORTS_WOOD_A || function == SUPPORTS_WOOD_B) {
if (expected.supports.type != actual.supports.type) return false;
if (expected.supports.special != actual.supports.special) return false;
if (expected.supports.height != actual.supports.height) return false;
if (expected.supports.colour_flags != actual.supports.colour_flags) return false;
if (function == SUPPORTS_WOOD_A || function == SUPPORTS_WOOD_B)
{
if (expected.supports.type != actual.supports.type)
return false;
if (expected.supports.special != actual.supports.special)
return false;
if (expected.supports.height != actual.supports.height)
return false;
if (expected.supports.colour_flags != actual.supports.colour_flags)
return false;
if (expected.supports.special == 14 || expected.supports.special == 15 ||
expected.supports.special == 18 || expected.supports.special == 19 ||
expected.supports.special == 22 || expected.supports.special == 23)
if (expected.supports.special == 14 || expected.supports.special == 15 || expected.supports.special == 18
|| expected.supports.special == 19 || expected.supports.special == 22 || expected.supports.special == 23)
{
if (expected.supports.prepend_to != actual.supports.prepend_to) return false;
if (expected.supports.prepend_to != actual.supports.prepend_to)
return false;
}
return true;
}
if (function == SUPPORTS_METAL_A || function == SUPPORTS_METAL_B) {
if (expected.supports.type != actual.supports.type) return false;
if (expected.supports.segment != actual.supports.segment) return false;
if (expected.supports.special != actual.supports.special) return false;
if (expected.supports.height != actual.supports.height) return false;
if (expected.supports.colour_flags != actual.supports.colour_flags) return false;
if (function == SUPPORTS_METAL_A || function == SUPPORTS_METAL_B)
{
if (expected.supports.type != actual.supports.type)
return false;
if (expected.supports.segment != actual.supports.segment)
return false;
if (expected.supports.special != actual.supports.special)
return false;
if (expected.supports.height != actual.supports.height)
return false;
if (expected.supports.colour_flags != actual.supports.colour_flags)
return false;
return true;
}
if (function == SET_SEGMENT_HEIGHT) {
if (function == SET_SEGMENT_HEIGHT)
{
return true;
}
if (expected.paint.image_id != actual.paint.image_id) {
if (expected.paint.image_id != actual.paint.image_id)
{
SpriteGroup expectedSpriteGroup = getSpriteGroup(expected.paint.image_id & 0x7FFFF);
SpriteGroup actualSpriteGroup = getSpriteGroup(actual.paint.image_id & 0x7FFFF);
if (expectedSpriteGroup != actualSpriteGroup) return false;
if (expectedSpriteGroup != actualSpriteGroup)
return false;
if (expectedSpriteGroup == SPRITEGROUP_NONE) return false;
if (expectedSpriteGroup == SPRITEGROUP_NONE)
return false;
return true;
}
if (expected.paint.offset.x != actual.paint.offset.x) return false;
if (expected.paint.offset.y != actual.paint.offset.y) return false;
if (expected.paint.bound_box_length.x != actual.paint.bound_box_length.x) return false;
if (expected.paint.bound_box_length.y != actual.paint.bound_box_length.y) return false;
if (expected.paint.bound_box_length.z != actual.paint.bound_box_length.z) return false;
if (function != PAINT_98196C) {
if (expected.paint.bound_box_offset.x != actual.paint.bound_box_offset.x) return false;
if (expected.paint.bound_box_offset.y != actual.paint.bound_box_offset.y) return false;
if (expected.paint.bound_box_offset.z != actual.paint.bound_box_offset.z) return false;
if (expected.paint.offset.x != actual.paint.offset.x)
return false;
if (expected.paint.offset.y != actual.paint.offset.y)
return false;
if (expected.paint.bound_box_length.x != actual.paint.bound_box_length.x)
return false;
if (expected.paint.bound_box_length.y != actual.paint.bound_box_length.y)
return false;
if (expected.paint.bound_box_length.z != actual.paint.bound_box_length.z)
return false;
if (function != PAINT_98196C)
{
if (expected.paint.bound_box_offset.x != actual.paint.bound_box_offset.x)
return false;
if (expected.paint.bound_box_offset.y != actual.paint.bound_box_offset.y)
return false;
if (expected.paint.bound_box_offset.z != actual.paint.bound_box_offset.z)
return false;
}
if (expected.paint.z_offset != actual.paint.z_offset) return false;
if (expected.paint.rotation != actual.paint.rotation) return false;
if (expected.paint.z_offset != actual.paint.z_offset)
return false;
if (expected.paint.rotation != actual.paint.rotation)
return false;
return true;
}
static void canonicalizeFunctionCall(function_call *call) {
if (call->function != PAINT_98197C) return;
if (call->paint.offset.x != call->paint.bound_box_offset.x) return;
if (call->paint.offset.y != call->paint.bound_box_offset.y) return;
if (call->paint.z_offset != call->paint.bound_box_offset.z) return;
static void canonicalizeFunctionCall(function_call* call)
{
if (call->function != PAINT_98197C)
return;
if (call->paint.offset.x != call->paint.bound_box_offset.x)
return;
if (call->paint.offset.y != call->paint.bound_box_offset.y)
return;
if (call->paint.z_offset != call->paint.bound_box_offset.z)
return;
call->function = PAINT_98196C;
}
static SpriteGroup getSpriteGroup(uint16_t spriteIndex) {
if (spriteIndex >= 14568 && spriteIndex <= 14571) {
static SpriteGroup getSpriteGroup(uint16_t spriteIndex)
{
if (spriteIndex >= 14568 && spriteIndex <= 14571)
{
return SPRITEGROUP_FENCE_METAL_A;
}
if (spriteIndex >= 14990 && spriteIndex <= 14993) {
if (spriteIndex >= 14990 && spriteIndex <= 14993)
{
return SPRITEGROUP_FENCE_METAL_B;
}
if (spriteIndex >= 20564 && spriteIndex <= 20567) {
if (spriteIndex >= 20564 && spriteIndex <= 20567)
{
return SPRITEGROUP_FENCE_SPIRAL_SLIDE;
}
if (spriteIndex >= 22134 && spriteIndex <= 22137) {
if (spriteIndex >= 22134 && spriteIndex <= 22137)
{
return SPRITEGROUP_FLOOR_CORK;
}
if (spriteIndex >= 22138 && spriteIndex <= 22141) {
if (spriteIndex >= 22138 && spriteIndex <= 22141)
{
return SPRITEGROUP_FENCE_ROPE;
}

View File

@ -9,9 +9,10 @@
#pragma once
#include <openrct2/common.h>
#include "TestPaint.hpp"
#include <openrct2/common.h>
enum
{
PAINT_98196C,
@ -51,7 +52,8 @@ struct function_call
} supports;
};
class FunctionCall {
class FunctionCall
{
public:
static bool AssertsEquals(function_call expected, function_call actual);
static bool AssertsEquals(std::vector<function_call> expected, std::vector<function_call> actual);

View File

@ -7,38 +7,50 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <map>
#include "GeneralSupportHeightCall.hpp"
bool GeneralSupportHeightCall::CallsMatch(SupportCall tileSupportCalls[4]) {
#include <map>
bool GeneralSupportHeightCall::CallsMatch(SupportCall tileSupportCalls[4])
{
SupportCall baseCall = tileSupportCalls[0];
for (int i = 1; i < 4; i++) {
if (tileSupportCalls[i] != baseCall) return false;
for (int i = 1; i < 4; i++)
{
if (tileSupportCalls[i] != baseCall)
return false;
}
return true;
}
bool GeneralSupportHeightCall::FindMostCommonSupportCall(SupportCall calls[4], SupportCall *out) {
bool GeneralSupportHeightCall::FindMostCommonSupportCall(SupportCall calls[4], SupportCall* out)
{
std::map<SupportCall, int> map;
for (int i = 0; i < 4; ++i) {
if (map.count(calls[i]) == 0) {
for (int i = 0; i < 4; ++i)
{
if (map.count(calls[i]) == 0)
{
map[calls[i]] = 1;
} else {
}
else
{
map[calls[i]] += 1;
}
}
if (map.size() == 1) {
if (map.size() == 1)
{
(*out) = calls[0];
return true;
}
if (map.size() == 2) {
for (auto &&item : map) {
if (item.second == 3) {
if (map.size() == 2)
{
for (auto&& item : map)
{
if (item.second == 3)
{
(*out) = item.first;
return true;
}
@ -50,12 +62,17 @@ bool GeneralSupportHeightCall::FindMostCommonSupportCall(SupportCall calls[4], S
return false;
}
bool GeneralSupportHeightCall::AssertEquals(const SupportCall *lhs, const SupportCall *rhs) {
if (lhs == nullptr && rhs == nullptr) return true;
if (lhs == nullptr || rhs == nullptr) return false;
bool GeneralSupportHeightCall::AssertEquals(const SupportCall* lhs, const SupportCall* rhs)
{
if (lhs == nullptr && rhs == nullptr)
return true;
if (lhs == nullptr || rhs == nullptr)
return false;
if (lhs->height != rhs->height) return false;
if (lhs->slope != rhs->slope) return false;
if (lhs->height != rhs->height)
return false;
if (lhs->slope != rhs->slope)
return false;
return true;
}

View File

@ -11,23 +11,30 @@
#include <openrct2/common.h>
struct SupportCall {
struct SupportCall
{
int32_t height;
int16_t slope;
friend bool operator==(const SupportCall& lhs, const SupportCall& rhs) {
if (lhs.height != rhs.height) return false;
if (lhs.slope != rhs.slope) return false;
friend bool operator==(const SupportCall& lhs, const SupportCall& rhs)
{
if (lhs.height != rhs.height)
return false;
if (lhs.slope != rhs.slope)
return false;
return true;
}
bool operator!=(const SupportCall &other) const {
bool operator!=(const SupportCall& other) const
{
return !(*this == other);
}
bool operator<(const SupportCall &other) const {
if (height != other.height) {
bool operator<(const SupportCall& other) const
{
if (height != other.height)
{
return height < other.height;
}
@ -35,10 +42,11 @@ struct SupportCall {
}
};
namespace GeneralSupportHeightCall {
namespace GeneralSupportHeightCall
{
bool CallsMatch(SupportCall tileSupportCalls[4]);
bool FindMostCommonSupportCall(SupportCall calls[4], SupportCall *out);
bool FindMostCommonSupportCall(SupportCall calls[4], SupportCall* out);
bool AssertEquals(const SupportCall *lhs, const SupportCall *rhs);
};
bool AssertEquals(const SupportCall* lhs, const SupportCall* rhs);
}; // namespace GeneralSupportHeightCall

View File

@ -15,9 +15,9 @@
#ifndef NO_RCT2
#ifdef _WIN32
#include <windows.h>
#include <windows.h>
#else
#include <sys/mman.h>
#include <sys/mman.h>
#endif // _WIN32
#include "Hook.h"
@ -31,18 +31,18 @@ registers gHookRegisters = {};
// This macro writes a little-endian 4-byte long value into *data
// It is used to avoid type punning.
#define write_address_strictalias(data, addr) \
*(data + 0) = ((addr) & 0x000000ff) >> 0; \
*(data + 1) = ((addr) & 0x0000ff00) >> 8; \
*(data + 2) = ((addr) & 0x00ff0000) >> 16; \
*(data + 3) = ((addr) & 0xff000000) >> 24;
#define write_address_strictalias(data, addr) \
*(data + 0) = ((addr)&0x000000ff) >> 0; \
*(data + 1) = ((addr)&0x0000ff00) >> 8; \
*(data + 2) = ((addr)&0x00ff0000) >> 16; \
*(data + 3) = ((addr)&0xff000000) >> 24;
static void hookfunc(uintptr_t address, uintptr_t hookAddress, int32_t stacksize)
{
int32_t i = 0;
uint8_t data[HOOK_BYTE_COUNT] = {};
uintptr_t registerAddress = (uintptr_t) &gHookRegisters;
uintptr_t registerAddress = (uintptr_t)&gHookRegisters;
data[i++] = 0x89; // mov [gHookRegisters], eax
data[i++] = (0b000 << 3) | 0b101;
@ -94,7 +94,6 @@ static void hookfunc(uintptr_t address, uintptr_t hookAddress, int32_t stacksize
write_address_strictalias(&data[i], hookAddress - address - i - 4);
i += 4;
data[i++] = 0x83; // add esp, 4
data[i++] = 0xC4;
data[i++] = 0x04;
@ -153,13 +152,14 @@ static void hookfunc(uintptr_t address, uintptr_t hookAddress, int32_t stacksize
WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0);
#else
// We own the pages with PROT_WRITE | PROT_EXEC, we can simply just memcpy the data
memcpy((void *)address, data, i);
memcpy((void*)address, data, i);
#endif // _WIN32
}
void addhook(uintptr_t address, hook_function function)
{
if (!_hookTableAddress) {
if (!_hookTableAddress)
{
size_t size = _maxHooks * HOOK_BYTE_COUNT;
#ifdef _WIN32
_hookTableAddress = VirtualAllocEx(GetCurrentProcess(), NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
@ -172,10 +172,11 @@ void addhook(uintptr_t address, hook_function function)
}
#endif // _WIN32
}
if (_hookTableOffset > _maxHooks) {
if (_hookTableOffset > _maxHooks)
{
return;
}
uint32_t hookaddress = (uint32_t)((uint64_t)(_hookTableAddress) & 0xFFFFFFFF) + (_hookTableOffset * HOOK_BYTE_COUNT);
uint32_t hookaddress = (uint32_t)((uint64_t)(_hookTableAddress)&0xFFFFFFFF) + (_hookTableOffset * HOOK_BYTE_COUNT);
uint8_t data[9];
int32_t i = 0;
data[i++] = 0xE9; // jmp
@ -188,15 +189,15 @@ void addhook(uintptr_t address, hook_function function)
WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0);
#else
// We own the pages with PROT_WRITE | PROT_EXEC, we can simply just memcpy the data
int32_t err = mprotect((void *)0x401000, 0x8a4000 - 0x401000, PROT_READ | PROT_WRITE);
int32_t err = mprotect((void*)0x401000, 0x8a4000 - 0x401000, PROT_READ | PROT_WRITE);
if (err != 0)
{
perror("mprotect");
}
memcpy((void *)address, data, i);
memcpy((void*)address, data, i);
err = mprotect((void *)0x401000, 0x8a4000 - 0x401000, PROT_READ | PROT_EXEC);
err = mprotect((void*)0x401000, 0x8a4000 - 0x401000, PROT_READ | PROT_EXEC);
if (err != 0)
{
perror("mprotect");

View File

@ -13,7 +13,8 @@
#include <openrct2/common.h>
enum {
enum
{
X86_FLAG_CARRY = 1 << 0,
X86_FLAG_PARITY = 1 << 2,
@ -23,7 +24,7 @@ enum {
X86_FLAG_SIGN = 1 << 7,
};
using hook_function = uint8_t (*)(registers * regs);
using hook_function = uint8_t (*)(registers* regs);
void addhook(uintptr_t address, hook_function function);

View File

@ -7,13 +7,13 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <cstring>
#include "Hook.h"
#include "PaintIntercept.hpp"
#include "FunctionCall.hpp"
#include "Hook.h"
#include "TestPaint.hpp"
#include <cstring>
#include <openrct2/common.h>
#include <openrct2/interface/Viewport.h>
#include <openrct2/paint/Supports.h>
@ -26,22 +26,38 @@ static uint8_t _callCount = 0;
static function_call _calls[256] = {};
static paint_struct _paintStructs = {};
namespace PaintIntercept {
static uint8_t InterceptWoodenASupports(registers *regs);
static uint8_t InterceptWoodenBSupports(registers *regs);
static uint8_t InterceptMetalASupports(registers *regs);
static uint8_t InterceptMetalBSupports(registers *regs);
static uint8_t InterceptPaint6C(registers *regs);
static uint8_t InterceptPaint7C(registers *regs);
static uint8_t InterceptPaint8C(registers *regs);
static uint8_t InterceptPaint9C(registers *regs);
static uint8_t InterceptPaintFull(uint8_t function, registers *regs);
namespace PaintIntercept
{
static uint8_t InterceptWoodenASupports(registers* regs);
static uint8_t InterceptWoodenBSupports(registers* regs);
static uint8_t InterceptMetalASupports(registers* regs);
static uint8_t InterceptMetalBSupports(registers* regs);
static uint8_t InterceptPaint6C(registers* regs);
static uint8_t InterceptPaint7C(registers* regs);
static uint8_t InterceptPaint8C(registers* regs);
static uint8_t InterceptPaint9C(registers* regs);
static uint8_t InterceptPaintFull(uint8_t function, registers* regs);
bool PaintMetalSupports(uint8_t function, int supportType, uint8_t segment, int special, int height, uint32_t imageColourFlags, const support_height * supportSegments);
bool PaintWoodenSupports(uint8_t function, int supportType, int special, int height, uint32_t imageColourFlags, bool *underground, const paint_struct * prependTo);
static void CheckSegmentSupportHeight(const support_height * supportSegments);
bool PaintMetalSupports(
uint8_t function,
int supportType,
uint8_t segment,
int special,
int height,
uint32_t imageColourFlags,
const support_height* supportSegments);
bool PaintWoodenSupports(
uint8_t function,
int supportType,
int special,
int height,
uint32_t imageColourFlags,
bool* underground,
const paint_struct* prependTo);
static void CheckSegmentSupportHeight(const support_height* supportSegments);
void InitHooks() {
void InitHooks()
{
addhook(0x006629BC, InterceptWoodenASupports);
addhook(0x00662D5C, InterceptWoodenBSupports);
@ -69,8 +85,16 @@ namespace PaintIntercept {
addhook(0x00687902, InterceptPaint9C);
}
bool PaintWoodenSupports(uint8_t function, int supportType, int special, int height, uint32_t imageColourFlags, bool *underground, const paint_struct * prependTo) {
function_call * call = &_calls[_callCount];
bool PaintWoodenSupports(
uint8_t function,
int supportType,
int special,
int height,
uint32_t imageColourFlags,
bool* underground,
const paint_struct* prependTo)
{
function_call* call = &_calls[_callCount];
call->function = function;
call->supports.type = supportType;
call->supports.special = special;
@ -95,10 +119,18 @@ namespace PaintIntercept {
return _woodenSupports;
}
bool PaintMetalSupports(uint8_t function, int supportType, uint8_t segment, int special, int height, uint32_t imageColourFlags, const support_height * supportSegments) {
bool PaintMetalSupports(
uint8_t function,
int supportType,
uint8_t segment,
int special,
int height,
uint32_t imageColourFlags,
const support_height* supportSegments)
{
CheckSegmentSupportHeight(supportSegments);
function_call * call = &_calls[_callCount];
function_call* call = &_calls[_callCount];
call->function = function;
call->supports.type = supportType;
call->supports.segment = segment;
@ -111,18 +143,21 @@ namespace PaintIntercept {
return false;
}
static paint_struct *Paint6C(
static paint_struct* Paint6C(
uint32_t imageID,
int8_t xOffset, int8_t yOffset,
int16_t boundBoxLengthX, int16_t boundBoxLengthY, int8_t boundBoxLengthZ,
int8_t xOffset,
int8_t yOffset,
int16_t boundBoxLengthX,
int16_t boundBoxLengthY,
int8_t boundBoxLengthZ,
int16_t zOffset,
uint32_t rotation
) {
function_call * call = &_calls[_callCount];
uint32_t rotation)
{
function_call* call = &_calls[_callCount];
call->function = PAINT_98196C;
call->paint.image_id = imageID;
call->paint.offset = {xOffset, yOffset};
call->paint.bound_box_length = {boundBoxLengthX, boundBoxLengthY, boundBoxLengthZ};
call->paint.offset = { xOffset, yOffset };
call->paint.bound_box_length = { boundBoxLengthX, boundBoxLengthY, boundBoxLengthZ };
call->paint.z_offset = zOffset;
call->paint.rotation = rotation;
@ -131,21 +166,26 @@ namespace PaintIntercept {
return &call->paint.output_struct;
}
static paint_struct *PaintFull(
static paint_struct* PaintFull(
uint8_t function,
uint32_t imageID,
int8_t xOffset, int8_t yOffset,
int16_t boundBoxLengthX, int16_t boundBoxLengthY, int8_t boundBoxLengthZ,
int8_t xOffset,
int8_t yOffset,
int16_t boundBoxLengthX,
int16_t boundBoxLengthY,
int8_t boundBoxLengthZ,
int16_t zOffset,
int16_t boundBoxOffsetX, int16_t boundBoxOffsetY, int16_t boundBoxOffsetZ,
uint32_t rotation
) {
function_call * call = &_calls[_callCount];
int16_t boundBoxOffsetX,
int16_t boundBoxOffsetY,
int16_t boundBoxOffsetZ,
uint32_t rotation)
{
function_call* call = &_calls[_callCount];
call->function = function;
call->paint.image_id = imageID;
call->paint.offset = {xOffset, yOffset};
call->paint.bound_box_length = {boundBoxLengthX, boundBoxLengthY, boundBoxLengthZ};
call->paint.bound_box_offset = {boundBoxOffsetX, boundBoxOffsetY, boundBoxOffsetZ};
call->paint.offset = { xOffset, yOffset };
call->paint.bound_box_length = { boundBoxLengthX, boundBoxLengthY, boundBoxLengthZ };
call->paint.bound_box_offset = { boundBoxOffsetX, boundBoxOffsetY, boundBoxOffsetZ };
call->paint.z_offset = zOffset;
call->paint.rotation = rotation;
@ -154,42 +194,52 @@ namespace PaintIntercept {
return &call->paint.output_struct;
}
void ClearCalls() {
void ClearCalls()
{
_callCount = 0;
memset(_calls, 0, sizeof(_calls));
}
int GetCalls(function_call *buffer) {
int GetCalls(function_call* buffer)
{
memcpy(buffer, _calls, _callCount * sizeof(function_call));
return _callCount;
}
void SetSimulateWoodenSupports(bool enabled) {
void SetSimulateWoodenSupports(bool enabled)
{
_woodenSupports = enabled;
}
static uint8_t InterceptMetalASupports(registers *regs)
static uint8_t InterceptMetalASupports(registers* regs)
{
bool output = PaintMetalSupports(SUPPORTS_METAL_A, regs->edi, regs->ebx, (int16_t) regs->ax, regs->dx, regs->ebp, gSupportSegments);
bool output = PaintMetalSupports(
SUPPORTS_METAL_A, regs->edi, regs->ebx, (int16_t)regs->ax, regs->dx, regs->ebp, gSupportSegments);
return output ? X86_FLAG_CARRY : 0;
}
static uint8_t InterceptMetalBSupports(registers *regs)
static uint8_t InterceptMetalBSupports(registers* regs)
{
bool output = PaintMetalSupports(SUPPORTS_METAL_B, regs->edi, regs->ebx, (int16_t) regs->ax, regs->dx, regs->ebp, gSupportSegments);
bool output = PaintMetalSupports(
SUPPORTS_METAL_B, regs->edi, regs->ebx, (int16_t)regs->ax, regs->dx, regs->ebp, gSupportSegments);
return output ? X86_FLAG_CARRY : 0;
}
static void CheckSegmentSupportHeight(const support_height * supportSegments) {
static void CheckSegmentSupportHeight(const support_height* supportSegments)
{
bool hasChanged = false;
for (int i = 0; i < 9; i++) {
if (supportSegments[i].height != 0) hasChanged = true;
if (supportSegments[i].slope != 0xFF) hasChanged = true;
for (int i = 0; i < 9; i++)
{
if (supportSegments[i].height != 0)
hasChanged = true;
if (supportSegments[i].slope != 0xFF)
hasChanged = true;
}
if (!hasChanged) {
if (!hasChanged)
{
return;
}
@ -200,10 +250,11 @@ namespace PaintIntercept {
_callCount++;
}
static uint8_t InterceptWoodenASupports(registers *regs)
static uint8_t InterceptWoodenASupports(registers* regs)
{
bool cf = false;
regs->al = PaintWoodenSupports(SUPPORTS_WOOD_A, regs->edi, regs->ax, regs->dx, regs->ebp, &cf, gWoodenSupportsPrependTo);
regs->al
= PaintWoodenSupports(SUPPORTS_WOOD_A, regs->edi, regs->ax, regs->dx, regs->ebp, &cf, gWoodenSupportsPrependTo);
if (cf)
{
@ -213,10 +264,11 @@ namespace PaintIntercept {
return 0;
}
static uint8_t InterceptWoodenBSupports(registers *regs)
static uint8_t InterceptWoodenBSupports(registers* regs)
{
bool cf = false;
regs->al = PaintWoodenSupports(SUPPORTS_WOOD_B, regs->edi, regs->ax, regs->dx, regs->ebp, &cf, gWoodenSupportsPrependTo);
regs->al
= PaintWoodenSupports(SUPPORTS_WOOD_B, regs->edi, regs->ax, regs->dx, regs->ebp, &cf, gWoodenSupportsPrependTo);
if (cf)
{
@ -226,7 +278,7 @@ namespace PaintIntercept {
return 0;
}
static uint8_t InterceptPaint6C(registers *regs)
static uint8_t InterceptPaint6C(registers* regs)
{
if ((regs->ebp & 0x03) != RCT2_CurrentRotation)
{
@ -234,148 +286,209 @@ namespace PaintIntercept {
log_error("Ebp is different from current rotation");
}
paint_struct *out = Paint6C(
paint_struct* out = Paint6C(
regs->ebx,
(int8_t) regs->al, (int8_t) regs->cl,
(int16_t) regs->di, (int16_t) regs->si, (int8_t) regs->ah,
(int8_t)regs->al,
(int8_t)regs->cl,
(int16_t)regs->di,
(int16_t)regs->si,
(int8_t)regs->ah,
regs->dx,
regs->ebp & 0x03
);
regs->ebp & 0x03);
if (out == nullptr)
{
return X86_FLAG_CARRY;
}
regs->ebp = (int) out;
regs->ebp = (int)out;
regs->al = 1;
return 0;
}
static uint8_t InterceptPaint7C(registers *regs)
static uint8_t InterceptPaint7C(registers* regs)
{
return InterceptPaintFull(PAINT_98197C, regs);
}
static uint8_t InterceptPaint8C(registers *regs)
static uint8_t InterceptPaint8C(registers* regs)
{
return InterceptPaintFull(PAINT_98198C, regs);
}
static uint8_t InterceptPaint9C(registers *regs)
static uint8_t InterceptPaint9C(registers* regs)
{
return InterceptPaintFull(PAINT_98199C, regs);
}
static uint8_t InterceptPaintFull(uint8_t function, registers *regs) {
if ((regs->ebp & 0x03) != RCT2_CurrentRotation) {
static uint8_t InterceptPaintFull(uint8_t function, registers* regs)
{
if ((regs->ebp & 0x03) != RCT2_CurrentRotation)
{
// Log error
log_error("Ebp is different from current rotation");
}
LocationXYZ16 boundOffset = {
RCT2_PaintBoundBoxOffsetX,
RCT2_PaintBoundBoxOffsetY,
RCT2_PaintBoundBoxOffsetZ
};
LocationXYZ16 boundOffset = { RCT2_PaintBoundBoxOffsetX, RCT2_PaintBoundBoxOffsetY, RCT2_PaintBoundBoxOffsetZ };
paint_struct *out = PaintFull(
paint_struct* out = PaintFull(
function,
regs->ebx,
(int8_t) regs->al, (int8_t) regs->cl,
(int16_t) regs->di, (int16_t) regs->si, (int8_t) regs->ah,
(int8_t)regs->al,
(int8_t)regs->cl,
(int16_t)regs->di,
(int16_t)regs->si,
(int8_t)regs->ah,
regs->dx,
boundOffset.x, boundOffset.y, boundOffset.z,
regs->ebp & 0x03
);
boundOffset.x,
boundOffset.y,
boundOffset.z,
regs->ebp & 0x03);
if (out == nullptr)
{
return X86_FLAG_CARRY;
}
regs->ebp = (int) out;
regs->ebp = (int)out;
return 0;
}
};
}; // namespace PaintIntercept
bool wooden_a_supports_paint_setup(paint_session * session, int supportType, int special, int height, uint32_t imageColourFlags, bool *underground) {
return PaintIntercept::PaintWoodenSupports(SUPPORTS_WOOD_A, supportType, special, height, imageColourFlags, underground, gPaintSession.WoodenSupportsPrependTo);
bool wooden_a_supports_paint_setup(
paint_session* session, int supportType, int special, int height, uint32_t imageColourFlags, bool* underground)
{
return PaintIntercept::PaintWoodenSupports(
SUPPORTS_WOOD_A, supportType, special, height, imageColourFlags, underground, gPaintSession.WoodenSupportsPrependTo);
}
bool wooden_b_supports_paint_setup(paint_session * session, int supportType, int special, int height, uint32_t imageColourFlags, bool *underground) {
return PaintIntercept::PaintWoodenSupports(SUPPORTS_WOOD_B, supportType, special, height, imageColourFlags, underground, gPaintSession.WoodenSupportsPrependTo);
bool wooden_b_supports_paint_setup(
paint_session* session, int supportType, int special, int height, uint32_t imageColourFlags, bool* underground)
{
return PaintIntercept::PaintWoodenSupports(
SUPPORTS_WOOD_B, supportType, special, height, imageColourFlags, underground, gPaintSession.WoodenSupportsPrependTo);
}
bool metal_a_supports_paint_setup(paint_session * session, uint8_t supportType, uint8_t segment, int special, int height, uint32_t imageColourFlags) {
return PaintIntercept::PaintMetalSupports(SUPPORTS_METAL_A, supportType, segment, special, height, imageColourFlags, gPaintSession.SupportSegments);
bool metal_a_supports_paint_setup(
paint_session* session, uint8_t supportType, uint8_t segment, int special, int height, uint32_t imageColourFlags)
{
return PaintIntercept::PaintMetalSupports(
SUPPORTS_METAL_A, supportType, segment, special, height, imageColourFlags, gPaintSession.SupportSegments);
}
bool metal_b_supports_paint_setup(paint_session * session, uint8_t supportType, uint8_t segment, int special, int height, uint32_t imageColourFlags) {
return PaintIntercept::PaintMetalSupports(SUPPORTS_METAL_B, supportType, segment, special, height, imageColourFlags, gPaintSession.SupportSegments);
bool metal_b_supports_paint_setup(
paint_session* session, uint8_t supportType, uint8_t segment, int special, int height, uint32_t imageColourFlags)
{
return PaintIntercept::PaintMetalSupports(
SUPPORTS_METAL_B, supportType, segment, special, height, imageColourFlags, gPaintSession.SupportSegments);
}
paint_struct *sub_98196C(paint_session * session, uint32_t image_id, int8_t x_offset, int8_t y_offset, int16_t bound_box_length_x, int16_t bound_box_length_y, int8_t bound_box_length_z, int16_t z_offset) {
return PaintIntercept::Paint6C(image_id, x_offset, y_offset, bound_box_length_x, bound_box_length_y, bound_box_length_z, z_offset, session->CurrentRotation);
}
paint_struct *sub_98197C(
paint_session * session,
paint_struct* sub_98196C(
paint_session* session,
uint32_t image_id,
int8_t x_offset, int8_t y_offset,
int16_t bound_box_length_x, int16_t bound_box_length_y, int8_t bound_box_length_z,
int8_t x_offset,
int8_t y_offset,
int16_t bound_box_length_x,
int16_t bound_box_length_y,
int8_t bound_box_length_z,
int16_t z_offset)
{
return PaintIntercept::Paint6C(
image_id,
x_offset,
y_offset,
bound_box_length_x,
bound_box_length_y,
bound_box_length_z,
z_offset,
session->CurrentRotation);
}
paint_struct* sub_98197C(
paint_session* session,
uint32_t image_id,
int8_t x_offset,
int8_t y_offset,
int16_t bound_box_length_x,
int16_t bound_box_length_y,
int8_t bound_box_length_z,
int16_t z_offset,
int16_t bound_box_offset_x, int16_t bound_box_offset_y, int16_t bound_box_offset_z
) {
int16_t bound_box_offset_x,
int16_t bound_box_offset_y,
int16_t bound_box_offset_z)
{
return PaintIntercept::PaintFull(
PAINT_98197C,
image_id,
x_offset, y_offset,
bound_box_length_x, bound_box_length_y, bound_box_length_z,
x_offset,
y_offset,
bound_box_length_x,
bound_box_length_y,
bound_box_length_z,
z_offset,
bound_box_offset_x, bound_box_offset_y, bound_box_offset_z,
session->CurrentRotation
);
bound_box_offset_x,
bound_box_offset_y,
bound_box_offset_z,
session->CurrentRotation);
}
paint_struct *sub_98198C(
paint_session * session,
paint_struct* sub_98198C(
paint_session* session,
uint32_t image_id,
int8_t x_offset, int8_t y_offset,
int16_t bound_box_length_x, int16_t bound_box_length_y, int8_t bound_box_length_z,
int8_t x_offset,
int8_t y_offset,
int16_t bound_box_length_x,
int16_t bound_box_length_y,
int8_t bound_box_length_z,
int16_t z_offset,
int16_t bound_box_offset_x, int16_t bound_box_offset_y, int16_t bound_box_offset_z
) {
int16_t bound_box_offset_x,
int16_t bound_box_offset_y,
int16_t bound_box_offset_z)
{
return PaintIntercept::PaintFull(
PAINT_98198C,
image_id,
x_offset, y_offset,
bound_box_length_x, bound_box_length_y, bound_box_length_z,
x_offset,
y_offset,
bound_box_length_x,
bound_box_length_y,
bound_box_length_z,
z_offset,
bound_box_offset_x, bound_box_offset_y, bound_box_offset_z,
session->CurrentRotation
);
bound_box_offset_x,
bound_box_offset_y,
bound_box_offset_z,
session->CurrentRotation);
}
paint_struct *sub_98199C(
paint_session * session,
paint_struct* sub_98199C(
paint_session* session,
uint32_t image_id,
int8_t x_offset, int8_t y_offset,
int16_t bound_box_length_x, int16_t bound_box_length_y, int8_t bound_box_length_z,
int8_t x_offset,
int8_t y_offset,
int16_t bound_box_length_x,
int16_t bound_box_length_y,
int8_t bound_box_length_z,
int16_t z_offset,
int16_t bound_box_offset_x, int16_t bound_box_offset_y, int16_t bound_box_offset_z
) {
int16_t bound_box_offset_x,
int16_t bound_box_offset_y,
int16_t bound_box_offset_z)
{
return PaintIntercept::PaintFull(
PAINT_98199C,
image_id,
x_offset, y_offset,
bound_box_length_x, bound_box_length_y, bound_box_length_z,
x_offset,
y_offset,
bound_box_length_x,
bound_box_length_y,
bound_box_length_z,
z_offset,
bound_box_offset_x, bound_box_offset_y, bound_box_offset_z,
session->CurrentRotation
);
bound_box_offset_x,
bound_box_offset_y,
bound_box_offset_z,
session->CurrentRotation);
}
bool paint_attach_to_previous_ps(paint_session * session, uint32_t image_id, uint16_t x, uint16_t y) {
bool paint_attach_to_previous_ps(paint_session* session, uint32_t image_id, uint16_t x, uint16_t y)
{
return false;
}

View File

@ -9,14 +9,16 @@
#pragma once
#include <openrct2/common.h>
#include "FunctionCall.hpp"
namespace PaintIntercept {
#include <openrct2/common.h>
namespace PaintIntercept
{
void InitHooks();
void ClearCalls();
int GetCalls(function_call *buffer);
int GetCalls(function_call* buffer);
void SetSimulateWoodenSupports(bool enabled);
};
}; // namespace PaintIntercept

View File

@ -8,15 +8,16 @@
*****************************************************************************/
#include "Printer.hpp"
#include "String.hpp"
#include <openrct2/core/Util.hpp>
#include "FunctionCall.hpp"
#include "FunctionCall.hpp"
#include "String.hpp"
#include <openrct2/core/Util.hpp>
#include <openrct2/sprites.h>
namespace Printer {
static const char *functionNames[] = {
namespace Printer
{
static const char* functionNames[] = {
"sub_98196C",
"sub_98197C",
"sub_98198C",
@ -36,10 +37,12 @@ namespace Printer {
static std::string PrintSideTunnelEdge(TunnelCall edge);
std::string PrintFunctionCalls(std::vector<function_call> calls, uint16_t baseHeight) {
std::string PrintFunctionCalls(std::vector<function_call> calls, uint16_t baseHeight)
{
std::string out;
for (auto &&call : calls) {
for (auto&& call : calls)
{
out += PrintFunctionCall(call, baseHeight).c_str();
out += "\n";
}
@ -47,30 +50,33 @@ namespace Printer {
return out;
}
std::string PrintFunctionCall(function_call call, uint16_t baseHeight) {
std::string PrintFunctionCall(function_call call, uint16_t baseHeight)
{
std::string imageId = GetImageIdString(call.supports.colour_flags);
assert(call.function < Util::CountOf(functionNames));
const char *functionName = functionNames[call.function];
const char* functionName = functionNames[call.function];
std::string out = "";
switch (call.function) {
switch (call.function)
{
case SUPPORTS_WOOD_A:
case SUPPORTS_WOOD_B:
out += String::Format(
"%s(%d, %d, %s, %s)", functionName, call.supports.type, call.supports.special,
PrintHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str()
);
if (call.supports.special == 14 ||
call.supports.special == 15 ||
call.supports.special == 18 ||
call.supports.special == 19 ||
call.supports.special == 22 ||
call.supports.special == 23)
"%s(%d, %d, %s, %s)",
functionName,
call.supports.type,
call.supports.special,
PrintHeightOffset(call.supports.height, baseHeight).c_str(),
imageId.c_str());
if (call.supports.special == 14 || call.supports.special == 15 || call.supports.special == 18
|| call.supports.special == 19 || call.supports.special == 22 || call.supports.special == 23)
{
if (call.supports.prepend_to == SPR_NONE)
{
out += " [prependTo:SPR_NONE]";
} else {
}
else
{
std::string prependId = GetImageIdString(call.supports.prepend_to);
out += String::Format(" [prependTo:%s]", prependId.c_str());
}
@ -85,9 +91,13 @@ namespace Printer {
case SUPPORTS_METAL_A:
case SUPPORTS_METAL_B:
return String::Format(
"%s(%d, %d, %d, %s, %s)", functionName, call.supports.type, call.supports.segment, call.supports.special,
PrintHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str()
);
"%s(%d, %d, %d, %s, %s)",
functionName,
call.supports.type,
call.supports.segment,
call.supports.special,
PrintHeightOffset(call.supports.height, baseHeight).c_str(),
imageId.c_str());
case SET_SEGMENT_HEIGHT:
return "paint_util_set_segment_support_height";
@ -99,45 +109,52 @@ namespace Printer {
s += String::Format("%s, ", imageId.c_str());
s += String::Format("%d, %d, ", call.paint.offset.x, call.paint.offset.y);
s += String::Format(
"%d, %d, %d, ",
call.paint.bound_box_length.x, call.paint.bound_box_length.y, call.paint.bound_box_length.z
);
"%d, %d, %d, ", call.paint.bound_box_length.x, call.paint.bound_box_length.y, call.paint.bound_box_length.z);
s += String::Format("%s, ", PrintHeightOffset(call.paint.z_offset, baseHeight).c_str());
if (call.function != PAINT_98196C) {
if (call.function != PAINT_98196C)
{
s += String::Format(
"%d, %d, %s, ",
call.paint.bound_box_offset.x, call.paint.bound_box_offset.y,
PrintHeightOffset(call.paint.bound_box_offset.z, baseHeight).c_str()
);
call.paint.bound_box_offset.x,
call.paint.bound_box_offset.y,
PrintHeightOffset(call.paint.bound_box_offset.z, baseHeight).c_str());
}
s += String::Format("%d)", call.paint.rotation);
if (call.function != PAINT_98196C) {
if (call.function != PAINT_98196C)
{
s += String::Format(
" = { %d, %d, %s }, { %d, %d, %s }, { %d, %d, %d }",
call.paint.offset.x, call.paint.offset.y, PrintHeightOffset(call.paint.z_offset, baseHeight).c_str(),
call.paint.bound_box_offset.x, call.paint.bound_box_offset.y,
call.paint.offset.x,
call.paint.offset.y,
PrintHeightOffset(call.paint.z_offset, baseHeight).c_str(),
call.paint.bound_box_offset.x,
call.paint.bound_box_offset.y,
PrintHeightOffset(call.paint.bound_box_offset.z, baseHeight).c_str(),
call.paint.bound_box_length.x, call.paint.bound_box_length.y, call.paint.bound_box_length.z);
call.paint.bound_box_length.x,
call.paint.bound_box_length.y,
call.paint.bound_box_length.z);
}
return s;
}
std::string PrintSegmentSupportHeightCalls(std::vector<SegmentSupportCall> calls) {
std::string PrintSegmentSupportHeightCalls(std::vector<SegmentSupportCall> calls)
{
std::string out = "";
for (auto &&call : calls) {
for (auto&& call : calls)
{
out += PrintSegmentSupportHeightCall(call);
}
return out;
}
static std::string PrintSegmentSupportHeightCall(SegmentSupportCall call) {
static std::string PrintSegmentSupportHeightCall(SegmentSupportCall call)
{
std::string out = "";
if (call.segments == SEGMENTS_ALL)
@ -161,9 +178,12 @@ namespace Printer {
}
}
if (call.height == 0xFFFF) {
if (call.height == 0xFFFF)
{
out += ", 0xFFFF";
} else {
}
else
{
out += String::Format(", %d", call.height);
}
@ -172,39 +192,46 @@ namespace Printer {
return out;
}
std::string PrintSideTunnelCalls(TunnelCall tunnelCalls[4][4]) {
std::string PrintSideTunnelCalls(TunnelCall tunnelCalls[4][4])
{
std::string s;
for (int direction = 0; direction < 4; ++direction) {
for (int direction = 0; direction < 4; ++direction)
{
s += " + ";
}
s += "\n";
for (int direction = 0; direction < 4; ++direction) {
for (int direction = 0; direction < 4; ++direction)
{
std::string leftEdge = PrintSideTunnelEdge(tunnelCalls[direction][3]);
std::string rightEdge = PrintSideTunnelEdge(tunnelCalls[direction][2]);
s += String::Format(" %s %s ", leftEdge.c_str(), rightEdge.c_str());
}
s += "\n";
for (int direction = 0; direction < 4; ++direction) {
for (int direction = 0; direction < 4; ++direction)
{
s += " + + ";
}
s += "\n";
for (int direction = 0; direction < 4; ++direction) {
for (int direction = 0; direction < 4; ++direction)
{
std::string leftEdge = PrintSideTunnelEdge(tunnelCalls[direction][0]);
std::string rightEdge = PrintSideTunnelEdge(tunnelCalls[direction][1]);
s += String::Format(" %s %s ", leftEdge.c_str(), rightEdge.c_str());
}
s += "\n";
for (int direction = 0; direction < 4; ++direction) {
for (int direction = 0; direction < 4; ++direction)
{
s += " + ";
}
s += "\n";
for (int direction = 0; direction < 4; ++direction) {
for (int direction = 0; direction < 4; ++direction)
{
s += String::Format(" direction %d ", direction);
}
s += "\n";
@ -212,10 +239,12 @@ namespace Printer {
return s;
}
static std::string PrintSideTunnelEdge(TunnelCall edge) {
static std::string PrintSideTunnelEdge(TunnelCall edge)
{
std::string s;
switch (edge.call) {
switch (edge.call)
{
case TUNNELCALL_SKIPPED:
s = " ";
break;
@ -227,9 +256,12 @@ namespace Printer {
case TUNNELCALL_CALL:
std::string offset;
if (edge.offset <= 0) {
if (edge.offset <= 0)
{
offset = String::Format("%d", edge.offset);
} else {
}
else
{
offset = String::Format("+%d", edge.offset);
}
s = String::Format("%3s/%X", offset.c_str(), edge.type);
@ -247,26 +279,37 @@ namespace Printer {
uint32_t palette = imageId & ~0x7FFFF;
std::string paletteName;
if (palette == TestPaint::DEFAULT_SCHEME_TRACK) paletteName = "SCHEME_TRACK";
else if (palette == TestPaint::DEFAULT_SCHEME_SUPPORTS) paletteName = "SCHEME_SUPPORTS";
else if (palette == TestPaint::DEFAULT_SCHEME_MISC) paletteName = "SCHEME_MISC";
else if (palette == TestPaint::DEFAULT_SCHEME_3) paletteName = "SCHEME_3";
else {
if (palette == TestPaint::DEFAULT_SCHEME_TRACK)
paletteName = "SCHEME_TRACK";
else if (palette == TestPaint::DEFAULT_SCHEME_SUPPORTS)
paletteName = "SCHEME_SUPPORTS";
else if (palette == TestPaint::DEFAULT_SCHEME_MISC)
paletteName = "SCHEME_MISC";
else if (palette == TestPaint::DEFAULT_SCHEME_3)
paletteName = "SCHEME_3";
else
{
paletteName = String::Format("0x%08X", palette);
}
if (image == 0) {
if (image == 0)
{
result = paletteName;
} else if (image & 0x70000) {
}
else if (image & 0x70000)
{
result = String::Format("%s | vehicle.base_image_id + %d", paletteName.c_str(), image & ~0x70000);
} else {
}
else
{
result = String::Format("%s | %d", paletteName.c_str(), image);
}
return result;
}
std::string PrintHeightOffset(uint16_t height, uint16_t baseHeight) {
std::string PrintHeightOffset(uint16_t height, uint16_t baseHeight)
{
int offset = height - baseHeight;
return String::Format("height%s", GetOffsetExpressionString(offset).c_str());
@ -274,8 +317,10 @@ namespace Printer {
static std::string GetOffsetExpressionString(int offset)
{
if (offset < 0) return std::string(" - ") + std::to_string(-offset);
if (offset > 0) return std::string(" + ") + std::to_string(offset);
if (offset < 0)
return std::string(" - ") + std::to_string(-offset);
if (offset > 0)
return std::string(" + ") + std::to_string(offset);
return std::string();
}
};
}; // namespace Printer

View File

@ -9,20 +9,21 @@
#pragma once
#include "FunctionCall.hpp"
#include "SegmentSupportHeightCall.hpp"
#include "SideTunnelCall.hpp"
#include <string>
#include <vector>
#include "FunctionCall.hpp"
#include "SideTunnelCall.hpp"
#include "SegmentSupportHeightCall.hpp"
namespace Printer {
namespace Printer
{
std::string PrintFunctionCall(function_call call, uint16_t baseHeight);
std::string PrintFunctionCalls(std::vector <function_call> calls, uint16_t baseHeight);
std::string PrintFunctionCalls(std::vector<function_call> calls, uint16_t baseHeight);
std::string PrintSegmentSupportHeightCalls(std::vector<SegmentSupportCall> calls);
std::string PrintSideTunnelCalls(TunnelCall tunnelCalls[4][4]);
std::string PrintHeightOffset(uint16_t height, uint16_t baseHeight);
}
} // namespace Printer

View File

@ -7,51 +7,60 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <map>
#include <algorithm>
#include "SegmentSupportHeightCall.hpp"
#include <algorithm>
#include <map>
#include <openrct2/paint/tile_element/Paint.TileElement.h>
static bool SortSegmentSupportCalls(SegmentSupportCall lhs, SegmentSupportCall rhs)
{
if (lhs.height != rhs.height) {
if (lhs.height != rhs.height)
{
return lhs.height < rhs.height;
}
if (lhs.slope != rhs.slope) {
if (lhs.slope != rhs.slope)
{
return lhs.slope < rhs.slope;
}
return lhs.segments < rhs.segments;
}
std::vector<SegmentSupportCall> SegmentSupportHeightCall::getSegmentCalls(support_height *supports, uint8_t rotation) {
std::vector<SegmentSupportCall> SegmentSupportHeightCall::getSegmentCalls(support_height* supports, uint8_t rotation)
{
uint16_t positionsRemaining = SEGMENTS_ALL;
for (int i = 0; i < 9; i++) {
if (supports[i].height == 0 && supports[i].slope == 0xFF) {
for (int i = 0; i < 9; i++)
{
if (supports[i].height == 0 && supports[i].slope == 0xFF)
{
positionsRemaining &= ~segment_offsets[i];
}
}
std::vector<SegmentSupportCall> calls;
while (positionsRemaining != 0) {
while (positionsRemaining != 0)
{
SegmentSupportCall call = {};
call.height = -1;
call.slope = -1;
support_height referenceSupport = {};
for (int i = 0; i < 9; i++) {
if (positionsRemaining & segment_offsets[i]) {
for (int i = 0; i < 9; i++)
{
if (positionsRemaining & segment_offsets[i])
{
referenceSupport = supports[i];
if (supports[i].height != 0) {
if (supports[i].height != 0)
{
call.height = supports[i].height;
}
if (supports[i].slope != 0xFF) {
if (supports[i].slope != 0xFF)
{
call.slope = supports[i].slope;
}
break;
@ -59,8 +68,10 @@ std::vector<SegmentSupportCall> SegmentSupportHeightCall::getSegmentCalls(suppor
}
uint16_t positionsMatched = 0;
for (int i = 0; i < 9; i++) {
if (supports[i].height == referenceSupport.height && supports[i].slope == referenceSupport.slope) {
for (int i = 0; i < 9; i++)
{
if (supports[i].height == referenceSupport.height && supports[i].slope == referenceSupport.slope)
{
positionsMatched |= segment_offsets[i];
}
}
@ -71,7 +82,8 @@ std::vector<SegmentSupportCall> SegmentSupportHeightCall::getSegmentCalls(suppor
calls.push_back(call);
}
if (calls.size() > 1) {
if (calls.size() > 1)
{
std::sort(calls.begin(), calls.end(), SortSegmentSupportCalls);
}
@ -81,8 +93,10 @@ std::vector<SegmentSupportCall> SegmentSupportHeightCall::getSegmentCalls(suppor
bool SegmentSupportHeightCall::CallsMatch(std::vector<SegmentSupportCall> tileSegmentSupportCalls[4])
{
std::vector<SegmentSupportCall> baseCallList = tileSegmentSupportCalls[0];
for (int i = 1; i < 4; i++) {
if (!CallsEqual(baseCallList, tileSegmentSupportCalls[i])) {
for (int i = 1; i < 4; i++)
{
if (!CallsEqual(baseCallList, tileSegmentSupportCalls[i]))
{
return false;
}
}
@ -92,8 +106,10 @@ bool SegmentSupportHeightCall::CallsMatch(std::vector<SegmentSupportCall> tileSe
bool SegmentSupportHeightCall::CallsEqual(std::vector<SegmentSupportCall> lhs, std::vector<SegmentSupportCall> rhs)
{
if (lhs.size() != rhs.size()) return false;
for (size_t i = 0; i < lhs.size(); ++i) {
if (lhs.size() != rhs.size())
return false;
for (size_t i = 0; i < lhs.size(); ++i)
{
if (lhs[i].segments != rhs[i].segments)
return false;
if (lhs[i].height != rhs[i].height)
@ -105,21 +121,28 @@ bool SegmentSupportHeightCall::CallsEqual(std::vector<SegmentSupportCall> lhs, s
return true;
}
bool SegmentSupportHeightCall::FindMostCommonSupportCall(std::vector<SegmentSupportCall> calls[4], std::vector<SegmentSupportCall> *out) {
bool SegmentSupportHeightCall::FindMostCommonSupportCall(
std::vector<SegmentSupportCall> calls[4], std::vector<SegmentSupportCall>* out)
{
std::map<std::vector<SegmentSupportCall>, int> map;
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4; ++i)
{
map[calls[i]] += 1;
}
if (map.size() == 1) {
if (map.size() == 1)
{
(*out) = calls[0];
return true;
}
if (map.size() == 2) {
for (auto &&item : map) {
if (item.second == 3) {
if (map.size() == 2)
{
for (auto&& item : map)
{
if (item.second == 3)
{
(*out) = item.first;
return true;
}

View File

@ -9,10 +9,9 @@
#pragma once
#include <vector>
#include <openrct2/common.h>
#include <openrct2/paint/Paint.h>
#include <vector>
struct SegmentSupportCall
{
@ -20,12 +19,15 @@ struct SegmentSupportCall
int32_t height;
int16_t slope;
bool operator<(const SegmentSupportCall &other) const {
if (height != other.height) {
bool operator<(const SegmentSupportCall& other) const
{
if (height != other.height)
{
return height < other.height;
}
if (segments != other.segments) {
if (segments != other.segments)
{
return segments < other.segments;
}
@ -33,10 +35,11 @@ struct SegmentSupportCall
}
};
class SegmentSupportHeightCall {
class SegmentSupportHeightCall
{
public:
static std::vector<SegmentSupportCall> getSegmentCalls(support_height supports[9], uint8_t rotation);
static bool CallsMatch(std::vector<SegmentSupportCall> tileSegmentSupportCalls[4]);
static bool CallsEqual(std::vector<SegmentSupportCall> lhs, std::vector<SegmentSupportCall> rhs);
static bool FindMostCommonSupportCall(std::vector<SegmentSupportCall> calls[4], std::vector<SegmentSupportCall> * out);
static bool FindMostCommonSupportCall(std::vector<SegmentSupportCall> calls[4], std::vector<SegmentSupportCall>* out);
};

View File

@ -9,11 +9,16 @@
#include "SideTunnelCall.hpp"
int16_t SideTunnelCall::GetTunnelOffset(uint32_t baseHeight, tunnel_entry calls[3]) {
for (int16_t offset = -56; offset <= 56; offset += 8) {
if (calls[0].height != (baseHeight - 8 + offset) / 16) continue;
if (calls[1].height != (baseHeight + 0 + offset) / 16) continue;
if (calls[2].height != (baseHeight + 8 + offset) / 16) continue;
int16_t SideTunnelCall::GetTunnelOffset(uint32_t baseHeight, tunnel_entry calls[3])
{
for (int16_t offset = -56; offset <= 56; offset += 8)
{
if (calls[0].height != (baseHeight - 8 + offset) / 16)
continue;
if (calls[1].height != (baseHeight + 0 + offset) / 16)
continue;
if (calls[2].height != (baseHeight + 8 + offset) / 16)
continue;
return offset;
}
@ -22,16 +27,18 @@ int16_t SideTunnelCall::GetTunnelOffset(uint32_t baseHeight, tunnel_entry calls[
return 0;
}
TunnelCall SideTunnelCall::ExtractTunnelCalls(tunnel_entry *calls, uint8_t count, uint16_t baseHeight, bool *error) {
TunnelCall SideTunnelCall::ExtractTunnelCalls(tunnel_entry* calls, uint8_t count, uint16_t baseHeight, bool* error)
{
TunnelCall tunnelCall = {};
if (count == 0) {
if (count == 0)
{
tunnelCall.call = TUNNELCALL_NONE;
return tunnelCall;
}
if (count == 3) {
if (count == 3)
{
tunnelCall.call = TUNNELCALL_CALL;
tunnelCall.offset = GetTunnelOffset(baseHeight, calls);
tunnelCall.type = calls[0].type;
@ -42,26 +49,33 @@ TunnelCall SideTunnelCall::ExtractTunnelCalls(tunnel_entry *calls, uint8_t count
return tunnelCall;
}
bool SideTunnelCall::TunnelCallsLineUp(TunnelCall tunnelCalls[4][4])
{
for (int side = 0; side < 4; ++side) {
TunnelCall * referenceCall = nullptr;
for (int direction = 0; direction < 4; ++direction) {
if (tunnelCalls[direction][side].call == TUNNELCALL_SKIPPED) {
for (int side = 0; side < 4; ++side)
{
TunnelCall* referenceCall = nullptr;
for (int direction = 0; direction < 4; ++direction)
{
if (tunnelCalls[direction][side].call == TUNNELCALL_SKIPPED)
{
continue;
}
if (referenceCall == nullptr) {
if (referenceCall == nullptr)
{
referenceCall = &tunnelCalls[direction][side];
continue;
}
if (referenceCall->call != tunnelCalls[direction][side].call) return false;
if (referenceCall->call != tunnelCalls[direction][side].call)
return false;
if (referenceCall->call == TUNNELCALL_CALL) {
if (referenceCall->type != tunnelCalls[direction][side].type) return false;
if (referenceCall->offset != tunnelCalls[direction][side].offset) return false;
if (referenceCall->call == TUNNELCALL_CALL)
{
if (referenceCall->type != tunnelCalls[direction][side].type)
return false;
if (referenceCall->offset != tunnelCalls[direction][side].offset)
return false;
}
}
}
@ -71,9 +85,12 @@ bool SideTunnelCall::TunnelCallsLineUp(TunnelCall tunnelCalls[4][4])
void SideTunnelCall::GetTunnelCallReferencePattern(TunnelCall tunnelCalls[4][4], TunnelCall (*out)[4])
{
for (int side = 0; side < 4; ++side) {
for (int direction = 0; direction < 4; ++direction) {
if (tunnelCalls[direction][side].call == TUNNELCALL_SKIPPED) {
for (int side = 0; side < 4; ++side)
{
for (int direction = 0; direction < 4; ++direction)
{
if (tunnelCalls[direction][side].call == TUNNELCALL_SKIPPED)
{
continue;
}
@ -86,12 +103,17 @@ void SideTunnelCall::GetTunnelCallReferencePattern(TunnelCall tunnelCalls[4][4],
bool SideTunnelCall::TunnelPatternsMatch(TunnelCall expected[4], TunnelCall actual[4])
{
for (int side = 0; side < 4; side++) {
if (expected[side].call != actual[side].call) return false;
for (int side = 0; side < 4; side++)
{
if (expected[side].call != actual[side].call)
return false;
if (expected[side].call == TUNNELCALL_CALL) {
if (expected[side].type != actual[side].type) return false;
if (expected[side].offset != actual[side].offset) return false;
if (expected[side].call == TUNNELCALL_CALL)
{
if (expected[side].type != actual[side].type)
return false;
if (expected[side].offset != actual[side].offset)
return false;
}
}

View File

@ -12,23 +12,26 @@
#include <openrct2/common.h>
#include <openrct2/paint/Paint.h>
enum {
enum
{
TUNNELCALL_SKIPPED,
TUNNELCALL_NONE,
TUNNELCALL_CALL,
};
struct TunnelCall {
struct TunnelCall
{
uint8_t call;
int16_t offset;
uint8_t type;
};
namespace SideTunnelCall {
namespace SideTunnelCall
{
int16_t GetTunnelOffset(uint32_t baseHeight, tunnel_entry calls[3]);
TunnelCall ExtractTunnelCalls(tunnel_entry * list, uint8_t count, uint16_t baseHeight, bool * error);
TunnelCall ExtractTunnelCalls(tunnel_entry* list, uint8_t count, uint16_t baseHeight, bool* error);
bool TunnelPatternsMatch(TunnelCall expected[4], TunnelCall actual[4]);
void GetTunnelCallReferencePattern(TunnelCall tunnelCalls[4][4], TunnelCall (*out)[4]);
bool TunnelCallsLineUp(TunnelCall tunnelCalls[4][4]);
};
}; // namespace SideTunnelCall

View File

@ -7,12 +7,13 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <cstdarg>
#include "String.hpp"
namespace String {
std::string Format(const char * format, ...)
#include <cstdarg>
namespace String
{
std::string Format(const char* format, ...)
{
va_list args;
char buffer[512];
@ -23,4 +24,4 @@ namespace String {
return std::string(buffer);
}
};
}; // namespace String

View File

@ -11,6 +11,7 @@
#include <string>
namespace String {
std::string Format(const char *format, ...);
namespace String
{
std::string Format(const char* format, ...);
}

View File

@ -7,25 +7,26 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <algorithm>
#include <vector>
#include "TestPaint.hpp"
#include "Hook.h"
#include "GeneralSupportHeightCall.hpp"
#include "Hook.h"
#include "Printer.hpp"
#include "SegmentSupportHeightCall.hpp"
#include "TestPaint.hpp"
#include "Utils.hpp"
#include <algorithm>
#include <openrct2/interface/Viewport.h>
#include <openrct2/paint/Paint.h>
#include <openrct2/paint/Supports.h>
#include <openrct2/ride/TrackData.h>
#include <openrct2/scenario/Scenario.h>
#include <openrct2/interface/Viewport.h>
#include <vector>
namespace TestPaint
{
void ResetEnvironment() {
void ResetEnvironment()
{
gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE;
gPaintSession.InteractionType = VIEWPORT_INTERACTION_ITEM_RIDE;
@ -48,7 +49,7 @@ namespace TestPaint
Ride ride = {};
ride.entrance_style = RIDE_ENTRANCE_STYLE_PLAIN;
static rct_ride_entry rideEntry = {};
rct_ride_entry_vehicle vehicleEntry {};
rct_ride_entry_vehicle vehicleEntry{};
vehicleEntry.base_image_id = 0x70000;
rideEntry.vehicles[0] = vehicleEntry;
gRideList[0] = ride;
@ -70,13 +71,15 @@ namespace TestPaint
RCT2_ScenarioTicks = 0;
}
void ResetTunnels() {
void ResetTunnels()
{
gLeftTunnelCount = 0;
gRightTunnelCount = 0;
gPaintSession.LeftTunnelCount = 0;
gPaintSession.RightTunnelCount = 0;
for (int i = 0; i < TUNNEL_MAX_COUNT; i++) {
for (int i = 0; i < TUNNEL_MAX_COUNT; i++)
{
gLeftTunnels[i].height = 0;
gLeftTunnels[i].type = 0;
gRightTunnels[i].height = 0;
@ -97,7 +100,8 @@ namespace TestPaint
gPaintSession.RightTunnels[0].type = 0xFF;
}
void ResetSupportHeights() {
void ResetSupportHeights()
{
for (int s = 0; s < 9; ++s)
{
gSupportSegments[s].height = 0;
@ -139,18 +143,18 @@ namespace TestPaint
bool testIsIgnored(uint8_t direction, uint8_t trackSequence)
{
if (_ignoredAll) return true;
for (const IgnoredEntry &entry : _ignoredEntries)
if (_ignoredAll)
return true;
for (const IgnoredEntry& entry : _ignoredEntries)
{
if (entry.Direction == direction &&
entry.TrackSequence == trackSequence)
if (entry.Direction == direction && entry.TrackSequence == trackSequence)
{
return true;
}
}
return false;
}
}
} // namespace TestPaint
void testpaint_clear_ignore()
{

View File

@ -9,46 +9,48 @@
#pragma once
#include <vector>
#include "Addresses.h"
#include <openrct2/common.h>
#include <openrct2/drawing/Drawing.h>
#include <openrct2/interface/Colour.h>
#include <openrct2/paint/Paint.h>
#include <openrct2/paint/tile_element/Paint.TileElement.h>
#include "Addresses.h"
#include <vector>
#define gRideEntries RCT2_ADDRESS(0x009ACFA4, rct_ride_entry*)
#define gSupportSegments RCT2_ADDRESS(0x0141E9B4, support_height)
#define gWoodenSupportsPrependTo RCT2_GLOBAL(0x009DEA58, paint_struct *)
#define gPaintStructs RCT2_ADDRESS(0x00EE788C, paint_entry)
#define g_currently_drawn_item RCT2_GLOBAL(0x009DE578, void*)
#define gEndOfPaintStructArray RCT2_GLOBAL(0x00EE7880, paint_entry *)
#define gPaintSpritePosition RCT2_GLOBAL(0x009DE568, LocationXY16)
#define gPaintInteractionType RCT2_GLOBAL(0x009DE570, uint8_t)
#define gSupportSegments RCT2_ADDRESS(0x0141E9B4, support_height)
#define gSupport RCT2_GLOBAL(0x0141E9D8, support_height)
#define gWoodenSupportsPrependTo RCT2_GLOBAL(0x009DEA58, paint_struct *)
#define gPaintMapPosition RCT2_GLOBAL(0x009DE574, LocationXY16)
#define gLeftTunnels RCT2_ADDRESS(0x009E3138, tunnel_entry)
#define gLeftTunnelCount RCT2_GLOBAL(0x0141F56A, uint8_t)
#define gRightTunnels RCT2_ADDRESS(0x009E30B6, tunnel_entry)
#define gRightTunnelCount RCT2_GLOBAL(0x0141F56B, uint8_t)
#define gVerticalTunnelHeight RCT2_GLOBAL(0x009E323C, uint8_t)
#define gSurfaceElement RCT2_GLOBAL(0x009E3250, rct_tile_element *)
#define gDidPassSurface RCT2_GLOBAL(0x009DE57C, bool)
#define g141E9DB RCT2_GLOBAL(0x0141E9DB, uint8_t)
#define gUnk141E9DC RCT2_GLOBAL(0x0141E9DC, uint16_t)
#define gTrackColours RCT2_ADDRESS(0x00F44198, uint32_t)
#define RCT2_CurrentViewportFlags RCT2_GLOBAL(0x0141E9E4, uint32_t)
#define RCT2_CurrentRotation RCT2_GLOBAL(0x0141E9E0, uint8_t)
#define RCT2_ScenarioTicks RCT2_GLOBAL(0x00F663AC, uint32_t)
#define RCT2_Rides RCT2_ADDRESS(0x013628F8, rct2_ride)
#define RCT2_Unk140E9A8 RCT2_GLOBAL(0x0140E9A8, rct_drawpixelinfo *)
#define RCT2_PaintBoundBoxOffsetX RCT2_GLOBAL(0x009DEA52, int16_t)
#define RCT2_PaintBoundBoxOffsetY RCT2_GLOBAL(0x009DEA54, int16_t)
#define RCT2_PaintBoundBoxOffsetZ RCT2_GLOBAL(0x009DEA56, int16_t)
#define gRideEntries RCT2_ADDRESS(0x009ACFA4, rct_ride_entry*)
#define gSupportSegments RCT2_ADDRESS(0x0141E9B4, support_height)
#define gWoodenSupportsPrependTo RCT2_GLOBAL(0x009DEA58, paint_struct*)
#define gPaintStructs RCT2_ADDRESS(0x00EE788C, paint_entry)
#define g_currently_drawn_item RCT2_GLOBAL(0x009DE578, void*)
#define gEndOfPaintStructArray RCT2_GLOBAL(0x00EE7880, paint_entry*)
#define gPaintSpritePosition RCT2_GLOBAL(0x009DE568, LocationXY16)
#define gPaintInteractionType RCT2_GLOBAL(0x009DE570, uint8_t)
#define gSupportSegments RCT2_ADDRESS(0x0141E9B4, support_height)
#define gSupport RCT2_GLOBAL(0x0141E9D8, support_height)
#define gWoodenSupportsPrependTo RCT2_GLOBAL(0x009DEA58, paint_struct*)
#define gPaintMapPosition RCT2_GLOBAL(0x009DE574, LocationXY16)
#define gLeftTunnels RCT2_ADDRESS(0x009E3138, tunnel_entry)
#define gLeftTunnelCount RCT2_GLOBAL(0x0141F56A, uint8_t)
#define gRightTunnels RCT2_ADDRESS(0x009E30B6, tunnel_entry)
#define gRightTunnelCount RCT2_GLOBAL(0x0141F56B, uint8_t)
#define gVerticalTunnelHeight RCT2_GLOBAL(0x009E323C, uint8_t)
#define gSurfaceElement RCT2_GLOBAL(0x009E3250, rct_tile_element*)
#define gDidPassSurface RCT2_GLOBAL(0x009DE57C, bool)
#define g141E9DB RCT2_GLOBAL(0x0141E9DB, uint8_t)
#define gUnk141E9DC RCT2_GLOBAL(0x0141E9DC, uint16_t)
#define gTrackColours RCT2_ADDRESS(0x00F44198, uint32_t)
#define RCT2_CurrentViewportFlags RCT2_GLOBAL(0x0141E9E4, uint32_t)
#define RCT2_CurrentRotation RCT2_GLOBAL(0x0141E9E0, uint8_t)
#define RCT2_ScenarioTicks RCT2_GLOBAL(0x00F663AC, uint32_t)
#define RCT2_Rides RCT2_ADDRESS(0x013628F8, rct2_ride)
#define RCT2_Unk140E9A8 RCT2_GLOBAL(0x0140E9A8, rct_drawpixelinfo*)
#define RCT2_PaintBoundBoxOffsetX RCT2_GLOBAL(0x009DEA52, int16_t)
#define RCT2_PaintBoundBoxOffsetY RCT2_GLOBAL(0x009DEA54, int16_t)
#define RCT2_PaintBoundBoxOffsetZ RCT2_GLOBAL(0x009DEA56, int16_t)
enum {
enum
{
TEST_SUCCESS,
TEST_FAILED,
TEST_SKIPPED,
@ -69,9 +71,10 @@ namespace TestPaint
void testIgnore(uint8_t direction, uint8_t trackSequence);
void testIgnoreAll();
bool testIsIgnored(uint8_t direction, uint8_t trackSequence);
}
} // namespace TestPaint
enum Verbosity {
enum Verbosity
{
QUIET,
NORMAL,
};

View File

@ -7,10 +7,8 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <string>
#include <vector>
#include "TestTrack.hpp"
#include "TestPaint.hpp"
#include "FunctionCall.hpp"
#include "GeneralSupportHeightCall.hpp"
#include "PaintIntercept.hpp"
@ -18,19 +16,24 @@
#include "SegmentSupportHeightCall.hpp"
#include "SideTunnelCall.hpp"
#include "String.hpp"
#include "TestTrack.hpp"
#include "TestPaint.hpp"
#include "Utils.hpp"
#include "VerticalTunnelCall.hpp"
#include <openrct2/paint/tile_element/Paint.TileElement.h>
#include <openrct2/paint/Supports.h>
#include <openrct2/paint/tile_element/Paint.TileElement.h>
#include <openrct2/ride/Ride.h>
#include <openrct2/ride/Track.h>
#include <openrct2/ride/TrackData.h>
#include <string>
#include <vector>
interface ITestTrackFilter {
interface ITestTrackFilter
{
public:
virtual ~ITestTrackFilter() {}
virtual ~ITestTrackFilter()
{
}
virtual bool AppliesTo(uint8_t rideType, uint8_t trackType) abstract;
@ -38,30 +41,43 @@ public:
virtual std::string VariantName(uint8_t rideType, uint8_t trackType, int variant) abstract;
virtual void ApplyTo(uint8_t rideType, uint8_t trackType, int variant,
rct_tile_element *tileElement, rct_tile_element *surfaceElement,
Ride *ride, rct_ride_entry *rideEntry
) abstract;
virtual void ApplyTo(
uint8_t rideType,
uint8_t trackType,
int variant,
rct_tile_element* tileElement,
rct_tile_element* surfaceElement,
Ride* ride,
rct_ride_entry* rideEntry) abstract;
};
class CableLiftFilter : public ITestTrackFilter {
class CableLiftFilter : public ITestTrackFilter
{
public:
bool AppliesTo(uint8_t rideType, uint8_t trackType) override {
bool AppliesTo(uint8_t rideType, uint8_t trackType) override
{
return rideType == RIDE_TYPE_GIGA_COASTER;
}
int Variations(uint8_t rideType, uint8_t trackType) override {
int Variations(uint8_t rideType, uint8_t trackType) override
{
return 2;
}
std::string VariantName(uint8_t rideType, uint8_t trackType, int variant) override {
std::string VariantName(uint8_t rideType, uint8_t trackType, int variant) override
{
return String::Format("cableLift:%d", variant);
}
virtual void ApplyTo(uint8_t rideType, uint8_t trackType, int variant,
rct_tile_element *tileElement, rct_tile_element *surfaceElement,
Ride *ride, rct_ride_entry *rideEntry
) override {
virtual void ApplyTo(
uint8_t rideType,
uint8_t trackType,
int variant,
rct_tile_element* tileElement,
rct_tile_element* surfaceElement,
Ride* ride,
rct_ride_entry* rideEntry) override
{
if (variant == 0)
{
track_element_clear_cable_lift(tileElement);
@ -73,56 +89,77 @@ public:
}
};
class ChainLiftFilter : public ITestTrackFilter {
class ChainLiftFilter : public ITestTrackFilter
{
public:
bool AppliesTo(uint8_t rideType, uint8_t trackType) override {
bool AppliesTo(uint8_t rideType, uint8_t trackType) override
{
return !ride_type_has_flag(rideType, RIDE_TYPE_FLAG_FLAT_RIDE);
}
int Variations(uint8_t rideType, uint8_t trackType) override {
int Variations(uint8_t rideType, uint8_t trackType) override
{
return 2;
}
std::string VariantName(uint8_t rideType, uint8_t trackType, int variant) override {
std::string VariantName(uint8_t rideType, uint8_t trackType, int variant) override
{
return String::Format("chainLift:%d", variant);
}
virtual void ApplyTo(uint8_t rideType, uint8_t trackType, int variant,
rct_tile_element *tileElement, rct_tile_element *surfaceElement,
Ride *ride, rct_ride_entry *rideEntry
) override {
if (variant == 0) {
virtual void ApplyTo(
uint8_t rideType,
uint8_t trackType,
int variant,
rct_tile_element* tileElement,
rct_tile_element* surfaceElement,
Ride* ride,
rct_ride_entry* rideEntry) override
{
if (variant == 0)
{
tileElement->type &= ~TRACK_ELEMENT_TYPE_FLAG_CHAIN_LIFT;
} else {
}
else
{
tileElement->type |= TRACK_ELEMENT_TYPE_FLAG_CHAIN_LIFT;
}
}
};
class InvertedFilter : public ITestTrackFilter {
class InvertedFilter : public ITestTrackFilter
{
public:
bool AppliesTo(uint8_t rideType, uint8_t trackType) override {
if (rideType == RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER ||
rideType == RIDE_TYPE_FLYING_ROLLER_COASTER ||
rideType == RIDE_TYPE_LAY_DOWN_ROLLER_COASTER) {
bool AppliesTo(uint8_t rideType, uint8_t trackType) override
{
if (rideType == RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER || rideType == RIDE_TYPE_FLYING_ROLLER_COASTER
|| rideType == RIDE_TYPE_LAY_DOWN_ROLLER_COASTER)
{
return true;
}
return false;
}
int Variations(uint8_t rideType, uint8_t trackType) override {
int Variations(uint8_t rideType, uint8_t trackType) override
{
return 2;
}
std::string VariantName(uint8_t rideType, uint8_t trackType, int variant) override {
std::string VariantName(uint8_t rideType, uint8_t trackType, int variant) override
{
return String::Format("inverted:%d", variant);
}
virtual void ApplyTo(uint8_t rideType, uint8_t trackType, int variant,
rct_tile_element *tileElement, rct_tile_element *surfaceElement,
Ride *ride, rct_ride_entry *rideEntry
) override {
virtual void ApplyTo(
uint8_t rideType,
uint8_t trackType,
int variant,
rct_tile_element* tileElement,
rct_tile_element* surfaceElement,
Ride* ride,
rct_ride_entry* rideEntry) override
{
if (variant == 0)
{
track_element_clear_cable_lift(tileElement);
@ -134,59 +171,65 @@ public:
}
};
class EntranceStyleFilter : public ITestTrackFilter {
class EntranceStyleFilter : public ITestTrackFilter
{
public:
bool AppliesTo(uint8_t rideType, uint8_t trackType) override {
if (trackType == TRACK_ELEM_BEGIN_STATION ||
trackType == TRACK_ELEM_MIDDLE_STATION ||
trackType == TRACK_ELEM_END_STATION) {
bool AppliesTo(uint8_t rideType, uint8_t trackType) override
{
if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION
|| trackType == TRACK_ELEM_END_STATION)
{
return true;
}
return false;
}
int Variations(uint8_t rideType, uint8_t trackType) override {
int Variations(uint8_t rideType, uint8_t trackType) override
{
return RIDE_ENTRANCE_STYLE_COUNT - 1;
}
std::string VariantName(uint8_t rideType, uint8_t trackType, int variant) override {
std::string VariantName(uint8_t rideType, uint8_t trackType, int variant) override
{
return String::Format("entranceStyle:%d", variant);
}
virtual void ApplyTo(uint8_t rideType, uint8_t trackType, int variant,
rct_tile_element *tileElement, rct_tile_element *surfaceElement,
Ride *ride, rct_ride_entry *rideEntry
) override {
virtual void ApplyTo(
uint8_t rideType,
uint8_t trackType,
int variant,
rct_tile_element* tileElement,
rct_tile_element* surfaceElement,
Ride* ride,
rct_ride_entry* rideEntry) override
{
ride->entrance_style = variant;
RCT2_Rides[0].entrance_style = variant;
}
};
static void CallOriginal(
uint8_t rideType,
uint8_t trackType,
uint8_t direction,
uint8_t trackSequence,
uint16_t height,
rct_tile_element *tileElement
) {
uint32_t *trackDirectionList = (uint32_t *) RideTypeTrackPaintFunctionsOld[rideType][trackType];
rct_tile_element* tileElement)
{
uint32_t* trackDirectionList = (uint32_t*)RideTypeTrackPaintFunctionsOld[rideType][trackType];
const uint8_t rideIndex = 0;
// Have to call from this point as it pushes esi and expects callee to pop it
RCT2_CALLPROC_X(
0x006C4934,
rideType,
(int) trackDirectionList,
(int)trackDirectionList,
direction,
height,
(int) tileElement,
(int)tileElement,
rideIndex * sizeof(Ride),
trackSequence
);
trackSequence);
}
static void CallNew(
@ -195,34 +238,40 @@ static void CallNew(
uint8_t direction,
uint8_t trackSequence,
uint16_t height,
rct_tile_element *tileElement
) {
rct_tile_element* tileElement)
{
TRACK_PAINT_FUNCTION_GETTER newPaintFunctionGetter = RideTypeTrackPaintFunctions[rideType];
TRACK_PAINT_FUNCTION newPaintFunction = newPaintFunctionGetter(trackType, direction);
newPaintFunction(&gPaintSession, 0, trackSequence, direction, height, tileElement);
}
using TestFunction = uint8_t (*)(uint8_t, uint8_t, uint8_t, std::string *);
using TestFunction = uint8_t (*)(uint8_t, uint8_t, uint8_t, std::string*);
static uint8_t TestTrackElementPaintCalls(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string *error);
static uint8_t TestTrackElementPaintCalls(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string* error);
static uint8_t TestTrackElementSegmentSupportHeight(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string *error);
static uint8_t
TestTrackElementSegmentSupportHeight(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string* error);
static uint8_t TestTrackElementGeneralSupportHeight(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string *error);
static uint8_t
TestTrackElementGeneralSupportHeight(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string* error);
static uint8_t TestTrackElementSideTunnels(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string *error);
static uint8_t TestTrackElementSideTunnels(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string* error);
static uint8_t TestTrackElementVerticalTunnels(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string *error);
static uint8_t TestTrackElementVerticalTunnels(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string* error);
uint8_t TestTrack::TestPaintTrackElement(uint8_t rideType, uint8_t trackType, std::string *out) {
if (!Utils::rideSupportsTrackType(rideType, trackType)) {
uint8_t TestTrack::TestPaintTrackElement(uint8_t rideType, uint8_t trackType, std::string* out)
{
if (!Utils::rideSupportsTrackType(rideType, trackType))
{
return TEST_FAILED;
}
if (rideType == RIDE_TYPE_CHAIRLIFT) {
if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION ||
trackType == TRACK_ELEM_END_STATION) {
if (rideType == RIDE_TYPE_CHAIRLIFT)
{
if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION
|| trackType == TRACK_ELEM_END_STATION)
{
// These rides check neighbouring tiles for tracks
return TEST_SKIPPED;
}
@ -234,18 +283,18 @@ uint8_t TestTrack::TestPaintTrackElement(uint8_t rideType, uint8_t trackType, st
uint8_t retVal = TEST_SUCCESS;
static TestFunction functions[] = {
TestTrackElementPaintCalls,
TestTrackElementSegmentSupportHeight,
TestTrackElementGeneralSupportHeight,
TestTrackElementSideTunnels,
TestTrackElementVerticalTunnels,
TestTrackElementPaintCalls, TestTrackElementSegmentSupportHeight, TestTrackElementGeneralSupportHeight,
TestTrackElementSideTunnels, TestTrackElementVerticalTunnels,
};
for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) {
for (auto &&function : functions) {
for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++)
{
for (auto&& function : functions)
{
retVal = function(rideType, trackType, trackSequence, &error);
if (retVal != TEST_SUCCESS) {
if (retVal != TEST_SUCCESS)
{
*out += error + "\n";
return retVal;
}
@ -255,7 +304,8 @@ uint8_t TestTrack::TestPaintTrackElement(uint8_t rideType, uint8_t trackType, st
return retVal;
}
static uint8_t TestTrackElementPaintCalls(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string *error) {
static uint8_t TestTrackElementPaintCalls(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string* error)
{
uint16_t height = 3 * 16;
rct_tile_element tileElement = {};
@ -286,16 +336,18 @@ static uint8_t TestTrackElementPaintCalls(uint8_t rideType, uint8_t trackType, u
// TODO: test underground (Wooden RC)
// TODO: test station fences
std::vector<ITestTrackFilter *> filters;
std::vector<ITestTrackFilter*> filters;
filters.push_back(new CableLiftFilter());
filters.push_back(new ChainLiftFilter());
filters.push_back(new InvertedFilter());
filters.push_back(new EntranceStyleFilter());
std::vector<ITestTrackFilter *> activeFilters;
std::vector<ITestTrackFilter*> activeFilters;
for (auto &&filter : filters) {
if (filter->AppliesTo(rideType, trackType)) {
for (auto&& filter : filters)
{
if (filter->AppliesTo(rideType, trackType))
{
activeFilters.push_back(filter);
}
}
@ -306,13 +358,16 @@ static uint8_t TestTrackElementPaintCalls(uint8_t rideType, uint8_t trackType, u
std::vector<std::vector<uint8_t>> argumentPermutations;
argumentPermutations.push_back(filler);
for (size_t filterIndex = 0; filterIndex < activeFilters.size(); ++filterIndex) {
ITestTrackFilter *filter = activeFilters[filterIndex];
for (size_t filterIndex = 0; filterIndex < activeFilters.size(); ++filterIndex)
{
ITestTrackFilter* filter = activeFilters[filterIndex];
uint8_t variantCount = filter->Variations(rideType, trackType);
std::vector<std::vector<uint8_t>> newArgumentPermutations;
for (int variant = 0; variant < variantCount; variant++) {
for (auto &&oldPermutation : argumentPermutations) {
for (int variant = 0; variant < variantCount; variant++)
{
for (auto&& oldPermutation : argumentPermutations)
{
std::vector<uint8_t> permutation;
permutation.insert(permutation.begin(), oldPermutation.begin(), oldPermutation.end());
permutation.push_back(variant);
@ -321,34 +376,40 @@ static uint8_t TestTrackElementPaintCalls(uint8_t rideType, uint8_t trackType, u
}
argumentPermutations.clear();
argumentPermutations.insert(argumentPermutations.begin(), newArgumentPermutations.begin(),
newArgumentPermutations.end());
argumentPermutations.insert(
argumentPermutations.begin(), newArgumentPermutations.begin(), newArgumentPermutations.end());
}
for (auto &&arguments : argumentPermutations) {
for (auto&& arguments : argumentPermutations)
{
std::string baseCaseName = "[";
for (size_t filterIndex = 0; filterIndex < activeFilters.size(); ++filterIndex) {
uint8_t &variant = arguments[1 + filterIndex];
for (size_t filterIndex = 0; filterIndex < activeFilters.size(); ++filterIndex)
{
uint8_t& variant = arguments[1 + filterIndex];
baseCaseName += activeFilters[filterIndex]->VariantName(rideType, trackType, variant);
baseCaseName += " ";
activeFilters[filterIndex]->ApplyTo(rideType, trackType, variant, &tileElement, &surfaceElement, &(gRideList[0]), gRideEntries[0]);
activeFilters[filterIndex]->ApplyTo(
rideType, trackType, variant, &tileElement, &surfaceElement, &(gRideList[0]), gRideEntries[0]);
}
for (int currentRotation = 0; currentRotation < 4; currentRotation++) {
for (int currentRotation = 0; currentRotation < 4; currentRotation++)
{
gCurrentRotation = currentRotation;
RCT2_CurrentRotation = currentRotation;
gPaintSession.CurrentRotation = currentRotation;
for (int direction = 0; direction < 4; direction++) {
for (int direction = 0; direction < 4; direction++)
{
RCT2_GLOBAL(0x009DE56A, int16_t) = 64; // x
RCT2_GLOBAL(0x009DE56E, int16_t) = 64; // y
std::string caseName = String::Format(
"%srotation:%d direction:%d trackSequence:%d]",
baseCaseName.c_str(), currentRotation, direction, trackSequence
);
baseCaseName.c_str(),
currentRotation,
direction,
trackSequence);
PaintIntercept::ClearCalls();
TestPaint::ResetSupportHeights();
@ -367,7 +428,8 @@ static uint8_t TestTrackElementPaintCalls(uint8_t rideType, uint8_t trackType, u
CallNew(rideType, trackType, direction, trackSequence, height, &tileElement);
if (TestPaint::testIsIgnored(direction, trackSequence)) {
if (TestPaint::testIsIgnored(direction, trackSequence))
{
*error += String::Format("[ IGNORED ] %s\n", caseName.c_str());
continue;
}
@ -377,18 +439,23 @@ static uint8_t TestTrackElementPaintCalls(uint8_t rideType, uint8_t trackType, u
newCalls.insert(newCalls.begin(), callBuffer, callBuffer + callCount);
bool sucess = true;
if (oldCalls.size() != newCalls.size()) {
if (oldCalls.size() != newCalls.size())
{
*error += String::Format(
"Call counts don't match (was %d, expected %d). %s\n",
newCalls.size(), oldCalls.size(), caseName.c_str()
);
newCalls.size(),
oldCalls.size(),
caseName.c_str());
sucess = false;
} else if (!FunctionCall::AssertsEquals(oldCalls, newCalls)) {
}
else if (!FunctionCall::AssertsEquals(oldCalls, newCalls))
{
*error += String::Format("Calls don't match. %s\n", caseName.c_str());
sucess = false;
}
if (!sucess) {
if (!sucess)
{
*error += " Expected:\n";
*error += Printer::PrintFunctionCalls(oldCalls, height);
*error += " Actual:\n";
@ -403,7 +470,9 @@ static uint8_t TestTrackElementPaintCalls(uint8_t rideType, uint8_t trackType, u
return TEST_SUCCESS;
}
static uint8_t TestTrackElementSegmentSupportHeight(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string *error) {
static uint8_t
TestTrackElementSegmentSupportHeight(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string* error)
{
uint16_t height = 3 * 16;
rct_tile_element tileElement = {};
@ -411,7 +480,7 @@ static uint8_t TestTrackElementSegmentSupportHeight(uint8_t rideType, uint8_t tr
track_element_set_type(&tileElement, trackType);
tileElement.base_height = height / 16;
g_currently_drawn_item = &tileElement;
rct_tile_element surfaceElement = {};
surfaceElement.type = TILE_ELEMENT_TYPE_SURFACE;
surfaceElement.base_height = 2;
@ -433,7 +502,8 @@ static uint8_t TestTrackElementSegmentSupportHeight(uint8_t rideType, uint8_t tr
std::vector<SegmentSupportCall> tileSegmentSupportCalls[4];
for (int direction = 0; direction < 4; direction++) {
for (int direction = 0; direction < 4; direction++)
{
TestPaint::ResetSupportHeights();
CallOriginal(rideType, trackType, direction, trackSequence, height, &tileElement);
@ -443,11 +513,14 @@ static uint8_t TestTrackElementSegmentSupportHeight(uint8_t rideType, uint8_t tr
std::vector<SegmentSupportCall> referenceCalls = tileSegmentSupportCalls[0];
if (!SegmentSupportHeightCall::CallsMatch(tileSegmentSupportCalls)) {
if (!SegmentSupportHeightCall::CallsMatch(tileSegmentSupportCalls))
{
bool success = SegmentSupportHeightCall::FindMostCommonSupportCall(tileSegmentSupportCalls, &referenceCalls);
if (!success) {
if (!success)
{
*error += String::Format("Original segment calls didn't match. %s\n", state.c_str());
for (int direction = 0; direction < 4; direction++) {
for (int direction = 0; direction < 4; direction++)
{
*error += String::Format("# %d\n", direction);
*error += Printer::PrintSegmentSupportHeightCalls(tileSegmentSupportCalls[direction]);
}
@ -455,21 +528,22 @@ static uint8_t TestTrackElementSegmentSupportHeight(uint8_t rideType, uint8_t tr
}
}
for (int direction = 0; direction < 4; direction++) {
for (int direction = 0; direction < 4; direction++)
{
TestPaint::ResetSupportHeights();
TestPaint::testClearIgnore();
CallNew(rideType, trackType, direction, trackSequence, height, &tileElement);
if (TestPaint::testIsIgnored(direction, trackSequence)) {
if (TestPaint::testIsIgnored(direction, trackSequence))
{
continue;
}
std::vector<SegmentSupportCall> newCalls = SegmentSupportHeightCall::getSegmentCalls(gPaintSession.SupportSegments, direction);
if (!SegmentSupportHeightCall::CallsEqual(referenceCalls, newCalls)) {
*error += String::Format(
"Segment support heights didn't match. [direction:%d] %s\n",
direction, state.c_str()
);
std::vector<SegmentSupportCall> newCalls
= SegmentSupportHeightCall::getSegmentCalls(gPaintSession.SupportSegments, direction);
if (!SegmentSupportHeightCall::CallsEqual(referenceCalls, newCalls))
{
*error += String::Format("Segment support heights didn't match. [direction:%d] %s\n", direction, state.c_str());
*error += " Expected:\n";
*error += Printer::PrintSegmentSupportHeightCalls(referenceCalls);
*error += " Actual:\n";
@ -482,7 +556,9 @@ static uint8_t TestTrackElementSegmentSupportHeight(uint8_t rideType, uint8_t tr
return TEST_SUCCESS;
}
static uint8_t TestTrackElementGeneralSupportHeight(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string *error) {
static uint8_t
TestTrackElementGeneralSupportHeight(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string* error)
{
uint16_t height = 3 * 16;
rct_tile_element tileElement = {};
@ -511,27 +587,33 @@ static uint8_t TestTrackElementGeneralSupportHeight(uint8_t rideType, uint8_t tr
std::string state = String::Format("[trackSequence:%d chainLift:%d]", trackSequence, 0);
SupportCall tileGeneralSupportCalls[4];
for (int direction = 0; direction < 4; direction++) {
for (int direction = 0; direction < 4; direction++)
{
TestPaint::ResetSupportHeights();
CallOriginal(rideType, trackType, direction, trackSequence, height, &tileElement);
tileGeneralSupportCalls[direction].height = -1;
tileGeneralSupportCalls[direction].slope = -1;
if (gSupport.height != 0) {
if (gSupport.height != 0)
{
tileGeneralSupportCalls[direction].height = gSupport.height;
}
if (gSupport.slope != 0xFF) {
if (gSupport.slope != 0xFF)
{
tileGeneralSupportCalls[direction].slope = gSupport.slope;
}
}
SupportCall referenceCall = tileGeneralSupportCalls[0];
if (!GeneralSupportHeightCall::CallsMatch(tileGeneralSupportCalls)) {
if (!GeneralSupportHeightCall::CallsMatch(tileGeneralSupportCalls))
{
bool success = GeneralSupportHeightCall::FindMostCommonSupportCall(tileGeneralSupportCalls, &referenceCall);
if (!success) {
if (!success)
{
*error += String::Format("Original support calls didn't match. %s\n", state.c_str());
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4; ++i)
{
*error += String::Format("[%d, 0x%02X] ", tileGeneralSupportCalls[i].height, tileGeneralSupportCalls[i].slope);
}
*error += "\n";
@ -539,37 +621,40 @@ static uint8_t TestTrackElementGeneralSupportHeight(uint8_t rideType, uint8_t tr
}
}
for (int direction = 0; direction < 4; direction++) {
for (int direction = 0; direction < 4; direction++)
{
TestPaint::ResetSupportHeights();
TestPaint::testClearIgnore();
CallNew(rideType, trackType, direction, trackSequence, height, &tileElement);
if (TestPaint::testIsIgnored(direction, trackSequence)) {
if (TestPaint::testIsIgnored(direction, trackSequence))
{
continue;
}
if (referenceCall.height != -1) {
if (gPaintSession.Support.height != referenceCall.height) {
if (referenceCall.height != -1)
{
if (gPaintSession.Support.height != referenceCall.height)
{
*error += String::Format(
"General support heights didn't match. (expected height + %d, actual: height + %d) [direction:%d] %s\n",
referenceCall.height - height,
gPaintSession.Support.height - height,
direction,
state.c_str()
);
state.c_str());
return TEST_FAILED;
}
}
if (referenceCall.slope != -1) {
if (gPaintSession.Support.slope != referenceCall.slope) {
if (referenceCall.slope != -1)
{
if (gPaintSession.Support.slope != referenceCall.slope)
{
*error += String::Format(
"General support slopes didn't match. (expected 0x%02X, actual: 0x%02X) [direction:%d] %s\n",
referenceCall.slope,
gPaintSession.Support.slope,
direction,
state.c_str()
);
state.c_str());
return TEST_FAILED;
}
}
@ -578,7 +663,8 @@ static uint8_t TestTrackElementGeneralSupportHeight(uint8_t rideType, uint8_t tr
return TEST_SUCCESS;
}
static uint8_t TestTrackElementSideTunnels(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string *error) {
static uint8_t TestTrackElementSideTunnels(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string* error)
{
uint16_t height = 3 * 16;
rct_tile_element tileElement = {};
@ -604,40 +690,46 @@ static uint8_t TestTrackElementSideTunnels(uint8_t rideType, uint8_t trackType,
// TODO: test inverted tracks
for (int direction = 0; direction < 4; direction++) {
for (int direction = 0; direction < 4; direction++)
{
TestPaint::ResetTunnels();
for (int8_t offset = -8; offset <= 8; offset += 8) {
for (int8_t offset = -8; offset <= 8; offset += 8)
{
CallOriginal(rideType, trackType, direction, trackSequence, height + offset, &tileElement);
}
uint8_t rightIndex = (direction + 1) % 4;
uint8_t leftIndex = direction;
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4; ++i)
{
tileTunnelCalls[direction][i].call = TUNNELCALL_SKIPPED;
}
bool err = false;
tileTunnelCalls[direction][rightIndex] = SideTunnelCall::ExtractTunnelCalls(gRightTunnels, gRightTunnelCount, height,
&err);
tileTunnelCalls[direction][rightIndex]
= SideTunnelCall::ExtractTunnelCalls(gRightTunnels, gRightTunnelCount, height, &err);
tileTunnelCalls[direction][leftIndex] = SideTunnelCall::ExtractTunnelCalls(gLeftTunnels, gLeftTunnelCount, height,
&err);
tileTunnelCalls[direction][leftIndex]
= SideTunnelCall::ExtractTunnelCalls(gLeftTunnels, gLeftTunnelCount, height, &err);
if (err) {
if (err)
{
*error += "Multiple tunnels on one side aren't supported.\n";
return TEST_FAILED;
}
}
TunnelCall newTileTunnelCalls[4][4];
for (int direction = 0; direction < 4; direction++) {
for (int direction = 0; direction < 4; direction++)
{
TestPaint::ResetTunnels();
TestPaint::testClearIgnore();
for (int8_t offset = -8; offset <= 8; offset += 8) {
for (int8_t offset = -8; offset <= 8; offset += 8)
{
// TODO: move tunnel pushing to interface so we don't have to check the output 3 times
CallNew(rideType, trackType, direction, trackSequence, height + offset, &tileElement);
}
@ -645,29 +737,32 @@ static uint8_t TestTrackElementSideTunnels(uint8_t rideType, uint8_t trackType,
uint8_t rightIndex = (direction + 1) % 4;
uint8_t leftIndex = direction;
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4; ++i)
{
newTileTunnelCalls[direction][i].call = TUNNELCALL_SKIPPED;
}
bool err = false;
newTileTunnelCalls[direction][rightIndex] = SideTunnelCall::ExtractTunnelCalls(gPaintSession.RightTunnels, gPaintSession.RightTunnelCount, height, &err);
newTileTunnelCalls[direction][leftIndex] = SideTunnelCall::ExtractTunnelCalls(gPaintSession.LeftTunnels, gPaintSession.LeftTunnelCount, height, &err);
if (err) {
newTileTunnelCalls[direction][rightIndex]
= SideTunnelCall::ExtractTunnelCalls(gPaintSession.RightTunnels, gPaintSession.RightTunnelCount, height, &err);
newTileTunnelCalls[direction][leftIndex]
= SideTunnelCall::ExtractTunnelCalls(gPaintSession.LeftTunnels, gPaintSession.LeftTunnelCount, height, &err);
if (err)
{
*error += "Multiple tunnels on one side aren't supported.\n";
return TEST_FAILED;
}
}
if (!SideTunnelCall::TunnelCallsLineUp(tileTunnelCalls)) {
if (!SideTunnelCall::TunnelCallsLineUp(tileTunnelCalls))
{
// TODO: Check that new pattern uses the same tunnel group (round, big round, etc.)
*error += String::Format(
"Original tunnel calls don\'t line up. Skipping tunnel validation [trackSequence:%d].\n",
trackSequence
);
"Original tunnel calls don\'t line up. Skipping tunnel validation [trackSequence:%d].\n", trackSequence);
*error += Printer::PrintSideTunnelCalls(tileTunnelCalls);
if (!SideTunnelCall::TunnelCallsLineUp(newTileTunnelCalls)) {
if (!SideTunnelCall::TunnelCallsLineUp(newTileTunnelCalls))
{
*error += String::Format("Decompiled tunnel calls don\'t line up. [trackSequence:%d].\n", trackSequence);
*error += Printer::PrintSideTunnelCalls(newTileTunnelCalls);
return TEST_FAILED;
@ -682,7 +777,8 @@ static uint8_t TestTrackElementSideTunnels(uint8_t rideType, uint8_t trackType,
TunnelCall actualPattern[4];
SideTunnelCall::GetTunnelCallReferencePattern(newTileTunnelCalls, &actualPattern);
if (!SideTunnelCall::TunnelPatternsMatch(referencePattern, actualPattern)) {
if (!SideTunnelCall::TunnelPatternsMatch(referencePattern, actualPattern))
{
*error += String::Format("Tunnel calls don't match expected pattern. [trackSequence:%d]\n", trackSequence);
*error += " Expected:\n";
*error += Printer::PrintSideTunnelCalls(tileTunnelCalls);
@ -694,7 +790,8 @@ static uint8_t TestTrackElementSideTunnels(uint8_t rideType, uint8_t trackType,
return TEST_SUCCESS;
}
static uint8_t TestTrackElementVerticalTunnels(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string *error) {
static uint8_t TestTrackElementVerticalTunnels(uint8_t rideType, uint8_t trackType, uint8_t trackSequence, std::string* error)
{
uint16_t height = 3 * 16;
rct_tile_element tileElement = {};
@ -718,10 +815,12 @@ static uint8_t TestTrackElementVerticalTunnels(uint8_t rideType, uint8_t trackTy
uint16_t verticalTunnelHeights[4];
for (int direction = 0; direction < 4; direction++) {
uint8_t tunnelHeights[3] = {0};
for (int direction = 0; direction < 4; direction++)
{
uint8_t tunnelHeights[3] = { 0 };
for (uint8_t i = 0; i < 3; i++) {
for (uint8_t i = 0; i < 3; i++)
{
gVerticalTunnelHeight = 0;
CallOriginal(rideType, trackType, direction, trackSequence, height - 8 + i * 8, &tileElement);
tunnelHeights[i] = gVerticalTunnelHeight;
@ -730,34 +829,35 @@ static uint8_t TestTrackElementVerticalTunnels(uint8_t rideType, uint8_t trackTy
verticalTunnelHeights[direction] = VerticalTunnelCall::GetTunnelHeight(height, tunnelHeights);
}
if (!VerticalTunnelCall::HeightIsConsistent(verticalTunnelHeights)) {
if (!VerticalTunnelCall::HeightIsConsistent(verticalTunnelHeights))
{
*error += String::Format(
"Original vertical tunnel height is inconsistent, skipping test. [trackSequence:%d]\n",
trackSequence
);
"Original vertical tunnel height is inconsistent, skipping test. [trackSequence:%d]\n", trackSequence);
return TEST_SUCCESS;
}
uint16_t referenceHeight = verticalTunnelHeights[0];
for (int direction = 0; direction < 4; direction++) {
for (int direction = 0; direction < 4; direction++)
{
TestPaint::testClearIgnore();
testPaintVerticalTunnelHeight = 0;
CallNew(rideType, trackType, direction, trackSequence, height, &tileElement);
if (TestPaint::testIsIgnored(direction, trackSequence)) {
if (TestPaint::testIsIgnored(direction, trackSequence))
{
continue;
}
if (testPaintVerticalTunnelHeight != referenceHeight) {
if (referenceHeight == 0) {
if (testPaintVerticalTunnelHeight != referenceHeight)
{
if (referenceHeight == 0)
{
*error += String::Format(
"Expected no tunnel. Actual: %s [trackSequence:%d]\n",
Printer::PrintHeightOffset(testPaintVerticalTunnelHeight, height).c_str(),
trackSequence
);
trackSequence);
return TEST_FAILED;
}
@ -766,8 +866,7 @@ static uint8_t TestTrackElementVerticalTunnels(uint8_t rideType, uint8_t trackTy
Printer::PrintHeightOffset(referenceHeight, height).c_str(),
Printer::PrintHeightOffset(testPaintVerticalTunnelHeight, height).c_str(),
trackSequence,
direction
);
direction);
return TEST_FAILED;
}

View File

@ -9,11 +9,11 @@
#pragma once
#include <openrct2/common.h>
#include <string>
#include <openrct2/common.h>
class TestTrack {
class TestTrack
{
public:
static uint8_t TestPaintTrackElement(uint8_t rideType, uint8_t trackType, std::string *out);
static uint8_t TestPaintTrackElement(uint8_t rideType, uint8_t trackType, std::string* out);
};

View File

@ -13,19 +13,26 @@
#include <openrct2/ride/Track.h>
#include <openrct2/ride/TrackData.h>
namespace Utils {
int getTrackSequenceCount(uint8_t rideType, uint8_t trackType) {
namespace Utils
{
int getTrackSequenceCount(uint8_t rideType, uint8_t trackType)
{
int sequenceCount = 0;
const rct_preview_track **trackBlocks;
const rct_preview_track** trackBlocks;
if (ride_type_has_flag(rideType, RIDE_TYPE_FLAG_FLAT_RIDE)) {
if (ride_type_has_flag(rideType, RIDE_TYPE_FLAG_FLAT_RIDE))
{
trackBlocks = FlatRideTrackBlocks;
} else {
}
else
{
trackBlocks = TrackBlocks;
}
for (int i = 0; i < 256; i++) {
if (trackBlocks[trackType][i].index == 0xFF) {
for (int i = 0; i < 256; i++)
{
if (trackBlocks[trackType][i].index == 0xFF)
{
break;
}
@ -35,26 +42,31 @@ namespace Utils {
return sequenceCount;
}
bool rideSupportsTrackType(uint8_t rideType, uint8_t trackType) {
bool rideSupportsTrackType(uint8_t rideType, uint8_t trackType)
{
TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType];
if (newPaintGetter == nullptr) {
if (newPaintGetter == nullptr)
{
return false;
}
if (newPaintGetter(trackType, 0) == nullptr) {
if (newPaintGetter(trackType, 0) == nullptr)
{
return false;
}
if (RideTypeTrackPaintFunctionsOld[rideType][trackType] == 0) {
if (RideTypeTrackPaintFunctionsOld[rideType][trackType] == 0)
{
return false;
}
return true;
}
bool rideIsImplemented(uint8_t rideType) {
bool rideIsImplemented(uint8_t rideType)
{
TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType];
return (newPaintGetter != 0);
}
}
} // namespace Utils

View File

@ -11,8 +11,9 @@
#include <openrct2/common.h>
namespace Utils {
namespace Utils
{
int getTrackSequenceCount(uint8_t rideType, uint8_t trackType);
bool rideSupportsTrackType(uint8_t rideType, uint8_t trackType);
bool rideIsImplemented(uint8_t rideType);
}
} // namespace Utils

View File

@ -9,15 +9,21 @@
#include "VerticalTunnelCall.hpp"
uint16_t VerticalTunnelCall::GetTunnelHeight(uint16_t baseHeight, uint8_t *calls) {
if (calls[0] == 0 && calls[1] == 0 && calls[2] == 0) {
uint16_t VerticalTunnelCall::GetTunnelHeight(uint16_t baseHeight, uint8_t* calls)
{
if (calls[0] == 0 && calls[1] == 0 && calls[2] == 0)
{
return 0;
}
for (int16_t offset = 0; offset <= 256; offset += 8) {
if (calls[0] != (baseHeight - 8 + offset) / 16) continue;
if (calls[1] != (baseHeight + 0 + offset) / 16) continue;
if (calls[2] != (baseHeight + 8 + offset) / 16) continue;
for (int16_t offset = 0; offset <= 256; offset += 8)
{
if (calls[0] != (baseHeight - 8 + offset) / 16)
continue;
if (calls[1] != (baseHeight + 0 + offset) / 16)
continue;
if (calls[2] != (baseHeight + 8 + offset) / 16)
continue;
return baseHeight + offset;
}
@ -26,9 +32,12 @@ uint16_t VerticalTunnelCall::GetTunnelHeight(uint16_t baseHeight, uint8_t *calls
return 0;
}
bool VerticalTunnelCall::HeightIsConsistent(uint16_t *heights) {
for (int i = 1; i < 4; ++i) {
if (heights[i] != heights[0]) return false;
bool VerticalTunnelCall::HeightIsConsistent(uint16_t* heights)
{
for (int i = 1; i < 4; ++i)
{
if (heights[i] != heights[0])
return false;
}
return true;

View File

@ -11,7 +11,8 @@
#include <openrct2/common.h>
namespace VerticalTunnelCall {
uint16_t GetTunnelHeight(uint16_t baseHeight, uint8_t *calls);
bool HeightIsConsistent(uint16_t *heights);
};
namespace VerticalTunnelCall
{
uint16_t GetTunnelHeight(uint16_t baseHeight, uint8_t* calls);
bool HeightIsConsistent(uint16_t* heights);
}; // namespace VerticalTunnelCall

View File

@ -7,12 +7,7 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <algorithm>
#include <cstdarg>
#include <cstring>
#include <string>
#include <vector>
#include "Data.h"
#include "FunctionCall.hpp"
#include "PaintIntercept.hpp"
#include "SegmentSupportHeightCall.hpp"
@ -20,13 +15,17 @@
#include "String.hpp"
#include "Utils.hpp"
#include "Data.h"
#include <algorithm>
#include <cstdarg>
#include <cstring>
#include <openrct2/interface/Viewport.h>
#include <openrct2/rct2/RCT2.h>
#include <openrct2/ride/Ride.h>
#include <openrct2/ride/RideData.h>
#include <openrct2/ride/Track.h>
#include <openrct2/ride/TrackData.h>
#include <string>
#include <vector>
class PaintCodeGenerator
{
@ -34,7 +33,7 @@ public:
int Generate(uint8_t rideType)
{
auto filename = "paint_" + std::to_string(rideType) + ".c";
FILE * file = fopen(filename.c_str(), "w");
FILE* file = fopen(filename.c_str(), "w");
if (file == nullptr)
{
fprintf(stderr, "Unable to save to ./%s\n", filename.c_str());
@ -52,11 +51,11 @@ public:
private:
std::string _rideName;
uint8_t _rideType;
FILE * _file;
uint8_t _rideType;
FILE* _file;
bool _conditionalSupports;
bool _invertedTrack;
bool _conditionalSupports;
bool _invertedTrack;
void Generate()
{
@ -88,8 +87,7 @@ private:
void GenerateIncludes()
{
const char * includes[] =
{
const char* includes[] = {
"../../drawing/Drawing.h",
"../../paint/supports.h",
"../../interface/Viewport.h",
@ -121,9 +119,18 @@ private:
if (trackType == TRACK_ELEM_END_STATION)
{
const uint32_t * paintFunctionList = RideTypeTrackPaintFunctionsOld[_rideType];
WriteLine(0, "/** rct2: 0x%08X, 0x%08X, 0x%08X */", paintFunctionList[TRACK_ELEM_END_STATION], paintFunctionList[TRACK_ELEM_BEGIN_STATION], paintFunctionList[TRACK_ELEM_MIDDLE_STATION]);
WriteLine(0, "static void " + _rideName + "_track_station(uint8_t rideIndex, uint8_t trackSequence, uint8_t direction, int height, rct_tile_element * tileElement)");
const uint32_t* paintFunctionList = RideTypeTrackPaintFunctionsOld[_rideType];
WriteLine(
0,
"/** rct2: 0x%08X, 0x%08X, 0x%08X */",
paintFunctionList[TRACK_ELEM_END_STATION],
paintFunctionList[TRACK_ELEM_BEGIN_STATION],
paintFunctionList[TRACK_ELEM_MIDDLE_STATION]);
WriteLine(
0,
"static void " + _rideName
+ "_track_station(uint8_t rideIndex, uint8_t trackSequence, uint8_t direction, int height, "
"rct_tile_element * tileElement)");
WriteLine(0, "{");
WriteLine(0, "}");
WriteLine();
@ -134,13 +141,15 @@ private:
void GenerateTrackFunction(int trackType)
{
WriteLine(0, "/** rct2: 0x%08X */", RideTypeTrackPaintFunctionsOld[_rideType][trackType]);
WriteLine(0, "static void " + GetTrackFunctionName(trackType) + "(uint8_t rideIndex, uint8_t trackSequence, uint8_t direction, int height, rct_tile_element * tileElement)");
WriteLine(
0,
"static void " + GetTrackFunctionName(trackType)
+ "(uint8_t rideIndex, uint8_t trackSequence, uint8_t direction, int height, rct_tile_element * tileElement)");
WriteLine(0, "{");
if (!GenerateMirrorCall(1, trackType))
{
if (_rideType == RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER ||
_rideType == RIDE_TYPE_FLYING_ROLLER_COASTER ||
_rideType == RIDE_TYPE_LAY_DOWN_ROLLER_COASTER)
if (_rideType == RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER || _rideType == RIDE_TYPE_FLYING_ROLLER_COASTER
|| _rideType == RIDE_TYPE_LAY_DOWN_ROLLER_COASTER)
{
WriteLine(1, "if (!track_element_is_inverted(tileElement)) {");
_invertedTrack = false;
@ -210,10 +219,18 @@ private:
{ 0, TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_25_DEG_DOWN, TRACK_ELEM_25_DEG_UP_TO_RIGHT_BANKED_25_DEG_UP },
{ 0, TRACK_ELEM_25_DEG_DOWN_TO_RIGHT_BANKED_25_DEG_DOWN, TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_25_DEG_UP },
{ 0, TRACK_ELEM_25_DEG_DOWN_TO_LEFT_BANKED_25_DEG_DOWN, TRACK_ELEM_RIGHT_BANKED_25_DEG_UP_TO_25_DEG_UP },
{ 0, TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_RIGHT_BANKED_FLAT, TRACK_ELEM_LEFT_BANKED_FLAT_TO_LEFT_BANKED_25_DEG_UP },
{ 0, TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_LEFT_BANKED_FLAT, TRACK_ELEM_RIGHT_BANKED_FLAT_TO_RIGHT_BANKED_25_DEG_UP },
{ 0, TRACK_ELEM_RIGHT_BANKED_FLAT_TO_RIGHT_BANKED_25_DEG_DOWN, TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_LEFT_BANKED_FLAT },
{ 0, TRACK_ELEM_LEFT_BANKED_FLAT_TO_LEFT_BANKED_25_DEG_DOWN, TRACK_ELEM_RIGHT_BANKED_25_DEG_UP_TO_RIGHT_BANKED_FLAT },
{ 0,
TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_RIGHT_BANKED_FLAT,
TRACK_ELEM_LEFT_BANKED_FLAT_TO_LEFT_BANKED_25_DEG_UP },
{ 0,
TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_LEFT_BANKED_FLAT,
TRACK_ELEM_RIGHT_BANKED_FLAT_TO_RIGHT_BANKED_25_DEG_UP },
{ 0,
TRACK_ELEM_RIGHT_BANKED_FLAT_TO_RIGHT_BANKED_25_DEG_DOWN,
TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_LEFT_BANKED_FLAT },
{ 0,
TRACK_ELEM_LEFT_BANKED_FLAT_TO_LEFT_BANKED_25_DEG_DOWN,
TRACK_ELEM_RIGHT_BANKED_25_DEG_UP_TO_RIGHT_BANKED_FLAT },
{ 0, TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_FLAT, TRACK_ELEM_FLAT_TO_LEFT_BANKED_25_DEG_UP },
{ 0, TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_FLAT, TRACK_ELEM_FLAT_TO_RIGHT_BANKED_25_DEG_UP },
{ 0, TRACK_ELEM_FLAT_TO_RIGHT_BANKED_25_DEG_DOWN, TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_FLAT },
@ -223,17 +240,25 @@ private:
{ 1, TRACK_ELEM_BANKED_RIGHT_QUARTER_TURN_5_TILES, TRACK_ELEM_BANKED_LEFT_QUARTER_TURN_5_TILES },
{ 1, TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_DOWN, TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_UP },
{ 1, TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_COVERED, TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_COVERED },
{ 1, TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_5_TILE_25_DEG_DOWN, TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_5_TILE_25_DEG_UP },
{ 1,
TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_5_TILE_25_DEG_DOWN,
TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_5_TILE_25_DEG_UP },
{ 2, TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_DOWN, TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_UP },
{ 2, TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_5_TILE_25_DEG_DOWN, TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_5_TILE_25_DEG_UP },
{ 2,
TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_5_TILE_25_DEG_DOWN,
TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_5_TILE_25_DEG_UP },
{ 3, TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES, TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES },
{ 3, TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_BANK, TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_BANK },
{ 3, TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN, TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP },
{ 3, TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_COVERED, TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_COVERED },
{ 3, TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_3_TILE_25_DEG_DOWN, TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_3_TILE_25_DEG_UP },
{ 3,
TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_3_TILE_25_DEG_DOWN,
TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_3_TILE_25_DEG_UP },
{ 4, TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN, TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP },
{ 4, TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_3_TILE_25_DEG_DOWN, TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_3_TILE_25_DEG_UP },
{ 4,
TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_3_TILE_25_DEG_DOWN,
TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_3_TILE_25_DEG_UP },
{ 5, TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE, TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE },
{ 5, TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_DOWN, TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_UP },
@ -273,93 +298,148 @@ private:
if (mirrorTable[i][1] == trackType)
{
std::string destFuncName = GetTrackFunctionName(mirrorTable[i][2]);
switch (mirrorTable[i][0]) {
case 0:
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 2) & 3, height, tileElement);", destFuncName.c_str());
break;
case 1:
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);", destFuncName.c_str());
break;
case 2:
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);", destFuncName.c_str());
break;
case 3:
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);", destFuncName.c_str());
break;
case 4:
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);", destFuncName.c_str());
break;
case 5:
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);", destFuncName.c_str());
break;
case 6:
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);", destFuncName.c_str());
break;
case 7:
WriteLine(tabs, "trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 3) & 3, height, tileElement);", destFuncName.c_str());
break;
case 8:
WriteLine(tabs, "trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 2) & 3, height, tileElement);", destFuncName.c_str());
break;
case 9:
WriteLine(tabs, "if (trackSequence >= 4) {");
WriteLine(tabs + 1, "trackSequence -= 4;");
WriteLine(tabs + 1, "direction = (direction + 1) & 3;");
WriteLine(tabs, "}");
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);", destFuncName.c_str());
break;
case 10:
WriteLine(tabs, "if (trackSequence >= 4) {");
WriteLine(tabs + 1, "trackSequence -= 4;");
WriteLine(tabs + 1, "direction = (direction - 1) & 3;");
WriteLine(tabs, "}");
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);", destFuncName.c_str());
break;
case 11:
WriteLine(tabs, "if (trackSequence >= 7) {");
WriteLine(tabs + 1, "trackSequence -= 7;");
WriteLine(tabs + 1, "direction = (direction + 1) & 3;");
WriteLine(tabs, "}");
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);", destFuncName.c_str());
break;
case 12:
WriteLine(tabs, "if (trackSequence >= 7) {");
WriteLine(tabs + 1, "trackSequence -= 7;");
WriteLine(tabs + 1, "direction = (direction - 1) & 3;");
WriteLine(tabs, "}");
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);", destFuncName.c_str());
break;
case 13:
WriteLine(tabs, "%s(rideIndex, 3 - trackSequence, (direction + 2) & 3, height, tileElement);", destFuncName.c_str());
break;
case 14:
WriteLine(tabs, "%s(rideIndex, 2 - trackSequence, (direction - 1) & 3, height, tileElement);", destFuncName.c_str());
break;
case 15:
WriteLine(tabs, "%s(rideIndex, 2 - trackSequence, (direction + 1) & 3, height, tileElement);", destFuncName.c_str());
break;
case 16:
WriteLine(tabs, "%s(rideIndex, 3 - trackSequence, direction, height, tileElement);", destFuncName.c_str());
break;
case 17:
WriteLine(tabs, "%s(rideIndex, 2 - trackSequence, direction, height, tileElement);", destFuncName.c_str());
break;
case 18:
WriteLine(tabs, "%s(rideIndex, 2 - trackSequence, (direction + 2) & 3, height, tileElement);", destFuncName.c_str());
break;
case 19:
WriteLine(tabs, "%s(rideIndex, 6 - trackSequence, direction, height, tileElement);", destFuncName.c_str());
break;
switch (mirrorTable[i][0])
{
case 0:
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 2) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 1:
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];");
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 2:
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];");
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 3:
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];");
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 4:
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];");
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 5:
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 6:
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 7:
WriteLine(tabs, "trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence];");
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 3) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 8:
WriteLine(tabs, "trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence];");
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 2) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 9:
WriteLine(tabs, "if (trackSequence >= 4) {");
WriteLine(tabs + 1, "trackSequence -= 4;");
WriteLine(tabs + 1, "direction = (direction + 1) & 3;");
WriteLine(tabs, "}");
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];");
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 10:
WriteLine(tabs, "if (trackSequence >= 4) {");
WriteLine(tabs + 1, "trackSequence -= 4;");
WriteLine(tabs + 1, "direction = (direction - 1) & 3;");
WriteLine(tabs, "}");
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];");
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 11:
WriteLine(tabs, "if (trackSequence >= 7) {");
WriteLine(tabs + 1, "trackSequence -= 7;");
WriteLine(tabs + 1, "direction = (direction + 1) & 3;");
WriteLine(tabs, "}");
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];");
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 12:
WriteLine(tabs, "if (trackSequence >= 7) {");
WriteLine(tabs + 1, "trackSequence -= 7;");
WriteLine(tabs + 1, "direction = (direction - 1) & 3;");
WriteLine(tabs, "}");
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];");
WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 13:
WriteLine(
tabs,
"%s(rideIndex, 3 - trackSequence, (direction + 2) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 14:
WriteLine(
tabs,
"%s(rideIndex, 2 - trackSequence, (direction - 1) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 15:
WriteLine(
tabs,
"%s(rideIndex, 2 - trackSequence, (direction + 1) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 16:
WriteLine(
tabs, "%s(rideIndex, 3 - trackSequence, direction, height, tileElement);", destFuncName.c_str());
break;
case 17:
WriteLine(
tabs, "%s(rideIndex, 2 - trackSequence, direction, height, tileElement);", destFuncName.c_str());
break;
case 18:
WriteLine(
tabs,
"%s(rideIndex, 2 - trackSequence, (direction + 2) & 3, height, tileElement);",
destFuncName.c_str());
break;
case 19:
WriteLine(
tabs, "%s(rideIndex, 6 - trackSequence, direction, height, tileElement);", destFuncName.c_str());
break;
}
return true;
}
@ -369,8 +449,8 @@ private:
void ExtractMetalSupportCalls(std::vector<function_call> calls[4], std::vector<function_call> output[4])
{
for (int direction = 0; direction < 4; direction++) {
for (int direction = 0; direction < 4; direction++)
{
auto cutPoint = std::find_if(calls[direction].begin(), calls[direction].end(), [](function_call call) {
return (call.function == SUPPORTS_METAL_A || call.function == SUPPORTS_METAL_B);
});
@ -390,7 +470,8 @@ private:
int16_t verticalTunnelHeights[4];
std::vector<SegmentSupportCall> segmentSupportCalls[4];
support_height generalSupports[4] = {};
for (int direction = 0; direction < 4; direction++) {
for (int direction = 0; direction < 4; direction++)
{
rct_tile_element tileElement = {};
tileElement.flags |= TILE_ELEMENT_FLAG_LAST_TILE;
track_element_set_type(&tileElement, trackType);
@ -411,8 +492,10 @@ private:
int numCalls = PaintIntercept::GetCalls(callBuffer);
calls[direction].insert(calls[direction].begin(), callBuffer, callBuffer + numCalls);
for (auto &&call : calls[direction]) {
if (call.function == SET_SEGMENT_HEIGHT) {
for (auto&& call : calls[direction])
{
if (call.function == SET_SEGMENT_HEIGHT)
{
blockSegmentsBeforeSupports = true;
break;
}
@ -464,7 +547,8 @@ private:
}
std::vector<function_call> supportCalls[4], chainLiftSupportCalls[4], cableLiftSupportCalls[4];
if (blockSegmentsBeforeSupports) {
if (blockSegmentsBeforeSupports)
{
ExtractMetalSupportCalls(calls, supportCalls);
ExtractMetalSupportCalls(cableLiftCalls, cableLiftSupportCalls);
ExtractMetalSupportCalls(chainLiftCalls, chainLiftSupportCalls);
@ -498,10 +582,14 @@ private:
GenerateCalls(tabs, calls, height);
}
if (blockSegmentsBeforeSupports) {
if (_rideType == RIDE_TYPE_GIGA_COASTER && !CompareFunctionCalls(supportCalls, cableLiftSupportCalls)) {
if (blockSegmentsBeforeSupports)
{
if (_rideType == RIDE_TYPE_GIGA_COASTER && !CompareFunctionCalls(supportCalls, cableLiftSupportCalls))
{
printf("Error: Supports differ for cable lift.\n");
} else if (!CompareFunctionCalls(supportCalls, chainLiftSupportCalls)) {
}
else if (!CompareFunctionCalls(supportCalls, chainLiftSupportCalls))
{
printf("Error: Supports differ for chain lift\n");
}
WriteLine();
@ -509,12 +597,14 @@ private:
bool conditionalSupports = _conditionalSupports;
_conditionalSupports = false;
if (conditionalSupports) {
if (conditionalSupports)
{
WriteLine(tabs, "if (track_paint_util_should_paint_supports(gPaintMapPosition)) {");
tabs++;
}
GenerateCalls(tabs, supportCalls, height);
if (conditionalSupports) {
if (conditionalSupports)
{
tabs--;
WriteLine(tabs, "}");
}
@ -522,7 +612,8 @@ private:
}
GenerateTunnelCall(tabs, tileTunnelCalls, verticalTunnelHeights);
if (!blockSegmentsBeforeSupports) {
if (!blockSegmentsBeforeSupports)
{
GenerateSegmentSupportCall(tabs, segmentSupportCalls);
}
GenerateGeneralSupportCall(tabs, generalSupports);
@ -542,7 +633,8 @@ private:
WriteLine(tabs, "switch (direction) {");
for (int direction = 0; direction < 4; direction++)
{
if (calls[direction].size() == 0) continue;
if (calls[direction].size() == 0)
continue;
WriteLine(tabs, "case %d:", direction);
for (int d2 = direction + 1; d2 < 4; d2++)
@ -570,60 +662,66 @@ private:
}
}
void GenerateCalls(int tabs, const function_call &call, int height, int direction)
void GenerateCalls(int tabs, const function_call& call, int height, int direction)
{
switch (call.function) {
case PAINT_98196C:
case PAINT_98197C:
case PAINT_98198C:
case PAINT_98199C:
GeneratePaintCall(tabs, call, height, direction);
break;
case SUPPORTS_METAL_A:
case SUPPORTS_METAL_B:
switch (call.function)
{
int callTabs = tabs;
if (_conditionalSupports)
case PAINT_98196C:
case PAINT_98197C:
case PAINT_98198C:
case PAINT_98199C:
GeneratePaintCall(tabs, call, height, direction);
break;
case SUPPORTS_METAL_A:
case SUPPORTS_METAL_B:
{
WriteLine(tabs, "if (track_paint_util_should_paint_supports(gPaintMapPosition)) {");
callTabs++;
}
int callTabs = tabs;
if (_conditionalSupports)
{
WriteLine(tabs, "if (track_paint_util_should_paint_supports(gPaintMapPosition)) {");
callTabs++;
}
WriteLine(callTabs, "%s(%d, %d, %d, height%s, %s);",
GetFunctionCallName(call.function),
call.supports.type,
call.supports.segment,
call.supports.special,
GetOffsetExpressionString(call.supports.height - height).c_str(),
GetImageIdString(call.supports.colour_flags).c_str());
WriteLine(
callTabs,
"%s(%d, %d, %d, height%s, %s);",
GetFunctionCallName(call.function),
call.supports.type,
call.supports.segment,
call.supports.special,
GetOffsetExpressionString(call.supports.height - height).c_str(),
GetImageIdString(call.supports.colour_flags).c_str());
if (_conditionalSupports)
{
WriteLine(tabs, "}");
if (_conditionalSupports)
{
WriteLine(tabs, "}");
}
break;
}
break;
}
case SUPPORTS_WOOD_A:
case SUPPORTS_WOOD_B:
WriteLine(tabs, "%s(%d, %d, height%s, %s, NULL);",
GetFunctionCallName(call.function),
call.supports.type,
call.supports.special,
GetOffsetExpressionString(call.supports.height - height).c_str(),
GetImageIdString(call.supports.colour_flags).c_str());
break;
case SUPPORTS_WOOD_A:
case SUPPORTS_WOOD_B:
WriteLine(
tabs,
"%s(%d, %d, height%s, %s, NULL);",
GetFunctionCallName(call.function),
call.supports.type,
call.supports.special,
GetOffsetExpressionString(call.supports.height - height).c_str(),
GetImageIdString(call.supports.colour_flags).c_str());
break;
}
}
void GeneratePaintCall(int tabs, const function_call &call, int height, int direction)
void GeneratePaintCall(int tabs, const function_call& call, int height, int direction)
{
const char * funcName = GetFunctionCallName(call.function);
const char* funcName = GetFunctionCallName(call.function);
std::string imageId = GetImageIdString(call.paint.image_id);
std::string s = String::Format("%s_rotated(direction, %s, ", funcName, imageId.c_str());
s += FormatXYSwap(call.paint.offset.x, call.paint.offset.y, direction);
s += ", ";
s += FormatXYSwap(call.paint.bound_box_length.x, call.paint.bound_box_length.y, direction);
s += String::Format(", %d, height%s", call.paint.bound_box_length.z, GetOffsetExpressionString(call.paint.z_offset - height).c_str());
s += String::Format(
", %d, height%s", call.paint.bound_box_length.z, GetOffsetExpressionString(call.paint.z_offset - height).c_str());
if (call.function != PAINT_98196C)
{
@ -685,9 +783,10 @@ private:
return true;
}
bool CompareFunctionCalls(const std::vector<function_call> &a, const std::vector<function_call> &b)
bool CompareFunctionCalls(const std::vector<function_call>& a, const std::vector<function_call>& b)
{
if (a.size() != b.size()) return false;
if (a.size() != b.size())
return false;
for (size_t i = 0; i < a.size(); i++)
{
if (!CompareFunctionCall(a[i], b[i]))
@ -698,14 +797,14 @@ private:
return true;
}
bool CompareFunctionCall(const function_call a, const function_call &b)
bool CompareFunctionCall(const function_call a, const function_call& b)
{
return FunctionCall::AssertsEquals(a, b);
}
const char * GetFunctionCallName(int function)
const char* GetFunctionCallName(int function)
{
const char * functionNames[] = {
const char* functionNames[] = {
"sub_98196C",
"sub_98197C",
"sub_98198C",
@ -718,13 +817,14 @@ private:
return functionNames[function];
}
bool GetTunnelCalls(int trackType,
int direction,
int trackSequence,
int height,
rct_tile_element * tileElement,
TunnelCall tileTunnelCalls[4][4],
int16_t verticalTunnelHeights[4])
bool GetTunnelCalls(
int trackType,
int direction,
int trackSequence,
int height,
rct_tile_element* tileElement,
TunnelCall tileTunnelCalls[4][4],
int16_t verticalTunnelHeights[4])
{
TestPaint::ResetTunnels();
@ -736,27 +836,38 @@ private:
uint8_t rightIndex = (4 - direction) % 4;
uint8_t leftIndex = (rightIndex + 1) % 4;
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4; ++i)
{
tileTunnelCalls[direction][i].call = TUNNELCALL_SKIPPED;
}
if (gRightTunnelCount == 0) {
if (gRightTunnelCount == 0)
{
tileTunnelCalls[direction][rightIndex].call = TUNNELCALL_NONE;
} else if (gRightTunnelCount == 3) {
}
else if (gRightTunnelCount == 3)
{
tileTunnelCalls[direction][rightIndex].call = TUNNELCALL_CALL;
tileTunnelCalls[direction][rightIndex].offset = SideTunnelCall::GetTunnelOffset(height, gRightTunnels);
tileTunnelCalls[direction][rightIndex].type = gRightTunnels[0].type;
} else {
}
else
{
printf("Multiple tunnels on one side aren't supported.\n");
return false;
}
if (gLeftTunnelCount == 0) {
if (gLeftTunnelCount == 0)
{
tileTunnelCalls[direction][leftIndex].call = TUNNELCALL_NONE;
} else if (gLeftTunnelCount == 3) {
}
else if (gLeftTunnelCount == 3)
{
tileTunnelCalls[direction][leftIndex].call = TUNNELCALL_CALL;
tileTunnelCalls[direction][leftIndex].offset = SideTunnelCall::GetTunnelOffset(height, gLeftTunnels);
tileTunnelCalls[direction][leftIndex].type = gLeftTunnels[0].type;
} else {
}
else
{
printf("Multiple tunnels on one side aren't supported.\n");
return false;
}
@ -779,15 +890,13 @@ private:
constexpr uint8_t TunnelLeft = 0;
constexpr uint8_t TunnelRight = 1;
constexpr uint8_t TunnelNA = 255;
static const uint8_t dsToWay[4][4] =
{
static const uint8_t dsToWay[4][4] = {
{ TunnelRight, TunnelLeft, TunnelNA, TunnelNA },
{ TunnelLeft, TunnelNA, TunnelNA, TunnelRight },
{ TunnelNA, TunnelNA, TunnelRight, TunnelLeft },
{ TunnelNA, TunnelRight, TunnelLeft, TunnelNA },
};
int16_t tunnelOffset[4] = { 0 };
uint8_t tunnelType[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
for (int direction = 0; direction < 4; direction++)
@ -811,9 +920,9 @@ private:
GenerateTunnelCall(tabs, tunnelOffset[0], tunnelType[0]);
}
}
else if (tunnelOffset[0] == tunnelOffset[3] && tunnelType[0] == tunnelType[3] &&
tunnelOffset[1] == tunnelOffset[2] && tunnelType[1] == tunnelType[2] &&
tunnelType[0] != 0xFF)
else if (
tunnelOffset[0] == tunnelOffset[3] && tunnelType[0] == tunnelType[3] && tunnelOffset[1] == tunnelOffset[2]
&& tunnelType[1] == tunnelType[2] && tunnelType[0] != 0xFF)
{
if (tunnelType[0] != 0xFF)
{
@ -845,7 +954,8 @@ private:
{
if (tileTunnelCalls[i][side].call == TUNNELCALL_CALL)
{
GenerateTunnelCall(tabs + 1, tileTunnelCalls[i][side].offset, tileTunnelCalls[i][side].type, dsToWay[i][side]);
GenerateTunnelCall(
tabs + 1, tileTunnelCalls[i][side].offset, tileTunnelCalls[i][side].type, dsToWay[i][side]);
}
}
WriteLine(tabs + 1, "break;");
@ -859,26 +969,42 @@ private:
int tunnelHeight = verticalTunnelHeights[0];
if (tunnelHeight != 0)
{
WriteLine(tabs, "paint_util_set_vertical_tunnel(session, height%s);", GetOffsetExpressionString(tunnelHeight).c_str());
WriteLine(
tabs,
"paint_util_set_vertical_tunnel(session, height%s);",
GetOffsetExpressionString(tunnelHeight).c_str());
}
}
}
void GenerateTunnelCall(int tabs, int offset, int type, int way)
{
switch (way) {
case 0:
WriteLine(tabs, "paint_util_push_tunnel_left(session, height%s, TUNNEL_%d);", GetOffsetExpressionString(offset).c_str(), type);
break;
case 1:
WriteLine(tabs, "paint_util_push_tunnel_right(session, height%s, TUNNEL_%d);", GetOffsetExpressionString(offset).c_str(), type);
break;
switch (way)
{
case 0:
WriteLine(
tabs,
"paint_util_push_tunnel_left(session, height%s, TUNNEL_%d);",
GetOffsetExpressionString(offset).c_str(),
type);
break;
case 1:
WriteLine(
tabs,
"paint_util_push_tunnel_right(session, height%s, TUNNEL_%d);",
GetOffsetExpressionString(offset).c_str(),
type);
break;
}
}
void GenerateTunnelCall(int tabs, int offset, int type)
{
WriteLine(tabs, "paint_util_push_tunnel_rotated(session, direction, height%s, TUNNEL_%d);", GetOffsetExpressionString(offset).c_str(), type);
WriteLine(
tabs,
"paint_util_push_tunnel_rotated(session, direction, height%s, TUNNEL_%d);",
GetOffsetExpressionString(offset).c_str(),
type);
}
void GenerateSegmentSupportCall(int tabs, std::vector<SegmentSupportCall> segmentSupportCalls[4])
@ -914,13 +1040,14 @@ private:
void GenerateGeneralSupportCall(int tabs, support_height generalSupports[4])
{
if (generalSupports[0].height == 0 &&
generalSupports[0].slope == 0xFF)
if (generalSupports[0].height == 0 && generalSupports[0].slope == 0xFF)
{
return;
}
WriteLine(tabs, "paint_util_set_general_support_height(session, height%s, 0x%02X);",
WriteLine(
tabs,
"paint_util_set_general_support_height(session, height%s, 0x%02X);",
GetOffsetExpressionString((int16_t)generalSupports[0].height).c_str(),
generalSupports[0].slope);
if (!AllMatch(generalSupports, 4))
@ -937,19 +1064,29 @@ private:
uint32_t palette = imageId & ~0x7FFFF;
std::string paletteName;
if (palette == TestPaint::DEFAULT_SCHEME_TRACK) paletteName = "gTrackColours[SCHEME_TRACK]";
else if (palette == TestPaint::DEFAULT_SCHEME_SUPPORTS) paletteName = "gTrackColours[SCHEME_SUPPORTS]";
else if (palette == TestPaint::DEFAULT_SCHEME_MISC) paletteName = "gTrackColours[SCHEME_MISC]";
else if (palette == TestPaint::DEFAULT_SCHEME_3) paletteName = "gTrackColours[SCHEME_3]";
else {
if (palette == TestPaint::DEFAULT_SCHEME_TRACK)
paletteName = "gTrackColours[SCHEME_TRACK]";
else if (palette == TestPaint::DEFAULT_SCHEME_SUPPORTS)
paletteName = "gTrackColours[SCHEME_SUPPORTS]";
else if (palette == TestPaint::DEFAULT_SCHEME_MISC)
paletteName = "gTrackColours[SCHEME_MISC]";
else if (palette == TestPaint::DEFAULT_SCHEME_3)
paletteName = "gTrackColours[SCHEME_3]";
else
{
paletteName = String::Format("0x%08X", palette);
}
if (image == 0) {
if (image == 0)
{
result = paletteName;
} else if (image & 0x70000) {
}
else if (image & 0x70000)
{
result = String::Format("%s | vehicle.base_image_id + %d", paletteName.c_str(), image & ~0x70000);
} else {
}
else
{
result = String::Format("%s | %d", paletteName.c_str(), image);
}
return result;
@ -957,8 +1094,10 @@ private:
std::string GetOffsetExpressionString(int offset)
{
if (offset < 0) return std::string(" - ") + std::to_string(-offset);
if (offset > 0) return std::string(" + ") + std::to_string(offset);
if (offset < 0)
return std::string(" - ") + std::to_string(-offset);
if (offset > 0)
return std::string(" + ") + std::to_string(offset);
return std::string();
}
@ -966,9 +1105,12 @@ private:
{
std::string s;
int segmentsPrinted = 0;
for (int i = 0; i < 9; i++) {
if (segments & segment_offsets[i]) {
if (segmentsPrinted > 0) {
for (int i = 0; i < 9; i++)
{
if (segments & segment_offsets[i])
{
if (segmentsPrinted > 0)
{
s += " | ";
}
s += String::Format("SEGMENT_%02X", 0xB4 + 4 * i);
@ -978,12 +1120,11 @@ private:
return s;
}
template<typename T>
bool AllMatch(T * arr, size_t count)
template<typename T> bool AllMatch(T* arr, size_t count)
{
for (size_t i = 1; i < count; i++)
{
if (memcmp((const void *)&arr[i], (const void *)&arr[0], sizeof(T)) != 0)
if (memcmp((const void*)&arr[i], (const void*)&arr[0], sizeof(T)) != 0)
{
return false;
}
@ -991,23 +1132,22 @@ private:
return true;
}
void CallOriginal(int trackType, int direction, int trackSequence, int height, rct_tile_element *tileElement)
void CallOriginal(int trackType, int direction, int trackSequence, int height, rct_tile_element* tileElement)
{
TestPaint::ResetEnvironment();
TestPaint::ResetSupportHeights();
uint32_t *trackDirectionList = (uint32_t *)RideTypeTrackPaintFunctionsOld[_rideType][trackType];
uint32_t* trackDirectionList = (uint32_t*)RideTypeTrackPaintFunctionsOld[_rideType][trackType];
// Have to call from this point as it pushes esi and expects callee to pop it
RCT2_CALLPROC_X(
0x006C4934,
_rideType,
(int) trackDirectionList,
(int)trackDirectionList,
direction,
height,
(int)tileElement,
0 * sizeof(Ride),
trackSequence
);
trackSequence);
}
void GenerateMainFunction()
@ -1017,7 +1157,8 @@ private:
WriteLine(1, "switch (trackType) {");
for (int trackType = 0; trackType < 256; trackType++)
{
if (trackType == TRACK_ELEM_END_STATION) {
if (trackType == TRACK_ELEM_END_STATION)
{
WriteLine(1, "case " + std::string(TrackElemNames[TRACK_ELEM_END_STATION]) + ":");
WriteLine(1, "case " + std::string(TrackElemNames[TRACK_ELEM_BEGIN_STATION]) + ":");
WriteLine(1, "case " + std::string(TrackElemNames[TRACK_ELEM_MIDDLE_STATION]) + ":");
@ -1044,9 +1185,8 @@ private:
bool IsTrackTypeSupported(int trackType)
{
if (trackType == TRACK_ELEM_BEGIN_STATION ||
trackType == TRACK_ELEM_MIDDLE_STATION ||
trackType == TRACK_ELEM_END_STATION)
if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION
|| trackType == TRACK_ELEM_END_STATION)
{
return false;
}
@ -1062,7 +1202,7 @@ private:
WriteLine(0, "");
}
void WriteLine(int tabs, const char * format, ...)
void WriteLine(int tabs, const char* format, ...)
{
va_list args;
char buffer[512];
@ -1094,4 +1234,3 @@ int generatePaintCode(uint8_t rideType)
auto pcg = PaintCodeGenerator();
return pcg.Generate(rideType);
}

View File

@ -15,27 +15,29 @@
#include <vector>
#if defined(__unix__)
#include <unistd.h>
#include <sys/mman.h>
#include <unistd.h>
#endif // defined(__unix__)
#include "Data.h"
#include "PaintIntercept.hpp"
#include "TestTrack.hpp"
#include "Utils.hpp"
#include "Data.h"
#include <openrct2/rct2/RCT2.h>
#include <openrct2/ride/Ride.h>
#include <openrct2/ride/RideData.h>
#include <openrct2/ride/Track.h>
#include <openrct2/ride/TrackData.h>
struct TestCase {
struct TestCase
{
uint8_t rideType;
std::vector<uint8_t> trackTypes;
};
enum CLIColour {
enum CLIColour
{
DEFAULT,
RED,
YELLOW,
@ -45,15 +47,19 @@ enum CLIColour {
bool gTestColor = true;
Verbosity _verbosity = NORMAL;
static bool CStringEquals(const char *lhs, const char *rhs) {
if (lhs == nullptr) return rhs == nullptr;
static bool CStringEquals(const char* lhs, const char* rhs)
{
if (lhs == nullptr)
return rhs == nullptr;
if (rhs == nullptr) return false;
if (rhs == nullptr)
return false;
return strcmp(lhs, rhs) == 0;
}
enum COLOUR_METHOD {
enum COLOUR_METHOD
{
COLOUR_METHOD_NONE,
COLOUR_METHOD_ANSI,
COLOUR_METHOD_WINDOWS,
@ -61,25 +67,19 @@ enum COLOUR_METHOD {
static COLOUR_METHOD GetColourMethod()
{
if (!gTestColor) {
if (!gTestColor)
{
return COLOUR_METHOD_NONE;
}
const char* const term = getenv("TERM");
const bool term_supports_color =
CStringEquals(term, "xterm") ||
CStringEquals(term, "xterm-color") ||
CStringEquals(term, "xterm-256color") ||
CStringEquals(term, "screen") ||
CStringEquals(term, "screen-256color") ||
CStringEquals(term, "tmux") ||
CStringEquals(term, "tmux-256color") ||
CStringEquals(term, "rxvt-unicode") ||
CStringEquals(term, "rxvt-unicode-256color") ||
CStringEquals(term, "linux") ||
CStringEquals(term, "cygwin");
const bool term_supports_color = CStringEquals(term, "xterm") || CStringEquals(term, "xterm-color")
|| CStringEquals(term, "xterm-256color") || CStringEquals(term, "screen") || CStringEquals(term, "screen-256color")
|| CStringEquals(term, "tmux") || CStringEquals(term, "tmux-256color") || CStringEquals(term, "rxvt-unicode")
|| CStringEquals(term, "rxvt-unicode-256color") || CStringEquals(term, "linux") || CStringEquals(term, "cygwin");
if (term_supports_color) {
if (term_supports_color)
{
return COLOUR_METHOD_ANSI;
}
@ -90,13 +90,18 @@ static COLOUR_METHOD GetColourMethod()
#endif
}
static const char* GetAnsiColorCode(CLIColour color) {
switch (color) {
case RED: return "1";
case GREEN: return "2";
static const char* GetAnsiColorCode(CLIColour color)
{
switch (color)
{
case RED:
return "1";
case GREEN:
return "2";
case YELLOW:
return "3";
default: return nullptr;
default:
return nullptr;
};
}
@ -111,29 +116,40 @@ static WORD GetCurrentWindowsConsoleAttribute(HANDLE hConsoleOutput)
static WORD GetWindowsConsoleAttribute(CLIColour color, WORD defaultAttr)
{
switch (color) {
case RED: return FOREGROUND_RED;
case GREEN: return FOREGROUND_GREEN;
case YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
default: return defaultAttr;
switch (color)
{
case RED:
return FOREGROUND_RED;
case GREEN:
return FOREGROUND_GREEN;
case YELLOW:
return FOREGROUND_RED | FOREGROUND_GREEN;
default:
return defaultAttr;
};
}
#endif
static void Write_VA(Verbosity verbosity, CLIColour colour, const char *fmt, va_list args)
static void Write_VA(Verbosity verbosity, CLIColour colour, const char* fmt, va_list args)
{
if (_verbosity < verbosity) return;
if (_verbosity < verbosity)
return;
COLOUR_METHOD colourMethod = GetColourMethod();
if (colour == CLIColour::DEFAULT || colourMethod == COLOUR_METHOD_NONE) {
if (colour == CLIColour::DEFAULT || colourMethod == COLOUR_METHOD_NONE)
{
vprintf(fmt, args);
} else if (colourMethod == COLOUR_METHOD_ANSI) {
}
else if (colourMethod == COLOUR_METHOD_ANSI)
{
printf("\033[0;3%sm", GetAnsiColorCode(colour));
vprintf(fmt, args);
printf("\033[m");
} else if (colourMethod == COLOUR_METHOD_WINDOWS) {
}
else if (colourMethod == COLOUR_METHOD_WINDOWS)
{
#ifdef __WINDOWS__
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
WORD defaultAttr = GetCurrentWindowsConsoleAttribute(hStdOut);
@ -144,7 +160,7 @@ static void Write_VA(Verbosity verbosity, CLIColour colour, const char *fmt, va_
}
}
static void Write(Verbosity verbosity, CLIColour colour, const char *fmt, ...)
static void Write(Verbosity verbosity, CLIColour colour, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
@ -152,7 +168,7 @@ static void Write(Verbosity verbosity, CLIColour colour, const char *fmt, ...)
va_end(args);
}
static void Write(Verbosity verbosity, const char * fmt, ...)
static void Write(Verbosity verbosity, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
@ -160,7 +176,7 @@ static void Write(Verbosity verbosity, const char * fmt, ...)
va_end(args);
}
static void Write(CLIColour colour, const char * fmt, ...)
static void Write(CLIColour colour, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
@ -168,7 +184,7 @@ static void Write(CLIColour colour, const char * fmt, ...)
va_end(args);
}
static void Write(const char * fmt, ...)
static void Write(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
@ -180,27 +196,34 @@ static void Write(const char * fmt, ...)
#include <shellapi.h>
int main(int argc, char *argv[]);
int main(int argc, char* argv[]);
#define OPENRCT2_DLL_MODULE_NAME "openrct2.dll"
static HMODULE _dllModule = nullptr;
utf8 *utf8_write_codepoint(utf8 *dst, uint32_t codepoint)
utf8* utf8_write_codepoint(utf8* dst, uint32_t codepoint)
{
if (codepoint <= 0x7F) {
if (codepoint <= 0x7F)
{
dst[0] = (utf8)codepoint;
return dst + 1;
} else if (codepoint <= 0x7FF) {
}
else if (codepoint <= 0x7FF)
{
dst[0] = 0xC0 | ((codepoint >> 6) & 0x1F);
dst[1] = 0x80 | (codepoint & 0x3F);
return dst + 2;
} else if (codepoint <= 0xFFFF) {
}
else if (codepoint <= 0xFFFF)
{
dst[0] = 0xE0 | ((codepoint >> 12) & 0x0F);
dst[1] = 0x80 | ((codepoint >> 6) & 0x3F);
dst[2] = 0x80 | (codepoint & 0x3F);
return dst + 3;
} else {
}
else
{
dst[0] = 0xF0 | ((codepoint >> 18) & 0x07);
dst[1] = 0x80 | ((codepoint >> 12) & 0x3F);
dst[2] = 0x80 | ((codepoint >> 6) & 0x3F);
@ -209,31 +232,33 @@ utf8 *utf8_write_codepoint(utf8 *dst, uint32_t codepoint)
}
}
utf8 *widechar_to_utf8(const wchar_t *src)
utf8* widechar_to_utf8(const wchar_t* src)
{
utf8 *result = (utf8 *)malloc((wcslen(src) * 4) + 1);
utf8 *dst = result;
utf8* result = (utf8*)malloc((wcslen(src) * 4) + 1);
utf8* dst = result;
for (; *src != 0; src++) {
for (; *src != 0; src++)
{
dst = utf8_write_codepoint(dst, *src);
}
*dst++ = 0;
size_t size = (size_t)(dst - result);
return (utf8 *)realloc(result, size);
return (utf8*)realloc(result, size);
}
utf8 **windows_get_command_line_args(int *outNumArgs)
utf8** windows_get_command_line_args(int* outNumArgs)
{
int argc;
// Get command line arguments as widechar
LPWSTR commandLine = GetCommandLineW();
LPWSTR *argvW = CommandLineToArgvW(commandLine, &argc);
LPWSTR* argvW = CommandLineToArgvW(commandLine, &argc);
// Convert to UTF-8
utf8 **argvUtf8 = (utf8**)malloc(argc * sizeof(utf8*));
for (int i = 0; i < argc; i++) {
utf8** argvUtf8 = (utf8**)malloc(argc * sizeof(utf8*));
for (int i = 0; i < argc; i++)
{
argvUtf8[i] = widechar_to_utf8(argvW[i]);
}
LocalFree(argvW);
@ -250,18 +275,19 @@ BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
__declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
if (_dllModule == nullptr) {
if (_dllModule == nullptr)
{
_dllModule = GetModuleHandleA(OPENRCT2_DLL_MODULE_NAME);
}
int argc;
char ** argv = (char**)windows_get_command_line_args(&argc);
char** argv = (char**)windows_get_command_line_args(&argc);
int gExitCode = main(argc, argv);
// Free argv
for (int i = 0; i < argc; i++) {
for (int i = 0; i < argc; i++)
{
free(argv[i]);
}
free(argv);
@ -272,7 +298,7 @@ __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInsta
#endif
char *segments = (char *)(GOOD_PLACE_FOR_DATA_SEGMENT);
char* segments = (char*)(GOOD_PLACE_FOR_DATA_SEGMENT);
static uint32_t sawyercoding_calculate_checksum(const uint8_t* buffer, size_t length)
{
@ -298,9 +324,9 @@ static bool openrct2_setup_rct2_segment()
#if defined(__unix__)
int pageSize = getpagesize();
int numPages = (len + pageSize - 1) / pageSize;
unsigned char *dummy = (unsigned char *)malloc(numPages);
unsigned char* dummy = (unsigned char*)malloc(numPages);
err = mincore((void *)segments, len, dummy);
err = mincore((void*)segments, len, dummy);
bool pagesMissing = false;
if (err != 0)
{
@ -316,14 +342,16 @@ static bool openrct2_setup_rct2_segment()
pagesMissing = true;
perror("mincore");
#endif // __LINUX__
} else {
}
else
{
for (int i = 0; i < numPages; i++)
{
if (dummy[i] != 1)
{
pagesMissing = true;
void *start = (void *)(segments + i * pageSize);
void *end = (void *)(segments + (i + 1) * pageSize - 1);
void* start = (void*)(segments + i * pageSize);
void* end = (void*)(segments + (i + 1) * pageSize - 1);
log_warning("required page %p - %p is not in memory!", start, end);
}
}
@ -335,14 +363,14 @@ static bool openrct2_setup_rct2_segment()
}
// section: text
err = mprotect((void *)0x401000, 0x8a4000 - 0x401000, PROT_READ | PROT_EXEC | PROT_WRITE);
err = mprotect((void*)0x401000, 0x8a4000 - 0x401000, PROT_READ | PROT_EXEC | PROT_WRITE);
if (err != 0)
{
perror("mprotect");
}
// section: rw data
err = mprotect((void *)segments, 0x01429000 - 0x8a4000, PROT_READ | PROT_WRITE);
err = mprotect((void*)segments, 0x01429000 - 0x8a4000, PROT_READ | PROT_WRITE);
if (err != 0)
{
perror("mprotect");
@ -352,11 +380,14 @@ static bool openrct2_setup_rct2_segment()
// Check that the expected data is at various addresses.
// Start at 0x9a6000, which is start of .data, to skip the region containing addresses to DLL
// calls, which can be changed by windows/wine loader.
const uint32_t c1 = sawyercoding_calculate_checksum((const uint8_t*)(segments + (uintptr_t)(0x009A6000 - 0x8a4000)), 0x009E0000 - 0x009A6000);
const uint32_t c2 = sawyercoding_calculate_checksum((const uint8_t*)(segments + (uintptr_t)(0x01428000 - 0x8a4000)), 0x014282BC - 0x01428000);
const uint32_t c1 = sawyercoding_calculate_checksum(
(const uint8_t*)(segments + (uintptr_t)(0x009A6000 - 0x8a4000)), 0x009E0000 - 0x009A6000);
const uint32_t c2 = sawyercoding_calculate_checksum(
(const uint8_t*)(segments + (uintptr_t)(0x01428000 - 0x8a4000)), 0x014282BC - 0x01428000);
const uint32_t exp_c1 = 10114815;
const uint32_t exp_c2 = 23564;
if (c1 != exp_c1 || c2 != exp_c2) {
if (c1 != exp_c1 || c2 != exp_c2)
{
log_warning("c1 = %u, expected %u, match %d", c1, exp_c1, c1 == exp_c1);
log_warning("c2 = %u, expected %u, match %d", c2, exp_c2, c2 == exp_c2);
return false;
@ -367,12 +398,14 @@ static bool openrct2_setup_rct2_segment()
static void PrintRideTypes()
{
for (uint8_t rideType = 0; rideType < RIDE_TYPE_COUNT; rideType++) {
for (uint8_t rideType = 0; rideType < RIDE_TYPE_COUNT; rideType++)
{
CLIColour colour = CLIColour::DEFAULT;
bool implemented = Utils::rideIsImplemented(rideType);
const char * rideName = RideNames[rideType];
const char * status = "";
if (implemented) {
const char* rideName = RideNames[rideType];
const char* status = "";
if (implemented)
{
status = " [IMPLEMENTED]";
colour = CLIColour::GREEN;
}
@ -383,69 +416,81 @@ static void PrintRideTypes()
#include "GeneralSupportHeightCall.hpp"
static void TestGeneralSupportHeightCall() {
SupportCall callA = {16, 0x20};
SupportCall callB = {32, 0x20};
SupportCall callC = {48, 0x20};
SupportCall callD = {48, 0x1F};
static void TestGeneralSupportHeightCall()
{
SupportCall callA = { 16, 0x20 };
SupportCall callB = { 32, 0x20 };
SupportCall callC = { 48, 0x20 };
SupportCall callD = { 48, 0x1F };
SupportCall out = {0,0};
SupportCall out = { 0, 0 };
bool success;
SupportCall groupA[4] = {callA, callA, callA, callA};
SupportCall groupA[4] = { callA, callA, callA, callA };
success = GeneralSupportHeightCall::FindMostCommonSupportCall(groupA, &out);
assert(success);
assert(out == callA);
SupportCall groupB[4] = {callB, callA, callA, callA};
SupportCall groupB[4] = { callB, callA, callA, callA };
success = GeneralSupportHeightCall::FindMostCommonSupportCall(groupB, &out);
assert(success);
assert(out == callA);
SupportCall groupC[4] = {callB, callA, callB, callA};
SupportCall groupC[4] = { callB, callA, callB, callA };
success = GeneralSupportHeightCall::FindMostCommonSupportCall(groupC, &out);
assert(!success);
SupportCall groupD[4] = {callB, callC, callB, callA};
SupportCall groupD[4] = { callB, callC, callB, callA };
success = GeneralSupportHeightCall::FindMostCommonSupportCall(groupD, &out);
assert(!success);
SupportCall groupE[4] = {callD, callC, callB, callA};
SupportCall groupE[4] = { callD, callC, callB, callA };
success = GeneralSupportHeightCall::FindMostCommonSupportCall(groupE, &out);
assert(!success);
}
int main(int argc, char *argv[]) {
int main(int argc, char* argv[])
{
TestGeneralSupportHeightCall();
std::vector<TestCase> testCases;
bool generate = false;
uint8_t specificRideType = 0xFF;
for (int i = 0; i < argc; ++i) {
char *arg = argv[i];
if (strcmp(arg, "--gtest_color=no") == 0) {
for (int i = 0; i < argc; ++i)
{
char* arg = argv[i];
if (strcmp(arg, "--gtest_color=no") == 0)
{
gTestColor = false;
}
else if (strcmp(arg, "--quiet") == 0) {
else if (strcmp(arg, "--quiet") == 0)
{
_verbosity = Verbosity::QUIET;
}
else if (strcmp(arg, "--ride-type") == 0) {
if (i + 1 < argc) {
else if (strcmp(arg, "--ride-type") == 0)
{
if (i + 1 < argc)
{
i++;
specificRideType = atoi(argv[i]);
} else {
}
else
{
PrintRideTypes();
return 2;
}
}
else if (strcmp(arg, "--generate") == 0) {
else if (strcmp(arg, "--generate") == 0)
{
generate = true;
}
}
if (generate) {
if (specificRideType > 90) {
if (generate)
{
if (specificRideType > 90)
{
fprintf(stderr, "No ride or invalid ride specified.\n");
return 1;
}
@ -456,23 +501,31 @@ int main(int argc, char *argv[]) {
return generatePaintCode(specificRideType);
}
for (uint8_t rideType = 0; rideType < RIDE_TYPE_COUNT; rideType++) {
if (specificRideType != RIDE_TYPE_NULL && rideType != specificRideType) {
for (uint8_t rideType = 0; rideType < RIDE_TYPE_COUNT; rideType++)
{
if (specificRideType != RIDE_TYPE_NULL && rideType != specificRideType)
{
continue;
}
if (!Utils::rideIsImplemented(rideType)) {
if (!Utils::rideIsImplemented(rideType))
{
continue;
}
TestCase testCase = {};
testCase.rideType = rideType;
if (ride_type_has_flag(rideType, RIDE_TYPE_FLAG_FLAT_RIDE)) {
if (ride_type_has_flag(rideType, RIDE_TYPE_FLAG_FLAT_RIDE))
{
testCase.trackTypes.push_back(RideConstructionDefaultTrackType[rideType]);
} else {
for (int trackType = 0; trackType < 256; trackType++) {
if (Utils::rideSupportsTrackType(rideType, trackType)) {
}
else
{
for (int trackType = 0; trackType < 256; trackType++)
{
if (Utils::rideSupportsTrackType(rideType, trackType))
{
testCase.trackTypes.push_back(trackType);
}
}
@ -481,9 +534,10 @@ int main(int argc, char *argv[]) {
testCases.push_back(testCase);
}
int testCaseCount = (int) testCases.size();
int testCaseCount = (int)testCases.size();
int testCount = 0;
for (auto &&tc : testCases) {
for (auto&& tc : testCases)
{
testCount += tc.trackTypes.size();
}
@ -497,16 +551,21 @@ int main(int argc, char *argv[]) {
int successCount = 0;
std::vector<utf8string> failures;
for (auto &&tc : testCases) {
for (auto&& tc : testCases)
{
const utf8string rideTypeName = RideNames[tc.rideType];
Write(CLIColour::GREEN, "[----------] ");
Write("%d tests from %s\n", (int)tc.trackTypes.size(), rideTypeName);
for (auto &&trackType : tc.trackTypes) {
for (auto&& trackType : tc.trackTypes)
{
utf8string trackTypeName;
if (ride_type_has_flag(tc.rideType, RIDE_TYPE_FLAG_FLAT_RIDE)) {
if (ride_type_has_flag(tc.rideType, RIDE_TYPE_FLAG_FLAT_RIDE))
{
trackTypeName = FlatTrackNames[trackType];
} else {
}
else
{
trackTypeName = TrackNames[trackType];
}
@ -516,7 +575,8 @@ int main(int argc, char *argv[]) {
std::string out;
int retVal = TestTrack::TestPaintTrackElement(tc.rideType, trackType, &out);
Write("%s", out.c_str());
switch (retVal) {
switch (retVal)
{
case TEST_SUCCESS:
Write(CLIColour::GREEN, "[ OK ] ");
Write("%s.%s (0 ms)\n", rideTypeName, trackTypeName);
@ -543,7 +603,7 @@ int main(int argc, char *argv[]) {
}
Write(CLIColour::GREEN, "[----------] ");
Write("%d tests from %s (0 ms total)\n", (int)tc.trackTypes.size(), rideTypeName);
Write("%d tests from %s (0 ms total)\n", (int)tc.trackTypes.size(), rideTypeName);
}
Write("\n");
@ -556,14 +616,16 @@ int main(int argc, char *argv[]) {
Write(Verbosity::QUIET, CLIColour::GREEN, "[ PASSED ] ");
Write(Verbosity::QUIET, "%d tests.\n", successCount);
if (failures.size() > 0) {
if (failures.size() > 0)
{
Write(Verbosity::QUIET, CLIColour::RED, "[ FAILED ] ");
Write(Verbosity::QUIET, "%d tests, listed below:\n", (int)failures.size());
for (auto &&failure : failures) {
for (auto&& failure : failures)
{
Write(Verbosity::QUIET, CLIColour::RED, "[ FAILED ] ");
Write(Verbosity::QUIET, "%s\n", failure);
delete [] failure;
delete[] failure;
}
Write(Verbosity::QUIET, "\n");

View File

@ -9,26 +9,22 @@
#pragma once
#include <gtest/gtest.h>
#include <initializer_list>
#include <vector>
#include <gtest/gtest.h>
template<typename T, typename TExpected>
static void AssertVector(std::vector<T> actual, TExpected expected)
template<typename T, typename TExpected> static void AssertVector(std::vector<T> actual, TExpected expected)
{
ASSERT_EQ(actual.size(), expected.size()) <<
"Expected vector of size " << expected.size() << ", but was " << actual.size();
ASSERT_EQ(actual.size(), expected.size()) << "Expected vector of size " << expected.size() << ", but was " << actual.size();
size_t i = 0;
for (auto item : expected)
{
EXPECT_EQ(actual[i], item) <<
"Element at index " << i << " did not match";
EXPECT_EQ(actual[i], item) << "Element at index " << i << " did not match";
i++;
}
}
template<typename T>
static void AssertVector(std::vector<T> actual, std::initializer_list<T> expected)
template<typename T> static void AssertVector(std::vector<T> actual, std::initializer_list<T> expected)
{
AssertVector<T, std::initializer_list<T>>(actual, expected);
}

View File

@ -7,26 +7,25 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <string>
#include "TestData.h"
#include <gtest/gtest.h>
#include <openrct2/core/Crypt.h>
#include <openrct2/core/File.h>
#include <openrct2/core/Path.hpp>
#include <openrct2/network/NetworkKey.h>
#include <gtest/gtest.h>
#include "TestData.h"
#include <string>
class CryptTests : public testing::Test
{
public:
template<typename T>
void AssertHash(std::string expected, T hash)
template<typename T> void AssertHash(std::string expected, T hash)
{
auto actual = StringToHex(hash);
ASSERT_EQ(expected, actual);
}
template<typename T>
std::string StringToHex(T input)
template<typename T> std::string StringToHex(T input)
{
std::string result;
result.reserve(input.size() * 2);
@ -61,11 +60,9 @@ TEST_F(CryptTests, SHA1_Basic)
TEST_F(CryptTests, SHA1_Multiple)
{
std::string input[] = {
"Merry-go-round 2 looks too intense for me",
"This park is really clean and tidy",
"This balloon from Balloon Stall 1 is really good value"
};
std::string input[] = { "Merry-go-round 2 looks too intense for me",
"This park is really clean and tidy",
"This balloon from Balloon Stall 1 is really good value" };
auto alg = Crypt::CreateSHA1();
for (auto s : input)
@ -94,11 +91,9 @@ TEST_F(CryptTests, SHA1_Many)
auto alg = Crypt::CreateSHA1();
// First digest
std::string inputA[] = {
"Merry-go-round 2 looks too intense for me",
"This park is really clean and tidy",
"This balloon from Balloon Stall 1 is really good value"
};
std::string inputA[] = { "Merry-go-round 2 looks too intense for me",
"This park is really clean and tidy",
"This balloon from Balloon Stall 1 is really good value" };
for (auto s : inputA)
{
alg->Update(s.data(), s.size());

View File

@ -7,11 +7,12 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <string_view>
#include "TestData.h"
#include <gtest/gtest.h>
#include <openrct2/core/Path.hpp>
#include <openrct2/drawing/ImageImporter.h>
#include <gtest/gtest.h>
#include "TestData.h"
#include <string_view>
using namespace OpenRCT2::Drawing;
@ -23,12 +24,12 @@ public:
return Path::Combine(TestData::GetBasePath(), "images", name.data());
}
static uint32_t GetHash(void * buffer, size_t bufferLength)
static uint32_t GetHash(void* buffer, size_t bufferLength)
{
uint32_t hash = 27;
for (size_t i = 0; i < bufferLength; i++)
{
hash = (13 * hash) + ((uint8_t *)buffer)[i];
hash = (13 * hash) + ((uint8_t*)buffer)[i];
}
return hash;
}

View File

@ -7,13 +7,15 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "openrct2/config/IniReader.hpp"
#include "openrct2/config/ConfigEnum.hpp"
#include "openrct2/core/MemoryStream.h"
#include "openrct2/core/Util.hpp"
#include <gtest/gtest.h>
#include <limits>
#include <string>
#include "openrct2/config/ConfigEnum.hpp"
#include "openrct2/config/IniReader.hpp"
#include "openrct2/core/MemoryStream.h"
#include "openrct2/core/Util.hpp"
class IniReaderTest : public testing::Test
{
@ -31,7 +33,7 @@ TEST_F(IniReaderTest, create_empty)
MemoryStream ms(0);
ASSERT_EQ(ms.CanRead(), true);
ASSERT_EQ(ms.CanWrite(), true);
IIniReader * ir = CreateIniReader(&ms);
IIniReader* ir = CreateIniReader(&ms);
ASSERT_NE(ir, nullptr);
ASSERT_EQ(ir->GetBoolean("nobody", true), true);
ASSERT_EQ(ir->GetCString("expects", nullptr), nullptr);
@ -46,7 +48,7 @@ TEST_F(IniReaderTest, read_prepared)
MemoryStream ms(predefined.c_str(), predefined.size());
ASSERT_EQ(ms.CanRead(), true);
ASSERT_EQ(ms.CanWrite(), false);
IIniReader * ir = CreateIniReader(&ms);
IIniReader* ir = CreateIniReader(&ms);
ASSERT_NE(ir, nullptr);
ASSERT_EQ(ir->ReadSection("doesnt_exist"), false);
ASSERT_EQ(ir->ReadSection("bool"), true);
@ -62,7 +64,7 @@ TEST_F(IniReaderTest, read_prepared)
// values from different sections
ASSERT_EQ(ir->GetInt32("one", 42), 42);
ASSERT_EQ(ir->GetBoolean("boolval", false), true);
const utf8 * str = ir->GetCString("path", nullptr);
const utf8* str = ir->GetCString("path", nullptr);
ASSERT_STREQ(str, u8"C:'\\some/dir\\here/神鷹暢遊");
Memory::Free(str);
// go back a section
@ -76,7 +78,7 @@ TEST_F(IniReaderTest, read_duplicate)
MemoryStream ms(duplicate.c_str(), duplicate.size());
ASSERT_EQ(ms.CanRead(), true);
ASSERT_EQ(ms.CanWrite(), false);
IIniReader * ir = CreateIniReader(&ms);
IIniReader* ir = CreateIniReader(&ms);
ASSERT_NE(ir, nullptr);
// there should only be data from the last section
ASSERT_EQ(ir->ReadSection("section"), true);
@ -102,12 +104,12 @@ TEST_F(IniReaderTest, read_untrimmed)
MemoryStream ms(untrimmed.c_str(), untrimmed.size());
ASSERT_EQ(ms.CanRead(), true);
ASSERT_EQ(ms.CanWrite(), false);
IIniReader * ir = CreateIniReader(&ms);
IIniReader* ir = CreateIniReader(&ms);
ASSERT_NE(ir, nullptr);
// there should only be data from the last section
ASSERT_EQ(ir->ReadSection("section"), true);
ASSERT_EQ(ir->GetBoolean("one", false), true);
const utf8 * str = ir->GetCString("str", nullptr);
const utf8* str = ir->GetCString("str", nullptr);
ASSERT_STREQ(str, " xxx ");
Memory::Free(str);
ASSERT_EQ(ir->GetString("str", "yyy"), " xxx ");
@ -120,7 +122,7 @@ TEST_F(IniReaderTest, read_case_insensitive)
MemoryStream ms(caseInsensitive.c_str(), caseInsensitive.size());
ASSERT_EQ(ms.CanRead(), true);
ASSERT_EQ(ms.CanWrite(), false);
IIniReader * ir = CreateIniReader(&ms);
IIniReader* ir = CreateIniReader(&ms);
ASSERT_NE(ir, nullptr);
ASSERT_EQ(ir->ReadSection("section"), true);
ASSERT_EQ(ir->GetString("foo", "yyy"), "bar");
@ -128,32 +130,28 @@ TEST_F(IniReaderTest, read_case_insensitive)
delete ir;
}
const std::string IniReaderTest::predefined =
"[bool]\n"
"boolval = true\n\n"
"[int]\n"
"one = 1\n"
"zero = 0\n\n"
"[string]\n"
"path = "
"\"C:'\\\\some/dir\\\\here/\xE7\xA5\x9E\xE9\xB7\xB9\xE6\x9A\xA2\xE9\x81\x8A\"\n";
const std::string IniReaderTest::predefined = "[bool]\n"
"boolval = true\n\n"
"[int]\n"
"one = 1\n"
"zero = 0\n\n"
"[string]\n"
"path = "
"\"C:'\\\\some/dir\\\\here/\xE7\xA5\x9E\xE9\xB7\xB9\xE6\x9A\xA2\xE9\x81\x8A\"\n";
const std::string IniReaderTest::duplicate =
"[section]\n"
"one = true\n"
"fortytwo = 13\n"
"[section]\n"
"two = true\n"
"[section]\n"
"three = true\n"
"fortytwo = 42\n"
"fortytwo = 41\n";
const std::string IniReaderTest::duplicate = "[section]\n"
"one = true\n"
"fortytwo = 13\n"
"[section]\n"
"two = true\n"
"[section]\n"
"three = true\n"
"fortytwo = 42\n"
"fortytwo = 41\n";
const std::string IniReaderTest::untrimmed =
"[section]\n"
"one = true \n"
" str = \" xxx \"";
const std::string IniReaderTest::untrimmed = "[section]\n"
"one = true \n"
" str = \" xxx \"";
const std::string IniReaderTest::caseInsensitive =
"[sEcTiOn]\n"
"foo = \"bar\"\n";
const std::string IniReaderTest::caseInsensitive = "[sEcTiOn]\n"
"foo = \"bar\"\n";

View File

@ -7,13 +7,14 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "openrct2/config/IniWriter.hpp"
#include "openrct2/config/ConfigEnum.hpp"
#include "openrct2/core/MemoryStream.h"
#include "openrct2/platform/platform.h"
#include <gtest/gtest.h>
#include <limits>
#include "openrct2/config/ConfigEnum.hpp"
#include "openrct2/config/IniWriter.hpp"
#include "openrct2/core/MemoryStream.h"
#include "openrct2/platform/platform.h"
class IniWriterTest : public testing::Test
{
@ -28,7 +29,7 @@ TEST_F(IniWriterTest, create_empty)
MemoryStream ms(0);
ASSERT_EQ(ms.CanRead(), true);
ASSERT_EQ(ms.CanWrite(), true);
IIniWriter * iw = CreateIniWriter(&ms);
IIniWriter* iw = CreateIniWriter(&ms);
ASSERT_NE(iw, nullptr);
delete iw;
}
@ -36,7 +37,7 @@ TEST_F(IniWriterTest, create_empty)
TEST_F(IniWriterTest, create_one_section)
{
MemoryStream ms(1000);
IIniWriter * iw = CreateIniWriter(&ms);
IIniWriter* iw = CreateIniWriter(&ms);
ASSERT_NE(iw, nullptr);
iw->WriteSection("OpenRCT2");
uint8_t null_terminator = 0;
@ -45,7 +46,7 @@ TEST_F(IniWriterTest, create_one_section)
ASSERT_LE(ms.GetPosition(), 13); // Accommodate for varying-sized newline (Windows)
ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0);
const char * ini = (const char *)ms.ReadString();
const char* ini = (const char*)ms.ReadString();
ASSERT_STREQ(ini, "[OpenRCT2]" PLATFORM_NEWLINE);
Memory::Free(ini);
delete iw;
@ -54,7 +55,7 @@ TEST_F(IniWriterTest, create_one_section)
TEST_F(IniWriterTest, create_multiple_sections)
{
MemoryStream ms(1000);
IIniWriter * iw = CreateIniWriter(&ms);
IIniWriter* iw = CreateIniWriter(&ms);
ASSERT_NE(iw, nullptr);
iw->WriteSection("OpenRCT1");
iw->WriteSection("OpenRCT2");
@ -66,9 +67,11 @@ TEST_F(IniWriterTest, create_multiple_sections)
ASSERT_LE(ms.GetPosition(), 55); // Accommodate for varying-sized newline (Windows)
ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0);
const char * ini = (const char *)ms.ReadString();
ASSERT_STREQ(ini, "[OpenRCT1]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[OpenRCT2]" PLATFORM_NEWLINE PLATFORM_NEWLINE
"[OpenRCT3]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[OpenRCT4]" PLATFORM_NEWLINE);
const char* ini = (const char*)ms.ReadString();
ASSERT_STREQ(
ini,
"[OpenRCT1]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[OpenRCT2]" PLATFORM_NEWLINE PLATFORM_NEWLINE
"[OpenRCT3]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[OpenRCT4]" PLATFORM_NEWLINE);
Memory::Free(ini);
delete iw;
}
@ -76,7 +79,7 @@ TEST_F(IniWriterTest, create_multiple_sections)
TEST_F(IniWriterTest, create_loose_bool_entry)
{
MemoryStream ms(1000);
IIniWriter * iw = CreateIniWriter(&ms);
IIniWriter* iw = CreateIniWriter(&ms);
ASSERT_NE(iw, nullptr);
iw->WriteBoolean("boolval", true);
uint8_t null_terminator = 0;
@ -85,7 +88,7 @@ TEST_F(IniWriterTest, create_loose_bool_entry)
ASSERT_LE(ms.GetPosition(), 17); // Accommodate for varying-sized newline (Windows)
ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0);
const char * ini = (const char *)ms.ReadString();
const char* ini = (const char*)ms.ReadString();
ASSERT_STREQ(ini, "boolval = true" PLATFORM_NEWLINE);
Memory::Free(ini);
delete iw;
@ -94,7 +97,7 @@ TEST_F(IniWriterTest, create_loose_bool_entry)
TEST_F(IniWriterTest, create_loose_enum_entry)
{
MemoryStream ms(1000);
IIniWriter * iw = CreateIniWriter(&ms);
IIniWriter* iw = CreateIniWriter(&ms);
ASSERT_NE(iw, nullptr);
iw->WriteEnum("by_string", "stringval");
iw->WriteEnum<int32_t>("int32_t", 0, Enum_Currency);
@ -104,7 +107,7 @@ TEST_F(IniWriterTest, create_loose_enum_entry)
ASSERT_LE(ms.GetPosition(), 37); // Accommodate for varying-sized newline (Windows)
ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0);
const char * ini = (const char *)ms.ReadString();
const char* ini = (const char*)ms.ReadString();
ASSERT_STREQ(ini, "by_string = stringval" PLATFORM_NEWLINE "int32_t = 0" PLATFORM_NEWLINE);
Memory::Free(ini);
delete iw;
@ -113,7 +116,7 @@ TEST_F(IniWriterTest, create_loose_enum_entry)
TEST_F(IniWriterTest, create_loose_float_entry)
{
MemoryStream ms(1000);
IIniWriter * iw = CreateIniWriter(&ms);
IIniWriter* iw = CreateIniWriter(&ms);
ASSERT_NE(iw, nullptr);
iw->WriteFloat("one", 1.);
uint8_t null_terminator = 0;
@ -122,7 +125,7 @@ TEST_F(IniWriterTest, create_loose_float_entry)
ASSERT_LE(ms.GetPosition(), 17); // Accommodate for varying-sized newline (Windows)
ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0);
const char * ini = (const char *)ms.ReadString();
const char* ini = (const char*)ms.ReadString();
// This will be non-fatal due to float.
EXPECT_STREQ(ini, "one = 1.000000" PLATFORM_NEWLINE);
Memory::Free(ini);
@ -132,7 +135,7 @@ TEST_F(IniWriterTest, create_loose_float_entry)
TEST_F(IniWriterTest, create_loose_int32_t_entry)
{
MemoryStream ms(1000);
IIniWriter * iw = CreateIniWriter(&ms);
IIniWriter* iw = CreateIniWriter(&ms);
ASSERT_NE(iw, nullptr);
iw->WriteInt32("one", 1);
iw->WriteInt32("zero", 0);
@ -145,9 +148,11 @@ TEST_F(IniWriterTest, create_loose_int32_t_entry)
ASSERT_LE(ms.GetPosition(), 78); // Accommodate for varying-sized newline (Windows)
ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0);
const char * ini = (const char *)ms.ReadString();
ASSERT_STREQ(ini, "one = 1" PLATFORM_NEWLINE "zero = 0" PLATFORM_NEWLINE "minusone = -1" PLATFORM_NEWLINE
"intmin = -2147483648" PLATFORM_NEWLINE "intmax = 2147483647" PLATFORM_NEWLINE);
const char* ini = (const char*)ms.ReadString();
ASSERT_STREQ(
ini,
"one = 1" PLATFORM_NEWLINE "zero = 0" PLATFORM_NEWLINE "minusone = -1" PLATFORM_NEWLINE
"intmin = -2147483648" PLATFORM_NEWLINE "intmax = 2147483647" PLATFORM_NEWLINE);
Memory::Free(ini);
delete iw;
}
@ -155,7 +160,7 @@ TEST_F(IniWriterTest, create_loose_int32_t_entry)
TEST_F(IniWriterTest, create_loose_string_entry)
{
MemoryStream ms(1000);
IIniWriter * iw = CreateIniWriter(&ms);
IIniWriter* iw = CreateIniWriter(&ms);
ASSERT_NE(iw, nullptr);
iw->WriteString("path", u8"C:'\\some/dir\\here/神鷹暢遊");
uint8_t null_terminator = 0;
@ -164,7 +169,7 @@ TEST_F(IniWriterTest, create_loose_string_entry)
ASSERT_LE(ms.GetPosition(), 44); // Accommodate for varying-sized newline (Windows)
ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0);
const char * ini = (const char *)ms.ReadString();
const char* ini = (const char*)ms.ReadString();
ASSERT_STREQ(ini, "path = \"C:'\\\\some/dir\\\\here/\xE7\xA5\x9E\xE9\xB7\xB9\xE6\x9A\xA2\xE9\x81\x8A\"" PLATFORM_NEWLINE);
Memory::Free(ini);
delete iw;
@ -173,7 +178,7 @@ TEST_F(IniWriterTest, create_loose_string_entry)
TEST_F(IniWriterTest, create_multiple_section_with_values)
{
MemoryStream ms(1000);
IIniWriter * iw = CreateIniWriter(&ms);
IIniWriter* iw = CreateIniWriter(&ms);
ASSERT_NE(iw, nullptr);
iw->WriteSection("bool");
iw->WriteBoolean("boolval", true);
@ -188,11 +193,12 @@ TEST_F(IniWriterTest, create_multiple_section_with_values)
ASSERT_LE(ms.GetPosition(), 108); // Accommodate for varying-sized newline (Windows)
ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0);
const char * ini = (const char *)ms.ReadString();
ASSERT_STREQ(ini,
"[bool]" PLATFORM_NEWLINE "boolval = true" PLATFORM_NEWLINE PLATFORM_NEWLINE "[int]" PLATFORM_NEWLINE
"one = 1" PLATFORM_NEWLINE "zero = 0" PLATFORM_NEWLINE PLATFORM_NEWLINE "[string]" PLATFORM_NEWLINE "path = "
"\"C:'\\\\some/dir\\\\here/\xE7\xA5\x9E\xE9\xB7\xB9\xE6\x9A\xA2\xE9\x81\x8A\"" PLATFORM_NEWLINE);
const char* ini = (const char*)ms.ReadString();
ASSERT_STREQ(
ini,
"[bool]" PLATFORM_NEWLINE "boolval = true" PLATFORM_NEWLINE PLATFORM_NEWLINE "[int]" PLATFORM_NEWLINE
"one = 1" PLATFORM_NEWLINE "zero = 0" PLATFORM_NEWLINE PLATFORM_NEWLINE "[string]" PLATFORM_NEWLINE "path = "
"\"C:'\\\\some/dir\\\\here/\xE7\xA5\x9E\xE9\xB7\xB9\xE6\x9A\xA2\xE9\x81\x8A\"" PLATFORM_NEWLINE);
Memory::Free(ini);
delete iw;
}
@ -200,7 +206,7 @@ TEST_F(IniWriterTest, create_multiple_section_with_values)
TEST_F(IniWriterTest, create_duplicate_sections)
{
MemoryStream ms(1000);
IIniWriter * iw = CreateIniWriter(&ms);
IIniWriter* iw = CreateIniWriter(&ms);
ASSERT_NE(iw, nullptr);
iw->WriteSection("section");
iw->WriteSection("section");
@ -211,9 +217,11 @@ TEST_F(IniWriterTest, create_duplicate_sections)
ASSERT_LE(ms.GetPosition(), 43); // Accommodate for varying-sized newline (Windows)
ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0);
const char * ini = (const char *)ms.ReadString();
ASSERT_STREQ(ini, "[section]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[section]" PLATFORM_NEWLINE PLATFORM_NEWLINE
"[section]" PLATFORM_NEWLINE);
const char* ini = (const char*)ms.ReadString();
ASSERT_STREQ(
ini,
"[section]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[section]" PLATFORM_NEWLINE PLATFORM_NEWLINE
"[section]" PLATFORM_NEWLINE);
Memory::Free(ini);
delete iw;
}

View File

@ -8,19 +8,21 @@
*****************************************************************************/
#include "openrct2/localisation/LanguagePack.h"
#include "openrct2/localisation/StringIds.h"
#include <gtest/gtest.h>
class LanguagePackTest : public testing::Test
{
protected:
static const utf8 * LanguageEnGB;
static const utf8* LanguageEnGB;
static const unsigned char LanguageZhTW[];
};
TEST_F(LanguagePackTest, create_empty)
{
ILanguagePack * empty = LanguagePackFactory::FromText(0, "");
ILanguagePack* empty = LanguagePackFactory::FromText(0, "");
ASSERT_EQ(empty->GetId(), 0);
ASSERT_EQ(empty->GetCount(), 0);
delete empty;
@ -28,7 +30,7 @@ TEST_F(LanguagePackTest, create_empty)
TEST_F(LanguagePackTest, create_mutable_id_1)
{
ILanguagePack * lang = LanguagePackFactory::FromText(1, "STR_0000:\n");
ILanguagePack* lang = LanguagePackFactory::FromText(1, "STR_0000:\n");
ASSERT_EQ(lang->GetId(), 1);
ASSERT_EQ(lang->GetCount(), 1);
ASSERT_STREQ(lang->GetString(0), nullptr);
@ -40,7 +42,7 @@ TEST_F(LanguagePackTest, create_mutable_id_1)
TEST_F(LanguagePackTest, language_pack_simple)
{
ILanguagePack * lang = LanguagePackFactory::FromText(0, LanguageEnGB);
ILanguagePack* lang = LanguagePackFactory::FromText(0, LanguageEnGB);
ASSERT_EQ(lang->GetId(), 0);
ASSERT_EQ(lang->GetCount(), 4);
ASSERT_STREQ(lang->GetString(2), "Spiral Roller Coaster");
@ -57,7 +59,7 @@ TEST_F(LanguagePackTest, language_pack_simple)
TEST_F(LanguagePackTest, language_pack_multibyte)
{
ILanguagePack * lang = LanguagePackFactory::FromText(0, (const utf8 *)LanguageZhTW);
ILanguagePack* lang = LanguagePackFactory::FromText(0, (const utf8*)LanguageZhTW);
ASSERT_EQ(lang->GetId(), 0);
ASSERT_EQ(lang->GetCount(), 4);
ASSERT_STREQ(lang->GetString(2), u8"懸吊式雲霄飛車");
@ -70,50 +72,49 @@ TEST_F(LanguagePackTest, language_pack_multibyte)
delete lang;
}
const utf8 * LanguagePackTest::LanguageEnGB = "# STR_XXXX part is read and XXXX becomes the string id number.\n"
"# Everything after the colon and before the new line will be saved as the "
"string.\n"
"# Use # at the beginning of a line to leave a comment.\n"
"STR_0000 :\n"
"STR_0001 :{STRINGID} {COMMA16}\n"
"STR_0002 :Spiral Roller Coaster\n"
"STR_0003 :Stand-up Roller Coaster\n"
"<Arid Heights>\n"
"STR_SCNR :Arid Heights scenario string\n"
"STR_PARK :Arid Heights park string\n"
"STR_DTLS :Free of any financial limits, your challenge is to develop "
"this desert park while keeping the guests happy\n"
"[CONDORRD]\n"
"STR_NAME :my test ride\n"
"STR_DESC :ride description\n"
"STR_CPTY :ride capacity\n";
const utf8* LanguagePackTest::LanguageEnGB = "# STR_XXXX part is read and XXXX becomes the string id number.\n"
"# Everything after the colon and before the new line will be saved as the "
"string.\n"
"# Use # at the beginning of a line to leave a comment.\n"
"STR_0000 :\n"
"STR_0001 :{STRINGID} {COMMA16}\n"
"STR_0002 :Spiral Roller Coaster\n"
"STR_0003 :Stand-up Roller Coaster\n"
"<Arid Heights>\n"
"STR_SCNR :Arid Heights scenario string\n"
"STR_PARK :Arid Heights park string\n"
"STR_DTLS :Free of any financial limits, your challenge is to develop "
"this desert park while keeping the guests happy\n"
"[CONDORRD]\n"
"STR_NAME :my test ride\n"
"STR_DESC :ride description\n"
"STR_CPTY :ride capacity\n";
// This includes a few entries extracted from zh-TW localisation.
// It has to be declared as `unsigned char`, or else the values overflow signed byte.
const unsigned char LanguagePackTest::LanguageZhTW[] = {
0x53, 0x54, 0x52, 0x5f, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe8, 0x9e, 0xba, 0xe6, 0x97, 0x8b, 0xe5,
0xbc, 0x8f, 0xe9, 0x9b, 0xb2, 0xe9, 0x9c, 0x84, 0xe9, 0xa3, 0x9b, 0xe8, 0xbb, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x30,
0x30, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe7, 0xab, 0x99, 0xe7, 0xab, 0x8b, 0xe5, 0xbc, 0x8f, 0xe9, 0x9b, 0xb2,
0xe9, 0x9c, 0x84, 0xe9, 0xa3, 0x9b, 0xe8, 0xbb, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x30, 0x30, 0x30, 0x32, 0x20, 0x20,
0x20, 0x20, 0x3a, 0xe6, 0x87, 0xb8, 0xe5, 0x90, 0x8a, 0xe5, 0xbc, 0x8f, 0xe9, 0x9b, 0xb2, 0xe9, 0x9c, 0x84, 0xe9, 0xa3,
0x9b, 0xe8, 0xbb, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x30, 0x30, 0x30, 0x33, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe5, 0x8f,
0x8d, 0xe8, 0xbd, 0x89, 0xe5, 0xbc, 0x8f, 0xe9, 0x9b, 0xb2, 0xe9, 0x9c, 0x84, 0xe9, 0xa3, 0x9b, 0xe8, 0xbb, 0x8a, 0x0a,
0x3c, 0x46, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x20, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x73, 0x3e, 0x0a, 0x53,
0x54, 0x52, 0x5f, 0x53, 0x43, 0x4e, 0x52, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x46, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x20, 0x46,
0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x73, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x50, 0x41, 0x52, 0x4b, 0x20, 0x20, 0x20,
0x20, 0x3a, 0x46, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x20, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x73, 0x0a, 0x53,
0x54, 0x52, 0x5f, 0x44, 0x54, 0x4c, 0x53, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe5, 0x9c, 0xa8, 0xe9, 0x9a, 0xb1, 0xe8, 0x97,
0x8f, 0xe6, 0x96, 0xbc, 0xe6, 0xa3, 0xae, 0xe6, 0x9e, 0x97, 0xe6, 0xb7, 0xb1, 0xe8, 0x99, 0x95, 0xe7, 0x9a, 0x84, 0xe6,
0xb8, 0x85, 0xe7, 0xa9, 0xba, 0xe7, 0xaf, 0x84, 0xe5, 0x9c, 0x8d, 0xe4, 0xb8, 0xad, 0x2c, 0x20, 0xe5, 0xbb, 0xba, 0xe9,
0x80, 0xa0, 0xe4, 0xb8, 0x80, 0xe5, 0x80, 0x8b, 0xe5, 0xbe, 0x88, 0xe5, 0x8f, 0x97, 0xe6, 0xad, 0xa1, 0xe8, 0xbf, 0x8e,
0xe7, 0x9a, 0x84, 0xe6, 0xa8, 0x82, 0xe5, 0x9c, 0x92, 0x0a, 0x5b, 0x43, 0x4f, 0x4e, 0x44, 0x4f, 0x52, 0x52, 0x44, 0x5d,
0x0a, 0x53, 0x54, 0x52, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe7, 0xa5, 0x9e, 0xe9, 0xb7, 0xb9,
0xe6, 0x9a, 0xa2, 0xe9, 0x81, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x44, 0x45, 0x53, 0x43, 0x20, 0x20, 0x20, 0x20, 0x3a,
0xe4, 0xb9, 0x98, 0xe5, 0xae, 0xa2, 0xe4, 0xb9, 0x98, 0xe5, 0x9d, 0x90, 0xe6, 0x96, 0xbc, 0xe8, 0xbb, 0x8c, 0xe9, 0x81,
0x93, 0xe4, 0xb8, 0x8b, 0xe7, 0x9a, 0x84, 0xe7, 0xa5, 0x9e, 0xe9, 0xb7, 0xb9, 0xe9, 0x80, 0xa0, 0xe5, 0x9e, 0x8b, 0xe5,
0x88, 0x97, 0xe8, 0xbb, 0x8a, 0xe4, 0xb8, 0x8a, 0x2c, 0x20, 0xe5, 0xb0, 0x87, 0xe6, 0x9c, 0x83, 0xe6, 0x96, 0xbc, 0xe9,
0xa3, 0x9b, 0xe9, 0xa6, 0xb3, 0xe4, 0xb8, 0xad, 0xe9, 0xab, 0x94, 0xe9, 0xa9, 0x97, 0xe9, 0xa3, 0x9b, 0xe4, 0xb8, 0x80,
0xe8, 0x88, 0xac, 0xe7, 0x9a, 0x84, 0xe5, 0xbf, 0xab, 0xe6, 0x84, 0x9f, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x43, 0x50, 0x54,
0x59, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe6, 0xaf, 0x8f, 0xe8, 0xbb, 0x8a, 0xe5, 0x8d, 0xa1, 0x34, 0xe4, 0xbd, 0x8d, 0xe4,
0xb9, 0x98, 0xe5, 0xae, 0xa2, 0x0a, 0x00
};
const unsigned char LanguagePackTest::LanguageZhTW[]
= { 0x53, 0x54, 0x52, 0x5f, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe8, 0x9e, 0xba, 0xe6, 0x97, 0x8b, 0xe5,
0xbc, 0x8f, 0xe9, 0x9b, 0xb2, 0xe9, 0x9c, 0x84, 0xe9, 0xa3, 0x9b, 0xe8, 0xbb, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x30,
0x30, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe7, 0xab, 0x99, 0xe7, 0xab, 0x8b, 0xe5, 0xbc, 0x8f, 0xe9, 0x9b, 0xb2,
0xe9, 0x9c, 0x84, 0xe9, 0xa3, 0x9b, 0xe8, 0xbb, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x30, 0x30, 0x30, 0x32, 0x20, 0x20,
0x20, 0x20, 0x3a, 0xe6, 0x87, 0xb8, 0xe5, 0x90, 0x8a, 0xe5, 0xbc, 0x8f, 0xe9, 0x9b, 0xb2, 0xe9, 0x9c, 0x84, 0xe9, 0xa3,
0x9b, 0xe8, 0xbb, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x30, 0x30, 0x30, 0x33, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe5, 0x8f,
0x8d, 0xe8, 0xbd, 0x89, 0xe5, 0xbc, 0x8f, 0xe9, 0x9b, 0xb2, 0xe9, 0x9c, 0x84, 0xe9, 0xa3, 0x9b, 0xe8, 0xbb, 0x8a, 0x0a,
0x3c, 0x46, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x20, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x73, 0x3e, 0x0a, 0x53,
0x54, 0x52, 0x5f, 0x53, 0x43, 0x4e, 0x52, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x46, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x20, 0x46,
0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x73, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x50, 0x41, 0x52, 0x4b, 0x20, 0x20, 0x20,
0x20, 0x3a, 0x46, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x20, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x69, 0x65, 0x72, 0x73, 0x0a, 0x53,
0x54, 0x52, 0x5f, 0x44, 0x54, 0x4c, 0x53, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe5, 0x9c, 0xa8, 0xe9, 0x9a, 0xb1, 0xe8, 0x97,
0x8f, 0xe6, 0x96, 0xbc, 0xe6, 0xa3, 0xae, 0xe6, 0x9e, 0x97, 0xe6, 0xb7, 0xb1, 0xe8, 0x99, 0x95, 0xe7, 0x9a, 0x84, 0xe6,
0xb8, 0x85, 0xe7, 0xa9, 0xba, 0xe7, 0xaf, 0x84, 0xe5, 0x9c, 0x8d, 0xe4, 0xb8, 0xad, 0x2c, 0x20, 0xe5, 0xbb, 0xba, 0xe9,
0x80, 0xa0, 0xe4, 0xb8, 0x80, 0xe5, 0x80, 0x8b, 0xe5, 0xbe, 0x88, 0xe5, 0x8f, 0x97, 0xe6, 0xad, 0xa1, 0xe8, 0xbf, 0x8e,
0xe7, 0x9a, 0x84, 0xe6, 0xa8, 0x82, 0xe5, 0x9c, 0x92, 0x0a, 0x5b, 0x43, 0x4f, 0x4e, 0x44, 0x4f, 0x52, 0x52, 0x44, 0x5d,
0x0a, 0x53, 0x54, 0x52, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe7, 0xa5, 0x9e, 0xe9, 0xb7, 0xb9,
0xe6, 0x9a, 0xa2, 0xe9, 0x81, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x44, 0x45, 0x53, 0x43, 0x20, 0x20, 0x20, 0x20, 0x3a,
0xe4, 0xb9, 0x98, 0xe5, 0xae, 0xa2, 0xe4, 0xb9, 0x98, 0xe5, 0x9d, 0x90, 0xe6, 0x96, 0xbc, 0xe8, 0xbb, 0x8c, 0xe9, 0x81,
0x93, 0xe4, 0xb8, 0x8b, 0xe7, 0x9a, 0x84, 0xe7, 0xa5, 0x9e, 0xe9, 0xb7, 0xb9, 0xe9, 0x80, 0xa0, 0xe5, 0x9e, 0x8b, 0xe5,
0x88, 0x97, 0xe8, 0xbb, 0x8a, 0xe4, 0xb8, 0x8a, 0x2c, 0x20, 0xe5, 0xb0, 0x87, 0xe6, 0x9c, 0x83, 0xe6, 0x96, 0xbc, 0xe9,
0xa3, 0x9b, 0xe9, 0xa6, 0xb3, 0xe4, 0xb8, 0xad, 0xe9, 0xab, 0x94, 0xe9, 0xa9, 0x97, 0xe9, 0xa3, 0x9b, 0xe4, 0xb8, 0x80,
0xe8, 0x88, 0xac, 0xe7, 0x9a, 0x84, 0xe5, 0xbf, 0xab, 0xe6, 0x84, 0x9f, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x43, 0x50, 0x54,
0x59, 0x20, 0x20, 0x20, 0x20, 0x3a, 0xe6, 0xaf, 0x8f, 0xe8, 0xbb, 0x8a, 0xe5, 0x8d, 0xa1, 0x34, 0xe4, 0xbd, 0x8d, 0xe4,
0xb9, 0x98, 0xe5, 0xae, 0xa2, 0x0a, 0x00 };

View File

@ -7,8 +7,10 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "helpers/StringHelpers.hpp"
#include "openrct2/localisation/Localisation.h"
#include "helpers/StringHelpers.hpp"
#include <gtest/gtest.h>
class Localisation : public testing::Test

View File

@ -7,21 +7,21 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <string>
#include "TestData.h"
#include <gtest/gtest.h>
#include <openrct2/audio/AudioContext.h>
#include <openrct2/Context.h>
#include <openrct2/core/File.h>
#include <openrct2/core/Path.hpp>
#include <openrct2/core/String.hpp>
#include <openrct2/Game.h>
#include <openrct2/GameState.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/ParkImporter.h>
#include <openrct2/ride/Ride.h>
#include "TestData.h"
#include <openrct2/audio/AudioContext.h>
#include <openrct2/core/File.h>
#include <openrct2/core/Path.hpp>
#include <openrct2/core/String.hpp>
#include <openrct2/platform/platform.h>
#include <openrct2/Game.h>
#include <openrct2/ride/Ride.h>
#include <string>
using namespace OpenRCT2;

View File

@ -7,19 +7,19 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <string>
#include "TestData.h"
#include <gtest/gtest.h>
#include <openrct2/audio/AudioContext.h>
#include <openrct2/Context.h>
#include <openrct2/Game.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/audio/AudioContext.h>
#include <openrct2/core/File.h>
#include <openrct2/core/Path.hpp>
#include <openrct2/core/String.hpp>
#include <openrct2/OpenRCT2.h>
#include <openrct2/ride/Ride.h>
#include "TestData.h"
#include <openrct2/platform/platform.h>
#include <openrct2/Game.h>
#include <openrct2/ride/Ride.h>
#include <string>
using namespace OpenRCT2;
@ -30,7 +30,7 @@ protected:
{
for (int rideId = 0; rideId < MAX_RIDES; rideId++)
{
Ride * ride = get_ride(rideId);
Ride* ride = get_ride(rideId);
if (ride->type != RIDE_TYPE_NULL)
{
ride_ratings_update_ride(rideId);
@ -42,7 +42,7 @@ protected:
{
for (int rideId = 0; rideId < MAX_RIDES; rideId++)
{
Ride * ride = get_ride(rideId);
Ride* ride = get_ride(rideId);
if (ride->type != RIDE_TYPE_NULL)
{
std::string line = FormatRatings(ride);
@ -51,10 +51,11 @@ protected:
}
}
std::string FormatRatings(Ride * ride)
std::string FormatRatings(Ride* ride)
{
rating_tuple ratings = ride->ratings;
std::string line = String::StdFormat("%s: (%d, %d, %d)",
std::string line = String::StdFormat(
"%s: (%d, %d, %d)",
ride_type_get_enum_name(ride->type),
(int)ratings.excitement,
(int)ratings.intensity,
@ -90,7 +91,7 @@ TEST_F(RideRatings, all)
int expI = 0;
for (int rideId = 0; rideId < MAX_RIDES; rideId++)
{
Ride * ride = get_ride(rideId);
Ride* ride = get_ride(rideId);
if (ride->type != RIDE_TYPE_NULL)
{
std::string actual = FormatRatings(ride);

View File

@ -7,13 +7,14 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "AssertHelpers.hpp"
#include "helpers/StringHelpers.hpp"
#include <gtest/gtest.h>
#include <openrct2/core/String.hpp>
#include <string>
#include <tuple>
#include <utility>
#include <gtest/gtest.h>
#include <openrct2/core/String.hpp>
#include "AssertHelpers.hpp"
#include "helpers/StringHelpers.hpp"
using TCase = std::tuple<std::string, std::string, std::string>;
@ -25,22 +26,24 @@ class StringTest : public testing::TestWithParam<TCase>
// Tests for String::Trim
///////////////////////////////////////////////////////////////////////////////
INSTANTIATE_TEST_CASE_P(TrimData, StringTest, testing::Values(
// input after Trim after TrimStart
TCase("string", "string", "string"),
TCase(" string", "string", "string"),
TCase("string ", "string", "string "),
TCase(" some string ", "some string", "some string "),
TCase(" ", "", ""),
TCase(" ストリング", "ストリング", "ストリング"),
TCase("ストリング ", "ストリング", "ストリング "),
TCase(" ストリング ", "ストリング", "ストリング "),
TCase("    ", "", ""),
TCase("", "", ""),
TCase("\n", "", ""),
TCase("\n\n\n\r\n", "", ""),
TCase("\n\n\n\r\nstring\n\n", "string", "string\n\n")
));
INSTANTIATE_TEST_CASE_P(
TrimData,
StringTest,
testing::Values(
// input after Trim after TrimStart
TCase("string", "string", "string"),
TCase(" string", "string", "string"),
TCase("string ", "string", "string "),
TCase(" some string ", "some string", "some string "),
TCase(" ", "", ""),
TCase(" ストリング", "ストリング", "ストリング"),
TCase("ストリング ", "ストリング", "ストリング "),
TCase(" ストリング ", "ストリング", "ストリング "),
TCase("    ", "", ""),
TCase("", "", ""),
TCase("\n", "", ""),
TCase("\n\n\n\r\n", "", ""),
TCase("\n\n\n\r\nstring\n\n", "string", "string\n\n")));
TEST_P(StringTest, Trim)
{
auto testCase = GetParam();
@ -76,7 +79,7 @@ TEST_F(StringTest, Split_ByColonColon)
TEST_F(StringTest, Split_Empty)
{
auto actual = String::Split("", ".");
AssertVector<std::string>(actual, { });
AssertVector<std::string>(actual, {});
}
TEST_F(StringTest, Split_ByEmpty)
{

View File

@ -7,9 +7,10 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <openrct2/core/Path.hpp>
#include "TestData.h"
#include <openrct2/core/Path.hpp>
namespace TestData
{
std::string GetBasePath()

View File

@ -15,4 +15,4 @@ namespace TestData
{
std::string GetBasePath();
std::string GetParkPath(std::string name);
};
}; // namespace TestData

View File

@ -7,6 +7,8 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "TestData.h"
#include <gtest/gtest.h>
#include <openrct2/Context.h>
#include <openrct2/Game.h>
@ -14,7 +16,6 @@
#include <openrct2/ParkImporter.h>
#include <openrct2/world/Footpath.h>
#include <openrct2/world/Map.h>
#include "TestData.h"
using namespace OpenRCT2;
@ -24,16 +25,17 @@ protected:
static void SetUpTestCase()
{
std::string parkPath = TestData::GetParkPath("tile-element-tests.sv6");
gOpenRCT2Headless = true;
gOpenRCT2NoGraphics = true;
_context = CreateContext();
bool initialised = _context->Initialise();
gOpenRCT2Headless = true;
gOpenRCT2NoGraphics = true;
_context = CreateContext();
bool initialised = _context->Initialise();
ASSERT_TRUE(initialised);
load_from_sv6(parkPath.c_str());
game_load_init();
SUCCEED();
}
private:
static std::shared_ptr<IContext> _context;
};
@ -43,7 +45,7 @@ std::shared_ptr<IContext> TileElementWantsFootpathConnection::_context;
TEST_F(TileElementWantsFootpathConnection, FlatPath)
{
// Flat paths want to connect to other paths in any direction
const rct_tile_element * const pathElement = map_get_footpath_element(19, 18, 14);
const rct_tile_element* const pathElement = map_get_footpath_element(19, 18, 14);
ASSERT_NE(pathElement, nullptr);
EXPECT_TRUE(tile_element_wants_path_connection_towards({ 19, 18, 14, 0 }, nullptr));
EXPECT_TRUE(tile_element_wants_path_connection_towards({ 19, 18, 14, 1 }, nullptr));
@ -55,7 +57,7 @@ TEST_F(TileElementWantsFootpathConnection, FlatPath)
TEST_F(TileElementWantsFootpathConnection, SlopedPath)
{
// Sloped paths only want to connect in two directions, of which is one at a higher offset
const rct_tile_element * const slopedPathElement = map_get_footpath_element(18, 18, 14);
const rct_tile_element* const slopedPathElement = map_get_footpath_element(18, 18, 14);
ASSERT_NE(slopedPathElement, nullptr);
ASSERT_TRUE(footpath_element_is_sloped(slopedPathElement));
// Bottom and top of sloped path want a path connection
@ -74,7 +76,7 @@ TEST_F(TileElementWantsFootpathConnection, SlopedPath)
TEST_F(TileElementWantsFootpathConnection, Stall)
{
// Stalls usually have one path direction flag, but can have multiple (info kiosk for example)
const rct_tile_element * const stallElement = map_get_track_element_at(19 << 5, 15 << 5, 14);
const rct_tile_element* const stallElement = map_get_track_element_at(19 << 5, 15 << 5, 14);
ASSERT_NE(stallElement, nullptr);
EXPECT_TRUE(tile_element_wants_path_connection_towards({ 19, 15, 14, 0 }, nullptr));
EXPECT_FALSE(tile_element_wants_path_connection_towards({ 19, 15, 14, 1 }, nullptr));
@ -86,7 +88,7 @@ TEST_F(TileElementWantsFootpathConnection, Stall)
TEST_F(TileElementWantsFootpathConnection, RideEntrance)
{
// Ride entrances and exits want a connection in one direction
const rct_tile_element * const entranceElement = map_get_ride_entrance_element_at(18 << 5, 8 << 5, 14, false);
const rct_tile_element* const entranceElement = map_get_ride_entrance_element_at(18 << 5, 8 << 5, 14, false);
ASSERT_NE(entranceElement, nullptr);
EXPECT_TRUE(tile_element_wants_path_connection_towards({ 18, 8, 14, 0 }, nullptr));
EXPECT_FALSE(tile_element_wants_path_connection_towards({ 18, 8, 14, 1 }, nullptr));
@ -98,7 +100,7 @@ TEST_F(TileElementWantsFootpathConnection, RideEntrance)
TEST_F(TileElementWantsFootpathConnection, RideExit)
{
// The exit has been rotated; it wants a path connection in direction 1, but not 0 like the entrance
const rct_tile_element * const exitElement = map_get_ride_exit_element_at(18 << 5, 10 << 5, 14, false);
const rct_tile_element* const exitElement = map_get_ride_exit_element_at(18 << 5, 10 << 5, 14, false);
ASSERT_NE(exitElement, nullptr);
EXPECT_FALSE(tile_element_wants_path_connection_towards({ 18, 10, 14, 0 }, nullptr));
EXPECT_TRUE(tile_element_wants_path_connection_towards({ 18, 10, 14, 1 }, nullptr));

View File

@ -27,10 +27,10 @@ protected:
{
// Encode
sawyercoding_chunk_header chdr_in;
chdr_in.encoding = encoding_type;
chdr_in.length = sizeof(randomdata);
uint8_t * encodedDataBuffer = new uint8_t[BUFFER_SIZE];
size_t encodedDataSize = sawyercoding_write_chunk_buffer(encodedDataBuffer, (const uint8_t *)randomdata, chdr_in);
chdr_in.encoding = encoding_type;
chdr_in.length = sizeof(randomdata);
uint8_t* encodedDataBuffer = new uint8_t[BUFFER_SIZE];
size_t encodedDataSize = sawyercoding_write_chunk_buffer(encodedDataBuffer, (const uint8_t*)randomdata, chdr_in);
ASSERT_GT(encodedDataSize, sizeof(sawyercoding_chunk_header));
// Decode
@ -45,10 +45,10 @@ protected:
delete[] encodedDataBuffer;
}
void test_decode(const uint8_t * data, size_t size)
void test_decode(const uint8_t* data, size_t size)
{
auto expectedLength = size - sizeof(sawyercoding_chunk_header);
auto chdr_in = reinterpret_cast<const sawyercoding_chunk_header *>(data);
auto chdr_in = reinterpret_cast<const sawyercoding_chunk_header*>(data);
ASSERT_EQ(chdr_in->length, expectedLength);
MemoryStream ms(data, size);
@ -108,325 +108,320 @@ TEST_F(SawyerCodingTest, decode_chunk_rotate)
// 1024 bytes of random data
// use `dd if=/dev/urandom bs=1024 count=1 | xxd -i` to get your own
const uint8_t SawyerCodingTest::randomdata[] = {
0x3a, 0x97, 0x63, 0x8b, 0xbf, 0xe5, 0x6e, 0x0e, 0xc4, 0xac, 0xdc, 0x84, 0xd7, 0x68, 0xf1, 0x4d, 0xcb, 0xaf, 0x1e, 0x5a,
0x29, 0x40, 0x87, 0x80, 0x3f, 0xf9, 0xb8, 0xad, 0x01, 0xd3, 0x79, 0x3d, 0xe9, 0x87, 0xa8, 0x95, 0x68, 0xc0, 0xc2, 0x3d,
0x15, 0x87, 0xdb, 0xa6, 0x90, 0x8c, 0x26, 0x98, 0x2a, 0x3f, 0x2e, 0x0c, 0x82, 0x43, 0x00, 0x10, 0x6d, 0x60, 0xb9, 0xd4,
0xed, 0xf1, 0x49, 0xbb, 0xf6, 0x7f, 0x21, 0x24, 0xc3, 0xfb, 0x42, 0xe1, 0xfc, 0xb8, 0x82, 0x5e, 0x01, 0x5d, 0x96, 0x2d,
0x0f, 0x48, 0x12, 0xdf, 0x4b, 0x6c, 0x7e, 0x99, 0x01, 0xfa, 0x46, 0x7d, 0x2c, 0xeb, 0xd6, 0xf3, 0x77, 0xa3, 0x85, 0x8e,
0x00, 0x34, 0xee, 0x73, 0x31, 0x76, 0x53, 0x17, 0x5a, 0x2b, 0x19, 0x65, 0x2f, 0x32, 0x99, 0x57, 0xc4, 0xf8, 0x05, 0x0d,
0xc3, 0x59, 0x29, 0x9a, 0x19, 0x3c, 0x33, 0x58, 0x8c, 0xd1, 0x1f, 0x3b, 0xa5, 0x66, 0xa7, 0xfc, 0x7c, 0x99, 0xa9, 0x1a,
0x5e, 0x65, 0x92, 0x9e, 0x71, 0x27, 0x07, 0xbc, 0x71, 0xed, 0xe5, 0xc6, 0x0e, 0x74, 0xdb, 0x15, 0x91, 0xd7, 0xff, 0xf7,
0x30, 0x6e, 0x6a, 0x00, 0x40, 0x0e, 0x76, 0x8a, 0xb2, 0x31, 0xa3, 0x81, 0x83, 0xc8, 0xed, 0x08, 0x1f, 0xe5, 0x8d, 0x13,
0x3e, 0x9a, 0xca, 0x9c, 0xd4, 0x01, 0x28, 0xe6, 0xaf, 0xd6, 0x2f, 0xbc, 0xe1, 0xb7, 0xbb, 0x48, 0x88, 0x86, 0x19, 0xbb,
0x52, 0xfc, 0x18, 0xc9, 0xe3, 0x90, 0x88, 0x6c, 0x54, 0x53, 0x08, 0x26, 0xff, 0x38, 0xe3, 0x5e, 0x06, 0xa1, 0xac, 0xc2,
0x83, 0x23, 0x0d, 0x42, 0xe6, 0xa9, 0x81, 0x38, 0x0b, 0x4f, 0x16, 0x2a, 0x77, 0x3b, 0x24, 0xfb, 0x94, 0x53, 0x78, 0x6a,
0xf3, 0x17, 0x6a, 0x60, 0x44, 0x58, 0x5c, 0x50, 0x80, 0xc8, 0x0f, 0x87, 0x7b, 0x95, 0x0a, 0xdc, 0xf1, 0x1a, 0x6a, 0xa3,
0xff, 0x79, 0xda, 0x14, 0xd4, 0x6c, 0x7a, 0xfd, 0x7e, 0x1e, 0xfe, 0xd2, 0x28, 0xd0, 0x06, 0x95, 0x40, 0x80, 0xa1, 0x84,
0xc9, 0xc0, 0x4b, 0xa5, 0x97, 0xb2, 0xb9, 0x20, 0x27, 0x94, 0x87, 0x91, 0xba, 0xb2, 0xc6, 0xdb, 0x78, 0x19, 0x40, 0x35,
0x9f, 0xbd, 0xfb, 0xc1, 0x45, 0xbe, 0xdc, 0x30, 0xad, 0x38, 0xd4, 0x14, 0x46, 0x98, 0x2a, 0x90, 0xc8, 0x85, 0x5e, 0x7e,
0x76, 0x0f, 0xc4, 0x20, 0x07, 0x54, 0x1a, 0x60, 0x3a, 0x8c, 0x75, 0xb0, 0x43, 0xab, 0xbb, 0x05, 0xca, 0x93, 0xeb, 0x18,
0x94, 0xf1, 0x64, 0x8a, 0x01, 0xe0, 0xe6, 0x24, 0x78, 0x50, 0x93, 0xd3, 0xb9, 0xe1, 0xbf, 0x1c, 0xb0, 0x5c, 0xad, 0x94,
0x17, 0x8a, 0xd1, 0xef, 0x66, 0x08, 0xa7, 0x08, 0x6d, 0x6a, 0xb7, 0x06, 0x31, 0xa6, 0x9d, 0xe5, 0xb2, 0xd8, 0xf9, 0xa6,
0xf2, 0xe1, 0x63, 0xba, 0x36, 0x7a, 0x53, 0xc0, 0x22, 0x40, 0x3e, 0xa1, 0x95, 0xe5, 0xae, 0x8c, 0x35, 0x7d, 0x34, 0xae,
0x0c, 0x69, 0x8a, 0x0e, 0xd4, 0x53, 0x19, 0xc9, 0x90, 0x78, 0x36, 0x38, 0xc8, 0xa0, 0xc6, 0x49, 0xef, 0xe3, 0xb2, 0x1d,
0x7c, 0xd3, 0x38, 0x33, 0x51, 0x69, 0x2b, 0xd2, 0x8e, 0xa8, 0x6d, 0x9c, 0x01, 0x06, 0x9f, 0x93, 0xa5, 0x13, 0x86, 0x67,
0x72, 0x3e, 0xc7, 0x38, 0x97, 0xe6, 0x1d, 0xce, 0x61, 0x5a, 0x57, 0x10, 0xf7, 0x49, 0x32, 0xea, 0x8f, 0xce, 0x37, 0xea,
0x38, 0x65, 0x76, 0x86, 0xf4, 0x63, 0x9c, 0x44, 0xe6, 0x4c, 0x7b, 0x3f, 0x9b, 0x61, 0xf7, 0xb4, 0x2a, 0x7a, 0x9c, 0x03,
0x29, 0xf3, 0x6f, 0xff, 0x76, 0x1a, 0xb8, 0x21, 0xd7, 0xd0, 0xbf, 0x10, 0x1e, 0x82, 0x96, 0x9f, 0xe3, 0xc4, 0xcf, 0x19,
0x39, 0xd0, 0x4b, 0x4b, 0xa4, 0x7e, 0xd7, 0x4e, 0x3b, 0x2c, 0x0c, 0x35, 0xe1, 0xd4, 0x45, 0x10, 0x28, 0x67, 0x18, 0xdc,
0x2d, 0x77, 0x68, 0xf2, 0x39, 0x87, 0x52, 0xd7, 0xd1, 0x50, 0x04, 0x45, 0xf6, 0x1d, 0xb8, 0x9d, 0xfa, 0xe8, 0xd8, 0x94,
0xe0, 0xae, 0x31, 0x66, 0xc7, 0xee, 0xa9, 0xa8, 0x51, 0xe9, 0x14, 0x67, 0x53, 0x4c, 0x40, 0xf6, 0xee, 0x50, 0x67, 0x57,
0xf4, 0xd8, 0xd1, 0x95, 0x17, 0x2c, 0x5a, 0x72, 0x8f, 0xdc, 0xeb, 0x6c, 0x9b, 0x24, 0xfc, 0x67, 0x11, 0x07, 0x82, 0x2a,
0xae, 0xfb, 0xd9, 0xfd, 0x89, 0x75, 0x71, 0x75, 0x74, 0x08, 0x0d, 0xf7, 0xba, 0x5d, 0x56, 0xdf, 0x7e, 0x52, 0x5b, 0xce,
0xef, 0xeb, 0xf6, 0x32, 0x11, 0x93, 0x5f, 0xab, 0xfe, 0x08, 0xec, 0x20, 0x18, 0x0a, 0x4e, 0xc5, 0xb6, 0x42, 0xe4, 0x70,
0xbb, 0xba, 0x1b, 0xec, 0x01, 0x9c, 0xe5, 0x1c, 0xf4, 0xd2, 0x68, 0x0b, 0x30, 0x2d, 0xec, 0xda, 0x23, 0xff, 0xbd, 0x95,
0x46, 0x55, 0x59, 0xab, 0x03, 0x0f, 0xe4, 0xeb, 0x8c, 0xca, 0xc1, 0x13, 0x28, 0x49, 0x12, 0x66, 0xd7, 0x85, 0xcb, 0x21,
0x8d, 0x8a, 0x34, 0x4c, 0x2e, 0x28, 0x25, 0x79, 0xbf, 0x98, 0x04, 0xcd, 0x8a, 0x3e, 0xad, 0x08, 0xd3, 0x21, 0x32, 0xed,
0x54, 0x7e, 0x17, 0xfe, 0x89, 0xe9, 0x09, 0x18, 0xac, 0x96, 0xda, 0x51, 0x61, 0x85, 0x44, 0xd2, 0xdf, 0xd9, 0x61, 0xa2,
0x44, 0x07, 0x29, 0xa5, 0xdc, 0x16, 0xac, 0x3d, 0x6e, 0x27, 0xb6, 0x5a, 0x15, 0x87, 0x6c, 0x48, 0x3e, 0x34, 0xdd, 0xec,
0xf2, 0x7c, 0xc6, 0x87, 0x0f, 0xcf, 0xac, 0xde, 0x42, 0x02, 0x93, 0xff, 0x4f, 0x10, 0x0f, 0x03, 0xf3, 0x1b, 0x1e, 0xaf,
0x94, 0x8e, 0x77, 0x7c, 0x66, 0x65, 0xfb, 0xd9, 0x0d, 0xf8, 0x36, 0x0c, 0xac, 0xdc, 0x8e, 0xd1, 0x1e, 0x19, 0xa8, 0x87,
0x97, 0x39, 0x77, 0x98, 0x6c, 0xfb, 0x5d, 0xc1, 0x09, 0x7e, 0x5d, 0xab, 0xde, 0xdc, 0x1f, 0x21, 0xd0, 0x7a, 0xaa, 0xeb,
0x96, 0x60, 0xf9, 0x95, 0xed, 0x13, 0xf4, 0x82, 0xa9, 0x94, 0x7e, 0xa8, 0x5e, 0xe2, 0xca, 0x08, 0xed, 0xfe, 0x9d, 0x94,
0x3f, 0x08, 0xd8, 0xd8, 0x9d, 0xb0, 0x84, 0xd6, 0x6a, 0xcb, 0xc1, 0xd4, 0xd0, 0xe8, 0xe7, 0xae, 0x44, 0x28, 0x47, 0x75,
0xa6, 0x2a, 0x40, 0x0b, 0x82, 0x57, 0xd5, 0x49, 0x40, 0x85, 0x5c, 0x92, 0x95, 0x6b, 0x7d, 0xbe, 0xcc, 0xb6, 0x2d, 0x2b,
0x71, 0x85, 0x63, 0x39, 0xfa, 0xbc, 0x19, 0x7c, 0xe2, 0x3a, 0x81, 0xf1, 0x86, 0x9e, 0x46, 0x3d, 0x5f, 0x71, 0xa4, 0xb7,
0xd4, 0x2c, 0x98, 0xfa, 0xb5, 0x95, 0xac, 0x33, 0x1a, 0x53, 0x9d, 0xe3, 0x4e, 0x5d, 0x4f, 0x54, 0x0d, 0xe8, 0xa4, 0x32,
0x25, 0x4d, 0x5e, 0x4c, 0xe1, 0xae, 0x46, 0x85, 0x1e, 0xc4, 0x20, 0xdf, 0x73, 0x1e, 0x81, 0x40, 0xa2, 0x33, 0x75, 0x1e,
0x1d, 0x1d, 0x7c, 0x1f, 0x07, 0xe5, 0x9e, 0x76, 0x9f, 0x42, 0xeb, 0xc4, 0xb4, 0xd3, 0xcb, 0x55, 0xe8, 0xbf, 0xf7, 0xeb,
0x7c, 0x2d, 0xa5, 0xfd, 0xda, 0xb4, 0x5b, 0x1f, 0xa8, 0xd2, 0xeb, 0xdf, 0xd9, 0xf2, 0x35, 0xc6, 0x0c, 0x36, 0x66, 0x28,
0x95, 0xe2, 0x34, 0x64, 0xea, 0xaf, 0x3a, 0x36, 0x3c, 0x38, 0x31, 0x99, 0x8d, 0x80, 0x78, 0x18, 0x48, 0x2c, 0xe9, 0xe5,
0xb7, 0xe6, 0x2e, 0x73, 0xf1, 0x7c, 0x84, 0x21, 0x04, 0x00, 0x8e, 0x12, 0x66, 0x6c, 0x9b, 0x09, 0x88, 0xe2, 0xd5, 0xec,
0xb4, 0xdd, 0x2b, 0xda, 0x29, 0x6f, 0x1b, 0x81, 0x21, 0xe4, 0x5c, 0x36, 0x73, 0x2d, 0x9d, 0xdd, 0xb6, 0x69, 0x21, 0x40,
0x4e, 0x70, 0xde, 0x9d, 0x0c, 0x17, 0x1d, 0x15, 0x29, 0x5b, 0xd0, 0x66, 0x72, 0xb8, 0x38, 0x80, 0xbe, 0x9e, 0xd7, 0x5e,
0xb5, 0x72, 0x22, 0xbc
};
const uint8_t SawyerCodingTest::randomdata[]
= { 0x3a, 0x97, 0x63, 0x8b, 0xbf, 0xe5, 0x6e, 0x0e, 0xc4, 0xac, 0xdc, 0x84, 0xd7, 0x68, 0xf1, 0x4d, 0xcb, 0xaf, 0x1e, 0x5a,
0x29, 0x40, 0x87, 0x80, 0x3f, 0xf9, 0xb8, 0xad, 0x01, 0xd3, 0x79, 0x3d, 0xe9, 0x87, 0xa8, 0x95, 0x68, 0xc0, 0xc2, 0x3d,
0x15, 0x87, 0xdb, 0xa6, 0x90, 0x8c, 0x26, 0x98, 0x2a, 0x3f, 0x2e, 0x0c, 0x82, 0x43, 0x00, 0x10, 0x6d, 0x60, 0xb9, 0xd4,
0xed, 0xf1, 0x49, 0xbb, 0xf6, 0x7f, 0x21, 0x24, 0xc3, 0xfb, 0x42, 0xe1, 0xfc, 0xb8, 0x82, 0x5e, 0x01, 0x5d, 0x96, 0x2d,
0x0f, 0x48, 0x12, 0xdf, 0x4b, 0x6c, 0x7e, 0x99, 0x01, 0xfa, 0x46, 0x7d, 0x2c, 0xeb, 0xd6, 0xf3, 0x77, 0xa3, 0x85, 0x8e,
0x00, 0x34, 0xee, 0x73, 0x31, 0x76, 0x53, 0x17, 0x5a, 0x2b, 0x19, 0x65, 0x2f, 0x32, 0x99, 0x57, 0xc4, 0xf8, 0x05, 0x0d,
0xc3, 0x59, 0x29, 0x9a, 0x19, 0x3c, 0x33, 0x58, 0x8c, 0xd1, 0x1f, 0x3b, 0xa5, 0x66, 0xa7, 0xfc, 0x7c, 0x99, 0xa9, 0x1a,
0x5e, 0x65, 0x92, 0x9e, 0x71, 0x27, 0x07, 0xbc, 0x71, 0xed, 0xe5, 0xc6, 0x0e, 0x74, 0xdb, 0x15, 0x91, 0xd7, 0xff, 0xf7,
0x30, 0x6e, 0x6a, 0x00, 0x40, 0x0e, 0x76, 0x8a, 0xb2, 0x31, 0xa3, 0x81, 0x83, 0xc8, 0xed, 0x08, 0x1f, 0xe5, 0x8d, 0x13,
0x3e, 0x9a, 0xca, 0x9c, 0xd4, 0x01, 0x28, 0xe6, 0xaf, 0xd6, 0x2f, 0xbc, 0xe1, 0xb7, 0xbb, 0x48, 0x88, 0x86, 0x19, 0xbb,
0x52, 0xfc, 0x18, 0xc9, 0xe3, 0x90, 0x88, 0x6c, 0x54, 0x53, 0x08, 0x26, 0xff, 0x38, 0xe3, 0x5e, 0x06, 0xa1, 0xac, 0xc2,
0x83, 0x23, 0x0d, 0x42, 0xe6, 0xa9, 0x81, 0x38, 0x0b, 0x4f, 0x16, 0x2a, 0x77, 0x3b, 0x24, 0xfb, 0x94, 0x53, 0x78, 0x6a,
0xf3, 0x17, 0x6a, 0x60, 0x44, 0x58, 0x5c, 0x50, 0x80, 0xc8, 0x0f, 0x87, 0x7b, 0x95, 0x0a, 0xdc, 0xf1, 0x1a, 0x6a, 0xa3,
0xff, 0x79, 0xda, 0x14, 0xd4, 0x6c, 0x7a, 0xfd, 0x7e, 0x1e, 0xfe, 0xd2, 0x28, 0xd0, 0x06, 0x95, 0x40, 0x80, 0xa1, 0x84,
0xc9, 0xc0, 0x4b, 0xa5, 0x97, 0xb2, 0xb9, 0x20, 0x27, 0x94, 0x87, 0x91, 0xba, 0xb2, 0xc6, 0xdb, 0x78, 0x19, 0x40, 0x35,
0x9f, 0xbd, 0xfb, 0xc1, 0x45, 0xbe, 0xdc, 0x30, 0xad, 0x38, 0xd4, 0x14, 0x46, 0x98, 0x2a, 0x90, 0xc8, 0x85, 0x5e, 0x7e,
0x76, 0x0f, 0xc4, 0x20, 0x07, 0x54, 0x1a, 0x60, 0x3a, 0x8c, 0x75, 0xb0, 0x43, 0xab, 0xbb, 0x05, 0xca, 0x93, 0xeb, 0x18,
0x94, 0xf1, 0x64, 0x8a, 0x01, 0xe0, 0xe6, 0x24, 0x78, 0x50, 0x93, 0xd3, 0xb9, 0xe1, 0xbf, 0x1c, 0xb0, 0x5c, 0xad, 0x94,
0x17, 0x8a, 0xd1, 0xef, 0x66, 0x08, 0xa7, 0x08, 0x6d, 0x6a, 0xb7, 0x06, 0x31, 0xa6, 0x9d, 0xe5, 0xb2, 0xd8, 0xf9, 0xa6,
0xf2, 0xe1, 0x63, 0xba, 0x36, 0x7a, 0x53, 0xc0, 0x22, 0x40, 0x3e, 0xa1, 0x95, 0xe5, 0xae, 0x8c, 0x35, 0x7d, 0x34, 0xae,
0x0c, 0x69, 0x8a, 0x0e, 0xd4, 0x53, 0x19, 0xc9, 0x90, 0x78, 0x36, 0x38, 0xc8, 0xa0, 0xc6, 0x49, 0xef, 0xe3, 0xb2, 0x1d,
0x7c, 0xd3, 0x38, 0x33, 0x51, 0x69, 0x2b, 0xd2, 0x8e, 0xa8, 0x6d, 0x9c, 0x01, 0x06, 0x9f, 0x93, 0xa5, 0x13, 0x86, 0x67,
0x72, 0x3e, 0xc7, 0x38, 0x97, 0xe6, 0x1d, 0xce, 0x61, 0x5a, 0x57, 0x10, 0xf7, 0x49, 0x32, 0xea, 0x8f, 0xce, 0x37, 0xea,
0x38, 0x65, 0x76, 0x86, 0xf4, 0x63, 0x9c, 0x44, 0xe6, 0x4c, 0x7b, 0x3f, 0x9b, 0x61, 0xf7, 0xb4, 0x2a, 0x7a, 0x9c, 0x03,
0x29, 0xf3, 0x6f, 0xff, 0x76, 0x1a, 0xb8, 0x21, 0xd7, 0xd0, 0xbf, 0x10, 0x1e, 0x82, 0x96, 0x9f, 0xe3, 0xc4, 0xcf, 0x19,
0x39, 0xd0, 0x4b, 0x4b, 0xa4, 0x7e, 0xd7, 0x4e, 0x3b, 0x2c, 0x0c, 0x35, 0xe1, 0xd4, 0x45, 0x10, 0x28, 0x67, 0x18, 0xdc,
0x2d, 0x77, 0x68, 0xf2, 0x39, 0x87, 0x52, 0xd7, 0xd1, 0x50, 0x04, 0x45, 0xf6, 0x1d, 0xb8, 0x9d, 0xfa, 0xe8, 0xd8, 0x94,
0xe0, 0xae, 0x31, 0x66, 0xc7, 0xee, 0xa9, 0xa8, 0x51, 0xe9, 0x14, 0x67, 0x53, 0x4c, 0x40, 0xf6, 0xee, 0x50, 0x67, 0x57,
0xf4, 0xd8, 0xd1, 0x95, 0x17, 0x2c, 0x5a, 0x72, 0x8f, 0xdc, 0xeb, 0x6c, 0x9b, 0x24, 0xfc, 0x67, 0x11, 0x07, 0x82, 0x2a,
0xae, 0xfb, 0xd9, 0xfd, 0x89, 0x75, 0x71, 0x75, 0x74, 0x08, 0x0d, 0xf7, 0xba, 0x5d, 0x56, 0xdf, 0x7e, 0x52, 0x5b, 0xce,
0xef, 0xeb, 0xf6, 0x32, 0x11, 0x93, 0x5f, 0xab, 0xfe, 0x08, 0xec, 0x20, 0x18, 0x0a, 0x4e, 0xc5, 0xb6, 0x42, 0xe4, 0x70,
0xbb, 0xba, 0x1b, 0xec, 0x01, 0x9c, 0xe5, 0x1c, 0xf4, 0xd2, 0x68, 0x0b, 0x30, 0x2d, 0xec, 0xda, 0x23, 0xff, 0xbd, 0x95,
0x46, 0x55, 0x59, 0xab, 0x03, 0x0f, 0xe4, 0xeb, 0x8c, 0xca, 0xc1, 0x13, 0x28, 0x49, 0x12, 0x66, 0xd7, 0x85, 0xcb, 0x21,
0x8d, 0x8a, 0x34, 0x4c, 0x2e, 0x28, 0x25, 0x79, 0xbf, 0x98, 0x04, 0xcd, 0x8a, 0x3e, 0xad, 0x08, 0xd3, 0x21, 0x32, 0xed,
0x54, 0x7e, 0x17, 0xfe, 0x89, 0xe9, 0x09, 0x18, 0xac, 0x96, 0xda, 0x51, 0x61, 0x85, 0x44, 0xd2, 0xdf, 0xd9, 0x61, 0xa2,
0x44, 0x07, 0x29, 0xa5, 0xdc, 0x16, 0xac, 0x3d, 0x6e, 0x27, 0xb6, 0x5a, 0x15, 0x87, 0x6c, 0x48, 0x3e, 0x34, 0xdd, 0xec,
0xf2, 0x7c, 0xc6, 0x87, 0x0f, 0xcf, 0xac, 0xde, 0x42, 0x02, 0x93, 0xff, 0x4f, 0x10, 0x0f, 0x03, 0xf3, 0x1b, 0x1e, 0xaf,
0x94, 0x8e, 0x77, 0x7c, 0x66, 0x65, 0xfb, 0xd9, 0x0d, 0xf8, 0x36, 0x0c, 0xac, 0xdc, 0x8e, 0xd1, 0x1e, 0x19, 0xa8, 0x87,
0x97, 0x39, 0x77, 0x98, 0x6c, 0xfb, 0x5d, 0xc1, 0x09, 0x7e, 0x5d, 0xab, 0xde, 0xdc, 0x1f, 0x21, 0xd0, 0x7a, 0xaa, 0xeb,
0x96, 0x60, 0xf9, 0x95, 0xed, 0x13, 0xf4, 0x82, 0xa9, 0x94, 0x7e, 0xa8, 0x5e, 0xe2, 0xca, 0x08, 0xed, 0xfe, 0x9d, 0x94,
0x3f, 0x08, 0xd8, 0xd8, 0x9d, 0xb0, 0x84, 0xd6, 0x6a, 0xcb, 0xc1, 0xd4, 0xd0, 0xe8, 0xe7, 0xae, 0x44, 0x28, 0x47, 0x75,
0xa6, 0x2a, 0x40, 0x0b, 0x82, 0x57, 0xd5, 0x49, 0x40, 0x85, 0x5c, 0x92, 0x95, 0x6b, 0x7d, 0xbe, 0xcc, 0xb6, 0x2d, 0x2b,
0x71, 0x85, 0x63, 0x39, 0xfa, 0xbc, 0x19, 0x7c, 0xe2, 0x3a, 0x81, 0xf1, 0x86, 0x9e, 0x46, 0x3d, 0x5f, 0x71, 0xa4, 0xb7,
0xd4, 0x2c, 0x98, 0xfa, 0xb5, 0x95, 0xac, 0x33, 0x1a, 0x53, 0x9d, 0xe3, 0x4e, 0x5d, 0x4f, 0x54, 0x0d, 0xe8, 0xa4, 0x32,
0x25, 0x4d, 0x5e, 0x4c, 0xe1, 0xae, 0x46, 0x85, 0x1e, 0xc4, 0x20, 0xdf, 0x73, 0x1e, 0x81, 0x40, 0xa2, 0x33, 0x75, 0x1e,
0x1d, 0x1d, 0x7c, 0x1f, 0x07, 0xe5, 0x9e, 0x76, 0x9f, 0x42, 0xeb, 0xc4, 0xb4, 0xd3, 0xcb, 0x55, 0xe8, 0xbf, 0xf7, 0xeb,
0x7c, 0x2d, 0xa5, 0xfd, 0xda, 0xb4, 0x5b, 0x1f, 0xa8, 0xd2, 0xeb, 0xdf, 0xd9, 0xf2, 0x35, 0xc6, 0x0c, 0x36, 0x66, 0x28,
0x95, 0xe2, 0x34, 0x64, 0xea, 0xaf, 0x3a, 0x36, 0x3c, 0x38, 0x31, 0x99, 0x8d, 0x80, 0x78, 0x18, 0x48, 0x2c, 0xe9, 0xe5,
0xb7, 0xe6, 0x2e, 0x73, 0xf1, 0x7c, 0x84, 0x21, 0x04, 0x00, 0x8e, 0x12, 0x66, 0x6c, 0x9b, 0x09, 0x88, 0xe2, 0xd5, 0xec,
0xb4, 0xdd, 0x2b, 0xda, 0x29, 0x6f, 0x1b, 0x81, 0x21, 0xe4, 0x5c, 0x36, 0x73, 0x2d, 0x9d, 0xdd, 0xb6, 0x69, 0x21, 0x40,
0x4e, 0x70, 0xde, 0x9d, 0x0c, 0x17, 0x1d, 0x15, 0x29, 0x5b, 0xd0, 0x66, 0x72, 0xb8, 0x38, 0x80, 0xbe, 0x9e, 0xd7, 0x5e,
0xb5, 0x72, 0x22, 0xbc };
// Following are compressed versions of the data above.
const uint8_t SawyerCodingTest::nonedata[] = {
0x00, 0x00, 0x04, 0x00, 0x00, 0x3a, 0x97, 0x63, 0x8b, 0xbf, 0xe5, 0x6e, 0x0e, 0xc4, 0xac, 0xdc, 0x84, 0xd7, 0x68, 0xf1,
0x4d, 0xcb, 0xaf, 0x1e, 0x5a, 0x29, 0x40, 0x87, 0x80, 0x3f, 0xf9, 0xb8, 0xad, 0x01, 0xd3, 0x79, 0x3d, 0xe9, 0x87, 0xa8,
0x95, 0x68, 0xc0, 0xc2, 0x3d, 0x15, 0x87, 0xdb, 0xa6, 0x90, 0x8c, 0x26, 0x98, 0x2a, 0x3f, 0x2e, 0x0c, 0x82, 0x43, 0x00,
0x10, 0x6d, 0x60, 0xb9, 0xd4, 0xed, 0xf1, 0x49, 0xbb, 0xf6, 0x7f, 0x21, 0x24, 0xc3, 0xfb, 0x42, 0xe1, 0xfc, 0xb8, 0x82,
0x5e, 0x01, 0x5d, 0x96, 0x2d, 0x0f, 0x48, 0x12, 0xdf, 0x4b, 0x6c, 0x7e, 0x99, 0x01, 0xfa, 0x46, 0x7d, 0x2c, 0xeb, 0xd6,
0xf3, 0x77, 0xa3, 0x85, 0x8e, 0x00, 0x34, 0xee, 0x73, 0x31, 0x76, 0x53, 0x17, 0x5a, 0x2b, 0x19, 0x65, 0x2f, 0x32, 0x99,
0x57, 0xc4, 0xf8, 0x05, 0x0d, 0xc3, 0x59, 0x29, 0x9a, 0x19, 0x3c, 0x33, 0x58, 0x8c, 0xd1, 0x1f, 0x3b, 0xa5, 0x66, 0xa7,
0xfc, 0x7c, 0x99, 0xa9, 0x1a, 0x5e, 0x65, 0x92, 0x9e, 0x71, 0x27, 0x07, 0xbc, 0x71, 0xed, 0xe5, 0xc6, 0x0e, 0x74, 0xdb,
0x15, 0x91, 0xd7, 0xff, 0xf7, 0x30, 0x6e, 0x6a, 0x00, 0x40, 0x0e, 0x76, 0x8a, 0xb2, 0x31, 0xa3, 0x81, 0x83, 0xc8, 0xed,
0x08, 0x1f, 0xe5, 0x8d, 0x13, 0x3e, 0x9a, 0xca, 0x9c, 0xd4, 0x01, 0x28, 0xe6, 0xaf, 0xd6, 0x2f, 0xbc, 0xe1, 0xb7, 0xbb,
0x48, 0x88, 0x86, 0x19, 0xbb, 0x52, 0xfc, 0x18, 0xc9, 0xe3, 0x90, 0x88, 0x6c, 0x54, 0x53, 0x08, 0x26, 0xff, 0x38, 0xe3,
0x5e, 0x06, 0xa1, 0xac, 0xc2, 0x83, 0x23, 0x0d, 0x42, 0xe6, 0xa9, 0x81, 0x38, 0x0b, 0x4f, 0x16, 0x2a, 0x77, 0x3b, 0x24,
0xfb, 0x94, 0x53, 0x78, 0x6a, 0xf3, 0x17, 0x6a, 0x60, 0x44, 0x58, 0x5c, 0x50, 0x80, 0xc8, 0x0f, 0x87, 0x7b, 0x95, 0x0a,
0xdc, 0xf1, 0x1a, 0x6a, 0xa3, 0xff, 0x79, 0xda, 0x14, 0xd4, 0x6c, 0x7a, 0xfd, 0x7e, 0x1e, 0xfe, 0xd2, 0x28, 0xd0, 0x06,
0x95, 0x40, 0x80, 0xa1, 0x84, 0xc9, 0xc0, 0x4b, 0xa5, 0x97, 0xb2, 0xb9, 0x20, 0x27, 0x94, 0x87, 0x91, 0xba, 0xb2, 0xc6,
0xdb, 0x78, 0x19, 0x40, 0x35, 0x9f, 0xbd, 0xfb, 0xc1, 0x45, 0xbe, 0xdc, 0x30, 0xad, 0x38, 0xd4, 0x14, 0x46, 0x98, 0x2a,
0x90, 0xc8, 0x85, 0x5e, 0x7e, 0x76, 0x0f, 0xc4, 0x20, 0x07, 0x54, 0x1a, 0x60, 0x3a, 0x8c, 0x75, 0xb0, 0x43, 0xab, 0xbb,
0x05, 0xca, 0x93, 0xeb, 0x18, 0x94, 0xf1, 0x64, 0x8a, 0x01, 0xe0, 0xe6, 0x24, 0x78, 0x50, 0x93, 0xd3, 0xb9, 0xe1, 0xbf,
0x1c, 0xb0, 0x5c, 0xad, 0x94, 0x17, 0x8a, 0xd1, 0xef, 0x66, 0x08, 0xa7, 0x08, 0x6d, 0x6a, 0xb7, 0x06, 0x31, 0xa6, 0x9d,
0xe5, 0xb2, 0xd8, 0xf9, 0xa6, 0xf2, 0xe1, 0x63, 0xba, 0x36, 0x7a, 0x53, 0xc0, 0x22, 0x40, 0x3e, 0xa1, 0x95, 0xe5, 0xae,
0x8c, 0x35, 0x7d, 0x34, 0xae, 0x0c, 0x69, 0x8a, 0x0e, 0xd4, 0x53, 0x19, 0xc9, 0x90, 0x78, 0x36, 0x38, 0xc8, 0xa0, 0xc6,
0x49, 0xef, 0xe3, 0xb2, 0x1d, 0x7c, 0xd3, 0x38, 0x33, 0x51, 0x69, 0x2b, 0xd2, 0x8e, 0xa8, 0x6d, 0x9c, 0x01, 0x06, 0x9f,
0x93, 0xa5, 0x13, 0x86, 0x67, 0x72, 0x3e, 0xc7, 0x38, 0x97, 0xe6, 0x1d, 0xce, 0x61, 0x5a, 0x57, 0x10, 0xf7, 0x49, 0x32,
0xea, 0x8f, 0xce, 0x37, 0xea, 0x38, 0x65, 0x76, 0x86, 0xf4, 0x63, 0x9c, 0x44, 0xe6, 0x4c, 0x7b, 0x3f, 0x9b, 0x61, 0xf7,
0xb4, 0x2a, 0x7a, 0x9c, 0x03, 0x29, 0xf3, 0x6f, 0xff, 0x76, 0x1a, 0xb8, 0x21, 0xd7, 0xd0, 0xbf, 0x10, 0x1e, 0x82, 0x96,
0x9f, 0xe3, 0xc4, 0xcf, 0x19, 0x39, 0xd0, 0x4b, 0x4b, 0xa4, 0x7e, 0xd7, 0x4e, 0x3b, 0x2c, 0x0c, 0x35, 0xe1, 0xd4, 0x45,
0x10, 0x28, 0x67, 0x18, 0xdc, 0x2d, 0x77, 0x68, 0xf2, 0x39, 0x87, 0x52, 0xd7, 0xd1, 0x50, 0x04, 0x45, 0xf6, 0x1d, 0xb8,
0x9d, 0xfa, 0xe8, 0xd8, 0x94, 0xe0, 0xae, 0x31, 0x66, 0xc7, 0xee, 0xa9, 0xa8, 0x51, 0xe9, 0x14, 0x67, 0x53, 0x4c, 0x40,
0xf6, 0xee, 0x50, 0x67, 0x57, 0xf4, 0xd8, 0xd1, 0x95, 0x17, 0x2c, 0x5a, 0x72, 0x8f, 0xdc, 0xeb, 0x6c, 0x9b, 0x24, 0xfc,
0x67, 0x11, 0x07, 0x82, 0x2a, 0xae, 0xfb, 0xd9, 0xfd, 0x89, 0x75, 0x71, 0x75, 0x74, 0x08, 0x0d, 0xf7, 0xba, 0x5d, 0x56,
0xdf, 0x7e, 0x52, 0x5b, 0xce, 0xef, 0xeb, 0xf6, 0x32, 0x11, 0x93, 0x5f, 0xab, 0xfe, 0x08, 0xec, 0x20, 0x18, 0x0a, 0x4e,
0xc5, 0xb6, 0x42, 0xe4, 0x70, 0xbb, 0xba, 0x1b, 0xec, 0x01, 0x9c, 0xe5, 0x1c, 0xf4, 0xd2, 0x68, 0x0b, 0x30, 0x2d, 0xec,
0xda, 0x23, 0xff, 0xbd, 0x95, 0x46, 0x55, 0x59, 0xab, 0x03, 0x0f, 0xe4, 0xeb, 0x8c, 0xca, 0xc1, 0x13, 0x28, 0x49, 0x12,
0x66, 0xd7, 0x85, 0xcb, 0x21, 0x8d, 0x8a, 0x34, 0x4c, 0x2e, 0x28, 0x25, 0x79, 0xbf, 0x98, 0x04, 0xcd, 0x8a, 0x3e, 0xad,
0x08, 0xd3, 0x21, 0x32, 0xed, 0x54, 0x7e, 0x17, 0xfe, 0x89, 0xe9, 0x09, 0x18, 0xac, 0x96, 0xda, 0x51, 0x61, 0x85, 0x44,
0xd2, 0xdf, 0xd9, 0x61, 0xa2, 0x44, 0x07, 0x29, 0xa5, 0xdc, 0x16, 0xac, 0x3d, 0x6e, 0x27, 0xb6, 0x5a, 0x15, 0x87, 0x6c,
0x48, 0x3e, 0x34, 0xdd, 0xec, 0xf2, 0x7c, 0xc6, 0x87, 0x0f, 0xcf, 0xac, 0xde, 0x42, 0x02, 0x93, 0xff, 0x4f, 0x10, 0x0f,
0x03, 0xf3, 0x1b, 0x1e, 0xaf, 0x94, 0x8e, 0x77, 0x7c, 0x66, 0x65, 0xfb, 0xd9, 0x0d, 0xf8, 0x36, 0x0c, 0xac, 0xdc, 0x8e,
0xd1, 0x1e, 0x19, 0xa8, 0x87, 0x97, 0x39, 0x77, 0x98, 0x6c, 0xfb, 0x5d, 0xc1, 0x09, 0x7e, 0x5d, 0xab, 0xde, 0xdc, 0x1f,
0x21, 0xd0, 0x7a, 0xaa, 0xeb, 0x96, 0x60, 0xf9, 0x95, 0xed, 0x13, 0xf4, 0x82, 0xa9, 0x94, 0x7e, 0xa8, 0x5e, 0xe2, 0xca,
0x08, 0xed, 0xfe, 0x9d, 0x94, 0x3f, 0x08, 0xd8, 0xd8, 0x9d, 0xb0, 0x84, 0xd6, 0x6a, 0xcb, 0xc1, 0xd4, 0xd0, 0xe8, 0xe7,
0xae, 0x44, 0x28, 0x47, 0x75, 0xa6, 0x2a, 0x40, 0x0b, 0x82, 0x57, 0xd5, 0x49, 0x40, 0x85, 0x5c, 0x92, 0x95, 0x6b, 0x7d,
0xbe, 0xcc, 0xb6, 0x2d, 0x2b, 0x71, 0x85, 0x63, 0x39, 0xfa, 0xbc, 0x19, 0x7c, 0xe2, 0x3a, 0x81, 0xf1, 0x86, 0x9e, 0x46,
0x3d, 0x5f, 0x71, 0xa4, 0xb7, 0xd4, 0x2c, 0x98, 0xfa, 0xb5, 0x95, 0xac, 0x33, 0x1a, 0x53, 0x9d, 0xe3, 0x4e, 0x5d, 0x4f,
0x54, 0x0d, 0xe8, 0xa4, 0x32, 0x25, 0x4d, 0x5e, 0x4c, 0xe1, 0xae, 0x46, 0x85, 0x1e, 0xc4, 0x20, 0xdf, 0x73, 0x1e, 0x81,
0x40, 0xa2, 0x33, 0x75, 0x1e, 0x1d, 0x1d, 0x7c, 0x1f, 0x07, 0xe5, 0x9e, 0x76, 0x9f, 0x42, 0xeb, 0xc4, 0xb4, 0xd3, 0xcb,
0x55, 0xe8, 0xbf, 0xf7, 0xeb, 0x7c, 0x2d, 0xa5, 0xfd, 0xda, 0xb4, 0x5b, 0x1f, 0xa8, 0xd2, 0xeb, 0xdf, 0xd9, 0xf2, 0x35,
0xc6, 0x0c, 0x36, 0x66, 0x28, 0x95, 0xe2, 0x34, 0x64, 0xea, 0xaf, 0x3a, 0x36, 0x3c, 0x38, 0x31, 0x99, 0x8d, 0x80, 0x78,
0x18, 0x48, 0x2c, 0xe9, 0xe5, 0xb7, 0xe6, 0x2e, 0x73, 0xf1, 0x7c, 0x84, 0x21, 0x04, 0x00, 0x8e, 0x12, 0x66, 0x6c, 0x9b,
0x09, 0x88, 0xe2, 0xd5, 0xec, 0xb4, 0xdd, 0x2b, 0xda, 0x29, 0x6f, 0x1b, 0x81, 0x21, 0xe4, 0x5c, 0x36, 0x73, 0x2d, 0x9d,
0xdd, 0xb6, 0x69, 0x21, 0x40, 0x4e, 0x70, 0xde, 0x9d, 0x0c, 0x17, 0x1d, 0x15, 0x29, 0x5b, 0xd0, 0x66, 0x72, 0xb8, 0x38,
0x80, 0xbe, 0x9e, 0xd7, 0x5e, 0xb5, 0x72, 0x22, 0xbc
};
const uint8_t SawyerCodingTest::nonedata[]
= { 0x00, 0x00, 0x04, 0x00, 0x00, 0x3a, 0x97, 0x63, 0x8b, 0xbf, 0xe5, 0x6e, 0x0e, 0xc4, 0xac, 0xdc, 0x84, 0xd7, 0x68, 0xf1,
0x4d, 0xcb, 0xaf, 0x1e, 0x5a, 0x29, 0x40, 0x87, 0x80, 0x3f, 0xf9, 0xb8, 0xad, 0x01, 0xd3, 0x79, 0x3d, 0xe9, 0x87, 0xa8,
0x95, 0x68, 0xc0, 0xc2, 0x3d, 0x15, 0x87, 0xdb, 0xa6, 0x90, 0x8c, 0x26, 0x98, 0x2a, 0x3f, 0x2e, 0x0c, 0x82, 0x43, 0x00,
0x10, 0x6d, 0x60, 0xb9, 0xd4, 0xed, 0xf1, 0x49, 0xbb, 0xf6, 0x7f, 0x21, 0x24, 0xc3, 0xfb, 0x42, 0xe1, 0xfc, 0xb8, 0x82,
0x5e, 0x01, 0x5d, 0x96, 0x2d, 0x0f, 0x48, 0x12, 0xdf, 0x4b, 0x6c, 0x7e, 0x99, 0x01, 0xfa, 0x46, 0x7d, 0x2c, 0xeb, 0xd6,
0xf3, 0x77, 0xa3, 0x85, 0x8e, 0x00, 0x34, 0xee, 0x73, 0x31, 0x76, 0x53, 0x17, 0x5a, 0x2b, 0x19, 0x65, 0x2f, 0x32, 0x99,
0x57, 0xc4, 0xf8, 0x05, 0x0d, 0xc3, 0x59, 0x29, 0x9a, 0x19, 0x3c, 0x33, 0x58, 0x8c, 0xd1, 0x1f, 0x3b, 0xa5, 0x66, 0xa7,
0xfc, 0x7c, 0x99, 0xa9, 0x1a, 0x5e, 0x65, 0x92, 0x9e, 0x71, 0x27, 0x07, 0xbc, 0x71, 0xed, 0xe5, 0xc6, 0x0e, 0x74, 0xdb,
0x15, 0x91, 0xd7, 0xff, 0xf7, 0x30, 0x6e, 0x6a, 0x00, 0x40, 0x0e, 0x76, 0x8a, 0xb2, 0x31, 0xa3, 0x81, 0x83, 0xc8, 0xed,
0x08, 0x1f, 0xe5, 0x8d, 0x13, 0x3e, 0x9a, 0xca, 0x9c, 0xd4, 0x01, 0x28, 0xe6, 0xaf, 0xd6, 0x2f, 0xbc, 0xe1, 0xb7, 0xbb,
0x48, 0x88, 0x86, 0x19, 0xbb, 0x52, 0xfc, 0x18, 0xc9, 0xe3, 0x90, 0x88, 0x6c, 0x54, 0x53, 0x08, 0x26, 0xff, 0x38, 0xe3,
0x5e, 0x06, 0xa1, 0xac, 0xc2, 0x83, 0x23, 0x0d, 0x42, 0xe6, 0xa9, 0x81, 0x38, 0x0b, 0x4f, 0x16, 0x2a, 0x77, 0x3b, 0x24,
0xfb, 0x94, 0x53, 0x78, 0x6a, 0xf3, 0x17, 0x6a, 0x60, 0x44, 0x58, 0x5c, 0x50, 0x80, 0xc8, 0x0f, 0x87, 0x7b, 0x95, 0x0a,
0xdc, 0xf1, 0x1a, 0x6a, 0xa3, 0xff, 0x79, 0xda, 0x14, 0xd4, 0x6c, 0x7a, 0xfd, 0x7e, 0x1e, 0xfe, 0xd2, 0x28, 0xd0, 0x06,
0x95, 0x40, 0x80, 0xa1, 0x84, 0xc9, 0xc0, 0x4b, 0xa5, 0x97, 0xb2, 0xb9, 0x20, 0x27, 0x94, 0x87, 0x91, 0xba, 0xb2, 0xc6,
0xdb, 0x78, 0x19, 0x40, 0x35, 0x9f, 0xbd, 0xfb, 0xc1, 0x45, 0xbe, 0xdc, 0x30, 0xad, 0x38, 0xd4, 0x14, 0x46, 0x98, 0x2a,
0x90, 0xc8, 0x85, 0x5e, 0x7e, 0x76, 0x0f, 0xc4, 0x20, 0x07, 0x54, 0x1a, 0x60, 0x3a, 0x8c, 0x75, 0xb0, 0x43, 0xab, 0xbb,
0x05, 0xca, 0x93, 0xeb, 0x18, 0x94, 0xf1, 0x64, 0x8a, 0x01, 0xe0, 0xe6, 0x24, 0x78, 0x50, 0x93, 0xd3, 0xb9, 0xe1, 0xbf,
0x1c, 0xb0, 0x5c, 0xad, 0x94, 0x17, 0x8a, 0xd1, 0xef, 0x66, 0x08, 0xa7, 0x08, 0x6d, 0x6a, 0xb7, 0x06, 0x31, 0xa6, 0x9d,
0xe5, 0xb2, 0xd8, 0xf9, 0xa6, 0xf2, 0xe1, 0x63, 0xba, 0x36, 0x7a, 0x53, 0xc0, 0x22, 0x40, 0x3e, 0xa1, 0x95, 0xe5, 0xae,
0x8c, 0x35, 0x7d, 0x34, 0xae, 0x0c, 0x69, 0x8a, 0x0e, 0xd4, 0x53, 0x19, 0xc9, 0x90, 0x78, 0x36, 0x38, 0xc8, 0xa0, 0xc6,
0x49, 0xef, 0xe3, 0xb2, 0x1d, 0x7c, 0xd3, 0x38, 0x33, 0x51, 0x69, 0x2b, 0xd2, 0x8e, 0xa8, 0x6d, 0x9c, 0x01, 0x06, 0x9f,
0x93, 0xa5, 0x13, 0x86, 0x67, 0x72, 0x3e, 0xc7, 0x38, 0x97, 0xe6, 0x1d, 0xce, 0x61, 0x5a, 0x57, 0x10, 0xf7, 0x49, 0x32,
0xea, 0x8f, 0xce, 0x37, 0xea, 0x38, 0x65, 0x76, 0x86, 0xf4, 0x63, 0x9c, 0x44, 0xe6, 0x4c, 0x7b, 0x3f, 0x9b, 0x61, 0xf7,
0xb4, 0x2a, 0x7a, 0x9c, 0x03, 0x29, 0xf3, 0x6f, 0xff, 0x76, 0x1a, 0xb8, 0x21, 0xd7, 0xd0, 0xbf, 0x10, 0x1e, 0x82, 0x96,
0x9f, 0xe3, 0xc4, 0xcf, 0x19, 0x39, 0xd0, 0x4b, 0x4b, 0xa4, 0x7e, 0xd7, 0x4e, 0x3b, 0x2c, 0x0c, 0x35, 0xe1, 0xd4, 0x45,
0x10, 0x28, 0x67, 0x18, 0xdc, 0x2d, 0x77, 0x68, 0xf2, 0x39, 0x87, 0x52, 0xd7, 0xd1, 0x50, 0x04, 0x45, 0xf6, 0x1d, 0xb8,
0x9d, 0xfa, 0xe8, 0xd8, 0x94, 0xe0, 0xae, 0x31, 0x66, 0xc7, 0xee, 0xa9, 0xa8, 0x51, 0xe9, 0x14, 0x67, 0x53, 0x4c, 0x40,
0xf6, 0xee, 0x50, 0x67, 0x57, 0xf4, 0xd8, 0xd1, 0x95, 0x17, 0x2c, 0x5a, 0x72, 0x8f, 0xdc, 0xeb, 0x6c, 0x9b, 0x24, 0xfc,
0x67, 0x11, 0x07, 0x82, 0x2a, 0xae, 0xfb, 0xd9, 0xfd, 0x89, 0x75, 0x71, 0x75, 0x74, 0x08, 0x0d, 0xf7, 0xba, 0x5d, 0x56,
0xdf, 0x7e, 0x52, 0x5b, 0xce, 0xef, 0xeb, 0xf6, 0x32, 0x11, 0x93, 0x5f, 0xab, 0xfe, 0x08, 0xec, 0x20, 0x18, 0x0a, 0x4e,
0xc5, 0xb6, 0x42, 0xe4, 0x70, 0xbb, 0xba, 0x1b, 0xec, 0x01, 0x9c, 0xe5, 0x1c, 0xf4, 0xd2, 0x68, 0x0b, 0x30, 0x2d, 0xec,
0xda, 0x23, 0xff, 0xbd, 0x95, 0x46, 0x55, 0x59, 0xab, 0x03, 0x0f, 0xe4, 0xeb, 0x8c, 0xca, 0xc1, 0x13, 0x28, 0x49, 0x12,
0x66, 0xd7, 0x85, 0xcb, 0x21, 0x8d, 0x8a, 0x34, 0x4c, 0x2e, 0x28, 0x25, 0x79, 0xbf, 0x98, 0x04, 0xcd, 0x8a, 0x3e, 0xad,
0x08, 0xd3, 0x21, 0x32, 0xed, 0x54, 0x7e, 0x17, 0xfe, 0x89, 0xe9, 0x09, 0x18, 0xac, 0x96, 0xda, 0x51, 0x61, 0x85, 0x44,
0xd2, 0xdf, 0xd9, 0x61, 0xa2, 0x44, 0x07, 0x29, 0xa5, 0xdc, 0x16, 0xac, 0x3d, 0x6e, 0x27, 0xb6, 0x5a, 0x15, 0x87, 0x6c,
0x48, 0x3e, 0x34, 0xdd, 0xec, 0xf2, 0x7c, 0xc6, 0x87, 0x0f, 0xcf, 0xac, 0xde, 0x42, 0x02, 0x93, 0xff, 0x4f, 0x10, 0x0f,
0x03, 0xf3, 0x1b, 0x1e, 0xaf, 0x94, 0x8e, 0x77, 0x7c, 0x66, 0x65, 0xfb, 0xd9, 0x0d, 0xf8, 0x36, 0x0c, 0xac, 0xdc, 0x8e,
0xd1, 0x1e, 0x19, 0xa8, 0x87, 0x97, 0x39, 0x77, 0x98, 0x6c, 0xfb, 0x5d, 0xc1, 0x09, 0x7e, 0x5d, 0xab, 0xde, 0xdc, 0x1f,
0x21, 0xd0, 0x7a, 0xaa, 0xeb, 0x96, 0x60, 0xf9, 0x95, 0xed, 0x13, 0xf4, 0x82, 0xa9, 0x94, 0x7e, 0xa8, 0x5e, 0xe2, 0xca,
0x08, 0xed, 0xfe, 0x9d, 0x94, 0x3f, 0x08, 0xd8, 0xd8, 0x9d, 0xb0, 0x84, 0xd6, 0x6a, 0xcb, 0xc1, 0xd4, 0xd0, 0xe8, 0xe7,
0xae, 0x44, 0x28, 0x47, 0x75, 0xa6, 0x2a, 0x40, 0x0b, 0x82, 0x57, 0xd5, 0x49, 0x40, 0x85, 0x5c, 0x92, 0x95, 0x6b, 0x7d,
0xbe, 0xcc, 0xb6, 0x2d, 0x2b, 0x71, 0x85, 0x63, 0x39, 0xfa, 0xbc, 0x19, 0x7c, 0xe2, 0x3a, 0x81, 0xf1, 0x86, 0x9e, 0x46,
0x3d, 0x5f, 0x71, 0xa4, 0xb7, 0xd4, 0x2c, 0x98, 0xfa, 0xb5, 0x95, 0xac, 0x33, 0x1a, 0x53, 0x9d, 0xe3, 0x4e, 0x5d, 0x4f,
0x54, 0x0d, 0xe8, 0xa4, 0x32, 0x25, 0x4d, 0x5e, 0x4c, 0xe1, 0xae, 0x46, 0x85, 0x1e, 0xc4, 0x20, 0xdf, 0x73, 0x1e, 0x81,
0x40, 0xa2, 0x33, 0x75, 0x1e, 0x1d, 0x1d, 0x7c, 0x1f, 0x07, 0xe5, 0x9e, 0x76, 0x9f, 0x42, 0xeb, 0xc4, 0xb4, 0xd3, 0xcb,
0x55, 0xe8, 0xbf, 0xf7, 0xeb, 0x7c, 0x2d, 0xa5, 0xfd, 0xda, 0xb4, 0x5b, 0x1f, 0xa8, 0xd2, 0xeb, 0xdf, 0xd9, 0xf2, 0x35,
0xc6, 0x0c, 0x36, 0x66, 0x28, 0x95, 0xe2, 0x34, 0x64, 0xea, 0xaf, 0x3a, 0x36, 0x3c, 0x38, 0x31, 0x99, 0x8d, 0x80, 0x78,
0x18, 0x48, 0x2c, 0xe9, 0xe5, 0xb7, 0xe6, 0x2e, 0x73, 0xf1, 0x7c, 0x84, 0x21, 0x04, 0x00, 0x8e, 0x12, 0x66, 0x6c, 0x9b,
0x09, 0x88, 0xe2, 0xd5, 0xec, 0xb4, 0xdd, 0x2b, 0xda, 0x29, 0x6f, 0x1b, 0x81, 0x21, 0xe4, 0x5c, 0x36, 0x73, 0x2d, 0x9d,
0xdd, 0xb6, 0x69, 0x21, 0x40, 0x4e, 0x70, 0xde, 0x9d, 0x0c, 0x17, 0x1d, 0x15, 0x29, 0x5b, 0xd0, 0x66, 0x72, 0xb8, 0x38,
0x80, 0xbe, 0x9e, 0xd7, 0x5e, 0xb5, 0x72, 0x22, 0xbc };
const uint8_t SawyerCodingTest::rledata[] = {
0x01, 0x09, 0x04, 0x00, 0x00, 0x7d, 0x3a, 0x97, 0x63, 0x8b, 0xbf, 0xe5, 0x6e, 0x0e, 0xc4, 0xac, 0xdc, 0x84, 0xd7, 0x68,
0xf1, 0x4d, 0xcb, 0xaf, 0x1e, 0x5a, 0x29, 0x40, 0x87, 0x80, 0x3f, 0xf9, 0xb8, 0xad, 0x01, 0xd3, 0x79, 0x3d, 0xe9, 0x87,
0xa8, 0x95, 0x68, 0xc0, 0xc2, 0x3d, 0x15, 0x87, 0xdb, 0xa6, 0x90, 0x8c, 0x26, 0x98, 0x2a, 0x3f, 0x2e, 0x0c, 0x82, 0x43,
0x00, 0x10, 0x6d, 0x60, 0xb9, 0xd4, 0xed, 0xf1, 0x49, 0xbb, 0xf6, 0x7f, 0x21, 0x24, 0xc3, 0xfb, 0x42, 0xe1, 0xfc, 0xb8,
0x82, 0x5e, 0x01, 0x5d, 0x96, 0x2d, 0x0f, 0x48, 0x12, 0xdf, 0x4b, 0x6c, 0x7e, 0x99, 0x01, 0xfa, 0x46, 0x7d, 0x2c, 0xeb,
0xd6, 0xf3, 0x77, 0xa3, 0x85, 0x8e, 0x00, 0x34, 0xee, 0x73, 0x31, 0x76, 0x53, 0x17, 0x5a, 0x2b, 0x19, 0x65, 0x2f, 0x32,
0x99, 0x57, 0xc4, 0xf8, 0x05, 0x0d, 0xc3, 0x59, 0x29, 0x9a, 0x19, 0x3c, 0x7d, 0x33, 0x58, 0x8c, 0xd1, 0x1f, 0x3b, 0xa5,
0x66, 0xa7, 0xfc, 0x7c, 0x99, 0xa9, 0x1a, 0x5e, 0x65, 0x92, 0x9e, 0x71, 0x27, 0x07, 0xbc, 0x71, 0xed, 0xe5, 0xc6, 0x0e,
0x74, 0xdb, 0x15, 0x91, 0xd7, 0xff, 0xf7, 0x30, 0x6e, 0x6a, 0x00, 0x40, 0x0e, 0x76, 0x8a, 0xb2, 0x31, 0xa3, 0x81, 0x83,
0xc8, 0xed, 0x08, 0x1f, 0xe5, 0x8d, 0x13, 0x3e, 0x9a, 0xca, 0x9c, 0xd4, 0x01, 0x28, 0xe6, 0xaf, 0xd6, 0x2f, 0xbc, 0xe1,
0xb7, 0xbb, 0x48, 0x88, 0x86, 0x19, 0xbb, 0x52, 0xfc, 0x18, 0xc9, 0xe3, 0x90, 0x88, 0x6c, 0x54, 0x53, 0x08, 0x26, 0xff,
0x38, 0xe3, 0x5e, 0x06, 0xa1, 0xac, 0xc2, 0x83, 0x23, 0x0d, 0x42, 0xe6, 0xa9, 0x81, 0x38, 0x0b, 0x4f, 0x16, 0x2a, 0x77,
0x3b, 0x24, 0xfb, 0x94, 0x53, 0x78, 0x6a, 0xf3, 0x17, 0x6a, 0x60, 0x44, 0x58, 0x5c, 0x50, 0x80, 0xc8, 0x0f, 0x87, 0x7d,
0x7b, 0x95, 0x0a, 0xdc, 0xf1, 0x1a, 0x6a, 0xa3, 0xff, 0x79, 0xda, 0x14, 0xd4, 0x6c, 0x7a, 0xfd, 0x7e, 0x1e, 0xfe, 0xd2,
0x28, 0xd0, 0x06, 0x95, 0x40, 0x80, 0xa1, 0x84, 0xc9, 0xc0, 0x4b, 0xa5, 0x97, 0xb2, 0xb9, 0x20, 0x27, 0x94, 0x87, 0x91,
0xba, 0xb2, 0xc6, 0xdb, 0x78, 0x19, 0x40, 0x35, 0x9f, 0xbd, 0xfb, 0xc1, 0x45, 0xbe, 0xdc, 0x30, 0xad, 0x38, 0xd4, 0x14,
0x46, 0x98, 0x2a, 0x90, 0xc8, 0x85, 0x5e, 0x7e, 0x76, 0x0f, 0xc4, 0x20, 0x07, 0x54, 0x1a, 0x60, 0x3a, 0x8c, 0x75, 0xb0,
0x43, 0xab, 0xbb, 0x05, 0xca, 0x93, 0xeb, 0x18, 0x94, 0xf1, 0x64, 0x8a, 0x01, 0xe0, 0xe6, 0x24, 0x78, 0x50, 0x93, 0xd3,
0xb9, 0xe1, 0xbf, 0x1c, 0xb0, 0x5c, 0xad, 0x94, 0x17, 0x8a, 0xd1, 0xef, 0x66, 0x08, 0xa7, 0x08, 0x6d, 0x6a, 0xb7, 0x06,
0x31, 0xa6, 0x9d, 0xe5, 0xb2, 0xd8, 0x7b, 0xf9, 0xa6, 0xf2, 0xe1, 0x63, 0xba, 0x36, 0x7a, 0x53, 0xc0, 0x22, 0x40, 0x3e,
0xa1, 0x95, 0xe5, 0xae, 0x8c, 0x35, 0x7d, 0x34, 0xae, 0x0c, 0x69, 0x8a, 0x0e, 0xd4, 0x53, 0x19, 0xc9, 0x90, 0x78, 0x36,
0x38, 0xc8, 0xa0, 0xc6, 0x49, 0xef, 0xe3, 0xb2, 0x1d, 0x7c, 0xd3, 0x38, 0x33, 0x51, 0x69, 0x2b, 0xd2, 0x8e, 0xa8, 0x6d,
0x9c, 0x01, 0x06, 0x9f, 0x93, 0xa5, 0x13, 0x86, 0x67, 0x72, 0x3e, 0xc7, 0x38, 0x97, 0xe6, 0x1d, 0xce, 0x61, 0x5a, 0x57,
0x10, 0xf7, 0x49, 0x32, 0xea, 0x8f, 0xce, 0x37, 0xea, 0x38, 0x65, 0x76, 0x86, 0xf4, 0x63, 0x9c, 0x44, 0xe6, 0x4c, 0x7b,
0x3f, 0x9b, 0x61, 0xf7, 0xb4, 0x2a, 0x7a, 0x9c, 0x03, 0x29, 0xf3, 0x6f, 0xff, 0x76, 0x1a, 0xb8, 0x21, 0xd7, 0xd0, 0xbf,
0x10, 0x1e, 0x82, 0x96, 0x9f, 0xe3, 0xc4, 0xcf, 0x19, 0x39, 0xd0, 0xff, 0x4b, 0x7d, 0xa4, 0x7e, 0xd7, 0x4e, 0x3b, 0x2c,
0x0c, 0x35, 0xe1, 0xd4, 0x45, 0x10, 0x28, 0x67, 0x18, 0xdc, 0x2d, 0x77, 0x68, 0xf2, 0x39, 0x87, 0x52, 0xd7, 0xd1, 0x50,
0x04, 0x45, 0xf6, 0x1d, 0xb8, 0x9d, 0xfa, 0xe8, 0xd8, 0x94, 0xe0, 0xae, 0x31, 0x66, 0xc7, 0xee, 0xa9, 0xa8, 0x51, 0xe9,
0x14, 0x67, 0x53, 0x4c, 0x40, 0xf6, 0xee, 0x50, 0x67, 0x57, 0xf4, 0xd8, 0xd1, 0x95, 0x17, 0x2c, 0x5a, 0x72, 0x8f, 0xdc,
0xeb, 0x6c, 0x9b, 0x24, 0xfc, 0x67, 0x11, 0x07, 0x82, 0x2a, 0xae, 0xfb, 0xd9, 0xfd, 0x89, 0x75, 0x71, 0x75, 0x74, 0x08,
0x0d, 0xf7, 0xba, 0x5d, 0x56, 0xdf, 0x7e, 0x52, 0x5b, 0xce, 0xef, 0xeb, 0xf6, 0x32, 0x11, 0x93, 0x5f, 0xab, 0xfe, 0x08,
0xec, 0x20, 0x18, 0x0a, 0x4e, 0xc5, 0xb6, 0x42, 0xe4, 0x70, 0xbb, 0xba, 0x1b, 0xec, 0x01, 0x9c, 0xe5, 0x1c, 0xf4, 0xd2,
0x7d, 0x68, 0x0b, 0x30, 0x2d, 0xec, 0xda, 0x23, 0xff, 0xbd, 0x95, 0x46, 0x55, 0x59, 0xab, 0x03, 0x0f, 0xe4, 0xeb, 0x8c,
0xca, 0xc1, 0x13, 0x28, 0x49, 0x12, 0x66, 0xd7, 0x85, 0xcb, 0x21, 0x8d, 0x8a, 0x34, 0x4c, 0x2e, 0x28, 0x25, 0x79, 0xbf,
0x98, 0x04, 0xcd, 0x8a, 0x3e, 0xad, 0x08, 0xd3, 0x21, 0x32, 0xed, 0x54, 0x7e, 0x17, 0xfe, 0x89, 0xe9, 0x09, 0x18, 0xac,
0x96, 0xda, 0x51, 0x61, 0x85, 0x44, 0xd2, 0xdf, 0xd9, 0x61, 0xa2, 0x44, 0x07, 0x29, 0xa5, 0xdc, 0x16, 0xac, 0x3d, 0x6e,
0x27, 0xb6, 0x5a, 0x15, 0x87, 0x6c, 0x48, 0x3e, 0x34, 0xdd, 0xec, 0xf2, 0x7c, 0xc6, 0x87, 0x0f, 0xcf, 0xac, 0xde, 0x42,
0x02, 0x93, 0xff, 0x4f, 0x10, 0x0f, 0x03, 0xf3, 0x1b, 0x1e, 0xaf, 0x94, 0x8e, 0x77, 0x7c, 0x66, 0x65, 0xfb, 0xd9, 0x0d,
0xf8, 0x36, 0x0c, 0xac, 0xdc, 0x8e, 0xd1, 0x2d, 0x1e, 0x19, 0xa8, 0x87, 0x97, 0x39, 0x77, 0x98, 0x6c, 0xfb, 0x5d, 0xc1,
0x09, 0x7e, 0x5d, 0xab, 0xde, 0xdc, 0x1f, 0x21, 0xd0, 0x7a, 0xaa, 0xeb, 0x96, 0x60, 0xf9, 0x95, 0xed, 0x13, 0xf4, 0x82,
0xa9, 0x94, 0x7e, 0xa8, 0x5e, 0xe2, 0xca, 0x08, 0xed, 0xfe, 0x9d, 0x94, 0x3f, 0x08, 0xff, 0xd8, 0x5f, 0x9d, 0xb0, 0x84,
0xd6, 0x6a, 0xcb, 0xc1, 0xd4, 0xd0, 0xe8, 0xe7, 0xae, 0x44, 0x28, 0x47, 0x75, 0xa6, 0x2a, 0x40, 0x0b, 0x82, 0x57, 0xd5,
0x49, 0x40, 0x85, 0x5c, 0x92, 0x95, 0x6b, 0x7d, 0xbe, 0xcc, 0xb6, 0x2d, 0x2b, 0x71, 0x85, 0x63, 0x39, 0xfa, 0xbc, 0x19,
0x7c, 0xe2, 0x3a, 0x81, 0xf1, 0x86, 0x9e, 0x46, 0x3d, 0x5f, 0x71, 0xa4, 0xb7, 0xd4, 0x2c, 0x98, 0xfa, 0xb5, 0x95, 0xac,
0x33, 0x1a, 0x53, 0x9d, 0xe3, 0x4e, 0x5d, 0x4f, 0x54, 0x0d, 0xe8, 0xa4, 0x32, 0x25, 0x4d, 0x5e, 0x4c, 0xe1, 0xae, 0x46,
0x85, 0x1e, 0xc4, 0x20, 0xdf, 0x73, 0x1e, 0x81, 0x40, 0xa2, 0x33, 0x75, 0x1e, 0xff, 0x1d, 0x79, 0x7c, 0x1f, 0x07, 0xe5,
0x9e, 0x76, 0x9f, 0x42, 0xeb, 0xc4, 0xb4, 0xd3, 0xcb, 0x55, 0xe8, 0xbf, 0xf7, 0xeb, 0x7c, 0x2d, 0xa5, 0xfd, 0xda, 0xb4,
0x5b, 0x1f, 0xa8, 0xd2, 0xeb, 0xdf, 0xd9, 0xf2, 0x35, 0xc6, 0x0c, 0x36, 0x66, 0x28, 0x95, 0xe2, 0x34, 0x64, 0xea, 0xaf,
0x3a, 0x36, 0x3c, 0x38, 0x31, 0x99, 0x8d, 0x80, 0x78, 0x18, 0x48, 0x2c, 0xe9, 0xe5, 0xb7, 0xe6, 0x2e, 0x73, 0xf1, 0x7c,
0x84, 0x21, 0x04, 0x00, 0x8e, 0x12, 0x66, 0x6c, 0x9b, 0x09, 0x88, 0xe2, 0xd5, 0xec, 0xb4, 0xdd, 0x2b, 0xda, 0x29, 0x6f,
0x1b, 0x81, 0x21, 0xe4, 0x5c, 0x36, 0x73, 0x2d, 0x9d, 0xdd, 0xb6, 0x69, 0x21, 0x40, 0x4e, 0x70, 0xde, 0x9d, 0x0c, 0x17,
0x1d, 0x15, 0x29, 0x5b, 0xd0, 0x66, 0x72, 0xb8, 0x38, 0x80, 0xbe, 0x9e, 0xd7, 0x5e, 0xb5, 0x72, 0x22, 0xbc
};
const uint8_t SawyerCodingTest::rledata[]
= { 0x01, 0x09, 0x04, 0x00, 0x00, 0x7d, 0x3a, 0x97, 0x63, 0x8b, 0xbf, 0xe5, 0x6e, 0x0e, 0xc4, 0xac, 0xdc, 0x84, 0xd7, 0x68,
0xf1, 0x4d, 0xcb, 0xaf, 0x1e, 0x5a, 0x29, 0x40, 0x87, 0x80, 0x3f, 0xf9, 0xb8, 0xad, 0x01, 0xd3, 0x79, 0x3d, 0xe9, 0x87,
0xa8, 0x95, 0x68, 0xc0, 0xc2, 0x3d, 0x15, 0x87, 0xdb, 0xa6, 0x90, 0x8c, 0x26, 0x98, 0x2a, 0x3f, 0x2e, 0x0c, 0x82, 0x43,
0x00, 0x10, 0x6d, 0x60, 0xb9, 0xd4, 0xed, 0xf1, 0x49, 0xbb, 0xf6, 0x7f, 0x21, 0x24, 0xc3, 0xfb, 0x42, 0xe1, 0xfc, 0xb8,
0x82, 0x5e, 0x01, 0x5d, 0x96, 0x2d, 0x0f, 0x48, 0x12, 0xdf, 0x4b, 0x6c, 0x7e, 0x99, 0x01, 0xfa, 0x46, 0x7d, 0x2c, 0xeb,
0xd6, 0xf3, 0x77, 0xa3, 0x85, 0x8e, 0x00, 0x34, 0xee, 0x73, 0x31, 0x76, 0x53, 0x17, 0x5a, 0x2b, 0x19, 0x65, 0x2f, 0x32,
0x99, 0x57, 0xc4, 0xf8, 0x05, 0x0d, 0xc3, 0x59, 0x29, 0x9a, 0x19, 0x3c, 0x7d, 0x33, 0x58, 0x8c, 0xd1, 0x1f, 0x3b, 0xa5,
0x66, 0xa7, 0xfc, 0x7c, 0x99, 0xa9, 0x1a, 0x5e, 0x65, 0x92, 0x9e, 0x71, 0x27, 0x07, 0xbc, 0x71, 0xed, 0xe5, 0xc6, 0x0e,
0x74, 0xdb, 0x15, 0x91, 0xd7, 0xff, 0xf7, 0x30, 0x6e, 0x6a, 0x00, 0x40, 0x0e, 0x76, 0x8a, 0xb2, 0x31, 0xa3, 0x81, 0x83,
0xc8, 0xed, 0x08, 0x1f, 0xe5, 0x8d, 0x13, 0x3e, 0x9a, 0xca, 0x9c, 0xd4, 0x01, 0x28, 0xe6, 0xaf, 0xd6, 0x2f, 0xbc, 0xe1,
0xb7, 0xbb, 0x48, 0x88, 0x86, 0x19, 0xbb, 0x52, 0xfc, 0x18, 0xc9, 0xe3, 0x90, 0x88, 0x6c, 0x54, 0x53, 0x08, 0x26, 0xff,
0x38, 0xe3, 0x5e, 0x06, 0xa1, 0xac, 0xc2, 0x83, 0x23, 0x0d, 0x42, 0xe6, 0xa9, 0x81, 0x38, 0x0b, 0x4f, 0x16, 0x2a, 0x77,
0x3b, 0x24, 0xfb, 0x94, 0x53, 0x78, 0x6a, 0xf3, 0x17, 0x6a, 0x60, 0x44, 0x58, 0x5c, 0x50, 0x80, 0xc8, 0x0f, 0x87, 0x7d,
0x7b, 0x95, 0x0a, 0xdc, 0xf1, 0x1a, 0x6a, 0xa3, 0xff, 0x79, 0xda, 0x14, 0xd4, 0x6c, 0x7a, 0xfd, 0x7e, 0x1e, 0xfe, 0xd2,
0x28, 0xd0, 0x06, 0x95, 0x40, 0x80, 0xa1, 0x84, 0xc9, 0xc0, 0x4b, 0xa5, 0x97, 0xb2, 0xb9, 0x20, 0x27, 0x94, 0x87, 0x91,
0xba, 0xb2, 0xc6, 0xdb, 0x78, 0x19, 0x40, 0x35, 0x9f, 0xbd, 0xfb, 0xc1, 0x45, 0xbe, 0xdc, 0x30, 0xad, 0x38, 0xd4, 0x14,
0x46, 0x98, 0x2a, 0x90, 0xc8, 0x85, 0x5e, 0x7e, 0x76, 0x0f, 0xc4, 0x20, 0x07, 0x54, 0x1a, 0x60, 0x3a, 0x8c, 0x75, 0xb0,
0x43, 0xab, 0xbb, 0x05, 0xca, 0x93, 0xeb, 0x18, 0x94, 0xf1, 0x64, 0x8a, 0x01, 0xe0, 0xe6, 0x24, 0x78, 0x50, 0x93, 0xd3,
0xb9, 0xe1, 0xbf, 0x1c, 0xb0, 0x5c, 0xad, 0x94, 0x17, 0x8a, 0xd1, 0xef, 0x66, 0x08, 0xa7, 0x08, 0x6d, 0x6a, 0xb7, 0x06,
0x31, 0xa6, 0x9d, 0xe5, 0xb2, 0xd8, 0x7b, 0xf9, 0xa6, 0xf2, 0xe1, 0x63, 0xba, 0x36, 0x7a, 0x53, 0xc0, 0x22, 0x40, 0x3e,
0xa1, 0x95, 0xe5, 0xae, 0x8c, 0x35, 0x7d, 0x34, 0xae, 0x0c, 0x69, 0x8a, 0x0e, 0xd4, 0x53, 0x19, 0xc9, 0x90, 0x78, 0x36,
0x38, 0xc8, 0xa0, 0xc6, 0x49, 0xef, 0xe3, 0xb2, 0x1d, 0x7c, 0xd3, 0x38, 0x33, 0x51, 0x69, 0x2b, 0xd2, 0x8e, 0xa8, 0x6d,
0x9c, 0x01, 0x06, 0x9f, 0x93, 0xa5, 0x13, 0x86, 0x67, 0x72, 0x3e, 0xc7, 0x38, 0x97, 0xe6, 0x1d, 0xce, 0x61, 0x5a, 0x57,
0x10, 0xf7, 0x49, 0x32, 0xea, 0x8f, 0xce, 0x37, 0xea, 0x38, 0x65, 0x76, 0x86, 0xf4, 0x63, 0x9c, 0x44, 0xe6, 0x4c, 0x7b,
0x3f, 0x9b, 0x61, 0xf7, 0xb4, 0x2a, 0x7a, 0x9c, 0x03, 0x29, 0xf3, 0x6f, 0xff, 0x76, 0x1a, 0xb8, 0x21, 0xd7, 0xd0, 0xbf,
0x10, 0x1e, 0x82, 0x96, 0x9f, 0xe3, 0xc4, 0xcf, 0x19, 0x39, 0xd0, 0xff, 0x4b, 0x7d, 0xa4, 0x7e, 0xd7, 0x4e, 0x3b, 0x2c,
0x0c, 0x35, 0xe1, 0xd4, 0x45, 0x10, 0x28, 0x67, 0x18, 0xdc, 0x2d, 0x77, 0x68, 0xf2, 0x39, 0x87, 0x52, 0xd7, 0xd1, 0x50,
0x04, 0x45, 0xf6, 0x1d, 0xb8, 0x9d, 0xfa, 0xe8, 0xd8, 0x94, 0xe0, 0xae, 0x31, 0x66, 0xc7, 0xee, 0xa9, 0xa8, 0x51, 0xe9,
0x14, 0x67, 0x53, 0x4c, 0x40, 0xf6, 0xee, 0x50, 0x67, 0x57, 0xf4, 0xd8, 0xd1, 0x95, 0x17, 0x2c, 0x5a, 0x72, 0x8f, 0xdc,
0xeb, 0x6c, 0x9b, 0x24, 0xfc, 0x67, 0x11, 0x07, 0x82, 0x2a, 0xae, 0xfb, 0xd9, 0xfd, 0x89, 0x75, 0x71, 0x75, 0x74, 0x08,
0x0d, 0xf7, 0xba, 0x5d, 0x56, 0xdf, 0x7e, 0x52, 0x5b, 0xce, 0xef, 0xeb, 0xf6, 0x32, 0x11, 0x93, 0x5f, 0xab, 0xfe, 0x08,
0xec, 0x20, 0x18, 0x0a, 0x4e, 0xc5, 0xb6, 0x42, 0xe4, 0x70, 0xbb, 0xba, 0x1b, 0xec, 0x01, 0x9c, 0xe5, 0x1c, 0xf4, 0xd2,
0x7d, 0x68, 0x0b, 0x30, 0x2d, 0xec, 0xda, 0x23, 0xff, 0xbd, 0x95, 0x46, 0x55, 0x59, 0xab, 0x03, 0x0f, 0xe4, 0xeb, 0x8c,
0xca, 0xc1, 0x13, 0x28, 0x49, 0x12, 0x66, 0xd7, 0x85, 0xcb, 0x21, 0x8d, 0x8a, 0x34, 0x4c, 0x2e, 0x28, 0x25, 0x79, 0xbf,
0x98, 0x04, 0xcd, 0x8a, 0x3e, 0xad, 0x08, 0xd3, 0x21, 0x32, 0xed, 0x54, 0x7e, 0x17, 0xfe, 0x89, 0xe9, 0x09, 0x18, 0xac,
0x96, 0xda, 0x51, 0x61, 0x85, 0x44, 0xd2, 0xdf, 0xd9, 0x61, 0xa2, 0x44, 0x07, 0x29, 0xa5, 0xdc, 0x16, 0xac, 0x3d, 0x6e,
0x27, 0xb6, 0x5a, 0x15, 0x87, 0x6c, 0x48, 0x3e, 0x34, 0xdd, 0xec, 0xf2, 0x7c, 0xc6, 0x87, 0x0f, 0xcf, 0xac, 0xde, 0x42,
0x02, 0x93, 0xff, 0x4f, 0x10, 0x0f, 0x03, 0xf3, 0x1b, 0x1e, 0xaf, 0x94, 0x8e, 0x77, 0x7c, 0x66, 0x65, 0xfb, 0xd9, 0x0d,
0xf8, 0x36, 0x0c, 0xac, 0xdc, 0x8e, 0xd1, 0x2d, 0x1e, 0x19, 0xa8, 0x87, 0x97, 0x39, 0x77, 0x98, 0x6c, 0xfb, 0x5d, 0xc1,
0x09, 0x7e, 0x5d, 0xab, 0xde, 0xdc, 0x1f, 0x21, 0xd0, 0x7a, 0xaa, 0xeb, 0x96, 0x60, 0xf9, 0x95, 0xed, 0x13, 0xf4, 0x82,
0xa9, 0x94, 0x7e, 0xa8, 0x5e, 0xe2, 0xca, 0x08, 0xed, 0xfe, 0x9d, 0x94, 0x3f, 0x08, 0xff, 0xd8, 0x5f, 0x9d, 0xb0, 0x84,
0xd6, 0x6a, 0xcb, 0xc1, 0xd4, 0xd0, 0xe8, 0xe7, 0xae, 0x44, 0x28, 0x47, 0x75, 0xa6, 0x2a, 0x40, 0x0b, 0x82, 0x57, 0xd5,
0x49, 0x40, 0x85, 0x5c, 0x92, 0x95, 0x6b, 0x7d, 0xbe, 0xcc, 0xb6, 0x2d, 0x2b, 0x71, 0x85, 0x63, 0x39, 0xfa, 0xbc, 0x19,
0x7c, 0xe2, 0x3a, 0x81, 0xf1, 0x86, 0x9e, 0x46, 0x3d, 0x5f, 0x71, 0xa4, 0xb7, 0xd4, 0x2c, 0x98, 0xfa, 0xb5, 0x95, 0xac,
0x33, 0x1a, 0x53, 0x9d, 0xe3, 0x4e, 0x5d, 0x4f, 0x54, 0x0d, 0xe8, 0xa4, 0x32, 0x25, 0x4d, 0x5e, 0x4c, 0xe1, 0xae, 0x46,
0x85, 0x1e, 0xc4, 0x20, 0xdf, 0x73, 0x1e, 0x81, 0x40, 0xa2, 0x33, 0x75, 0x1e, 0xff, 0x1d, 0x79, 0x7c, 0x1f, 0x07, 0xe5,
0x9e, 0x76, 0x9f, 0x42, 0xeb, 0xc4, 0xb4, 0xd3, 0xcb, 0x55, 0xe8, 0xbf, 0xf7, 0xeb, 0x7c, 0x2d, 0xa5, 0xfd, 0xda, 0xb4,
0x5b, 0x1f, 0xa8, 0xd2, 0xeb, 0xdf, 0xd9, 0xf2, 0x35, 0xc6, 0x0c, 0x36, 0x66, 0x28, 0x95, 0xe2, 0x34, 0x64, 0xea, 0xaf,
0x3a, 0x36, 0x3c, 0x38, 0x31, 0x99, 0x8d, 0x80, 0x78, 0x18, 0x48, 0x2c, 0xe9, 0xe5, 0xb7, 0xe6, 0x2e, 0x73, 0xf1, 0x7c,
0x84, 0x21, 0x04, 0x00, 0x8e, 0x12, 0x66, 0x6c, 0x9b, 0x09, 0x88, 0xe2, 0xd5, 0xec, 0xb4, 0xdd, 0x2b, 0xda, 0x29, 0x6f,
0x1b, 0x81, 0x21, 0xe4, 0x5c, 0x36, 0x73, 0x2d, 0x9d, 0xdd, 0xb6, 0x69, 0x21, 0x40, 0x4e, 0x70, 0xde, 0x9d, 0x0c, 0x17,
0x1d, 0x15, 0x29, 0x5b, 0xd0, 0x66, 0x72, 0xb8, 0x38, 0x80, 0xbe, 0x9e, 0xd7, 0x5e, 0xb5, 0x72, 0x22, 0xbc };
const uint8_t SawyerCodingTest::rlecompresseddata[] = {
0x02, 0x98, 0x07, 0x00, 0x00, 0x7d, 0xff, 0x3a, 0xff, 0x97, 0xff, 0x63, 0xff, 0x8b, 0xff, 0xbf, 0xff, 0xe5, 0xff, 0x6e,
0xff, 0x0e, 0xff, 0xc4, 0xff, 0xac, 0xff, 0xdc, 0xff, 0x84, 0xff, 0xd7, 0xff, 0x68, 0xff, 0xf1, 0xff, 0x4d, 0xff, 0xcb,
0xff, 0xaf, 0xff, 0x1e, 0xff, 0x5a, 0xff, 0x29, 0xff, 0x40, 0xff, 0x87, 0xff, 0x80, 0xff, 0x3f, 0xff, 0xf9, 0xff, 0xb8,
0xff, 0xad, 0xff, 0x01, 0xff, 0xd3, 0xff, 0x79, 0xff, 0x3d, 0xff, 0xe9, 0xa8, 0xff, 0xa8, 0xff, 0x95, 0x48, 0xff, 0xc0,
0xff, 0xc2, 0xc0, 0xff, 0x15, 0x68, 0xff, 0xdb, 0xff, 0xa6, 0xff, 0x90, 0xff, 0x8c, 0xff, 0x26, 0xff, 0x98, 0xff, 0x2a,
0x38, 0xff, 0x2e, 0xff, 0x0c, 0xff, 0x82, 0xff, 0x43, 0xff, 0x00, 0xff, 0x10, 0xff, 0x6d, 0xff, 0x60, 0xff, 0xb9, 0xff,
0xd4, 0xff, 0xed, 0xff, 0xf1, 0xff, 0x49, 0xff, 0xbb, 0xff, 0xf6, 0xff, 0x7d, 0x7f, 0xff, 0x21, 0xff, 0x24, 0xff, 0xc3,
0xff, 0xfb, 0xff, 0x42, 0xff, 0xe1, 0xff, 0xfc, 0xff, 0xb8, 0x50, 0xff, 0x5e, 0xff, 0x01, 0xff, 0x5d, 0xff, 0x96, 0xff,
0x2d, 0xff, 0x0f, 0xff, 0x48, 0xff, 0x12, 0xff, 0xdf, 0xff, 0x4b, 0xff, 0x6c, 0xff, 0x7e, 0xff, 0x99, 0xa0, 0xff, 0xfa,
0xff, 0x46, 0xff, 0x7d, 0xff, 0x2c, 0xff, 0xeb, 0xff, 0xd6, 0xff, 0xf3, 0xff, 0x77, 0xff, 0xa3, 0xff, 0x85, 0xff, 0x8e,
0xff, 0x00, 0xff, 0x34, 0xff, 0xee, 0xff, 0x73, 0xff, 0x31, 0xff, 0x76, 0xff, 0x53, 0xff, 0x17, 0xff, 0x5a, 0xff, 0x2b,
0xff, 0x19, 0xff, 0x65, 0xff, 0x2f, 0xff, 0x32, 0x28, 0xff, 0x57, 0xff, 0xc4, 0xff, 0xf8, 0xff, 0x05, 0xff, 0x0d, 0xff,
0xc3, 0xff, 0x59, 0xff, 0x29, 0xff, 0x9a, 0x90, 0xff, 0x3c, 0xff, 0x33, 0xff, 0x58, 0xff, 0x8c, 0xff, 0xd1, 0xff, 0x33,
0x1f, 0xff, 0x3b, 0xff, 0xa5, 0xff, 0x66, 0xff, 0xa7, 0xff, 0xfc, 0xff, 0x7c, 0x48, 0xff, 0xa9, 0xff, 0x1a, 0xff, 0x5e,
0x10, 0xff, 0x92, 0xff, 0x9e, 0xff, 0x71, 0xff, 0x27, 0xff, 0x07, 0xff, 0xbc, 0xe0, 0xff, 0xed, 0xff, 0xe5, 0xff, 0xc6,
0xff, 0x0e, 0xff, 0x74, 0xff, 0xdb, 0xff, 0x15, 0xff, 0x91, 0xff, 0xd7, 0xfe, 0xff, 0x63, 0xf7, 0xff, 0x30, 0xff, 0x6e,
0xff, 0x6a, 0xff, 0x00, 0xff, 0x40, 0x98, 0xff, 0x76, 0xff, 0x8a, 0xff, 0xb2, 0xff, 0x31, 0xff, 0xa3, 0xff, 0x81, 0xff,
0x83, 0xff, 0xc8, 0x38, 0xff, 0x08, 0xff, 0x1f, 0x28, 0xff, 0x8d, 0xff, 0x13, 0xff, 0x3e, 0xff, 0x9a, 0xff, 0xca, 0xff,
0x9c, 0xff, 0xd4, 0xff, 0x01, 0xff, 0x28, 0xff, 0xe6, 0xff, 0xaf, 0xff, 0xd6, 0xff, 0x2f, 0xff, 0xbc, 0xff, 0xe1, 0xff,
0xb7, 0xff, 0xbb, 0xff, 0x48, 0xff, 0x88, 0xff, 0x86, 0xff, 0x19, 0xd8, 0xff, 0x52, 0xff, 0xfc, 0xff, 0x18, 0xff, 0xc9,
0xff, 0xe3, 0xff, 0x90, 0xb0, 0xff, 0x6c, 0xff, 0x54, 0xff, 0x53, 0xff, 0x08, 0xff, 0x26, 0xfe, 0xff, 0x57, 0x38, 0xb0,
0xff, 0x5e, 0xff, 0x06, 0xff, 0xa1, 0xff, 0xac, 0xff, 0xc2, 0xff, 0x83, 0xff, 0x23, 0xff, 0x0d, 0xff, 0x42, 0xff, 0xe6,
0xff, 0xa9, 0xff, 0x81, 0x90, 0xff, 0x0b, 0xff, 0x4f, 0xff, 0x16, 0xff, 0x2a, 0xff, 0x77, 0xff, 0x3b, 0xff, 0x24, 0xff,
0xfb, 0xff, 0x94, 0x20, 0xff, 0x78, 0xff, 0x6a, 0xff, 0xf3, 0xff, 0x17, 0xe8, 0xff, 0x60, 0xff, 0x44, 0xff, 0x58, 0xff,
0x5c, 0xff, 0x50, 0xff, 0x80, 0xff, 0xc8, 0xff, 0x0f, 0xff, 0x87, 0xff, 0x7b, 0xff, 0x95, 0xff, 0x0a, 0xff, 0xdc, 0xff,
0xf1, 0xff, 0x1a, 0x68, 0xff, 0xa3, 0xfe, 0xff, 0x7d, 0x79, 0xff, 0xda, 0xff, 0x14, 0xff, 0xd4, 0xff, 0x6c, 0xff, 0x7a,
0xff, 0xfd, 0xff, 0x7e, 0xff, 0x1e, 0xff, 0xfe, 0xff, 0xd2, 0xff, 0x28, 0xff, 0xd0, 0xff, 0x06, 0x50, 0xff, 0x40, 0x18,
0xff, 0xa1, 0xff, 0x84, 0xff, 0xc9, 0xff, 0xc0, 0xff, 0x4b, 0xff, 0xa5, 0xff, 0x97, 0xff, 0xb2, 0xff, 0xb9, 0xff, 0x20,
0xff, 0x27, 0xff, 0x94, 0xff, 0x87, 0xff, 0x91, 0xff, 0xba, 0xc0, 0xff, 0xc6, 0xff, 0xdb, 0xff, 0x78, 0xff, 0x19, 0x50,
0xff, 0x35, 0xff, 0x9f, 0xff, 0xbd, 0xff, 0xfb, 0xff, 0xc1, 0xff, 0x45, 0xff, 0xbe, 0xff, 0xdc, 0xff, 0x30, 0xff, 0xad,
0xff, 0x38, 0xff, 0xd4, 0xff, 0x14, 0xff, 0x46, 0xff, 0x98, 0xff, 0x2a, 0xff, 0x90, 0xff, 0xc8, 0xff, 0x85, 0xff, 0x5e,
0xff, 0x7e, 0xff, 0x76, 0xff, 0x0f, 0xff, 0xc4, 0xff, 0x20, 0xff, 0x07, 0xff, 0x54, 0xff, 0x7d, 0x1a, 0xff, 0x60, 0xff,
0x3a, 0xff, 0x8c, 0xff, 0x75, 0xff, 0xb0, 0xff, 0x43, 0xff, 0xab, 0xff, 0xbb, 0xff, 0x05, 0xff, 0xca, 0xff, 0x93, 0xff,
0xeb, 0xff, 0x18, 0xff, 0x94, 0xff, 0xf1, 0xff, 0x64, 0xff, 0x8a, 0xff, 0x01, 0xff, 0xe0, 0xff, 0xe6, 0xff, 0x24, 0xff,
0x78, 0xff, 0x50, 0x98, 0xff, 0xd3, 0xff, 0xb9, 0xff, 0xe1, 0xff, 0xbf, 0xff, 0x1c, 0x38, 0xff, 0x5c, 0xff, 0xad, 0x68,
0xff, 0x17, 0x70, 0xff, 0xd1, 0xff, 0xef, 0xff, 0x66, 0xff, 0x08, 0xff, 0xa7, 0xf0, 0xff, 0x6d, 0xff, 0x6a, 0xff, 0xb7,
0xff, 0x06, 0xff, 0x31, 0xff, 0xa6, 0xff, 0x9d, 0xff, 0xe5, 0xff, 0xb2, 0xff, 0xd8, 0xff, 0xf9, 0xd0, 0xff, 0xf2, 0x20,
0xff, 0x63, 0xff, 0xba, 0xff, 0x36, 0xff, 0x7a, 0xff, 0x53, 0xff, 0xc0, 0xff, 0x22, 0xff, 0x40, 0xff, 0x3e, 0xff, 0xa1,
0xff, 0x95, 0x7d, 0x70, 0xff, 0xae, 0xff, 0x8c, 0xff, 0x35, 0xff, 0x7d, 0xff, 0x34, 0xd8, 0xff, 0x0c, 0xff, 0x69, 0xff,
0x8a, 0xff, 0x0e, 0xff, 0xd4, 0x68, 0xff, 0x19, 0xff, 0xc9, 0xff, 0x90, 0xff, 0x78, 0x30, 0xff, 0x38, 0xff, 0xc8, 0xff,
0xa0, 0xff, 0xc6, 0xff, 0x49, 0xff, 0xef, 0xff, 0xe3, 0xff, 0xb2, 0xff, 0x1d, 0xff, 0x7c, 0xff, 0xd3, 0xa8, 0xff, 0x33,
0xff, 0x51, 0x40, 0xff, 0x2b, 0xff, 0xd2, 0xff, 0x8e, 0xff, 0xa8, 0xff, 0x6d, 0xff, 0x9c, 0xff, 0x01, 0xff, 0x06, 0xff,
0x9f, 0xff, 0x93, 0xff, 0xa5, 0xff, 0x13, 0xff, 0x86, 0xff, 0x67, 0xff, 0x72, 0xff, 0x3e, 0xff, 0xc7, 0x00, 0xff, 0x97,
0xff, 0xe6, 0x28, 0xff, 0xce, 0xff, 0x61, 0xff, 0x5a, 0xff, 0x57, 0xff, 0x10, 0xff, 0xf7, 0xff, 0x49, 0xff, 0x32, 0xff,
0xea, 0xff, 0x8f, 0xb0, 0xff, 0x37, 0xe0, 0x78, 0xff, 0x25, 0x65, 0xff, 0x76, 0x38, 0xff, 0xf4, 0xff, 0x63, 0xff, 0x9c,
0xff, 0x44, 0x48, 0xff, 0x4c, 0xff, 0x7b, 0xff, 0x3f, 0xff, 0x9b, 0x38, 0x50, 0xff, 0xb4, 0xff, 0x2a, 0xff, 0x7a, 0xa0,
0xff, 0x03, 0xff, 0x29, 0xff, 0xf3, 0xff, 0x6f, 0xff, 0xff, 0x7d, 0x50, 0xff, 0x1a, 0xff, 0xb8, 0xff, 0x21, 0xff, 0xd7,
0xff, 0xd0, 0xff, 0xbf, 0xff, 0x10, 0xff, 0x1e, 0xff, 0x82, 0xff, 0x96, 0xff, 0x9f, 0xff, 0xe3, 0xff, 0xc4, 0xff, 0xcf,
0xff, 0x19, 0xff, 0x39, 0xa0, 0xff, 0x4b, 0xf8, 0xff, 0xa4, 0xff, 0x7e, 0x70, 0xff, 0x4e, 0xff, 0x3b, 0xff, 0x2c, 0xff,
0x0c, 0xff, 0x35, 0xff, 0xe1, 0xff, 0xd4, 0xff, 0x45, 0x40, 0xff, 0x28, 0xff, 0x67, 0xff, 0x18, 0xff, 0xdc, 0xff, 0x2d,
0xff, 0x77, 0xff, 0x68, 0xff, 0xf2, 0x40, 0xff, 0x87, 0xff, 0x52, 0x58, 0xff, 0xd1, 0xff, 0x50, 0xff, 0x04, 0x78, 0xff,
0xf6, 0xff, 0x1d, 0xff, 0xb8, 0xff, 0x9d, 0xff, 0xfa, 0xff, 0xe8, 0xff, 0xd8, 0xff, 0x94, 0xff, 0xe0, 0xff, 0xae, 0xff,
0x31, 0xff, 0x66, 0xff, 0xc7, 0xff, 0xee, 0xff, 0xa9, 0xff, 0xa8, 0xff, 0x51, 0xff, 0xe9, 0xff, 0x14, 0x7d, 0xff, 0x67,
0xff, 0x53, 0xff, 0x4c, 0xff, 0x40, 0x48, 0xa8, 0x20, 0xc8, 0xff, 0x57, 0xff, 0xf4, 0x48, 0xff, 0xd1, 0xff, 0x95, 0xff,
0x17, 0xff, 0x2c, 0xff, 0x5a, 0xff, 0x72, 0xff, 0x8f, 0xff, 0xdc, 0xff, 0xeb, 0xff, 0x6c, 0xff, 0x9b, 0xff, 0x24, 0xff,
0xfc, 0x40, 0xff, 0x11, 0xff, 0x07, 0xff, 0x82, 0xff, 0x2a, 0xff, 0xae, 0xff, 0xfb, 0xff, 0xd9, 0xff, 0xfd, 0xff, 0x89,
0xff, 0x75, 0xff, 0x71, 0xf0, 0xff, 0x74, 0xff, 0x08, 0xff, 0x0d, 0xff, 0xf7, 0xff, 0xba, 0xff, 0x5d, 0xff, 0x56, 0xff,
0xdf, 0xff, 0x7e, 0xff, 0x52, 0xff, 0x5b, 0xff, 0xce, 0xff, 0xef, 0x08, 0xff, 0xf6, 0xff, 0x32, 0x20, 0xff, 0x93, 0xff,
0x5f, 0xff, 0xab, 0xff, 0xfe, 0x60, 0xff, 0xec, 0xff, 0x20, 0xff, 0x18, 0xff, 0x0a, 0xff, 0x4e, 0xff, 0xc5, 0xff, 0xb6,
0xff, 0x42, 0xff, 0xe4, 0x20, 0xff, 0x70, 0xff, 0xbb, 0x18, 0xff, 0x1b, 0x98, 0xff, 0x01, 0xff, 0x9c, 0xff, 0xe5, 0xff,
0x1c, 0xff, 0xf4, 0xff, 0xd2, 0xff, 0x68, 0xff, 0x0b, 0xff, 0x30, 0xff, 0x2d, 0x40, 0xff, 0xda, 0xff, 0x23, 0xfe, 0xff,
0x7d, 0xbd, 0xff, 0x95, 0xff, 0x46, 0xff, 0x55, 0xff, 0x59, 0xff, 0xab, 0xff, 0x03, 0xff, 0x0f, 0x20, 0xff, 0xeb, 0xff,
0x8c, 0xff, 0xca, 0xff, 0xc1, 0xff, 0x13, 0xff, 0x28, 0xff, 0x49, 0xff, 0x12, 0xff, 0x66, 0xff, 0xd7, 0xff, 0x85, 0xff,
0xcb, 0xff, 0x21, 0xff, 0x8d, 0xff, 0x8a, 0xff, 0x34, 0xff, 0x4c, 0xff, 0x2e, 0x98, 0xff, 0x25, 0xff, 0x79, 0xff, 0xbf,
0xff, 0x98, 0xff, 0x04, 0xff, 0xcd, 0xa8, 0xff, 0x3e, 0xff, 0xad, 0xff, 0x08, 0xff, 0xd3, 0x70, 0xff, 0x32, 0xff, 0xed,
0xff, 0x54, 0xff, 0x7e, 0xff, 0x17, 0xff, 0xfe, 0xff, 0x89, 0xff, 0xe9, 0xff, 0x09, 0xff, 0x18, 0xff, 0xac, 0xff, 0x96,
0xff, 0xda, 0xff, 0x51, 0xff, 0x61, 0xff, 0x85, 0xff, 0x44, 0xff, 0xd2, 0xff, 0xdf, 0xff, 0xd9, 0xd0, 0xff, 0xa2, 0xd0,
0xff, 0x07, 0xff, 0x29, 0xff, 0xa5, 0xff, 0x31, 0xdc, 0xff, 0x16, 0x70, 0xff, 0x3d, 0xff, 0x6e, 0xff, 0x27, 0xff, 0xb6,
0xff, 0x5a, 0xff, 0x15, 0xff, 0x87, 0xff, 0x6c, 0xff, 0x48, 0xff, 0x3e, 0xff, 0x34, 0xff, 0xdd, 0xff, 0xec, 0xff, 0xf2,
0xff, 0x7c, 0xff, 0xc6, 0xb0, 0xff, 0x0f, 0xff, 0xcf, 0x60, 0xff, 0xde, 0xff, 0x42, 0xff, 0x02, 0xff, 0x93, 0xfe, 0xff,
0x7d, 0x4f, 0xff, 0x10, 0xb0, 0xff, 0x03, 0xff, 0xf3, 0xff, 0x1b, 0xff, 0x1e, 0xff, 0xaf, 0xff, 0x94, 0xff, 0x8e, 0xff,
0x77, 0x50, 0xff, 0x66, 0xff, 0x65, 0xff, 0xfb, 0xff, 0xd9, 0xff, 0x0d, 0xff, 0xf8, 0xff, 0x36, 0xff, 0x0c, 0x30, 0xff,
0xdc, 0x98, 0xff, 0xd1, 0x70, 0xff, 0x19, 0xff, 0xa8, 0xff, 0x87, 0xff, 0x97, 0xff, 0x39, 0x60, 0xff, 0x98, 0xff, 0x6c,
0x68, 0xff, 0x5d, 0xff, 0xc1, 0xff, 0x09, 0xff, 0x7e, 0xe0, 0xff, 0xab, 0xff, 0xde, 0x60, 0xff, 0x1f, 0xff, 0x21, 0xff,
0xd0, 0xff, 0x7a, 0xff, 0xaa, 0xff, 0xeb, 0xff, 0x96, 0xff, 0x60, 0xff, 0xf9, 0xff, 0x95, 0xff, 0xed, 0xff, 0x13, 0xff,
0xf4, 0xff, 0x82, 0xff, 0xa9, 0xff, 0x94, 0x58, 0xff, 0xa8, 0xff, 0x5e, 0xff, 0xe2, 0xff, 0xca, 0xff, 0x08, 0xa0, 0xff,
0xfe, 0xff, 0x9d, 0xb0, 0xff, 0x3f, 0xd0, 0x7d, 0xff, 0xd8, 0xf8, 0xd0, 0xff, 0xb0, 0xff, 0x84, 0xff, 0xd6, 0xff, 0x6a,
0xff, 0xcb, 0xff, 0xc1, 0xff, 0xd4, 0xff, 0xd0, 0xff, 0xe8, 0xff, 0xe7, 0xff, 0xae, 0xff, 0x44, 0xff, 0x28, 0xff, 0x47,
0xff, 0x75, 0xff, 0xa6, 0xff, 0x2a, 0xff, 0x40, 0xff, 0x0b, 0xff, 0x82, 0xff, 0x57, 0xff, 0xd5, 0xff, 0x49, 0xd0, 0xff,
0x85, 0xff, 0x5c, 0xff, 0x92, 0xff, 0x95, 0xff, 0x6b, 0xff, 0x7d, 0xff, 0xbe, 0xff, 0xcc, 0xff, 0xb6, 0xff, 0x2d, 0xff,
0x2b, 0xff, 0x71, 0xa0, 0xff, 0x63, 0xff, 0x39, 0xff, 0xfa, 0xff, 0xbc, 0xff, 0x19, 0xff, 0x7c, 0xff, 0xe2, 0xff, 0x3a,
0xff, 0x81, 0xff, 0xf1, 0xff, 0x86, 0xff, 0x9e, 0xff, 0x46, 0xff, 0x3d, 0xff, 0x5f, 0x78, 0xff, 0xa4, 0xff, 0xb7, 0xff,
0xd4, 0xff, 0x2c, 0xff, 0x98, 0x68, 0xff, 0xb5, 0xff, 0x95, 0xff, 0xac, 0xff, 0x33, 0x7d, 0xff, 0x1a, 0xff, 0x53, 0xff,
0x9d, 0xff, 0xe3, 0xff, 0x4e, 0xff, 0x5d, 0xff, 0x4f, 0xff, 0x54, 0xff, 0x0d, 0xff, 0xe8, 0x60, 0xff, 0x32, 0xff, 0x25,
0xff, 0x4d, 0xff, 0x5e, 0xff, 0x4c, 0xff, 0xe1, 0xff, 0xae, 0x00, 0xff, 0x85, 0xff, 0x1e, 0xff, 0xc4, 0xff, 0x20, 0xff,
0xdf, 0xff, 0x73, 0xd8, 0xff, 0x81, 0xff, 0x40, 0xff, 0xa2, 0x10, 0xff, 0x75, 0xa8, 0xff, 0x1d, 0xf8, 0xff, 0x7c, 0xff,
0x1f, 0xff, 0x07, 0xff, 0xe5, 0xff, 0x9e, 0xff, 0x76, 0xff, 0x9f, 0xff, 0x42, 0xff, 0xeb, 0x50, 0xff, 0xb4, 0xff, 0xd3,
0xff, 0xcb, 0xff, 0x55, 0xff, 0xe8, 0xff, 0xbf, 0xff, 0xf7, 0xb8, 0x70, 0xff, 0x2d, 0xff, 0xa5, 0xff, 0xfd, 0xff, 0xda,
0x98, 0xff, 0x5b, 0x40, 0xff, 0xa8, 0xff, 0xd2, 0x60, 0xff, 0xdf, 0xff, 0xd9, 0xff, 0xf2, 0xff, 0x35, 0xff, 0xc6, 0xff,
0x0c, 0x7d, 0xff, 0x36, 0xff, 0x66, 0xff, 0x28, 0xff, 0x95, 0xff, 0xe2, 0xff, 0x34, 0xff, 0x64, 0xff, 0xea, 0xff, 0xaf,
0xff, 0x3a, 0xb0, 0xff, 0x3c, 0xff, 0x38, 0xff, 0x31, 0xff, 0x99, 0xff, 0x8d, 0xff, 0x80, 0xff, 0x78, 0xff, 0x18, 0xff,
0x48, 0xff, 0x2c, 0xff, 0xe9, 0xff, 0xe5, 0xff, 0xb7, 0xff, 0xe6, 0xff, 0x2e, 0xff, 0x73, 0xff, 0xf1, 0xff, 0x7c, 0xff,
0x84, 0xff, 0x21, 0xff, 0x04, 0xff, 0x00, 0xff, 0x8e, 0xff, 0x12, 0xff, 0x66, 0xff, 0x6c, 0xff, 0x9b, 0xff, 0x09, 0xff,
0x88, 0xff, 0xe2, 0xff, 0xd5, 0xff, 0xec, 0xff, 0xb4, 0xff, 0xdd, 0xff, 0x2b, 0xff, 0xda, 0xff, 0x29, 0xff, 0x6f, 0xff,
0x1b, 0xff, 0x81, 0x58, 0xff, 0xe4, 0xff, 0x5c, 0xff, 0x36, 0x18, 0xff, 0x2d, 0xff, 0x9d, 0x90, 0xff, 0xb6, 0xff, 0x69,
0x08, 0xff, 0x40, 0xff, 0x4e, 0xff, 0x70, 0xff, 0x27, 0xde, 0xb8, 0xff, 0x0c, 0xff, 0x17, 0xff, 0x1d, 0xff, 0x15, 0x40,
0xff, 0x5b, 0xff, 0xd0, 0xff, 0x66, 0xff, 0x72, 0xff, 0xb8, 0xff, 0x38, 0xff, 0x80, 0xff, 0xbe, 0xff, 0x9e, 0xff, 0xd7,
0xff, 0x5e, 0xff, 0xb5, 0xb8, 0xff, 0x22, 0xff, 0xbc
};
const uint8_t SawyerCodingTest::rlecompresseddata[]
= { 0x02, 0x98, 0x07, 0x00, 0x00, 0x7d, 0xff, 0x3a, 0xff, 0x97, 0xff, 0x63, 0xff, 0x8b, 0xff, 0xbf, 0xff, 0xe5, 0xff, 0x6e,
0xff, 0x0e, 0xff, 0xc4, 0xff, 0xac, 0xff, 0xdc, 0xff, 0x84, 0xff, 0xd7, 0xff, 0x68, 0xff, 0xf1, 0xff, 0x4d, 0xff, 0xcb,
0xff, 0xaf, 0xff, 0x1e, 0xff, 0x5a, 0xff, 0x29, 0xff, 0x40, 0xff, 0x87, 0xff, 0x80, 0xff, 0x3f, 0xff, 0xf9, 0xff, 0xb8,
0xff, 0xad, 0xff, 0x01, 0xff, 0xd3, 0xff, 0x79, 0xff, 0x3d, 0xff, 0xe9, 0xa8, 0xff, 0xa8, 0xff, 0x95, 0x48, 0xff, 0xc0,
0xff, 0xc2, 0xc0, 0xff, 0x15, 0x68, 0xff, 0xdb, 0xff, 0xa6, 0xff, 0x90, 0xff, 0x8c, 0xff, 0x26, 0xff, 0x98, 0xff, 0x2a,
0x38, 0xff, 0x2e, 0xff, 0x0c, 0xff, 0x82, 0xff, 0x43, 0xff, 0x00, 0xff, 0x10, 0xff, 0x6d, 0xff, 0x60, 0xff, 0xb9, 0xff,
0xd4, 0xff, 0xed, 0xff, 0xf1, 0xff, 0x49, 0xff, 0xbb, 0xff, 0xf6, 0xff, 0x7d, 0x7f, 0xff, 0x21, 0xff, 0x24, 0xff, 0xc3,
0xff, 0xfb, 0xff, 0x42, 0xff, 0xe1, 0xff, 0xfc, 0xff, 0xb8, 0x50, 0xff, 0x5e, 0xff, 0x01, 0xff, 0x5d, 0xff, 0x96, 0xff,
0x2d, 0xff, 0x0f, 0xff, 0x48, 0xff, 0x12, 0xff, 0xdf, 0xff, 0x4b, 0xff, 0x6c, 0xff, 0x7e, 0xff, 0x99, 0xa0, 0xff, 0xfa,
0xff, 0x46, 0xff, 0x7d, 0xff, 0x2c, 0xff, 0xeb, 0xff, 0xd6, 0xff, 0xf3, 0xff, 0x77, 0xff, 0xa3, 0xff, 0x85, 0xff, 0x8e,
0xff, 0x00, 0xff, 0x34, 0xff, 0xee, 0xff, 0x73, 0xff, 0x31, 0xff, 0x76, 0xff, 0x53, 0xff, 0x17, 0xff, 0x5a, 0xff, 0x2b,
0xff, 0x19, 0xff, 0x65, 0xff, 0x2f, 0xff, 0x32, 0x28, 0xff, 0x57, 0xff, 0xc4, 0xff, 0xf8, 0xff, 0x05, 0xff, 0x0d, 0xff,
0xc3, 0xff, 0x59, 0xff, 0x29, 0xff, 0x9a, 0x90, 0xff, 0x3c, 0xff, 0x33, 0xff, 0x58, 0xff, 0x8c, 0xff, 0xd1, 0xff, 0x33,
0x1f, 0xff, 0x3b, 0xff, 0xa5, 0xff, 0x66, 0xff, 0xa7, 0xff, 0xfc, 0xff, 0x7c, 0x48, 0xff, 0xa9, 0xff, 0x1a, 0xff, 0x5e,
0x10, 0xff, 0x92, 0xff, 0x9e, 0xff, 0x71, 0xff, 0x27, 0xff, 0x07, 0xff, 0xbc, 0xe0, 0xff, 0xed, 0xff, 0xe5, 0xff, 0xc6,
0xff, 0x0e, 0xff, 0x74, 0xff, 0xdb, 0xff, 0x15, 0xff, 0x91, 0xff, 0xd7, 0xfe, 0xff, 0x63, 0xf7, 0xff, 0x30, 0xff, 0x6e,
0xff, 0x6a, 0xff, 0x00, 0xff, 0x40, 0x98, 0xff, 0x76, 0xff, 0x8a, 0xff, 0xb2, 0xff, 0x31, 0xff, 0xa3, 0xff, 0x81, 0xff,
0x83, 0xff, 0xc8, 0x38, 0xff, 0x08, 0xff, 0x1f, 0x28, 0xff, 0x8d, 0xff, 0x13, 0xff, 0x3e, 0xff, 0x9a, 0xff, 0xca, 0xff,
0x9c, 0xff, 0xd4, 0xff, 0x01, 0xff, 0x28, 0xff, 0xe6, 0xff, 0xaf, 0xff, 0xd6, 0xff, 0x2f, 0xff, 0xbc, 0xff, 0xe1, 0xff,
0xb7, 0xff, 0xbb, 0xff, 0x48, 0xff, 0x88, 0xff, 0x86, 0xff, 0x19, 0xd8, 0xff, 0x52, 0xff, 0xfc, 0xff, 0x18, 0xff, 0xc9,
0xff, 0xe3, 0xff, 0x90, 0xb0, 0xff, 0x6c, 0xff, 0x54, 0xff, 0x53, 0xff, 0x08, 0xff, 0x26, 0xfe, 0xff, 0x57, 0x38, 0xb0,
0xff, 0x5e, 0xff, 0x06, 0xff, 0xa1, 0xff, 0xac, 0xff, 0xc2, 0xff, 0x83, 0xff, 0x23, 0xff, 0x0d, 0xff, 0x42, 0xff, 0xe6,
0xff, 0xa9, 0xff, 0x81, 0x90, 0xff, 0x0b, 0xff, 0x4f, 0xff, 0x16, 0xff, 0x2a, 0xff, 0x77, 0xff, 0x3b, 0xff, 0x24, 0xff,
0xfb, 0xff, 0x94, 0x20, 0xff, 0x78, 0xff, 0x6a, 0xff, 0xf3, 0xff, 0x17, 0xe8, 0xff, 0x60, 0xff, 0x44, 0xff, 0x58, 0xff,
0x5c, 0xff, 0x50, 0xff, 0x80, 0xff, 0xc8, 0xff, 0x0f, 0xff, 0x87, 0xff, 0x7b, 0xff, 0x95, 0xff, 0x0a, 0xff, 0xdc, 0xff,
0xf1, 0xff, 0x1a, 0x68, 0xff, 0xa3, 0xfe, 0xff, 0x7d, 0x79, 0xff, 0xda, 0xff, 0x14, 0xff, 0xd4, 0xff, 0x6c, 0xff, 0x7a,
0xff, 0xfd, 0xff, 0x7e, 0xff, 0x1e, 0xff, 0xfe, 0xff, 0xd2, 0xff, 0x28, 0xff, 0xd0, 0xff, 0x06, 0x50, 0xff, 0x40, 0x18,
0xff, 0xa1, 0xff, 0x84, 0xff, 0xc9, 0xff, 0xc0, 0xff, 0x4b, 0xff, 0xa5, 0xff, 0x97, 0xff, 0xb2, 0xff, 0xb9, 0xff, 0x20,
0xff, 0x27, 0xff, 0x94, 0xff, 0x87, 0xff, 0x91, 0xff, 0xba, 0xc0, 0xff, 0xc6, 0xff, 0xdb, 0xff, 0x78, 0xff, 0x19, 0x50,
0xff, 0x35, 0xff, 0x9f, 0xff, 0xbd, 0xff, 0xfb, 0xff, 0xc1, 0xff, 0x45, 0xff, 0xbe, 0xff, 0xdc, 0xff, 0x30, 0xff, 0xad,
0xff, 0x38, 0xff, 0xd4, 0xff, 0x14, 0xff, 0x46, 0xff, 0x98, 0xff, 0x2a, 0xff, 0x90, 0xff, 0xc8, 0xff, 0x85, 0xff, 0x5e,
0xff, 0x7e, 0xff, 0x76, 0xff, 0x0f, 0xff, 0xc4, 0xff, 0x20, 0xff, 0x07, 0xff, 0x54, 0xff, 0x7d, 0x1a, 0xff, 0x60, 0xff,
0x3a, 0xff, 0x8c, 0xff, 0x75, 0xff, 0xb0, 0xff, 0x43, 0xff, 0xab, 0xff, 0xbb, 0xff, 0x05, 0xff, 0xca, 0xff, 0x93, 0xff,
0xeb, 0xff, 0x18, 0xff, 0x94, 0xff, 0xf1, 0xff, 0x64, 0xff, 0x8a, 0xff, 0x01, 0xff, 0xe0, 0xff, 0xe6, 0xff, 0x24, 0xff,
0x78, 0xff, 0x50, 0x98, 0xff, 0xd3, 0xff, 0xb9, 0xff, 0xe1, 0xff, 0xbf, 0xff, 0x1c, 0x38, 0xff, 0x5c, 0xff, 0xad, 0x68,
0xff, 0x17, 0x70, 0xff, 0xd1, 0xff, 0xef, 0xff, 0x66, 0xff, 0x08, 0xff, 0xa7, 0xf0, 0xff, 0x6d, 0xff, 0x6a, 0xff, 0xb7,
0xff, 0x06, 0xff, 0x31, 0xff, 0xa6, 0xff, 0x9d, 0xff, 0xe5, 0xff, 0xb2, 0xff, 0xd8, 0xff, 0xf9, 0xd0, 0xff, 0xf2, 0x20,
0xff, 0x63, 0xff, 0xba, 0xff, 0x36, 0xff, 0x7a, 0xff, 0x53, 0xff, 0xc0, 0xff, 0x22, 0xff, 0x40, 0xff, 0x3e, 0xff, 0xa1,
0xff, 0x95, 0x7d, 0x70, 0xff, 0xae, 0xff, 0x8c, 0xff, 0x35, 0xff, 0x7d, 0xff, 0x34, 0xd8, 0xff, 0x0c, 0xff, 0x69, 0xff,
0x8a, 0xff, 0x0e, 0xff, 0xd4, 0x68, 0xff, 0x19, 0xff, 0xc9, 0xff, 0x90, 0xff, 0x78, 0x30, 0xff, 0x38, 0xff, 0xc8, 0xff,
0xa0, 0xff, 0xc6, 0xff, 0x49, 0xff, 0xef, 0xff, 0xe3, 0xff, 0xb2, 0xff, 0x1d, 0xff, 0x7c, 0xff, 0xd3, 0xa8, 0xff, 0x33,
0xff, 0x51, 0x40, 0xff, 0x2b, 0xff, 0xd2, 0xff, 0x8e, 0xff, 0xa8, 0xff, 0x6d, 0xff, 0x9c, 0xff, 0x01, 0xff, 0x06, 0xff,
0x9f, 0xff, 0x93, 0xff, 0xa5, 0xff, 0x13, 0xff, 0x86, 0xff, 0x67, 0xff, 0x72, 0xff, 0x3e, 0xff, 0xc7, 0x00, 0xff, 0x97,
0xff, 0xe6, 0x28, 0xff, 0xce, 0xff, 0x61, 0xff, 0x5a, 0xff, 0x57, 0xff, 0x10, 0xff, 0xf7, 0xff, 0x49, 0xff, 0x32, 0xff,
0xea, 0xff, 0x8f, 0xb0, 0xff, 0x37, 0xe0, 0x78, 0xff, 0x25, 0x65, 0xff, 0x76, 0x38, 0xff, 0xf4, 0xff, 0x63, 0xff, 0x9c,
0xff, 0x44, 0x48, 0xff, 0x4c, 0xff, 0x7b, 0xff, 0x3f, 0xff, 0x9b, 0x38, 0x50, 0xff, 0xb4, 0xff, 0x2a, 0xff, 0x7a, 0xa0,
0xff, 0x03, 0xff, 0x29, 0xff, 0xf3, 0xff, 0x6f, 0xff, 0xff, 0x7d, 0x50, 0xff, 0x1a, 0xff, 0xb8, 0xff, 0x21, 0xff, 0xd7,
0xff, 0xd0, 0xff, 0xbf, 0xff, 0x10, 0xff, 0x1e, 0xff, 0x82, 0xff, 0x96, 0xff, 0x9f, 0xff, 0xe3, 0xff, 0xc4, 0xff, 0xcf,
0xff, 0x19, 0xff, 0x39, 0xa0, 0xff, 0x4b, 0xf8, 0xff, 0xa4, 0xff, 0x7e, 0x70, 0xff, 0x4e, 0xff, 0x3b, 0xff, 0x2c, 0xff,
0x0c, 0xff, 0x35, 0xff, 0xe1, 0xff, 0xd4, 0xff, 0x45, 0x40, 0xff, 0x28, 0xff, 0x67, 0xff, 0x18, 0xff, 0xdc, 0xff, 0x2d,
0xff, 0x77, 0xff, 0x68, 0xff, 0xf2, 0x40, 0xff, 0x87, 0xff, 0x52, 0x58, 0xff, 0xd1, 0xff, 0x50, 0xff, 0x04, 0x78, 0xff,
0xf6, 0xff, 0x1d, 0xff, 0xb8, 0xff, 0x9d, 0xff, 0xfa, 0xff, 0xe8, 0xff, 0xd8, 0xff, 0x94, 0xff, 0xe0, 0xff, 0xae, 0xff,
0x31, 0xff, 0x66, 0xff, 0xc7, 0xff, 0xee, 0xff, 0xa9, 0xff, 0xa8, 0xff, 0x51, 0xff, 0xe9, 0xff, 0x14, 0x7d, 0xff, 0x67,
0xff, 0x53, 0xff, 0x4c, 0xff, 0x40, 0x48, 0xa8, 0x20, 0xc8, 0xff, 0x57, 0xff, 0xf4, 0x48, 0xff, 0xd1, 0xff, 0x95, 0xff,
0x17, 0xff, 0x2c, 0xff, 0x5a, 0xff, 0x72, 0xff, 0x8f, 0xff, 0xdc, 0xff, 0xeb, 0xff, 0x6c, 0xff, 0x9b, 0xff, 0x24, 0xff,
0xfc, 0x40, 0xff, 0x11, 0xff, 0x07, 0xff, 0x82, 0xff, 0x2a, 0xff, 0xae, 0xff, 0xfb, 0xff, 0xd9, 0xff, 0xfd, 0xff, 0x89,
0xff, 0x75, 0xff, 0x71, 0xf0, 0xff, 0x74, 0xff, 0x08, 0xff, 0x0d, 0xff, 0xf7, 0xff, 0xba, 0xff, 0x5d, 0xff, 0x56, 0xff,
0xdf, 0xff, 0x7e, 0xff, 0x52, 0xff, 0x5b, 0xff, 0xce, 0xff, 0xef, 0x08, 0xff, 0xf6, 0xff, 0x32, 0x20, 0xff, 0x93, 0xff,
0x5f, 0xff, 0xab, 0xff, 0xfe, 0x60, 0xff, 0xec, 0xff, 0x20, 0xff, 0x18, 0xff, 0x0a, 0xff, 0x4e, 0xff, 0xc5, 0xff, 0xb6,
0xff, 0x42, 0xff, 0xe4, 0x20, 0xff, 0x70, 0xff, 0xbb, 0x18, 0xff, 0x1b, 0x98, 0xff, 0x01, 0xff, 0x9c, 0xff, 0xe5, 0xff,
0x1c, 0xff, 0xf4, 0xff, 0xd2, 0xff, 0x68, 0xff, 0x0b, 0xff, 0x30, 0xff, 0x2d, 0x40, 0xff, 0xda, 0xff, 0x23, 0xfe, 0xff,
0x7d, 0xbd, 0xff, 0x95, 0xff, 0x46, 0xff, 0x55, 0xff, 0x59, 0xff, 0xab, 0xff, 0x03, 0xff, 0x0f, 0x20, 0xff, 0xeb, 0xff,
0x8c, 0xff, 0xca, 0xff, 0xc1, 0xff, 0x13, 0xff, 0x28, 0xff, 0x49, 0xff, 0x12, 0xff, 0x66, 0xff, 0xd7, 0xff, 0x85, 0xff,
0xcb, 0xff, 0x21, 0xff, 0x8d, 0xff, 0x8a, 0xff, 0x34, 0xff, 0x4c, 0xff, 0x2e, 0x98, 0xff, 0x25, 0xff, 0x79, 0xff, 0xbf,
0xff, 0x98, 0xff, 0x04, 0xff, 0xcd, 0xa8, 0xff, 0x3e, 0xff, 0xad, 0xff, 0x08, 0xff, 0xd3, 0x70, 0xff, 0x32, 0xff, 0xed,
0xff, 0x54, 0xff, 0x7e, 0xff, 0x17, 0xff, 0xfe, 0xff, 0x89, 0xff, 0xe9, 0xff, 0x09, 0xff, 0x18, 0xff, 0xac, 0xff, 0x96,
0xff, 0xda, 0xff, 0x51, 0xff, 0x61, 0xff, 0x85, 0xff, 0x44, 0xff, 0xd2, 0xff, 0xdf, 0xff, 0xd9, 0xd0, 0xff, 0xa2, 0xd0,
0xff, 0x07, 0xff, 0x29, 0xff, 0xa5, 0xff, 0x31, 0xdc, 0xff, 0x16, 0x70, 0xff, 0x3d, 0xff, 0x6e, 0xff, 0x27, 0xff, 0xb6,
0xff, 0x5a, 0xff, 0x15, 0xff, 0x87, 0xff, 0x6c, 0xff, 0x48, 0xff, 0x3e, 0xff, 0x34, 0xff, 0xdd, 0xff, 0xec, 0xff, 0xf2,
0xff, 0x7c, 0xff, 0xc6, 0xb0, 0xff, 0x0f, 0xff, 0xcf, 0x60, 0xff, 0xde, 0xff, 0x42, 0xff, 0x02, 0xff, 0x93, 0xfe, 0xff,
0x7d, 0x4f, 0xff, 0x10, 0xb0, 0xff, 0x03, 0xff, 0xf3, 0xff, 0x1b, 0xff, 0x1e, 0xff, 0xaf, 0xff, 0x94, 0xff, 0x8e, 0xff,
0x77, 0x50, 0xff, 0x66, 0xff, 0x65, 0xff, 0xfb, 0xff, 0xd9, 0xff, 0x0d, 0xff, 0xf8, 0xff, 0x36, 0xff, 0x0c, 0x30, 0xff,
0xdc, 0x98, 0xff, 0xd1, 0x70, 0xff, 0x19, 0xff, 0xa8, 0xff, 0x87, 0xff, 0x97, 0xff, 0x39, 0x60, 0xff, 0x98, 0xff, 0x6c,
0x68, 0xff, 0x5d, 0xff, 0xc1, 0xff, 0x09, 0xff, 0x7e, 0xe0, 0xff, 0xab, 0xff, 0xde, 0x60, 0xff, 0x1f, 0xff, 0x21, 0xff,
0xd0, 0xff, 0x7a, 0xff, 0xaa, 0xff, 0xeb, 0xff, 0x96, 0xff, 0x60, 0xff, 0xf9, 0xff, 0x95, 0xff, 0xed, 0xff, 0x13, 0xff,
0xf4, 0xff, 0x82, 0xff, 0xa9, 0xff, 0x94, 0x58, 0xff, 0xa8, 0xff, 0x5e, 0xff, 0xe2, 0xff, 0xca, 0xff, 0x08, 0xa0, 0xff,
0xfe, 0xff, 0x9d, 0xb0, 0xff, 0x3f, 0xd0, 0x7d, 0xff, 0xd8, 0xf8, 0xd0, 0xff, 0xb0, 0xff, 0x84, 0xff, 0xd6, 0xff, 0x6a,
0xff, 0xcb, 0xff, 0xc1, 0xff, 0xd4, 0xff, 0xd0, 0xff, 0xe8, 0xff, 0xe7, 0xff, 0xae, 0xff, 0x44, 0xff, 0x28, 0xff, 0x47,
0xff, 0x75, 0xff, 0xa6, 0xff, 0x2a, 0xff, 0x40, 0xff, 0x0b, 0xff, 0x82, 0xff, 0x57, 0xff, 0xd5, 0xff, 0x49, 0xd0, 0xff,
0x85, 0xff, 0x5c, 0xff, 0x92, 0xff, 0x95, 0xff, 0x6b, 0xff, 0x7d, 0xff, 0xbe, 0xff, 0xcc, 0xff, 0xb6, 0xff, 0x2d, 0xff,
0x2b, 0xff, 0x71, 0xa0, 0xff, 0x63, 0xff, 0x39, 0xff, 0xfa, 0xff, 0xbc, 0xff, 0x19, 0xff, 0x7c, 0xff, 0xe2, 0xff, 0x3a,
0xff, 0x81, 0xff, 0xf1, 0xff, 0x86, 0xff, 0x9e, 0xff, 0x46, 0xff, 0x3d, 0xff, 0x5f, 0x78, 0xff, 0xa4, 0xff, 0xb7, 0xff,
0xd4, 0xff, 0x2c, 0xff, 0x98, 0x68, 0xff, 0xb5, 0xff, 0x95, 0xff, 0xac, 0xff, 0x33, 0x7d, 0xff, 0x1a, 0xff, 0x53, 0xff,
0x9d, 0xff, 0xe3, 0xff, 0x4e, 0xff, 0x5d, 0xff, 0x4f, 0xff, 0x54, 0xff, 0x0d, 0xff, 0xe8, 0x60, 0xff, 0x32, 0xff, 0x25,
0xff, 0x4d, 0xff, 0x5e, 0xff, 0x4c, 0xff, 0xe1, 0xff, 0xae, 0x00, 0xff, 0x85, 0xff, 0x1e, 0xff, 0xc4, 0xff, 0x20, 0xff,
0xdf, 0xff, 0x73, 0xd8, 0xff, 0x81, 0xff, 0x40, 0xff, 0xa2, 0x10, 0xff, 0x75, 0xa8, 0xff, 0x1d, 0xf8, 0xff, 0x7c, 0xff,
0x1f, 0xff, 0x07, 0xff, 0xe5, 0xff, 0x9e, 0xff, 0x76, 0xff, 0x9f, 0xff, 0x42, 0xff, 0xeb, 0x50, 0xff, 0xb4, 0xff, 0xd3,
0xff, 0xcb, 0xff, 0x55, 0xff, 0xe8, 0xff, 0xbf, 0xff, 0xf7, 0xb8, 0x70, 0xff, 0x2d, 0xff, 0xa5, 0xff, 0xfd, 0xff, 0xda,
0x98, 0xff, 0x5b, 0x40, 0xff, 0xa8, 0xff, 0xd2, 0x60, 0xff, 0xdf, 0xff, 0xd9, 0xff, 0xf2, 0xff, 0x35, 0xff, 0xc6, 0xff,
0x0c, 0x7d, 0xff, 0x36, 0xff, 0x66, 0xff, 0x28, 0xff, 0x95, 0xff, 0xe2, 0xff, 0x34, 0xff, 0x64, 0xff, 0xea, 0xff, 0xaf,
0xff, 0x3a, 0xb0, 0xff, 0x3c, 0xff, 0x38, 0xff, 0x31, 0xff, 0x99, 0xff, 0x8d, 0xff, 0x80, 0xff, 0x78, 0xff, 0x18, 0xff,
0x48, 0xff, 0x2c, 0xff, 0xe9, 0xff, 0xe5, 0xff, 0xb7, 0xff, 0xe6, 0xff, 0x2e, 0xff, 0x73, 0xff, 0xf1, 0xff, 0x7c, 0xff,
0x84, 0xff, 0x21, 0xff, 0x04, 0xff, 0x00, 0xff, 0x8e, 0xff, 0x12, 0xff, 0x66, 0xff, 0x6c, 0xff, 0x9b, 0xff, 0x09, 0xff,
0x88, 0xff, 0xe2, 0xff, 0xd5, 0xff, 0xec, 0xff, 0xb4, 0xff, 0xdd, 0xff, 0x2b, 0xff, 0xda, 0xff, 0x29, 0xff, 0x6f, 0xff,
0x1b, 0xff, 0x81, 0x58, 0xff, 0xe4, 0xff, 0x5c, 0xff, 0x36, 0x18, 0xff, 0x2d, 0xff, 0x9d, 0x90, 0xff, 0xb6, 0xff, 0x69,
0x08, 0xff, 0x40, 0xff, 0x4e, 0xff, 0x70, 0xff, 0x27, 0xde, 0xb8, 0xff, 0x0c, 0xff, 0x17, 0xff, 0x1d, 0xff, 0x15, 0x40,
0xff, 0x5b, 0xff, 0xd0, 0xff, 0x66, 0xff, 0x72, 0xff, 0xb8, 0xff, 0x38, 0xff, 0x80, 0xff, 0xbe, 0xff, 0x9e, 0xff, 0xd7,
0xff, 0x5e, 0xff, 0xb5, 0xb8, 0xff, 0x22, 0xff, 0xbc };
const uint8_t SawyerCodingTest::rotatedata[] = {
0x03, 0x00, 0x04, 0x00, 0x00, 0x74, 0xbc, 0x6c, 0xc5, 0x7f, 0x2f, 0xcd, 0x07, 0x89, 0x65, 0x9b, 0x42, 0xaf, 0x43, 0x3e,
0xa6, 0x97, 0x7d, 0xc3, 0x2d, 0x52, 0x02, 0xf0, 0x40, 0x7e, 0xcf, 0x17, 0xd6, 0x02, 0x9e, 0x2f, 0x9e, 0xd3, 0x3c, 0x15,
0xca, 0xd0, 0x06, 0x58, 0x9e, 0x2a, 0x3c, 0x7b, 0x53, 0x21, 0x64, 0xc4, 0x4c, 0x54, 0xf9, 0xc5, 0x06, 0x05, 0x1a, 0x00,
0x08, 0xda, 0x03, 0x37, 0x6a, 0xdb, 0x8f, 0x29, 0xdd, 0xed, 0xfb, 0x24, 0x12, 0x87, 0xdf, 0x48, 0xf0, 0xf9, 0xc5, 0x50,
0x2f, 0x02, 0xea, 0xd2, 0x96, 0x1e, 0x42, 0x42, 0xef, 0x96, 0x63, 0xcf, 0xcc, 0x02, 0xd7, 0xc8, 0xbe, 0x58, 0x5f, 0xda,
0xf9, 0xee, 0x1d, 0xb0, 0x47, 0x00, 0xa1, 0xdd, 0xb9, 0x62, 0xb3, 0x6a, 0x8b, 0xb4, 0x59, 0x23, 0xb2, 0x5e, 0x91, 0x33,
0xab, 0x89, 0xc7, 0xa0, 0x86, 0x87, 0xca, 0x25, 0x4d, 0x32, 0xe1, 0x66, 0x2c, 0x19, 0x8e, 0xe3, 0x9d, 0x4b, 0x33, 0xf4,
0x7e, 0xf8, 0xcc, 0x35, 0x0d, 0xbc, 0x2b, 0x52, 0x4f, 0xe2, 0x39, 0xe0, 0x5e, 0xe2, 0x6f, 0xbc, 0x63, 0x1c, 0xa3, 0x7b,
0x8a, 0x23, 0xbe, 0xff, 0xfb, 0x60, 0x73, 0x4d, 0x00, 0x80, 0x70, 0xce, 0x45, 0x65, 0x89, 0x74, 0xc0, 0x07, 0x46, 0xbd,
0x04, 0x3e, 0x2f, 0xb1, 0x89, 0x7c, 0xd4, 0x59, 0x4e, 0xa9, 0x08, 0x05, 0x73, 0x5f, 0xb6, 0xe5, 0x5e, 0xc3, 0xbd, 0x77,
0x24, 0x11, 0x34, 0x23, 0xdd, 0xa4, 0xe7, 0x03, 0xe4, 0xc7, 0x84, 0x11, 0x36, 0xa8, 0x9a, 0x01, 0x13, 0xff, 0xc1, 0x7c,
0x2f, 0x0c, 0x0d, 0x95, 0x61, 0x07, 0x19, 0xa1, 0x21, 0xcd, 0x4d, 0x30, 0x1c, 0x16, 0x7a, 0xc2, 0x15, 0xee, 0xd9, 0x84,
0xfd, 0x29, 0x9a, 0x0f, 0x35, 0xe7, 0xb8, 0x4d, 0x30, 0x88, 0xc2, 0x8b, 0x28, 0x01, 0x46, 0xe1, 0xc3, 0xf6, 0xac, 0x41,
0x6e, 0xe3, 0xd0, 0x4d, 0xd1, 0xff, 0xcb, 0x5b, 0x0a, 0xa9, 0x63, 0x4f, 0xfe, 0xfc, 0xf0, 0xdf, 0x69, 0x50, 0x86, 0xc0,
0xca, 0x80, 0x04, 0x34, 0x42, 0x93, 0x06, 0x69, 0xd2, 0x2f, 0x95, 0x37, 0x10, 0x4e, 0xa4, 0xf0, 0xc8, 0x75, 0x95, 0xd8,
0xed, 0xf0, 0xc8, 0x08, 0x9a, 0x3f, 0xed, 0x7f, 0xe0, 0x8a, 0xf5, 0x9b, 0x18, 0x5b, 0xc1, 0x9a, 0x0a, 0x8c, 0xc4, 0x45,
0x48, 0x91, 0x2c, 0xcb, 0x3f, 0xec, 0x78, 0x98, 0x10, 0x0e, 0xa2, 0x43, 0x30, 0x74, 0x64, 0xae, 0x58, 0x86, 0x5d, 0x77,
0x82, 0x95, 0x9c, 0x7d, 0x0c, 0x29, 0x8f, 0x8c, 0x45, 0x02, 0x07, 0xdc, 0x12, 0xf0, 0x82, 0x72, 0xe9, 0x73, 0x0f, 0xf7,
0x0e, 0x61, 0xe2, 0xb5, 0x4a, 0x2e, 0x54, 0x3a, 0xf7, 0xcc, 0x40, 0xf4, 0x04, 0xda, 0x53, 0xf6, 0x03, 0x62, 0x35, 0xb3,
0xf2, 0x65, 0xc6, 0x3f, 0x53, 0xe5, 0x0f, 0x6c, 0x5d, 0x6c, 0xd3, 0x6a, 0x60, 0x44, 0x02, 0xc7, 0xd0, 0x2b, 0x2f, 0xd5,
0x46, 0x6a, 0xeb, 0x86, 0x57, 0x18, 0x4b, 0x51, 0x07, 0xa9, 0x9a, 0x23, 0xe4, 0x21, 0xc3, 0xc6, 0x1c, 0x91, 0x05, 0xd8,
0xa4, 0xdf, 0x1f, 0x56, 0x8e, 0xf8, 0x9e, 0x07, 0x99, 0xa2, 0x4b, 0x65, 0x69, 0x1d, 0x45, 0xad, 0x4e, 0x02, 0x30, 0xf3,
0xc9, 0x4b, 0x98, 0xd0, 0xb3, 0xe4, 0xf1, 0xf8, 0x1c, 0x2f, 0x37, 0xa3, 0x67, 0xc2, 0xd2, 0xea, 0x08, 0xef, 0x4a, 0x46,
0x75, 0x1f, 0x76, 0xe6, 0x75, 0x70, 0x2b, 0xce, 0x43, 0xe9, 0x1b, 0x93, 0x22, 0xcd, 0x62, 0x6f, 0x9f, 0x37, 0x0b, 0xfe,
0x5a, 0x54, 0xd3, 0x93, 0x81, 0x52, 0x9f, 0xed, 0xff, 0xec, 0xd0, 0x17, 0x90, 0xaf, 0x86, 0xf7, 0x08, 0x3c, 0x14, 0xd2,
0xcf, 0xc7, 0x26, 0xf9, 0x8c, 0x72, 0x86, 0x69, 0xa5, 0x49, 0xf3, 0xfa, 0x27, 0x76, 0x61, 0x81, 0x9a, 0xc3, 0xa6, 0xa8,
0x08, 0x50, 0x3b, 0x03, 0x6e, 0x5a, 0xbb, 0x0d, 0x79, 0x72, 0x3c, 0x4a, 0xeb, 0xa3, 0x82, 0x80, 0xa2, 0xed, 0xe8, 0x17,
0xce, 0xf5, 0x47, 0x1b, 0x4a, 0xc1, 0x75, 0x26, 0x33, 0x8f, 0x77, 0x35, 0x54, 0xa2, 0x4f, 0x82, 0xb3, 0xa6, 0x62, 0x08,
0x7b, 0xdd, 0x82, 0xec, 0xab, 0xe9, 0xc6, 0x3a, 0xca, 0x2e, 0x61, 0x4b, 0x39, 0x1f, 0xe6, 0x7d, 0x36, 0x37, 0x21, 0x9f,
0xb3, 0x22, 0x38, 0x50, 0x15, 0x5d, 0xdf, 0x3b, 0xfe, 0x13, 0xab, 0x2e, 0xba, 0xe8, 0x40, 0xa1, 0xfb, 0x75, 0xea, 0xca,
0xef, 0xfc, 0x92, 0x6b, 0x67, 0xdf, 0x5f, 0xde, 0x19, 0x22, 0x9c, 0xeb, 0xd5, 0xfd, 0x40, 0x9d, 0x10, 0x30, 0x50, 0xc9,
0xe2, 0x6d, 0x12, 0x9c, 0x38, 0x77, 0xd5, 0x63, 0x76, 0x02, 0xe4, 0xbc, 0x0e, 0xe9, 0x96, 0x0d, 0x85, 0x60, 0x69, 0x9d,
0x6d, 0x46, 0xff, 0xb7, 0xca, 0x8c, 0xaa, 0x2b, 0xd5, 0x06, 0x78, 0x9c, 0xf5, 0x19, 0x56, 0x38, 0x89, 0x50, 0x4a, 0x42,
0x33, 0xaf, 0x2c, 0x79, 0x90, 0x1b, 0x54, 0x86, 0x26, 0x5c, 0x41, 0xa4, 0xbc, 0x7f, 0xc4, 0x80, 0xe6, 0x15, 0xf1, 0xb5,
0x04, 0xa7, 0x09, 0x46, 0xf6, 0xa8, 0xf3, 0xe2, 0x7f, 0x13, 0x4f, 0x21, 0x0c, 0x59, 0xb4, 0x5b, 0xa8, 0xc2, 0x2c, 0x88,
0x69, 0xbf, 0xce, 0x2c, 0x51, 0x88, 0x38, 0x25, 0xd2, 0xb9, 0xb0, 0x95, 0x9e, 0xdc, 0x39, 0xd6, 0x2d, 0x2a, 0x3c, 0x8d,
0x24, 0x7c, 0xa1, 0xbb, 0x76, 0xe5, 0xe3, 0xd8, 0xc3, 0x1e, 0x7e, 0x95, 0x6f, 0x84, 0x10, 0x72, 0xff, 0x9e, 0x80, 0xe1,
0x81, 0xe7, 0xd8, 0xc3, 0xd7, 0x29, 0x74, 0xee, 0x3e, 0xcc, 0x2b, 0x7f, 0xec, 0x1a, 0xc7, 0xc6, 0x06, 0x59, 0xe6, 0xd1,
0xe8, 0x3c, 0xc8, 0x15, 0xc3, 0x2f, 0xc9, 0xee, 0x4c, 0xd8, 0xdf, 0xab, 0xe0, 0x12, 0xf3, 0xab, 0xd5, 0xbd, 0xe6, 0xe3,
0x90, 0xa1, 0xd3, 0x55, 0xf5, 0x2d, 0x03, 0x3f, 0xca, 0xdb, 0x98, 0x9e, 0x41, 0x53, 0xa4, 0xcf, 0x54, 0xbc, 0x17, 0x59,
0x04, 0xdb, 0xf7, 0xb3, 0x4a, 0x7e, 0x40, 0x1b, 0x6c, 0x3b, 0x85, 0x90, 0x6b, 0xd4, 0x5e, 0x38, 0x6a, 0xa1, 0x47, 0xfc,
0x57, 0x88, 0x41, 0xe8, 0xba, 0x4d, 0x51, 0x08, 0x85, 0x05, 0xba, 0xba, 0xa4, 0x80, 0x2c, 0x8b, 0x49, 0x2b, 0x5b, 0xaf,
0x5f, 0x99, 0xb5, 0xa5, 0x95, 0xe2, 0x2c, 0x6c, 0x9c, 0xf5, 0xe5, 0x23, 0x3e, 0xc5, 0xd1, 0x30, 0xf8, 0x0d, 0xf4, 0xc8,
0x9e, 0xbe, 0x8b, 0x94, 0xdb, 0xa9, 0x61, 0x13, 0x7d, 0x6b, 0xac, 0x95, 0x99, 0x34, 0x9a, 0xb3, 0xf1, 0x9c, 0xea, 0xe9,
0x2a, 0x1a, 0x47, 0x94, 0x19, 0x4a, 0x6a, 0xcb, 0x26, 0xc3, 0x75, 0xc8, 0xc2, 0x3c, 0x26, 0x04, 0xef, 0xe6, 0xf0, 0x30,
0x20, 0x45, 0x99, 0xae, 0x0f, 0x3a, 0xe8, 0x8f, 0x8f, 0x0e, 0x2f, 0xd3, 0x3b, 0x3f, 0x12, 0x7d, 0x62, 0x69, 0x9e, 0x79,
0xaa, 0xd1, 0xfd, 0xfe, 0xf5, 0xf8, 0x69, 0xb4, 0xfe, 0xb5, 0xa5, 0x6b, 0x8f, 0x51, 0x96, 0x7d, 0xef, 0xb3, 0x97, 0xa6,
0x63, 0x18, 0xb1, 0xcc, 0x14, 0x2b, 0x17, 0x86, 0x32, 0xd5, 0x7d, 0x47, 0x1b, 0x78, 0xc1, 0x26, 0xcc, 0x1b, 0x04, 0x0f,
0x0c, 0x90, 0x61, 0x3d, 0xf2, 0x6f, 0x37, 0xc5, 0xb9, 0xe3, 0xe3, 0x90, 0x90, 0x08, 0x00, 0xd1, 0x09, 0xcc, 0x63, 0x73,
0x84, 0x11, 0x17, 0xba, 0x76, 0x69, 0xee, 0x65, 0x6d, 0x52, 0x7b, 0x63, 0xc0, 0x42, 0x27, 0x8b, 0x1b, 0xe6, 0x69, 0xb3,
0xee, 0x6d, 0x4b, 0x24, 0x20, 0x9c, 0x83, 0xdb, 0xce, 0x18, 0xb8, 0xa3, 0x8a, 0x52, 0xda, 0x1a, 0x33, 0xe4, 0xc5, 0x07,
0x40, 0x7d, 0xf4, 0xfa, 0x2f, 0x6b, 0x93, 0x44, 0x5e
};
const uint8_t SawyerCodingTest::rotatedata[]
= { 0x03, 0x00, 0x04, 0x00, 0x00, 0x74, 0xbc, 0x6c, 0xc5, 0x7f, 0x2f, 0xcd, 0x07, 0x89, 0x65, 0x9b, 0x42, 0xaf, 0x43, 0x3e,
0xa6, 0x97, 0x7d, 0xc3, 0x2d, 0x52, 0x02, 0xf0, 0x40, 0x7e, 0xcf, 0x17, 0xd6, 0x02, 0x9e, 0x2f, 0x9e, 0xd3, 0x3c, 0x15,
0xca, 0xd0, 0x06, 0x58, 0x9e, 0x2a, 0x3c, 0x7b, 0x53, 0x21, 0x64, 0xc4, 0x4c, 0x54, 0xf9, 0xc5, 0x06, 0x05, 0x1a, 0x00,
0x08, 0xda, 0x03, 0x37, 0x6a, 0xdb, 0x8f, 0x29, 0xdd, 0xed, 0xfb, 0x24, 0x12, 0x87, 0xdf, 0x48, 0xf0, 0xf9, 0xc5, 0x50,
0x2f, 0x02, 0xea, 0xd2, 0x96, 0x1e, 0x42, 0x42, 0xef, 0x96, 0x63, 0xcf, 0xcc, 0x02, 0xd7, 0xc8, 0xbe, 0x58, 0x5f, 0xda,
0xf9, 0xee, 0x1d, 0xb0, 0x47, 0x00, 0xa1, 0xdd, 0xb9, 0x62, 0xb3, 0x6a, 0x8b, 0xb4, 0x59, 0x23, 0xb2, 0x5e, 0x91, 0x33,
0xab, 0x89, 0xc7, 0xa0, 0x86, 0x87, 0xca, 0x25, 0x4d, 0x32, 0xe1, 0x66, 0x2c, 0x19, 0x8e, 0xe3, 0x9d, 0x4b, 0x33, 0xf4,
0x7e, 0xf8, 0xcc, 0x35, 0x0d, 0xbc, 0x2b, 0x52, 0x4f, 0xe2, 0x39, 0xe0, 0x5e, 0xe2, 0x6f, 0xbc, 0x63, 0x1c, 0xa3, 0x7b,
0x8a, 0x23, 0xbe, 0xff, 0xfb, 0x60, 0x73, 0x4d, 0x00, 0x80, 0x70, 0xce, 0x45, 0x65, 0x89, 0x74, 0xc0, 0x07, 0x46, 0xbd,
0x04, 0x3e, 0x2f, 0xb1, 0x89, 0x7c, 0xd4, 0x59, 0x4e, 0xa9, 0x08, 0x05, 0x73, 0x5f, 0xb6, 0xe5, 0x5e, 0xc3, 0xbd, 0x77,
0x24, 0x11, 0x34, 0x23, 0xdd, 0xa4, 0xe7, 0x03, 0xe4, 0xc7, 0x84, 0x11, 0x36, 0xa8, 0x9a, 0x01, 0x13, 0xff, 0xc1, 0x7c,
0x2f, 0x0c, 0x0d, 0x95, 0x61, 0x07, 0x19, 0xa1, 0x21, 0xcd, 0x4d, 0x30, 0x1c, 0x16, 0x7a, 0xc2, 0x15, 0xee, 0xd9, 0x84,
0xfd, 0x29, 0x9a, 0x0f, 0x35, 0xe7, 0xb8, 0x4d, 0x30, 0x88, 0xc2, 0x8b, 0x28, 0x01, 0x46, 0xe1, 0xc3, 0xf6, 0xac, 0x41,
0x6e, 0xe3, 0xd0, 0x4d, 0xd1, 0xff, 0xcb, 0x5b, 0x0a, 0xa9, 0x63, 0x4f, 0xfe, 0xfc, 0xf0, 0xdf, 0x69, 0x50, 0x86, 0xc0,
0xca, 0x80, 0x04, 0x34, 0x42, 0x93, 0x06, 0x69, 0xd2, 0x2f, 0x95, 0x37, 0x10, 0x4e, 0xa4, 0xf0, 0xc8, 0x75, 0x95, 0xd8,
0xed, 0xf0, 0xc8, 0x08, 0x9a, 0x3f, 0xed, 0x7f, 0xe0, 0x8a, 0xf5, 0x9b, 0x18, 0x5b, 0xc1, 0x9a, 0x0a, 0x8c, 0xc4, 0x45,
0x48, 0x91, 0x2c, 0xcb, 0x3f, 0xec, 0x78, 0x98, 0x10, 0x0e, 0xa2, 0x43, 0x30, 0x74, 0x64, 0xae, 0x58, 0x86, 0x5d, 0x77,
0x82, 0x95, 0x9c, 0x7d, 0x0c, 0x29, 0x8f, 0x8c, 0x45, 0x02, 0x07, 0xdc, 0x12, 0xf0, 0x82, 0x72, 0xe9, 0x73, 0x0f, 0xf7,
0x0e, 0x61, 0xe2, 0xb5, 0x4a, 0x2e, 0x54, 0x3a, 0xf7, 0xcc, 0x40, 0xf4, 0x04, 0xda, 0x53, 0xf6, 0x03, 0x62, 0x35, 0xb3,
0xf2, 0x65, 0xc6, 0x3f, 0x53, 0xe5, 0x0f, 0x6c, 0x5d, 0x6c, 0xd3, 0x6a, 0x60, 0x44, 0x02, 0xc7, 0xd0, 0x2b, 0x2f, 0xd5,
0x46, 0x6a, 0xeb, 0x86, 0x57, 0x18, 0x4b, 0x51, 0x07, 0xa9, 0x9a, 0x23, 0xe4, 0x21, 0xc3, 0xc6, 0x1c, 0x91, 0x05, 0xd8,
0xa4, 0xdf, 0x1f, 0x56, 0x8e, 0xf8, 0x9e, 0x07, 0x99, 0xa2, 0x4b, 0x65, 0x69, 0x1d, 0x45, 0xad, 0x4e, 0x02, 0x30, 0xf3,
0xc9, 0x4b, 0x98, 0xd0, 0xb3, 0xe4, 0xf1, 0xf8, 0x1c, 0x2f, 0x37, 0xa3, 0x67, 0xc2, 0xd2, 0xea, 0x08, 0xef, 0x4a, 0x46,
0x75, 0x1f, 0x76, 0xe6, 0x75, 0x70, 0x2b, 0xce, 0x43, 0xe9, 0x1b, 0x93, 0x22, 0xcd, 0x62, 0x6f, 0x9f, 0x37, 0x0b, 0xfe,
0x5a, 0x54, 0xd3, 0x93, 0x81, 0x52, 0x9f, 0xed, 0xff, 0xec, 0xd0, 0x17, 0x90, 0xaf, 0x86, 0xf7, 0x08, 0x3c, 0x14, 0xd2,
0xcf, 0xc7, 0x26, 0xf9, 0x8c, 0x72, 0x86, 0x69, 0xa5, 0x49, 0xf3, 0xfa, 0x27, 0x76, 0x61, 0x81, 0x9a, 0xc3, 0xa6, 0xa8,
0x08, 0x50, 0x3b, 0x03, 0x6e, 0x5a, 0xbb, 0x0d, 0x79, 0x72, 0x3c, 0x4a, 0xeb, 0xa3, 0x82, 0x80, 0xa2, 0xed, 0xe8, 0x17,
0xce, 0xf5, 0x47, 0x1b, 0x4a, 0xc1, 0x75, 0x26, 0x33, 0x8f, 0x77, 0x35, 0x54, 0xa2, 0x4f, 0x82, 0xb3, 0xa6, 0x62, 0x08,
0x7b, 0xdd, 0x82, 0xec, 0xab, 0xe9, 0xc6, 0x3a, 0xca, 0x2e, 0x61, 0x4b, 0x39, 0x1f, 0xe6, 0x7d, 0x36, 0x37, 0x21, 0x9f,
0xb3, 0x22, 0x38, 0x50, 0x15, 0x5d, 0xdf, 0x3b, 0xfe, 0x13, 0xab, 0x2e, 0xba, 0xe8, 0x40, 0xa1, 0xfb, 0x75, 0xea, 0xca,
0xef, 0xfc, 0x92, 0x6b, 0x67, 0xdf, 0x5f, 0xde, 0x19, 0x22, 0x9c, 0xeb, 0xd5, 0xfd, 0x40, 0x9d, 0x10, 0x30, 0x50, 0xc9,
0xe2, 0x6d, 0x12, 0x9c, 0x38, 0x77, 0xd5, 0x63, 0x76, 0x02, 0xe4, 0xbc, 0x0e, 0xe9, 0x96, 0x0d, 0x85, 0x60, 0x69, 0x9d,
0x6d, 0x46, 0xff, 0xb7, 0xca, 0x8c, 0xaa, 0x2b, 0xd5, 0x06, 0x78, 0x9c, 0xf5, 0x19, 0x56, 0x38, 0x89, 0x50, 0x4a, 0x42,
0x33, 0xaf, 0x2c, 0x79, 0x90, 0x1b, 0x54, 0x86, 0x26, 0x5c, 0x41, 0xa4, 0xbc, 0x7f, 0xc4, 0x80, 0xe6, 0x15, 0xf1, 0xb5,
0x04, 0xa7, 0x09, 0x46, 0xf6, 0xa8, 0xf3, 0xe2, 0x7f, 0x13, 0x4f, 0x21, 0x0c, 0x59, 0xb4, 0x5b, 0xa8, 0xc2, 0x2c, 0x88,
0x69, 0xbf, 0xce, 0x2c, 0x51, 0x88, 0x38, 0x25, 0xd2, 0xb9, 0xb0, 0x95, 0x9e, 0xdc, 0x39, 0xd6, 0x2d, 0x2a, 0x3c, 0x8d,
0x24, 0x7c, 0xa1, 0xbb, 0x76, 0xe5, 0xe3, 0xd8, 0xc3, 0x1e, 0x7e, 0x95, 0x6f, 0x84, 0x10, 0x72, 0xff, 0x9e, 0x80, 0xe1,
0x81, 0xe7, 0xd8, 0xc3, 0xd7, 0x29, 0x74, 0xee, 0x3e, 0xcc, 0x2b, 0x7f, 0xec, 0x1a, 0xc7, 0xc6, 0x06, 0x59, 0xe6, 0xd1,
0xe8, 0x3c, 0xc8, 0x15, 0xc3, 0x2f, 0xc9, 0xee, 0x4c, 0xd8, 0xdf, 0xab, 0xe0, 0x12, 0xf3, 0xab, 0xd5, 0xbd, 0xe6, 0xe3,
0x90, 0xa1, 0xd3, 0x55, 0xf5, 0x2d, 0x03, 0x3f, 0xca, 0xdb, 0x98, 0x9e, 0x41, 0x53, 0xa4, 0xcf, 0x54, 0xbc, 0x17, 0x59,
0x04, 0xdb, 0xf7, 0xb3, 0x4a, 0x7e, 0x40, 0x1b, 0x6c, 0x3b, 0x85, 0x90, 0x6b, 0xd4, 0x5e, 0x38, 0x6a, 0xa1, 0x47, 0xfc,
0x57, 0x88, 0x41, 0xe8, 0xba, 0x4d, 0x51, 0x08, 0x85, 0x05, 0xba, 0xba, 0xa4, 0x80, 0x2c, 0x8b, 0x49, 0x2b, 0x5b, 0xaf,
0x5f, 0x99, 0xb5, 0xa5, 0x95, 0xe2, 0x2c, 0x6c, 0x9c, 0xf5, 0xe5, 0x23, 0x3e, 0xc5, 0xd1, 0x30, 0xf8, 0x0d, 0xf4, 0xc8,
0x9e, 0xbe, 0x8b, 0x94, 0xdb, 0xa9, 0x61, 0x13, 0x7d, 0x6b, 0xac, 0x95, 0x99, 0x34, 0x9a, 0xb3, 0xf1, 0x9c, 0xea, 0xe9,
0x2a, 0x1a, 0x47, 0x94, 0x19, 0x4a, 0x6a, 0xcb, 0x26, 0xc3, 0x75, 0xc8, 0xc2, 0x3c, 0x26, 0x04, 0xef, 0xe6, 0xf0, 0x30,
0x20, 0x45, 0x99, 0xae, 0x0f, 0x3a, 0xe8, 0x8f, 0x8f, 0x0e, 0x2f, 0xd3, 0x3b, 0x3f, 0x12, 0x7d, 0x62, 0x69, 0x9e, 0x79,
0xaa, 0xd1, 0xfd, 0xfe, 0xf5, 0xf8, 0x69, 0xb4, 0xfe, 0xb5, 0xa5, 0x6b, 0x8f, 0x51, 0x96, 0x7d, 0xef, 0xb3, 0x97, 0xa6,
0x63, 0x18, 0xb1, 0xcc, 0x14, 0x2b, 0x17, 0x86, 0x32, 0xd5, 0x7d, 0x47, 0x1b, 0x78, 0xc1, 0x26, 0xcc, 0x1b, 0x04, 0x0f,
0x0c, 0x90, 0x61, 0x3d, 0xf2, 0x6f, 0x37, 0xc5, 0xb9, 0xe3, 0xe3, 0x90, 0x90, 0x08, 0x00, 0xd1, 0x09, 0xcc, 0x63, 0x73,
0x84, 0x11, 0x17, 0xba, 0x76, 0x69, 0xee, 0x65, 0x6d, 0x52, 0x7b, 0x63, 0xc0, 0x42, 0x27, 0x8b, 0x1b, 0xe6, 0x69, 0xb3,
0xee, 0x6d, 0x4b, 0x24, 0x20, 0x9c, 0x83, 0xdb, 0xce, 0x18, 0xb8, 0xa3, 0x8a, 0x52, 0xda, 0x1a, 0x33, 0xe4, 0xc5, 0x07,
0x40, 0x7d, 0xf4, 0xfa, 0x2f, 0x6b, 0x93, 0x44, 0x5e };

View File

@ -14,7 +14,7 @@
#include <gtest/gtest.h>
#include <openrct2/core/Guard.hpp>
int main(int argc, char * * argv)
int main(int argc, char** argv)
{
// Abort on an assertions so the tests do not hang
Guard::SetAssertBehaviour(ASSERT_BEHAVIOUR::ABORT);