1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-20 14:23:08 +01:00

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

@@ -23,7 +23,8 @@
// When switching to original code, stack frame pointer is modified and prevents breakpad from providing stack trace. // When switching to original code, stack frame pointer is modified and prevents breakpad from providing stack trace.
volatile int32_t _originalAddress = 0; 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; int32_t result = 0;
_originalAddress = address; _originalAddress = address;
@@ -66,10 +67,18 @@ int32_t DISABLE_OPT RCT2_CALLPROC_X(int32_t address, int32_t _eax, int32_t _ebx,
pop %%ebx \n\ pop %%ebx \n\
/* Load result with flags */ \n\ /* Load result with flags */ \n\
mov %%eax, %[result] \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) "
: [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" : "eax", "ecx", "edx", "esi", "edi", "memory");
);
#endif #endif
#endif // PLATFORM_X86 #endif // PLATFORM_X86
_originalAddress = 0; _originalAddress = 0;

View File

@@ -39,8 +39,7 @@
* P = Parity flag * P = Parity flag
* All other bits are undefined. * 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 #endif

View File

@@ -36,32 +36,17 @@ uint32_t gCurrentViewportFlags;
uint32_t gScenarioTicks; uint32_t gScenarioTicks;
uint8_t gCurrentRotation; uint8_t gCurrentRotation;
const CoordsXY CoordsDirectionDelta[] = { const CoordsXY CoordsDirectionDelta[]
{ -32, 0 }, = { { -32, 0 }, { 0, +32 }, { +32, 0 }, { 0, -32 }, { -32, +32 }, { +32, +32 }, { +32, -32 }, { -32, -32 } };
{ 0, +32 },
{ +32, 0 },
{ 0, -32 },
{ -32, +32 },
{ +32, +32 },
{ +32, -32 },
{ -32, -32 }
};
const TileCoordsXY TileDirectionDelta[] = { const TileCoordsXY TileDirectionDelta[]
{ -1, 0 }, = { { -1, 0 }, { 0, +1 }, { +1, 0 }, { 0, -1 }, { -1, +1 }, { +1, +1 }, { +1, -1 }, { -1, -1 } };
{ 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_entrance_location(const Ride* ride, const int32_t 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);
uint8_t get_current_rotation() { uint8_t get_current_rotation()
{
return gCurrentRotation & 3; return gCurrentRotation & 3;
} }
@@ -92,24 +77,42 @@ LocationXY16 gMapSelectPositionB;
LocationXYZ16 gMapSelectArrowPosition; LocationXYZ16 gMapSelectArrowPosition;
uint8_t gMapSelectArrowDirection; uint8_t gMapSelectArrowDirection;
void entrance_paint(paint_session * session, uint8_t direction, int height, const rct_tile_element * tile_element) {} 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 banner_paint(paint_session* session, uint8_t direction, int height, const rct_tile_element* tile_element)
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 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) { Ride* get_ride(int index)
if (index < 0 || index >= MAX_RIDES) { {
if (index < 0 || index >= MAX_RIDES)
{
log_error("invalid index %d for ride", index); log_error("invalid index %d for ride", index);
return nullptr; return nullptr;
} }
return &gRideList[index]; return &gRideList[index];
} }
rct_ride_entry *get_ride_entry(int index) { rct_ride_entry* get_ride_entry(int index)
if (index < 0 || index >= object_entry_group_counts[OBJECT_TYPE_RIDE]) { {
if (index < 0 || index >= object_entry_group_counts[OBJECT_TYPE_RIDE])
{
log_error("invalid index %d for ride type", index); log_error("invalid index %d for ride type", index);
return nullptr; return nullptr;
} }
@@ -117,15 +120,18 @@ rct_ride_entry *get_ride_entry(int index) {
return gRideEntries[index]; return gRideEntries[index];
} }
rct_ride_entry *get_ride_entry_by_ride(Ride *ride) { rct_ride_entry* get_ride_entry_by_ride(Ride* ride)
{
rct_ride_entry* type = get_ride_entry(ride->subtype); rct_ride_entry* type = get_ride_entry(ride->subtype);
if (type == nullptr) { if (type == nullptr)
{
log_error("Invalid ride subtype for ride"); log_error("Invalid ride subtype for ride");
} }
return type; return type;
} }
rct_sprite *get_sprite(size_t sprite_idx) { rct_sprite* get_sprite(size_t sprite_idx)
{
assert(sprite_idx < MAX_SPRITES); assert(sprite_idx < MAX_SPRITES);
return &sprite_list[sprite_idx]; return &sprite_list[sprite_idx];
} }
@@ -140,23 +146,28 @@ uint8_t rct_tile_element::GetType() const
return this->type & TILE_ELEMENT_TYPE_MASK; 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; 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; return ((element->type & TILE_ELEMENT_DIRECTION_MASK) + offset) & TILE_ELEMENT_DIRECTION_MASK;
} }
rct_tile_element *map_get_first_element_at(int x, int y) { rct_tile_element* map_get_first_element_at(int x, int y)
if (x < 0 || y < 0 || x > 255 || y > 255) { {
if (x < 0 || y < 0 || x > 255 || y > 255)
{
log_error("Trying to access element outside of range"); log_error("Trying to access element outside of range");
return nullptr; return nullptr;
} }
return gTileElementTilePointers[x + y * 256]; 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; return (tileElement->properties.track.sequence & MAP_ELEM_TRACK_SEQUENCE_STATION_INDEX_MASK) >> 4;
} }

View File

@@ -364,262 +364,18 @@ const_utf8string TrackNames[256] = {
}; };
const_utf8string FlatTrackNames[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[] = { const_utf8string TrackElemNames[] = {
@@ -975,8 +731,7 @@ const_utf8string RideCodeNames[RIDE_TYPE_COUNT] = {
"lim_launched_rc", "lim_launched_rc",
}; };
const_utf8string TrackCodeNames[256] = { const_utf8string TrackCodeNames[256] = { "flat",
"flat",
"end_station", "end_station",
"begin_station", "begin_station",
"middle_station", "middle_station",
@@ -1231,5 +986,4 @@ const_utf8string TrackCodeNames[256] = {
"right_quarter_turn_1_90_deg_down", "right_quarter_turn_1_90_deg_down",
"multidim_90_deg_up_to_inverted_flat_quarter_loop", "multidim_90_deg_up_to_inverted_flat_quarter_loop",
"multidim_flat_to_90_deg_down_quarter_loop", "multidim_flat_to_90_deg_down_quarter_loop",
"elem_255" "elem_255" };
};

View File

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

View File

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

View File

@@ -9,9 +9,10 @@
#pragma once #pragma once
#include <openrct2/common.h>
#include "TestPaint.hpp" #include "TestPaint.hpp"
#include <openrct2/common.h>
enum enum
{ {
PAINT_98196C, PAINT_98196C,
@@ -51,7 +52,8 @@ struct function_call
} supports; } supports;
}; };
class FunctionCall { class FunctionCall
{
public: public:
static bool AssertsEquals(function_call expected, function_call actual); static bool AssertsEquals(function_call expected, function_call actual);
static bool AssertsEquals(std::vector<function_call> expected, std::vector<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. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <map>
#include "GeneralSupportHeightCall.hpp" #include "GeneralSupportHeightCall.hpp"
bool GeneralSupportHeightCall::CallsMatch(SupportCall tileSupportCalls[4]) { #include <map>
bool GeneralSupportHeightCall::CallsMatch(SupportCall tileSupportCalls[4])
{
SupportCall baseCall = tileSupportCalls[0]; SupportCall baseCall = tileSupportCalls[0];
for (int i = 1; i < 4; i++) { for (int i = 1; i < 4; i++)
if (tileSupportCalls[i] != baseCall) return false; {
if (tileSupportCalls[i] != baseCall)
return false;
} }
return true; return true;
} }
bool GeneralSupportHeightCall::FindMostCommonSupportCall(SupportCall calls[4], SupportCall *out) { bool GeneralSupportHeightCall::FindMostCommonSupportCall(SupportCall calls[4], SupportCall* out)
{
std::map<SupportCall, int> map; std::map<SupportCall, int> map;
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i)
if (map.count(calls[i]) == 0) { {
if (map.count(calls[i]) == 0)
{
map[calls[i]] = 1; map[calls[i]] = 1;
} else { }
else
{
map[calls[i]] += 1; map[calls[i]] += 1;
} }
} }
if (map.size() == 1) { if (map.size() == 1)
{
(*out) = calls[0]; (*out) = calls[0];
return true; return true;
} }
if (map.size() == 2) { if (map.size() == 2)
for (auto &&item : map) { {
if (item.second == 3) { for (auto&& item : map)
{
if (item.second == 3)
{
(*out) = item.first; (*out) = item.first;
return true; return true;
} }
@@ -50,12 +62,17 @@ bool GeneralSupportHeightCall::FindMostCommonSupportCall(SupportCall calls[4], S
return false; return false;
} }
bool GeneralSupportHeightCall::AssertEquals(const SupportCall *lhs, const SupportCall *rhs) { 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 == nullptr && rhs == nullptr)
return true;
if (lhs == nullptr || rhs == nullptr)
return false;
if (lhs->height != rhs->height) return false; if (lhs->height != rhs->height)
if (lhs->slope != rhs->slope) return false; return false;
if (lhs->slope != rhs->slope)
return false;
return true; return true;
} }

View File

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

@@ -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); write_address_strictalias(&data[i], hookAddress - address - i - 4);
i += 4; i += 4;
data[i++] = 0x83; // add esp, 4 data[i++] = 0x83; // add esp, 4
data[i++] = 0xC4; data[i++] = 0xC4;
data[i++] = 0x04; data[i++] = 0x04;
@@ -159,7 +158,8 @@ static void hookfunc(uintptr_t address, uintptr_t hookAddress, int32_t stacksize
void addhook(uintptr_t address, hook_function function) void addhook(uintptr_t address, hook_function function)
{ {
if (!_hookTableAddress) { if (!_hookTableAddress)
{
size_t size = _maxHooks * HOOK_BYTE_COUNT; size_t size = _maxHooks * HOOK_BYTE_COUNT;
#ifdef _WIN32 #ifdef _WIN32
_hookTableAddress = VirtualAllocEx(GetCurrentProcess(), NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); _hookTableAddress = VirtualAllocEx(GetCurrentProcess(), NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
@@ -172,7 +172,8 @@ void addhook(uintptr_t address, hook_function function)
} }
#endif // _WIN32 #endif // _WIN32
} }
if (_hookTableOffset > _maxHooks) { if (_hookTableOffset > _maxHooks)
{
return; 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);

View File

@@ -13,7 +13,8 @@
#include <openrct2/common.h> #include <openrct2/common.h>
enum { enum
{
X86_FLAG_CARRY = 1 << 0, X86_FLAG_CARRY = 1 << 0,
X86_FLAG_PARITY = 1 << 2, X86_FLAG_PARITY = 1 << 2,

View File

@@ -7,13 +7,13 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <cstring>
#include "Hook.h"
#include "PaintIntercept.hpp" #include "PaintIntercept.hpp"
#include "FunctionCall.hpp" #include "FunctionCall.hpp"
#include "Hook.h"
#include "TestPaint.hpp" #include "TestPaint.hpp"
#include <cstring>
#include <openrct2/common.h> #include <openrct2/common.h>
#include <openrct2/interface/Viewport.h> #include <openrct2/interface/Viewport.h>
#include <openrct2/paint/Supports.h> #include <openrct2/paint/Supports.h>
@@ -26,7 +26,8 @@ static uint8_t _callCount = 0;
static function_call _calls[256] = {}; static function_call _calls[256] = {};
static paint_struct _paintStructs = {}; static paint_struct _paintStructs = {};
namespace PaintIntercept { namespace PaintIntercept
{
static uint8_t InterceptWoodenASupports(registers* regs); static uint8_t InterceptWoodenASupports(registers* regs);
static uint8_t InterceptWoodenBSupports(registers* regs); static uint8_t InterceptWoodenBSupports(registers* regs);
static uint8_t InterceptMetalASupports(registers* regs); static uint8_t InterceptMetalASupports(registers* regs);
@@ -37,11 +38,26 @@ namespace PaintIntercept {
static uint8_t InterceptPaint9C(registers* regs); static uint8_t InterceptPaint9C(registers* regs);
static uint8_t InterceptPaintFull(uint8_t function, 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 PaintMetalSupports(
bool PaintWoodenSupports(uint8_t function, int supportType, int special, int height, uint32_t imageColourFlags, bool *underground, const paint_struct * prependTo); 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); static void CheckSegmentSupportHeight(const support_height* supportSegments);
void InitHooks() { void InitHooks()
{
addhook(0x006629BC, InterceptWoodenASupports); addhook(0x006629BC, InterceptWoodenASupports);
addhook(0x00662D5C, InterceptWoodenBSupports); addhook(0x00662D5C, InterceptWoodenBSupports);
@@ -69,7 +85,15 @@ namespace PaintIntercept {
addhook(0x00687902, InterceptPaint9C); addhook(0x00687902, InterceptPaint9C);
} }
bool PaintWoodenSupports(uint8_t function, int supportType, int special, int height, uint32_t imageColourFlags, bool *underground, const paint_struct * prependTo) { 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]; function_call* call = &_calls[_callCount];
call->function = function; call->function = function;
call->supports.type = supportType; call->supports.type = supportType;
@@ -95,7 +119,15 @@ namespace PaintIntercept {
return _woodenSupports; 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); CheckSegmentSupportHeight(supportSegments);
function_call* call = &_calls[_callCount]; function_call* call = &_calls[_callCount];
@@ -113,11 +145,14 @@ namespace PaintIntercept {
static paint_struct* Paint6C( static paint_struct* Paint6C(
uint32_t imageID, uint32_t imageID,
int8_t xOffset, int8_t yOffset, int8_t xOffset,
int16_t boundBoxLengthX, int16_t boundBoxLengthY, int8_t boundBoxLengthZ, int8_t yOffset,
int16_t boundBoxLengthX,
int16_t boundBoxLengthY,
int8_t boundBoxLengthZ,
int16_t zOffset, int16_t zOffset,
uint32_t rotation uint32_t rotation)
) { {
function_call* call = &_calls[_callCount]; function_call* call = &_calls[_callCount];
call->function = PAINT_98196C; call->function = PAINT_98196C;
call->paint.image_id = imageID; call->paint.image_id = imageID;
@@ -134,12 +169,17 @@ namespace PaintIntercept {
static paint_struct* PaintFull( static paint_struct* PaintFull(
uint8_t function, uint8_t function,
uint32_t imageID, uint32_t imageID,
int8_t xOffset, int8_t yOffset, int8_t xOffset,
int16_t boundBoxLengthX, int16_t boundBoxLengthY, int8_t boundBoxLengthZ, int8_t yOffset,
int16_t boundBoxLengthX,
int16_t boundBoxLengthY,
int8_t boundBoxLengthZ,
int16_t zOffset, int16_t zOffset,
int16_t boundBoxOffsetX, int16_t boundBoxOffsetY, int16_t boundBoxOffsetZ, int16_t boundBoxOffsetX,
uint32_t rotation int16_t boundBoxOffsetY,
) { int16_t boundBoxOffsetZ,
uint32_t rotation)
{
function_call* call = &_calls[_callCount]; function_call* call = &_calls[_callCount];
call->function = function; call->function = function;
call->paint.image_id = imageID; call->paint.image_id = imageID;
@@ -154,42 +194,52 @@ namespace PaintIntercept {
return &call->paint.output_struct; return &call->paint.output_struct;
} }
void ClearCalls() { void ClearCalls()
{
_callCount = 0; _callCount = 0;
memset(_calls, 0, sizeof(_calls)); memset(_calls, 0, sizeof(_calls));
} }
int GetCalls(function_call *buffer) { int GetCalls(function_call* buffer)
{
memcpy(buffer, _calls, _callCount * sizeof(function_call)); memcpy(buffer, _calls, _callCount * sizeof(function_call));
return _callCount; return _callCount;
} }
void SetSimulateWoodenSupports(bool enabled) { void SetSimulateWoodenSupports(bool enabled)
{
_woodenSupports = 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; 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; return output ? X86_FLAG_CARRY : 0;
} }
static void CheckSegmentSupportHeight(const support_height * supportSegments) { static void CheckSegmentSupportHeight(const support_height* supportSegments)
{
bool hasChanged = false; bool hasChanged = false;
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++)
if (supportSegments[i].height != 0) hasChanged = true; {
if (supportSegments[i].slope != 0xFF) hasChanged = true; if (supportSegments[i].height != 0)
hasChanged = true;
if (supportSegments[i].slope != 0xFF)
hasChanged = true;
} }
if (!hasChanged) { if (!hasChanged)
{
return; return;
} }
@@ -203,7 +253,8 @@ namespace PaintIntercept {
static uint8_t InterceptWoodenASupports(registers* regs) static uint8_t InterceptWoodenASupports(registers* regs)
{ {
bool cf = false; 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) if (cf)
{ {
@@ -216,7 +267,8 @@ namespace PaintIntercept {
static uint8_t InterceptWoodenBSupports(registers* regs) static uint8_t InterceptWoodenBSupports(registers* regs)
{ {
bool cf = false; 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) if (cf)
{ {
@@ -236,11 +288,13 @@ namespace PaintIntercept {
paint_struct* out = Paint6C( paint_struct* out = Paint6C(
regs->ebx, regs->ebx,
(int8_t) regs->al, (int8_t) regs->cl, (int8_t)regs->al,
(int16_t) regs->di, (int16_t) regs->si, (int8_t) regs->ah, (int8_t)regs->cl,
(int16_t)regs->di,
(int16_t)regs->si,
(int8_t)regs->ah,
regs->dx, regs->dx,
regs->ebp & 0x03 regs->ebp & 0x03);
);
if (out == nullptr) if (out == nullptr)
{ {
@@ -267,27 +321,29 @@ namespace PaintIntercept {
return InterceptPaintFull(PAINT_98199C, regs); return InterceptPaintFull(PAINT_98199C, regs);
} }
static uint8_t InterceptPaintFull(uint8_t function, registers *regs) { static uint8_t InterceptPaintFull(uint8_t function, registers* regs)
if ((regs->ebp & 0x03) != RCT2_CurrentRotation) { {
if ((regs->ebp & 0x03) != RCT2_CurrentRotation)
{
// Log error // Log error
log_error("Ebp is different from current rotation"); log_error("Ebp is different from current rotation");
} }
LocationXYZ16 boundOffset = { LocationXYZ16 boundOffset = { RCT2_PaintBoundBoxOffsetX, RCT2_PaintBoundBoxOffsetY, RCT2_PaintBoundBoxOffsetZ };
RCT2_PaintBoundBoxOffsetX,
RCT2_PaintBoundBoxOffsetY,
RCT2_PaintBoundBoxOffsetZ
};
paint_struct* out = PaintFull( paint_struct* out = PaintFull(
function, function,
regs->ebx, regs->ebx,
(int8_t) regs->al, (int8_t) regs->cl, (int8_t)regs->al,
(int16_t) regs->di, (int16_t) regs->si, (int8_t) regs->ah, (int8_t)regs->cl,
(int16_t)regs->di,
(int16_t)regs->si,
(int8_t)regs->ah,
regs->dx, regs->dx,
boundOffset.x, boundOffset.y, boundOffset.z, boundOffset.x,
regs->ebp & 0x03 boundOffset.y,
); boundOffset.z,
regs->ebp & 0x03);
if (out == nullptr) if (out == nullptr)
{ {
@@ -297,85 +353,142 @@ namespace PaintIntercept {
regs->ebp = (int)out; regs->ebp = (int)out;
return 0; return 0;
} }
}; }; // namespace PaintIntercept
bool wooden_a_supports_paint_setup(paint_session * session, int supportType, int special, int height, uint32_t imageColourFlags, bool *underground) { bool wooden_a_supports_paint_setup(
return PaintIntercept::PaintWoodenSupports(SUPPORTS_WOOD_A, supportType, special, height, imageColourFlags, underground, gPaintSession.WoodenSupportsPrependTo); 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) { bool wooden_b_supports_paint_setup(
return PaintIntercept::PaintWoodenSupports(SUPPORTS_WOOD_B, supportType, special, height, imageColourFlags, underground, gPaintSession.WoodenSupportsPrependTo); 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) { bool metal_a_supports_paint_setup(
return PaintIntercept::PaintMetalSupports(SUPPORTS_METAL_A, supportType, segment, special, height, imageColourFlags, gPaintSession.SupportSegments); 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) { bool metal_b_supports_paint_setup(
return PaintIntercept::PaintMetalSupports(SUPPORTS_METAL_B, supportType, segment, special, height, imageColourFlags, gPaintSession.SupportSegments); 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) { paint_struct* sub_98196C(
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_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_struct* sub_98197C(
paint_session* session, paint_session* session,
uint32_t image_id, uint32_t image_id,
int8_t x_offset, int8_t y_offset, int8_t x_offset,
int16_t bound_box_length_x, int16_t bound_box_length_y, int8_t bound_box_length_z, 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 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( return PaintIntercept::PaintFull(
PAINT_98197C, PAINT_98197C,
image_id, image_id,
x_offset, y_offset, x_offset,
bound_box_length_x, bound_box_length_y, bound_box_length_z, y_offset,
bound_box_length_x,
bound_box_length_y,
bound_box_length_z,
z_offset, z_offset,
bound_box_offset_x, bound_box_offset_y, bound_box_offset_z, bound_box_offset_x,
session->CurrentRotation bound_box_offset_y,
); bound_box_offset_z,
session->CurrentRotation);
} }
paint_struct* sub_98198C( paint_struct* sub_98198C(
paint_session* session, paint_session* session,
uint32_t image_id, uint32_t image_id,
int8_t x_offset, int8_t y_offset, int8_t x_offset,
int16_t bound_box_length_x, int16_t bound_box_length_y, int8_t bound_box_length_z, 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 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( return PaintIntercept::PaintFull(
PAINT_98198C, PAINT_98198C,
image_id, image_id,
x_offset, y_offset, x_offset,
bound_box_length_x, bound_box_length_y, bound_box_length_z, y_offset,
bound_box_length_x,
bound_box_length_y,
bound_box_length_z,
z_offset, z_offset,
bound_box_offset_x, bound_box_offset_y, bound_box_offset_z, bound_box_offset_x,
session->CurrentRotation bound_box_offset_y,
); bound_box_offset_z,
session->CurrentRotation);
} }
paint_struct* sub_98199C( paint_struct* sub_98199C(
paint_session* session, paint_session* session,
uint32_t image_id, uint32_t image_id,
int8_t x_offset, int8_t y_offset, int8_t x_offset,
int16_t bound_box_length_x, int16_t bound_box_length_y, int8_t bound_box_length_z, 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 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( return PaintIntercept::PaintFull(
PAINT_98199C, PAINT_98199C,
image_id, image_id,
x_offset, y_offset, x_offset,
bound_box_length_x, bound_box_length_y, bound_box_length_z, y_offset,
bound_box_length_x,
bound_box_length_y,
bound_box_length_z,
z_offset, z_offset,
bound_box_offset_x, bound_box_offset_y, bound_box_offset_z, bound_box_offset_x,
session->CurrentRotation 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; return false;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,13 +9,14 @@
#pragma once #pragma once
#include <vector> #include "Addresses.h"
#include <openrct2/common.h> #include <openrct2/common.h>
#include <openrct2/drawing/Drawing.h> #include <openrct2/drawing/Drawing.h>
#include <openrct2/interface/Colour.h> #include <openrct2/interface/Colour.h>
#include <openrct2/paint/Paint.h> #include <openrct2/paint/Paint.h>
#include <openrct2/paint/tile_element/Paint.TileElement.h> #include <openrct2/paint/tile_element/Paint.TileElement.h>
#include "Addresses.h" #include <vector>
#define gRideEntries RCT2_ADDRESS(0x009ACFA4, rct_ride_entry*) #define gRideEntries RCT2_ADDRESS(0x009ACFA4, rct_ride_entry*)
#define gSupportSegments RCT2_ADDRESS(0x0141E9B4, support_height) #define gSupportSegments RCT2_ADDRESS(0x0141E9B4, support_height)
@@ -48,7 +49,8 @@
#define RCT2_PaintBoundBoxOffsetY RCT2_GLOBAL(0x009DEA54, int16_t) #define RCT2_PaintBoundBoxOffsetY RCT2_GLOBAL(0x009DEA54, int16_t)
#define RCT2_PaintBoundBoxOffsetZ RCT2_GLOBAL(0x009DEA56, int16_t) #define RCT2_PaintBoundBoxOffsetZ RCT2_GLOBAL(0x009DEA56, int16_t)
enum { enum
{
TEST_SUCCESS, TEST_SUCCESS,
TEST_FAILED, TEST_FAILED,
TEST_SKIPPED, TEST_SKIPPED,
@@ -69,9 +71,10 @@ namespace TestPaint
void testIgnore(uint8_t direction, uint8_t trackSequence); void testIgnore(uint8_t direction, uint8_t trackSequence);
void testIgnoreAll(); void testIgnoreAll();
bool testIsIgnored(uint8_t direction, uint8_t trackSequence); bool testIsIgnored(uint8_t direction, uint8_t trackSequence);
} } // namespace TestPaint
enum Verbosity { enum Verbosity
{
QUIET, QUIET,
NORMAL, NORMAL,
}; };

View File

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

View File

@@ -9,11 +9,11 @@
#pragma once #pragma once
#include <openrct2/common.h>
#include <string> #include <string>
#include <openrct2/common.h> class TestTrack
{
class TestTrack {
public: 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/Track.h>
#include <openrct2/ride/TrackData.h> #include <openrct2/ride/TrackData.h>
namespace Utils { namespace Utils
int getTrackSequenceCount(uint8_t rideType, uint8_t trackType) { {
int getTrackSequenceCount(uint8_t rideType, uint8_t trackType)
{
int sequenceCount = 0; 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; trackBlocks = FlatRideTrackBlocks;
} else { }
else
{
trackBlocks = TrackBlocks; trackBlocks = TrackBlocks;
} }
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++)
if (trackBlocks[trackType][i].index == 0xFF) { {
if (trackBlocks[trackType][i].index == 0xFF)
{
break; break;
} }
@@ -35,26 +42,31 @@ namespace Utils {
return sequenceCount; 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]; TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType];
if (newPaintGetter == nullptr) { if (newPaintGetter == nullptr)
{
return false; return false;
} }
if (newPaintGetter(trackType, 0) == nullptr) { if (newPaintGetter(trackType, 0) == nullptr)
{
return false; return false;
} }
if (RideTypeTrackPaintFunctionsOld[rideType][trackType] == 0) { if (RideTypeTrackPaintFunctionsOld[rideType][trackType] == 0)
{
return false; return false;
} }
return true; return true;
} }
bool rideIsImplemented(uint8_t rideType) { bool rideIsImplemented(uint8_t rideType)
{
TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType];
return (newPaintGetter != 0); return (newPaintGetter != 0);
} }
} } // namespace Utils

View File

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

View File

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

View File

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

View File

@@ -7,12 +7,7 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <algorithm> #include "Data.h"
#include <cstdarg>
#include <cstring>
#include <string>
#include <vector>
#include "FunctionCall.hpp" #include "FunctionCall.hpp"
#include "PaintIntercept.hpp" #include "PaintIntercept.hpp"
#include "SegmentSupportHeightCall.hpp" #include "SegmentSupportHeightCall.hpp"
@@ -20,13 +15,17 @@
#include "String.hpp" #include "String.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "Data.h" #include <algorithm>
#include <cstdarg>
#include <cstring>
#include <openrct2/interface/Viewport.h> #include <openrct2/interface/Viewport.h>
#include <openrct2/rct2/RCT2.h> #include <openrct2/rct2/RCT2.h>
#include <openrct2/ride/Ride.h> #include <openrct2/ride/Ride.h>
#include <openrct2/ride/RideData.h> #include <openrct2/ride/RideData.h>
#include <openrct2/ride/Track.h> #include <openrct2/ride/Track.h>
#include <openrct2/ride/TrackData.h> #include <openrct2/ride/TrackData.h>
#include <string>
#include <vector>
class PaintCodeGenerator class PaintCodeGenerator
{ {
@@ -88,8 +87,7 @@ private:
void GenerateIncludes() void GenerateIncludes()
{ {
const char * includes[] = const char* includes[] = {
{
"../../drawing/Drawing.h", "../../drawing/Drawing.h",
"../../paint/supports.h", "../../paint/supports.h",
"../../interface/Viewport.h", "../../interface/Viewport.h",
@@ -122,8 +120,17 @@ private:
if (trackType == TRACK_ELEM_END_STATION) if (trackType == TRACK_ELEM_END_STATION)
{ {
const uint32_t* paintFunctionList = RideTypeTrackPaintFunctionsOld[_rideType]; 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(
WriteLine(0, "static void " + _rideName + "_track_station(uint8_t rideIndex, uint8_t trackSequence, uint8_t direction, int height, rct_tile_element * tileElement)"); 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(0, "}"); WriteLine(0, "}");
WriteLine(); WriteLine();
@@ -134,13 +141,15 @@ private:
void GenerateTrackFunction(int trackType) void GenerateTrackFunction(int trackType)
{ {
WriteLine(0, "/** rct2: 0x%08X */", RideTypeTrackPaintFunctionsOld[_rideType][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, "{"); WriteLine(0, "{");
if (!GenerateMirrorCall(1, trackType)) if (!GenerateMirrorCall(1, trackType))
{ {
if (_rideType == RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER || if (_rideType == RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER || _rideType == RIDE_TYPE_FLYING_ROLLER_COASTER
_rideType == RIDE_TYPE_FLYING_ROLLER_COASTER || || _rideType == RIDE_TYPE_LAY_DOWN_ROLLER_COASTER)
_rideType == RIDE_TYPE_LAY_DOWN_ROLLER_COASTER)
{ {
WriteLine(1, "if (!track_element_is_inverted(tileElement)) {"); WriteLine(1, "if (!track_element_is_inverted(tileElement)) {");
_invertedTrack = false; _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_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_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_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,
{ 0, TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_LEFT_BANKED_FLAT, TRACK_ELEM_RIGHT_BANKED_FLAT_TO_RIGHT_BANKED_25_DEG_UP }, TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_RIGHT_BANKED_FLAT,
{ 0, TRACK_ELEM_RIGHT_BANKED_FLAT_TO_RIGHT_BANKED_25_DEG_DOWN, TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_LEFT_BANKED_FLAT }, TRACK_ELEM_LEFT_BANKED_FLAT_TO_LEFT_BANKED_25_DEG_UP },
{ 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_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_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_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 }, { 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_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_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_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_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, 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_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_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_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_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, 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 }, { 5, TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_DOWN, TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_UP },
@@ -273,39 +298,67 @@ private:
if (mirrorTable[i][1] == trackType) if (mirrorTable[i][1] == trackType)
{ {
std::string destFuncName = GetTrackFunctionName(mirrorTable[i][2]); std::string destFuncName = GetTrackFunctionName(mirrorTable[i][2]);
switch (mirrorTable[i][0]) { switch (mirrorTable[i][0])
{
case 0: case 0:
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 2) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 2) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 1: case 1:
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];"); WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 2: case 2:
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];"); WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 3: case 3:
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];"); WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 4: case 4:
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];"); WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 5: case 5:
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 6: case 6:
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 7: case 7:
WriteLine(tabs, "trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence];"); WriteLine(tabs, "trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 3) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 3) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 8: case 8:
WriteLine(tabs, "trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence];"); WriteLine(tabs, "trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 2) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 2) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 9: case 9:
WriteLine(tabs, "if (trackSequence >= 4) {"); WriteLine(tabs, "if (trackSequence >= 4) {");
@@ -313,7 +366,10 @@ private:
WriteLine(tabs + 1, "direction = (direction + 1) & 3;"); WriteLine(tabs + 1, "direction = (direction + 1) & 3;");
WriteLine(tabs, "}"); WriteLine(tabs, "}");
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];"); WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 10: case 10:
WriteLine(tabs, "if (trackSequence >= 4) {"); WriteLine(tabs, "if (trackSequence >= 4) {");
@@ -321,7 +377,10 @@ private:
WriteLine(tabs + 1, "direction = (direction - 1) & 3;"); WriteLine(tabs + 1, "direction = (direction - 1) & 3;");
WriteLine(tabs, "}"); WriteLine(tabs, "}");
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];"); WriteLine(tabs, "trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 11: case 11:
WriteLine(tabs, "if (trackSequence >= 7) {"); WriteLine(tabs, "if (trackSequence >= 7) {");
@@ -329,7 +388,10 @@ private:
WriteLine(tabs + 1, "direction = (direction + 1) & 3;"); WriteLine(tabs + 1, "direction = (direction + 1) & 3;");
WriteLine(tabs, "}"); WriteLine(tabs, "}");
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];"); WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction - 1) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 12: case 12:
WriteLine(tabs, "if (trackSequence >= 7) {"); WriteLine(tabs, "if (trackSequence >= 7) {");
@@ -337,28 +399,46 @@ private:
WriteLine(tabs + 1, "direction = (direction - 1) & 3;"); WriteLine(tabs + 1, "direction = (direction - 1) & 3;");
WriteLine(tabs, "}"); WriteLine(tabs, "}");
WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];"); WriteLine(tabs, "trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];");
WriteLine(tabs, "%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, trackSequence, (direction + 1) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 13: case 13:
WriteLine(tabs, "%s(rideIndex, 3 - trackSequence, (direction + 2) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, 3 - trackSequence, (direction + 2) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 14: case 14:
WriteLine(tabs, "%s(rideIndex, 2 - trackSequence, (direction - 1) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, 2 - trackSequence, (direction - 1) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 15: case 15:
WriteLine(tabs, "%s(rideIndex, 2 - trackSequence, (direction + 1) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, 2 - trackSequence, (direction + 1) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 16: case 16:
WriteLine(tabs, "%s(rideIndex, 3 - trackSequence, direction, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs, "%s(rideIndex, 3 - trackSequence, direction, height, tileElement);", destFuncName.c_str());
break; break;
case 17: case 17:
WriteLine(tabs, "%s(rideIndex, 2 - trackSequence, direction, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs, "%s(rideIndex, 2 - trackSequence, direction, height, tileElement);", destFuncName.c_str());
break; break;
case 18: case 18:
WriteLine(tabs, "%s(rideIndex, 2 - trackSequence, (direction + 2) & 3, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs,
"%s(rideIndex, 2 - trackSequence, (direction + 2) & 3, height, tileElement);",
destFuncName.c_str());
break; break;
case 19: case 19:
WriteLine(tabs, "%s(rideIndex, 6 - trackSequence, direction, height, tileElement);", destFuncName.c_str()); WriteLine(
tabs, "%s(rideIndex, 6 - trackSequence, direction, height, tileElement);", destFuncName.c_str());
break; break;
} }
return true; return true;
@@ -369,8 +449,8 @@ private:
void ExtractMetalSupportCalls(std::vector<function_call> calls[4], std::vector<function_call> output[4]) 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) { 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); return (call.function == SUPPORTS_METAL_A || call.function == SUPPORTS_METAL_B);
}); });
@@ -390,7 +470,8 @@ private:
int16_t verticalTunnelHeights[4]; int16_t verticalTunnelHeights[4];
std::vector<SegmentSupportCall> segmentSupportCalls[4]; std::vector<SegmentSupportCall> segmentSupportCalls[4];
support_height generalSupports[4] = {}; support_height generalSupports[4] = {};
for (int direction = 0; direction < 4; direction++) { for (int direction = 0; direction < 4; direction++)
{
rct_tile_element tileElement = {}; rct_tile_element tileElement = {};
tileElement.flags |= TILE_ELEMENT_FLAG_LAST_TILE; tileElement.flags |= TILE_ELEMENT_FLAG_LAST_TILE;
track_element_set_type(&tileElement, trackType); track_element_set_type(&tileElement, trackType);
@@ -411,8 +492,10 @@ private:
int numCalls = PaintIntercept::GetCalls(callBuffer); int numCalls = PaintIntercept::GetCalls(callBuffer);
calls[direction].insert(calls[direction].begin(), callBuffer, callBuffer + numCalls); calls[direction].insert(calls[direction].begin(), callBuffer, callBuffer + numCalls);
for (auto &&call : calls[direction]) { for (auto&& call : calls[direction])
if (call.function == SET_SEGMENT_HEIGHT) { {
if (call.function == SET_SEGMENT_HEIGHT)
{
blockSegmentsBeforeSupports = true; blockSegmentsBeforeSupports = true;
break; break;
} }
@@ -464,7 +547,8 @@ private:
} }
std::vector<function_call> supportCalls[4], chainLiftSupportCalls[4], cableLiftSupportCalls[4]; std::vector<function_call> supportCalls[4], chainLiftSupportCalls[4], cableLiftSupportCalls[4];
if (blockSegmentsBeforeSupports) { if (blockSegmentsBeforeSupports)
{
ExtractMetalSupportCalls(calls, supportCalls); ExtractMetalSupportCalls(calls, supportCalls);
ExtractMetalSupportCalls(cableLiftCalls, cableLiftSupportCalls); ExtractMetalSupportCalls(cableLiftCalls, cableLiftSupportCalls);
ExtractMetalSupportCalls(chainLiftCalls, chainLiftSupportCalls); ExtractMetalSupportCalls(chainLiftCalls, chainLiftSupportCalls);
@@ -498,10 +582,14 @@ private:
GenerateCalls(tabs, calls, height); GenerateCalls(tabs, calls, height);
} }
if (blockSegmentsBeforeSupports) { if (blockSegmentsBeforeSupports)
if (_rideType == RIDE_TYPE_GIGA_COASTER && !CompareFunctionCalls(supportCalls, cableLiftSupportCalls)) { {
if (_rideType == RIDE_TYPE_GIGA_COASTER && !CompareFunctionCalls(supportCalls, cableLiftSupportCalls))
{
printf("Error: Supports differ for cable lift.\n"); 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"); printf("Error: Supports differ for chain lift\n");
} }
WriteLine(); WriteLine();
@@ -509,12 +597,14 @@ private:
bool conditionalSupports = _conditionalSupports; bool conditionalSupports = _conditionalSupports;
_conditionalSupports = false; _conditionalSupports = false;
if (conditionalSupports) { if (conditionalSupports)
{
WriteLine(tabs, "if (track_paint_util_should_paint_supports(gPaintMapPosition)) {"); WriteLine(tabs, "if (track_paint_util_should_paint_supports(gPaintMapPosition)) {");
tabs++; tabs++;
} }
GenerateCalls(tabs, supportCalls, height); GenerateCalls(tabs, supportCalls, height);
if (conditionalSupports) { if (conditionalSupports)
{
tabs--; tabs--;
WriteLine(tabs, "}"); WriteLine(tabs, "}");
} }
@@ -522,7 +612,8 @@ private:
} }
GenerateTunnelCall(tabs, tileTunnelCalls, verticalTunnelHeights); GenerateTunnelCall(tabs, tileTunnelCalls, verticalTunnelHeights);
if (!blockSegmentsBeforeSupports) { if (!blockSegmentsBeforeSupports)
{
GenerateSegmentSupportCall(tabs, segmentSupportCalls); GenerateSegmentSupportCall(tabs, segmentSupportCalls);
} }
GenerateGeneralSupportCall(tabs, generalSupports); GenerateGeneralSupportCall(tabs, generalSupports);
@@ -542,7 +633,8 @@ private:
WriteLine(tabs, "switch (direction) {"); WriteLine(tabs, "switch (direction) {");
for (int direction = 0; direction < 4; 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); WriteLine(tabs, "case %d:", direction);
for (int d2 = direction + 1; d2 < 4; d2++) for (int d2 = direction + 1; d2 < 4; d2++)
@@ -572,7 +664,8 @@ 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) { switch (call.function)
{
case PAINT_98196C: case PAINT_98196C:
case PAINT_98197C: case PAINT_98197C:
case PAINT_98198C: case PAINT_98198C:
@@ -589,7 +682,9 @@ private:
callTabs++; callTabs++;
} }
WriteLine(callTabs, "%s(%d, %d, %d, height%s, %s);", WriteLine(
callTabs,
"%s(%d, %d, %d, height%s, %s);",
GetFunctionCallName(call.function), GetFunctionCallName(call.function),
call.supports.type, call.supports.type,
call.supports.segment, call.supports.segment,
@@ -605,7 +700,9 @@ private:
} }
case SUPPORTS_WOOD_A: case SUPPORTS_WOOD_A:
case SUPPORTS_WOOD_B: case SUPPORTS_WOOD_B:
WriteLine(tabs, "%s(%d, %d, height%s, %s, NULL);", WriteLine(
tabs,
"%s(%d, %d, height%s, %s, NULL);",
GetFunctionCallName(call.function), GetFunctionCallName(call.function),
call.supports.type, call.supports.type,
call.supports.special, call.supports.special,
@@ -623,7 +720,8 @@ private:
s += FormatXYSwap(call.paint.offset.x, call.paint.offset.y, direction); s += FormatXYSwap(call.paint.offset.x, call.paint.offset.y, direction);
s += ", "; s += ", ";
s += FormatXYSwap(call.paint.bound_box_length.x, call.paint.bound_box_length.y, direction); 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) if (call.function != PAINT_98196C)
{ {
@@ -687,7 +785,8 @@ private:
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++) for (size_t i = 0; i < a.size(); i++)
{ {
if (!CompareFunctionCall(a[i], b[i])) if (!CompareFunctionCall(a[i], b[i]))
@@ -718,7 +817,8 @@ private:
return functionNames[function]; return functionNames[function];
} }
bool GetTunnelCalls(int trackType, bool GetTunnelCalls(
int trackType,
int direction, int direction,
int trackSequence, int trackSequence,
int height, int height,
@@ -736,27 +836,38 @@ private:
uint8_t rightIndex = (4 - direction) % 4; uint8_t rightIndex = (4 - direction) % 4;
uint8_t leftIndex = (rightIndex + 1) % 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; tileTunnelCalls[direction][i].call = TUNNELCALL_SKIPPED;
} }
if (gRightTunnelCount == 0) { if (gRightTunnelCount == 0)
{
tileTunnelCalls[direction][rightIndex].call = TUNNELCALL_NONE; tileTunnelCalls[direction][rightIndex].call = TUNNELCALL_NONE;
} else if (gRightTunnelCount == 3) { }
else if (gRightTunnelCount == 3)
{
tileTunnelCalls[direction][rightIndex].call = TUNNELCALL_CALL; tileTunnelCalls[direction][rightIndex].call = TUNNELCALL_CALL;
tileTunnelCalls[direction][rightIndex].offset = SideTunnelCall::GetTunnelOffset(height, gRightTunnels); tileTunnelCalls[direction][rightIndex].offset = SideTunnelCall::GetTunnelOffset(height, gRightTunnels);
tileTunnelCalls[direction][rightIndex].type = gRightTunnels[0].type; tileTunnelCalls[direction][rightIndex].type = gRightTunnels[0].type;
} else { }
else
{
printf("Multiple tunnels on one side aren't supported.\n"); printf("Multiple tunnels on one side aren't supported.\n");
return false; return false;
} }
if (gLeftTunnelCount == 0) { if (gLeftTunnelCount == 0)
{
tileTunnelCalls[direction][leftIndex].call = TUNNELCALL_NONE; tileTunnelCalls[direction][leftIndex].call = TUNNELCALL_NONE;
} else if (gLeftTunnelCount == 3) { }
else if (gLeftTunnelCount == 3)
{
tileTunnelCalls[direction][leftIndex].call = TUNNELCALL_CALL; tileTunnelCalls[direction][leftIndex].call = TUNNELCALL_CALL;
tileTunnelCalls[direction][leftIndex].offset = SideTunnelCall::GetTunnelOffset(height, gLeftTunnels); tileTunnelCalls[direction][leftIndex].offset = SideTunnelCall::GetTunnelOffset(height, gLeftTunnels);
tileTunnelCalls[direction][leftIndex].type = gLeftTunnels[0].type; tileTunnelCalls[direction][leftIndex].type = gLeftTunnels[0].type;
} else { }
else
{
printf("Multiple tunnels on one side aren't supported.\n"); printf("Multiple tunnels on one side aren't supported.\n");
return false; return false;
} }
@@ -779,15 +890,13 @@ private:
constexpr uint8_t TunnelLeft = 0; constexpr uint8_t TunnelLeft = 0;
constexpr uint8_t TunnelRight = 1; constexpr uint8_t TunnelRight = 1;
constexpr uint8_t TunnelNA = 255; constexpr uint8_t TunnelNA = 255;
static const uint8_t dsToWay[4][4] = static const uint8_t dsToWay[4][4] = {
{
{ TunnelRight, TunnelLeft, TunnelNA, TunnelNA }, { TunnelRight, TunnelLeft, TunnelNA, TunnelNA },
{ TunnelLeft, TunnelNA, TunnelNA, TunnelRight }, { TunnelLeft, TunnelNA, TunnelNA, TunnelRight },
{ TunnelNA, TunnelNA, TunnelRight, TunnelLeft }, { TunnelNA, TunnelNA, TunnelRight, TunnelLeft },
{ TunnelNA, TunnelRight, TunnelLeft, TunnelNA }, { TunnelNA, TunnelRight, TunnelLeft, TunnelNA },
}; };
int16_t tunnelOffset[4] = { 0 }; int16_t tunnelOffset[4] = { 0 };
uint8_t tunnelType[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; uint8_t tunnelType[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
for (int direction = 0; direction < 4; direction++) for (int direction = 0; direction < 4; direction++)
@@ -811,9 +920,9 @@ private:
GenerateTunnelCall(tabs, tunnelOffset[0], tunnelType[0]); GenerateTunnelCall(tabs, tunnelOffset[0], tunnelType[0]);
} }
} }
else if (tunnelOffset[0] == tunnelOffset[3] && tunnelType[0] == tunnelType[3] && else if (
tunnelOffset[1] == tunnelOffset[2] && tunnelType[1] == tunnelType[2] && tunnelOffset[0] == tunnelOffset[3] && tunnelType[0] == tunnelType[3] && tunnelOffset[1] == tunnelOffset[2]
tunnelType[0] != 0xFF) && tunnelType[1] == tunnelType[2] && tunnelType[0] != 0xFF)
{ {
if (tunnelType[0] != 0xFF) if (tunnelType[0] != 0xFF)
{ {
@@ -845,7 +954,8 @@ private:
{ {
if (tileTunnelCalls[i][side].call == TUNNELCALL_CALL) 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;"); WriteLine(tabs + 1, "break;");
@@ -859,26 +969,42 @@ private:
int tunnelHeight = verticalTunnelHeights[0]; int tunnelHeight = verticalTunnelHeights[0];
if (tunnelHeight != 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) void GenerateTunnelCall(int tabs, int offset, int type, int way)
{ {
switch (way) { switch (way)
{
case 0: case 0:
WriteLine(tabs, "paint_util_push_tunnel_left(session, height%s, TUNNEL_%d);", GetOffsetExpressionString(offset).c_str(), type); WriteLine(
tabs,
"paint_util_push_tunnel_left(session, height%s, TUNNEL_%d);",
GetOffsetExpressionString(offset).c_str(),
type);
break; break;
case 1: case 1:
WriteLine(tabs, "paint_util_push_tunnel_right(session, height%s, TUNNEL_%d);", GetOffsetExpressionString(offset).c_str(), type); WriteLine(
tabs,
"paint_util_push_tunnel_right(session, height%s, TUNNEL_%d);",
GetOffsetExpressionString(offset).c_str(),
type);
break; break;
} }
} }
void GenerateTunnelCall(int tabs, int offset, int type) 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]) void GenerateSegmentSupportCall(int tabs, std::vector<SegmentSupportCall> segmentSupportCalls[4])
@@ -914,13 +1040,14 @@ private:
void GenerateGeneralSupportCall(int tabs, support_height generalSupports[4]) void GenerateGeneralSupportCall(int tabs, support_height generalSupports[4])
{ {
if (generalSupports[0].height == 0 && if (generalSupports[0].height == 0 && generalSupports[0].slope == 0xFF)
generalSupports[0].slope == 0xFF)
{ {
return; 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(), GetOffsetExpressionString((int16_t)generalSupports[0].height).c_str(),
generalSupports[0].slope); generalSupports[0].slope);
if (!AllMatch(generalSupports, 4)) if (!AllMatch(generalSupports, 4))
@@ -937,19 +1064,29 @@ private:
uint32_t palette = imageId & ~0x7FFFF; uint32_t palette = imageId & ~0x7FFFF;
std::string paletteName; std::string paletteName;
if (palette == TestPaint::DEFAULT_SCHEME_TRACK) paletteName = "gTrackColours[SCHEME_TRACK]"; if (palette == TestPaint::DEFAULT_SCHEME_TRACK)
else if (palette == TestPaint::DEFAULT_SCHEME_SUPPORTS) paletteName = "gTrackColours[SCHEME_SUPPORTS]"; paletteName = "gTrackColours[SCHEME_TRACK]";
else if (palette == TestPaint::DEFAULT_SCHEME_MISC) paletteName = "gTrackColours[SCHEME_MISC]"; else if (palette == TestPaint::DEFAULT_SCHEME_SUPPORTS)
else if (palette == TestPaint::DEFAULT_SCHEME_3) paletteName = "gTrackColours[SCHEME_3]"; paletteName = "gTrackColours[SCHEME_SUPPORTS]";
else { 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); paletteName = String::Format("0x%08X", palette);
} }
if (image == 0) { if (image == 0)
{
result = paletteName; result = paletteName;
} else if (image & 0x70000) { }
else if (image & 0x70000)
{
result = String::Format("%s | vehicle.base_image_id + %d", paletteName.c_str(), 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); result = String::Format("%s | %d", paletteName.c_str(), image);
} }
return result; return result;
@@ -957,8 +1094,10 @@ private:
std::string GetOffsetExpressionString(int offset) std::string GetOffsetExpressionString(int offset)
{ {
if (offset < 0) return std::string(" - ") + std::to_string(-offset); if (offset < 0)
if (offset > 0) return std::string(" + ") + std::to_string(offset); return std::string(" - ") + std::to_string(-offset);
if (offset > 0)
return std::string(" + ") + std::to_string(offset);
return std::string(); return std::string();
} }
@@ -966,9 +1105,12 @@ private:
{ {
std::string s; std::string s;
int segmentsPrinted = 0; int segmentsPrinted = 0;
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++)
if (segments & segment_offsets[i]) { {
if (segmentsPrinted > 0) { if (segments & segment_offsets[i])
{
if (segmentsPrinted > 0)
{
s += " | "; s += " | ";
} }
s += String::Format("SEGMENT_%02X", 0xB4 + 4 * i); s += String::Format("SEGMENT_%02X", 0xB4 + 4 * i);
@@ -978,8 +1120,7 @@ private:
return s; return s;
} }
template<typename T> template<typename T> bool AllMatch(T* arr, size_t count)
bool AllMatch(T * arr, size_t count)
{ {
for (size_t i = 1; i < count; i++) for (size_t i = 1; i < count; i++)
{ {
@@ -1006,8 +1147,7 @@ private:
height, height,
(int)tileElement, (int)tileElement,
0 * sizeof(Ride), 0 * sizeof(Ride),
trackSequence trackSequence);
);
} }
void GenerateMainFunction() void GenerateMainFunction()
@@ -1017,7 +1157,8 @@ private:
WriteLine(1, "switch (trackType) {"); WriteLine(1, "switch (trackType) {");
for (int trackType = 0; trackType < 256; 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_END_STATION]) + ":");
WriteLine(1, "case " + std::string(TrackElemNames[TRACK_ELEM_BEGIN_STATION]) + ":"); WriteLine(1, "case " + std::string(TrackElemNames[TRACK_ELEM_BEGIN_STATION]) + ":");
WriteLine(1, "case " + std::string(TrackElemNames[TRACK_ELEM_MIDDLE_STATION]) + ":"); WriteLine(1, "case " + std::string(TrackElemNames[TRACK_ELEM_MIDDLE_STATION]) + ":");
@@ -1044,9 +1185,8 @@ private:
bool IsTrackTypeSupported(int trackType) bool IsTrackTypeSupported(int trackType)
{ {
if (trackType == TRACK_ELEM_BEGIN_STATION || if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION
trackType == TRACK_ELEM_MIDDLE_STATION || || trackType == TRACK_ELEM_END_STATION)
trackType == TRACK_ELEM_END_STATION)
{ {
return false; return false;
} }
@@ -1094,4 +1234,3 @@ int generatePaintCode(uint8_t rideType)
auto pcg = PaintCodeGenerator(); auto pcg = PaintCodeGenerator();
return pcg.Generate(rideType); return pcg.Generate(rideType);
} }

View File

@@ -15,27 +15,29 @@
#include <vector> #include <vector>
#if defined(__unix__) #if defined(__unix__)
#include <unistd.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <unistd.h>
#endif // defined(__unix__) #endif // defined(__unix__)
#include "Data.h"
#include "PaintIntercept.hpp" #include "PaintIntercept.hpp"
#include "TestTrack.hpp" #include "TestTrack.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "Data.h"
#include <openrct2/rct2/RCT2.h> #include <openrct2/rct2/RCT2.h>
#include <openrct2/ride/Ride.h> #include <openrct2/ride/Ride.h>
#include <openrct2/ride/RideData.h> #include <openrct2/ride/RideData.h>
#include <openrct2/ride/Track.h> #include <openrct2/ride/Track.h>
#include <openrct2/ride/TrackData.h> #include <openrct2/ride/TrackData.h>
struct TestCase { struct TestCase
{
uint8_t rideType; uint8_t rideType;
std::vector<uint8_t> trackTypes; std::vector<uint8_t> trackTypes;
}; };
enum CLIColour { enum CLIColour
{
DEFAULT, DEFAULT,
RED, RED,
YELLOW, YELLOW,
@@ -45,15 +47,19 @@ enum CLIColour {
bool gTestColor = true; bool gTestColor = true;
Verbosity _verbosity = NORMAL; Verbosity _verbosity = NORMAL;
static bool CStringEquals(const char *lhs, const char *rhs) { static bool CStringEquals(const char* lhs, const char* rhs)
if (lhs == nullptr) return rhs == nullptr; {
if (lhs == nullptr)
return rhs == nullptr;
if (rhs == nullptr) return false; if (rhs == nullptr)
return false;
return strcmp(lhs, rhs) == 0; return strcmp(lhs, rhs) == 0;
} }
enum COLOUR_METHOD { enum COLOUR_METHOD
{
COLOUR_METHOD_NONE, COLOUR_METHOD_NONE,
COLOUR_METHOD_ANSI, COLOUR_METHOD_ANSI,
COLOUR_METHOD_WINDOWS, COLOUR_METHOD_WINDOWS,
@@ -61,25 +67,19 @@ enum COLOUR_METHOD {
static COLOUR_METHOD GetColourMethod() static COLOUR_METHOD GetColourMethod()
{ {
if (!gTestColor) { if (!gTestColor)
{
return COLOUR_METHOD_NONE; return COLOUR_METHOD_NONE;
} }
const char* const term = getenv("TERM"); const char* const term = getenv("TERM");
const bool term_supports_color = const bool term_supports_color = CStringEquals(term, "xterm") || CStringEquals(term, "xterm-color")
CStringEquals(term, "xterm") || || CStringEquals(term, "xterm-256color") || CStringEquals(term, "screen") || CStringEquals(term, "screen-256color")
CStringEquals(term, "xterm-color") || || CStringEquals(term, "tmux") || CStringEquals(term, "tmux-256color") || CStringEquals(term, "rxvt-unicode")
CStringEquals(term, "xterm-256color") || || CStringEquals(term, "rxvt-unicode-256color") || CStringEquals(term, "linux") || CStringEquals(term, "cygwin");
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; return COLOUR_METHOD_ANSI;
} }
@@ -90,13 +90,18 @@ static COLOUR_METHOD GetColourMethod()
#endif #endif
} }
static const char* GetAnsiColorCode(CLIColour color) { static const char* GetAnsiColorCode(CLIColour color)
switch (color) { {
case RED: return "1"; switch (color)
case GREEN: return "2"; {
case RED:
return "1";
case GREEN:
return "2";
case YELLOW: case YELLOW:
return "3"; return "3";
default: return nullptr; default:
return nullptr;
}; };
} }
@@ -111,11 +116,16 @@ static WORD GetCurrentWindowsConsoleAttribute(HANDLE hConsoleOutput)
static WORD GetWindowsConsoleAttribute(CLIColour color, WORD defaultAttr) static WORD GetWindowsConsoleAttribute(CLIColour color, WORD defaultAttr)
{ {
switch (color) { switch (color)
case RED: return FOREGROUND_RED; {
case GREEN: return FOREGROUND_GREEN; case RED:
case YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; return FOREGROUND_RED;
default: return defaultAttr; case GREEN:
return FOREGROUND_GREEN;
case YELLOW:
return FOREGROUND_RED | FOREGROUND_GREEN;
default:
return defaultAttr;
}; };
} }
@@ -123,17 +133,23 @@ static WORD GetWindowsConsoleAttribute(CLIColour color, WORD defaultAttr)
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(); COLOUR_METHOD colourMethod = GetColourMethod();
if (colour == CLIColour::DEFAULT || colourMethod == COLOUR_METHOD_NONE) { if (colour == CLIColour::DEFAULT || colourMethod == COLOUR_METHOD_NONE)
{
vprintf(fmt, args); vprintf(fmt, args);
} else if (colourMethod == COLOUR_METHOD_ANSI) { }
else if (colourMethod == COLOUR_METHOD_ANSI)
{
printf("\033[0;3%sm", GetAnsiColorCode(colour)); printf("\033[0;3%sm", GetAnsiColorCode(colour));
vprintf(fmt, args); vprintf(fmt, args);
printf("\033[m"); printf("\033[m");
} else if (colourMethod == COLOUR_METHOD_WINDOWS) { }
else if (colourMethod == COLOUR_METHOD_WINDOWS)
{
#ifdef __WINDOWS__ #ifdef __WINDOWS__
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
WORD defaultAttr = GetCurrentWindowsConsoleAttribute(hStdOut); WORD defaultAttr = GetCurrentWindowsConsoleAttribute(hStdOut);
@@ -188,19 +204,26 @@ 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; dst[0] = (utf8)codepoint;
return dst + 1; return dst + 1;
} else if (codepoint <= 0x7FF) { }
else if (codepoint <= 0x7FF)
{
dst[0] = 0xC0 | ((codepoint >> 6) & 0x1F); dst[0] = 0xC0 | ((codepoint >> 6) & 0x1F);
dst[1] = 0x80 | (codepoint & 0x3F); dst[1] = 0x80 | (codepoint & 0x3F);
return dst + 2; return dst + 2;
} else if (codepoint <= 0xFFFF) { }
else if (codepoint <= 0xFFFF)
{
dst[0] = 0xE0 | ((codepoint >> 12) & 0x0F); dst[0] = 0xE0 | ((codepoint >> 12) & 0x0F);
dst[1] = 0x80 | ((codepoint >> 6) & 0x3F); dst[1] = 0x80 | ((codepoint >> 6) & 0x3F);
dst[2] = 0x80 | (codepoint & 0x3F); dst[2] = 0x80 | (codepoint & 0x3F);
return dst + 3; return dst + 3;
} else { }
else
{
dst[0] = 0xF0 | ((codepoint >> 18) & 0x07); dst[0] = 0xF0 | ((codepoint >> 18) & 0x07);
dst[1] = 0x80 | ((codepoint >> 12) & 0x3F); dst[1] = 0x80 | ((codepoint >> 12) & 0x3F);
dst[2] = 0x80 | ((codepoint >> 6) & 0x3F); dst[2] = 0x80 | ((codepoint >> 6) & 0x3F);
@@ -214,7 +237,8 @@ utf8 *widechar_to_utf8(const wchar_t *src)
utf8* result = (utf8*)malloc((wcslen(src) * 4) + 1); utf8* result = (utf8*)malloc((wcslen(src) * 4) + 1);
utf8* dst = result; utf8* dst = result;
for (; *src != 0; src++) { for (; *src != 0; src++)
{
dst = utf8_write_codepoint(dst, *src); dst = utf8_write_codepoint(dst, *src);
} }
*dst++ = 0; *dst++ = 0;
@@ -233,7 +257,8 @@ utf8 **windows_get_command_line_args(int *outNumArgs)
// Convert to UTF-8 // Convert to UTF-8
utf8** argvUtf8 = (utf8**)malloc(argc * sizeof(utf8*)); utf8** argvUtf8 = (utf8**)malloc(argc * sizeof(utf8*));
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++)
{
argvUtf8[i] = widechar_to_utf8(argvW[i]); argvUtf8[i] = widechar_to_utf8(argvW[i]);
} }
LocalFree(argvW); LocalFree(argvW);
@@ -250,8 +275,8 @@ BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
__declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{ {
if (_dllModule == nullptr)
if (_dllModule == nullptr) { {
_dllModule = GetModuleHandleA(OPENRCT2_DLL_MODULE_NAME); _dllModule = GetModuleHandleA(OPENRCT2_DLL_MODULE_NAME);
} }
@@ -261,7 +286,8 @@ __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInsta
int gExitCode = main(argc, argv); int gExitCode = main(argc, argv);
// Free argv // Free argv
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++)
{
free(argv[i]); free(argv[i]);
} }
free(argv); free(argv);
@@ -316,7 +342,9 @@ static bool openrct2_setup_rct2_segment()
pagesMissing = true; pagesMissing = true;
perror("mincore"); perror("mincore");
#endif // __LINUX__ #endif // __LINUX__
} else { }
else
{
for (int i = 0; i < numPages; i++) for (int i = 0; i < numPages; i++)
{ {
if (dummy[i] != 1) if (dummy[i] != 1)
@@ -352,11 +380,14 @@ static bool openrct2_setup_rct2_segment()
// Check that the expected data is at various addresses. // 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 // 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. // 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 c1 = sawyercoding_calculate_checksum(
const uint32_t c2 = sawyercoding_calculate_checksum((const uint8_t*)(segments + (uintptr_t)(0x01428000 - 0x8a4000)), 0x014282BC - 0x01428000); (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_c1 = 10114815;
const uint32_t exp_c2 = 23564; 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("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); log_warning("c2 = %u, expected %u, match %d", c2, exp_c2, c2 == exp_c2);
return false; return false;
@@ -367,12 +398,14 @@ static bool openrct2_setup_rct2_segment()
static void PrintRideTypes() 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; CLIColour colour = CLIColour::DEFAULT;
bool implemented = Utils::rideIsImplemented(rideType); bool implemented = Utils::rideIsImplemented(rideType);
const char* rideName = RideNames[rideType]; const char* rideName = RideNames[rideType];
const char* status = ""; const char* status = "";
if (implemented) { if (implemented)
{
status = " [IMPLEMENTED]"; status = " [IMPLEMENTED]";
colour = CLIColour::GREEN; colour = CLIColour::GREEN;
} }
@@ -383,7 +416,8 @@ static void PrintRideTypes()
#include "GeneralSupportHeightCall.hpp" #include "GeneralSupportHeightCall.hpp"
static void TestGeneralSupportHeightCall() { static void TestGeneralSupportHeightCall()
{
SupportCall callA = { 16, 0x20 }; SupportCall callA = { 16, 0x20 };
SupportCall callB = { 32, 0x20 }; SupportCall callB = { 32, 0x20 };
SupportCall callC = { 48, 0x20 }; SupportCall callC = { 48, 0x20 };
@@ -415,37 +449,48 @@ static void TestGeneralSupportHeightCall() {
assert(!success); assert(!success);
} }
int main(int argc, char *argv[]) { int main(int argc, char* argv[])
{
TestGeneralSupportHeightCall(); TestGeneralSupportHeightCall();
std::vector<TestCase> testCases; std::vector<TestCase> testCases;
bool generate = false; bool generate = false;
uint8_t specificRideType = 0xFF; uint8_t specificRideType = 0xFF;
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i)
{
char* arg = argv[i]; char* arg = argv[i];
if (strcmp(arg, "--gtest_color=no") == 0) { if (strcmp(arg, "--gtest_color=no") == 0)
{
gTestColor = false; gTestColor = false;
} }
else if (strcmp(arg, "--quiet") == 0) { else if (strcmp(arg, "--quiet") == 0)
{
_verbosity = Verbosity::QUIET; _verbosity = Verbosity::QUIET;
} }
else if (strcmp(arg, "--ride-type") == 0) { else if (strcmp(arg, "--ride-type") == 0)
if (i + 1 < argc) { {
if (i + 1 < argc)
{
i++; i++;
specificRideType = atoi(argv[i]); specificRideType = atoi(argv[i]);
} else { }
else
{
PrintRideTypes(); PrintRideTypes();
return 2; return 2;
} }
} }
else if (strcmp(arg, "--generate") == 0) { else if (strcmp(arg, "--generate") == 0)
{
generate = true; generate = true;
} }
} }
if (generate) { if (generate)
if (specificRideType > 90) { {
if (specificRideType > 90)
{
fprintf(stderr, "No ride or invalid ride specified.\n"); fprintf(stderr, "No ride or invalid ride specified.\n");
return 1; return 1;
} }
@@ -456,23 +501,31 @@ int main(int argc, char *argv[]) {
return generatePaintCode(specificRideType); return generatePaintCode(specificRideType);
} }
for (uint8_t rideType = 0; rideType < RIDE_TYPE_COUNT; rideType++) { for (uint8_t rideType = 0; rideType < RIDE_TYPE_COUNT; rideType++)
if (specificRideType != RIDE_TYPE_NULL && rideType != specificRideType) { {
if (specificRideType != RIDE_TYPE_NULL && rideType != specificRideType)
{
continue; continue;
} }
if (!Utils::rideIsImplemented(rideType)) { if (!Utils::rideIsImplemented(rideType))
{
continue; continue;
} }
TestCase testCase = {}; TestCase testCase = {};
testCase.rideType = rideType; 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]); testCase.trackTypes.push_back(RideConstructionDefaultTrackType[rideType]);
} else { }
for (int trackType = 0; trackType < 256; trackType++) { else
if (Utils::rideSupportsTrackType(rideType, trackType)) { {
for (int trackType = 0; trackType < 256; trackType++)
{
if (Utils::rideSupportsTrackType(rideType, trackType))
{
testCase.trackTypes.push_back(trackType); testCase.trackTypes.push_back(trackType);
} }
} }
@@ -483,7 +536,8 @@ int main(int argc, char *argv[]) {
int testCaseCount = (int)testCases.size(); int testCaseCount = (int)testCases.size();
int testCount = 0; int testCount = 0;
for (auto &&tc : testCases) { for (auto&& tc : testCases)
{
testCount += tc.trackTypes.size(); testCount += tc.trackTypes.size();
} }
@@ -497,16 +551,21 @@ int main(int argc, char *argv[]) {
int successCount = 0; int successCount = 0;
std::vector<utf8string> failures; std::vector<utf8string> failures;
for (auto &&tc : testCases) { for (auto&& tc : testCases)
{
const utf8string rideTypeName = RideNames[tc.rideType]; const utf8string rideTypeName = RideNames[tc.rideType];
Write(CLIColour::GREEN, "[----------] "); Write(CLIColour::GREEN, "[----------] ");
Write("%d tests from %s\n", (int)tc.trackTypes.size(), rideTypeName); Write("%d tests from %s\n", (int)tc.trackTypes.size(), rideTypeName);
for (auto &&trackType : tc.trackTypes) { for (auto&& trackType : tc.trackTypes)
{
utf8string trackTypeName; 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]; trackTypeName = FlatTrackNames[trackType];
} else { }
else
{
trackTypeName = TrackNames[trackType]; trackTypeName = TrackNames[trackType];
} }
@@ -516,7 +575,8 @@ int main(int argc, char *argv[]) {
std::string out; std::string out;
int retVal = TestTrack::TestPaintTrackElement(tc.rideType, trackType, &out); int retVal = TestTrack::TestPaintTrackElement(tc.rideType, trackType, &out);
Write("%s", out.c_str()); Write("%s", out.c_str());
switch (retVal) { switch (retVal)
{
case TEST_SUCCESS: case TEST_SUCCESS:
Write(CLIColour::GREEN, "[ OK ] "); Write(CLIColour::GREEN, "[ OK ] ");
Write("%s.%s (0 ms)\n", rideTypeName, trackTypeName); Write("%s.%s (0 ms)\n", rideTypeName, trackTypeName);
@@ -556,11 +616,13 @@ int main(int argc, char *argv[]) {
Write(Verbosity::QUIET, CLIColour::GREEN, "[ PASSED ] "); Write(Verbosity::QUIET, CLIColour::GREEN, "[ PASSED ] ");
Write(Verbosity::QUIET, "%d tests.\n", successCount); Write(Verbosity::QUIET, "%d tests.\n", successCount);
if (failures.size() > 0) { if (failures.size() > 0)
{
Write(Verbosity::QUIET, CLIColour::RED, "[ FAILED ] "); Write(Verbosity::QUIET, CLIColour::RED, "[ FAILED ] ");
Write(Verbosity::QUIET, "%d tests, listed below:\n", (int)failures.size()); 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, CLIColour::RED, "[ FAILED ] ");
Write(Verbosity::QUIET, "%s\n", failure); Write(Verbosity::QUIET, "%s\n", failure);
delete[] failure; delete[] failure;

View File

@@ -9,26 +9,22 @@
#pragma once #pragma once
#include <gtest/gtest.h>
#include <initializer_list> #include <initializer_list>
#include <vector> #include <vector>
#include <gtest/gtest.h>
template<typename T, typename TExpected> template<typename T, typename TExpected> static void AssertVector(std::vector<T> actual, TExpected expected)
static void AssertVector(std::vector<T> actual, TExpected expected)
{ {
ASSERT_EQ(actual.size(), expected.size()) << ASSERT_EQ(actual.size(), expected.size()) << "Expected vector of size " << expected.size() << ", but was " << actual.size();
"Expected vector of size " << expected.size() << ", but was " << actual.size();
size_t i = 0; size_t i = 0;
for (auto item : expected) for (auto item : expected)
{ {
EXPECT_EQ(actual[i], item) << EXPECT_EQ(actual[i], item) << "Element at index " << i << " did not match";
"Element at index " << i << " did not match";
i++; i++;
} }
} }
template<typename T> template<typename T> static void AssertVector(std::vector<T> actual, std::initializer_list<T> expected)
static void AssertVector(std::vector<T> actual, std::initializer_list<T> expected)
{ {
AssertVector<T, std::initializer_list<T>>(actual, 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. * 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/Crypt.h>
#include <openrct2/core/File.h> #include <openrct2/core/File.h>
#include <openrct2/core/Path.hpp> #include <openrct2/core/Path.hpp>
#include <openrct2/network/NetworkKey.h> #include <openrct2/network/NetworkKey.h>
#include <gtest/gtest.h> #include <string>
#include "TestData.h"
class CryptTests : public testing::Test class CryptTests : public testing::Test
{ {
public: public:
template<typename T> template<typename T> void AssertHash(std::string expected, T hash)
void AssertHash(std::string expected, T hash)
{ {
auto actual = StringToHex(hash); auto actual = StringToHex(hash);
ASSERT_EQ(expected, actual); ASSERT_EQ(expected, actual);
} }
template<typename T> template<typename T> std::string StringToHex(T input)
std::string StringToHex(T input)
{ {
std::string result; std::string result;
result.reserve(input.size() * 2); result.reserve(input.size() * 2);
@@ -61,11 +60,9 @@ TEST_F(CryptTests, SHA1_Basic)
TEST_F(CryptTests, SHA1_Multiple) TEST_F(CryptTests, SHA1_Multiple)
{ {
std::string input[] = { std::string input[] = { "Merry-go-round 2 looks too intense for me",
"Merry-go-round 2 looks too intense for me",
"This park is really clean and tidy", "This park is really clean and tidy",
"This balloon from Balloon Stall 1 is really good value" "This balloon from Balloon Stall 1 is really good value" };
};
auto alg = Crypt::CreateSHA1(); auto alg = Crypt::CreateSHA1();
for (auto s : input) for (auto s : input)
@@ -94,11 +91,9 @@ TEST_F(CryptTests, SHA1_Many)
auto alg = Crypt::CreateSHA1(); auto alg = Crypt::CreateSHA1();
// First digest // First digest
std::string inputA[] = { std::string inputA[] = { "Merry-go-round 2 looks too intense for me",
"Merry-go-round 2 looks too intense for me",
"This park is really clean and tidy", "This park is really clean and tidy",
"This balloon from Balloon Stall 1 is really good value" "This balloon from Balloon Stall 1 is really good value" };
};
for (auto s : inputA) for (auto s : inputA)
{ {
alg->Update(s.data(), s.size()); alg->Update(s.data(), s.size());

View File

@@ -7,11 +7,12 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * 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/core/Path.hpp>
#include <openrct2/drawing/ImageImporter.h> #include <openrct2/drawing/ImageImporter.h>
#include <gtest/gtest.h> #include <string_view>
#include "TestData.h"
using namespace OpenRCT2::Drawing; using namespace OpenRCT2::Drawing;

View File

@@ -7,13 +7,15 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * 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 <gtest/gtest.h>
#include <limits> #include <limits>
#include <string> #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 class IniReaderTest : public testing::Test
{ {
@@ -128,8 +130,7 @@ TEST_F(IniReaderTest, read_case_insensitive)
delete ir; delete ir;
} }
const std::string IniReaderTest::predefined = const std::string IniReaderTest::predefined = "[bool]\n"
"[bool]\n"
"boolval = true\n\n" "boolval = true\n\n"
"[int]\n" "[int]\n"
"one = 1\n" "one = 1\n"
@@ -138,8 +139,7 @@ const std::string IniReaderTest::predefined =
"path = " "path = "
"\"C:'\\\\some/dir\\\\here/\xE7\xA5\x9E\xE9\xB7\xB9\xE6\x9A\xA2\xE9\x81\x8A\"\n"; "\"C:'\\\\some/dir\\\\here/\xE7\xA5\x9E\xE9\xB7\xB9\xE6\x9A\xA2\xE9\x81\x8A\"\n";
const std::string IniReaderTest::duplicate = const std::string IniReaderTest::duplicate = "[section]\n"
"[section]\n"
"one = true\n" "one = true\n"
"fortytwo = 13\n" "fortytwo = 13\n"
"[section]\n" "[section]\n"
@@ -149,11 +149,9 @@ const std::string IniReaderTest::duplicate =
"fortytwo = 42\n" "fortytwo = 42\n"
"fortytwo = 41\n"; "fortytwo = 41\n";
const std::string IniReaderTest::untrimmed = const std::string IniReaderTest::untrimmed = "[section]\n"
"[section]\n"
"one = true \n" "one = true \n"
" str = \" xxx \""; " str = \" xxx \"";
const std::string IniReaderTest::caseInsensitive = const std::string IniReaderTest::caseInsensitive = "[sEcTiOn]\n"
"[sEcTiOn]\n"
"foo = \"bar\"\n"; "foo = \"bar\"\n";

View File

@@ -7,13 +7,14 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * 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 <gtest/gtest.h>
#include <limits> #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 class IniWriterTest : public testing::Test
{ {
@@ -67,7 +68,9 @@ TEST_F(IniWriterTest, create_multiple_sections)
ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0); ms.SetPosition(0);
const char* ini = (const char*)ms.ReadString(); const char* ini = (const char*)ms.ReadString();
ASSERT_STREQ(ini, "[OpenRCT1]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[OpenRCT2]" PLATFORM_NEWLINE PLATFORM_NEWLINE ASSERT_STREQ(
ini,
"[OpenRCT1]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[OpenRCT2]" PLATFORM_NEWLINE PLATFORM_NEWLINE
"[OpenRCT3]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[OpenRCT4]" PLATFORM_NEWLINE); "[OpenRCT3]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[OpenRCT4]" PLATFORM_NEWLINE);
Memory::Free(ini); Memory::Free(ini);
delete iw; delete iw;
@@ -146,7 +149,9 @@ TEST_F(IniWriterTest, create_loose_int32_t_entry)
ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0); ms.SetPosition(0);
const char* ini = (const char*)ms.ReadString(); const char* ini = (const char*)ms.ReadString();
ASSERT_STREQ(ini, "one = 1" PLATFORM_NEWLINE "zero = 0" PLATFORM_NEWLINE "minusone = -1" PLATFORM_NEWLINE ASSERT_STREQ(
ini,
"one = 1" PLATFORM_NEWLINE "zero = 0" PLATFORM_NEWLINE "minusone = -1" PLATFORM_NEWLINE
"intmin = -2147483648" PLATFORM_NEWLINE "intmax = 2147483647" PLATFORM_NEWLINE); "intmin = -2147483648" PLATFORM_NEWLINE "intmax = 2147483647" PLATFORM_NEWLINE);
Memory::Free(ini); Memory::Free(ini);
delete iw; delete iw;
@@ -189,7 +194,8 @@ TEST_F(IniWriterTest, create_multiple_section_with_values)
ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0); ms.SetPosition(0);
const char* ini = (const char*)ms.ReadString(); const char* ini = (const char*)ms.ReadString();
ASSERT_STREQ(ini, ASSERT_STREQ(
ini,
"[bool]" PLATFORM_NEWLINE "boolval = true" PLATFORM_NEWLINE PLATFORM_NEWLINE "[int]" PLATFORM_NEWLINE "[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 = " "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); "\"C:'\\\\some/dir\\\\here/\xE7\xA5\x9E\xE9\xB7\xB9\xE6\x9A\xA2\xE9\x81\x8A\"" PLATFORM_NEWLINE);
@@ -212,7 +218,9 @@ TEST_F(IniWriterTest, create_duplicate_sections)
ASSERT_EQ(ms.GetLength(), ms.GetPosition()); ASSERT_EQ(ms.GetLength(), ms.GetPosition());
ms.SetPosition(0); ms.SetPosition(0);
const char* ini = (const char*)ms.ReadString(); const char* ini = (const char*)ms.ReadString();
ASSERT_STREQ(ini, "[section]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[section]" PLATFORM_NEWLINE PLATFORM_NEWLINE ASSERT_STREQ(
ini,
"[section]" PLATFORM_NEWLINE PLATFORM_NEWLINE "[section]" PLATFORM_NEWLINE PLATFORM_NEWLINE
"[section]" PLATFORM_NEWLINE); "[section]" PLATFORM_NEWLINE);
Memory::Free(ini); Memory::Free(ini);
delete iw; delete iw;

View File

@@ -8,7 +8,9 @@
*****************************************************************************/ *****************************************************************************/
#include "openrct2/localisation/LanguagePack.h" #include "openrct2/localisation/LanguagePack.h"
#include "openrct2/localisation/StringIds.h" #include "openrct2/localisation/StringIds.h"
#include <gtest/gtest.h> #include <gtest/gtest.h>
class LanguagePackTest : public testing::Test class LanguagePackTest : public testing::Test
@@ -90,8 +92,8 @@ const utf8 * LanguagePackTest::LanguageEnGB = "# STR_XXXX part is read and XXXX
// This includes a few entries extracted from zh-TW localisation. // 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. // It has to be declared as `unsigned char`, or else the values overflow signed byte.
const unsigned char LanguagePackTest::LanguageZhTW[] = { 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, = { 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, 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, 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, 0xe9, 0x9c, 0x84, 0xe9, 0xa3, 0x9b, 0xe8, 0xbb, 0x8a, 0x0a, 0x53, 0x54, 0x52, 0x5f, 0x30, 0x30, 0x30, 0x32, 0x20, 0x20,
@@ -115,5 +117,4 @@ const unsigned char LanguagePackTest::LanguageZhTW[] = {
0xa3, 0x9b, 0xe9, 0xa6, 0xb3, 0xe4, 0xb8, 0xad, 0xe9, 0xab, 0x94, 0xe9, 0xa9, 0x97, 0xe9, 0xa3, 0x9b, 0xe4, 0xb8, 0x80, 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, 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, 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 0xb9, 0x98, 0xe5, 0xae, 0xa2, 0x0a, 0x00 };
};

View File

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

View File

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

View File

@@ -7,19 +7,19 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <string> #include "TestData.h"
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <openrct2/audio/AudioContext.h>
#include <openrct2/Context.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/File.h>
#include <openrct2/core/Path.hpp> #include <openrct2/core/Path.hpp>
#include <openrct2/core/String.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/platform/platform.h>
#include <openrct2/Game.h> #include <openrct2/ride/Ride.h>
#include <string>
using namespace OpenRCT2; using namespace OpenRCT2;
@@ -54,7 +54,8 @@ protected:
std::string FormatRatings(Ride* ride) std::string FormatRatings(Ride* ride)
{ {
rating_tuple ratings = ride->ratings; 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), ride_type_get_enum_name(ride->type),
(int)ratings.excitement, (int)ratings.excitement,
(int)ratings.intensity, (int)ratings.intensity,

View File

@@ -7,13 +7,14 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * 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 <string>
#include <tuple> #include <tuple>
#include <utility> #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>; using TCase = std::tuple<std::string, std::string, std::string>;
@@ -25,7 +26,10 @@ class StringTest : public testing::TestWithParam<TCase>
// Tests for String::Trim // Tests for String::Trim
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
INSTANTIATE_TEST_CASE_P(TrimData, StringTest, testing::Values( INSTANTIATE_TEST_CASE_P(
TrimData,
StringTest,
testing::Values(
// input after Trim after TrimStart // input after Trim after TrimStart
TCase("string", "string", "string"), TCase("string", "string", "string"),
TCase(" string", "string", "string"), TCase(" string", "string", "string"),
@@ -39,8 +43,7 @@ INSTANTIATE_TEST_CASE_P(TrimData, StringTest, testing::Values(
TCase("", "", ""), TCase("", "", ""),
TCase("\n", "", ""), TCase("\n", "", ""),
TCase("\n\n\n\r\n", "", ""), TCase("\n\n\n\r\n", "", ""),
TCase("\n\n\n\r\nstring\n\n", "string", "string\n\n") TCase("\n\n\n\r\nstring\n\n", "string", "string\n\n")));
));
TEST_P(StringTest, Trim) TEST_P(StringTest, Trim)
{ {
auto testCase = GetParam(); auto testCase = GetParam();

View File

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

View File

@@ -15,4 +15,4 @@ namespace TestData
{ {
std::string GetBasePath(); std::string GetBasePath();
std::string GetParkPath(std::string name); 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. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "TestData.h"
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <openrct2/Context.h> #include <openrct2/Context.h>
#include <openrct2/Game.h> #include <openrct2/Game.h>
@@ -14,7 +16,6 @@
#include <openrct2/ParkImporter.h> #include <openrct2/ParkImporter.h>
#include <openrct2/world/Footpath.h> #include <openrct2/world/Footpath.h>
#include <openrct2/world/Map.h> #include <openrct2/world/Map.h>
#include "TestData.h"
using namespace OpenRCT2; using namespace OpenRCT2;
@@ -34,6 +35,7 @@ protected:
game_load_init(); game_load_init();
SUCCEED(); SUCCEED();
} }
private: private:
static std::shared_ptr<IContext> _context; static std::shared_ptr<IContext> _context;
}; };

View File

@@ -108,8 +108,8 @@ TEST_F(SawyerCodingTest, decode_chunk_rotate)
// 1024 bytes of random data // 1024 bytes of random data
// use `dd if=/dev/urandom bs=1024 count=1 | xxd -i` to get your own // use `dd if=/dev/urandom bs=1024 count=1 | xxd -i` to get your own
const uint8_t SawyerCodingTest::randomdata[] = { 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, = { 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, 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, 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, 0xed, 0xf1, 0x49, 0xbb, 0xf6, 0x7f, 0x21, 0x24, 0xc3, 0xfb, 0x42, 0xe1, 0xfc, 0xb8, 0x82, 0x5e, 0x01, 0x5d, 0x96, 0x2d,
@@ -160,13 +160,12 @@ const uint8_t SawyerCodingTest::randomdata[] = {
0xb7, 0xe6, 0x2e, 0x73, 0xf1, 0x7c, 0x84, 0x21, 0x04, 0x00, 0x8e, 0x12, 0x66, 0x6c, 0x9b, 0x09, 0x88, 0xe2, 0xd5, 0xec, 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, 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, 0x4e, 0x70, 0xde, 0x9d, 0x0c, 0x17, 0x1d, 0x15, 0x29, 0x5b, 0xd0, 0x66, 0x72, 0xb8, 0x38, 0x80, 0xbe, 0x9e, 0xd7, 0x5e,
0xb5, 0x72, 0x22, 0xbc 0xb5, 0x72, 0x22, 0xbc };
};
// Following are compressed versions of the data above. // Following are compressed versions of the data above.
const uint8_t SawyerCodingTest::nonedata[] = { 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, = { 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, 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, 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, 0x10, 0x6d, 0x60, 0xb9, 0xd4, 0xed, 0xf1, 0x49, 0xbb, 0xf6, 0x7f, 0x21, 0x24, 0xc3, 0xfb, 0x42, 0xe1, 0xfc, 0xb8, 0x82,
@@ -217,11 +216,10 @@ const uint8_t SawyerCodingTest::nonedata[] = {
0x18, 0x48, 0x2c, 0xe9, 0xe5, 0xb7, 0xe6, 0x2e, 0x73, 0xf1, 0x7c, 0x84, 0x21, 0x04, 0x00, 0x8e, 0x12, 0x66, 0x6c, 0x9b, 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, 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, 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 0x80, 0xbe, 0x9e, 0xd7, 0x5e, 0xb5, 0x72, 0x22, 0xbc };
};
const uint8_t SawyerCodingTest::rledata[] = { 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, = { 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, 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, 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, 0x00, 0x10, 0x6d, 0x60, 0xb9, 0xd4, 0xed, 0xf1, 0x49, 0xbb, 0xf6, 0x7f, 0x21, 0x24, 0xc3, 0xfb, 0x42, 0xe1, 0xfc, 0xb8,
@@ -272,11 +270,10 @@ const uint8_t SawyerCodingTest::rledata[] = {
0x3a, 0x36, 0x3c, 0x38, 0x31, 0x99, 0x8d, 0x80, 0x78, 0x18, 0x48, 0x2c, 0xe9, 0xe5, 0xb7, 0xe6, 0x2e, 0x73, 0xf1, 0x7c, 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, 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, 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 0x1d, 0x15, 0x29, 0x5b, 0xd0, 0x66, 0x72, 0xb8, 0x38, 0x80, 0xbe, 0x9e, 0xd7, 0x5e, 0xb5, 0x72, 0x22, 0xbc };
};
const uint8_t SawyerCodingTest::rlecompresseddata[] = { 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, = { 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, 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, 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, 0xad, 0xff, 0x01, 0xff, 0xd3, 0xff, 0x79, 0xff, 0x3d, 0xff, 0xe9, 0xa8, 0xff, 0xa8, 0xff, 0x95, 0x48, 0xff, 0xc0,
@@ -373,11 +370,10 @@ const uint8_t SawyerCodingTest::rlecompresseddata[] = {
0x1b, 0xff, 0x81, 0x58, 0xff, 0xe4, 0xff, 0x5c, 0xff, 0x36, 0x18, 0xff, 0x2d, 0xff, 0x9d, 0x90, 0xff, 0xb6, 0xff, 0x69, 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, 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, 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 0xff, 0x5e, 0xff, 0xb5, 0xb8, 0xff, 0x22, 0xff, 0xbc };
};
const uint8_t SawyerCodingTest::rotatedata[] = { 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, = { 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, 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, 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, 0x08, 0xda, 0x03, 0x37, 0x6a, 0xdb, 0x8f, 0x29, 0xdd, 0xed, 0xfb, 0x24, 0x12, 0x87, 0xdf, 0x48, 0xf0, 0xf9, 0xc5, 0x50,
@@ -428,5 +424,4 @@ const uint8_t SawyerCodingTest::rotatedata[] = {
0x0c, 0x90, 0x61, 0x3d, 0xf2, 0x6f, 0x37, 0xc5, 0xb9, 0xe3, 0xe3, 0x90, 0x90, 0x08, 0x00, 0xd1, 0x09, 0xcc, 0x63, 0x73, 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, 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, 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 0x40, 0x7d, 0xf4, 0xfa, 0x2f, 0x6b, 0x93, 0x44, 0x5e };
};