From 8034f6f427e630182b620058c62c7a2204ab676d Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sat, 15 Oct 2016 21:44:51 +0200 Subject: [PATCH 01/42] Extract method interception to seperate class --- src/paint/supports.c | 4 +- src/paint/supports.h | 4 +- test/testpaint/PaintIntercept.cpp | 355 ++++++++++++++++++++++++++++++ test/testpaint/intercept.c | 325 +-------------------------- test/testpaint/intercept.h | 4 + 5 files changed, 371 insertions(+), 321 deletions(-) create mode 100644 test/testpaint/PaintIntercept.cpp diff --git a/src/paint/supports.c b/src/paint/supports.c index 263020d17f..320f3fbbcb 100644 --- a/src/paint/supports.c +++ b/src/paint/supports.c @@ -687,7 +687,7 @@ bool wooden_b_supports_paint_setup(int supportType, int special, int height, uin * @param imageColourFlags (ebp) * rct2: 0x00663105 */ -bool metal_a_supports_paint_setup(int supportType, int segment, int special, int height, uint32 imageColourFlags) +bool metal_a_supports_paint_setup(uint8 supportType, uint8 segment, int special, int height, uint32 imageColourFlags) { if (gCurrentViewportFlags & VIEWPORT_FLAG_INVISIBLE_SUPPORTS) { return false; @@ -876,7 +876,7 @@ bool metal_a_supports_paint_setup(int supportType, int segment, int special, int * * @return (Carry Flag) */ -bool metal_b_supports_paint_setup(int supportType, uint8 segment, int special, int height, uint32 imageColourFlags) +bool metal_b_supports_paint_setup(uint8 supportType, uint8 segment, int special, int height, uint32 imageColourFlags) { #ifndef NO_RCT2 if (gUseOriginalRidePaint) { diff --git a/src/paint/supports.h b/src/paint/supports.h index 06e4feb187..5c0985cf87 100644 --- a/src/paint/supports.h +++ b/src/paint/supports.h @@ -28,8 +28,8 @@ extern paint_struct * gWoodenSupportsPrependTo; bool wooden_a_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, bool* underground); bool wooden_b_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, bool* underground); -bool metal_a_supports_paint_setup(int supportType, int segment, int special, int height, uint32 imageColourFlags); -bool metal_b_supports_paint_setup(int supportType, uint8 segment, int special, int height, uint32 imageColourFlags); +bool metal_a_supports_paint_setup(uint8 supportType, uint8 segment, int special, int height, uint32 imageColourFlags); +bool metal_b_supports_paint_setup(uint8 supportType, uint8 segment, int special, int height, uint32 imageColourFlags); bool path_a_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, rct_footpath_entry * pathEntry, bool * underground); bool path_b_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, rct_footpath_entry * pathEntry); diff --git a/test/testpaint/PaintIntercept.cpp b/test/testpaint/PaintIntercept.cpp new file mode 100644 index 0000000000..ebaa33cee3 --- /dev/null +++ b/test/testpaint/PaintIntercept.cpp @@ -0,0 +1,355 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + + +#include "intercept.h" + +extern "C" { +#include "../../src/common.h" +#include "../../src/hook.h" +#include "../../src/interface/viewport.h" +} + +class PaintInterceptor { +public: + static void InitHooks() { + addhook(0x006629BC, (int) InterceptWoodenASupports, 0, (int[]) {EAX, EBX, EDX, EDI, EBP, END}, 0, EAX); + addhook(0x00662D5C, (int) InterceptWoodenBSupports, 0, (int[]) {EAX, EBX, EDX, EDI, EBP, END}, 0, EAX); + + addhook(0x00663105, (int) InterceptMetalASupports, 0, (int[]) {EAX, EBX, EDX, EDI, EBP, END}, 0, EAX); + addhook(0x00663584, (int) InterceptMetalBSupports, 0, (int[]) {EAX, EBX, EDX, EDI, EBP, END}, 0, EAX); + + addhook(0x006861AC, (int) InterceptPaint6C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x00686337, (int) InterceptPaint6C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x006864D0, (int) InterceptPaint6C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x0068666B, (int) InterceptPaint6C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + + addhook(0x00686806, (int) InterceptPaint7C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x006869B2, (int) InterceptPaint7C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x00686B6F, (int) InterceptPaint7C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x00686D31, (int) InterceptPaint7C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + + addhook(0x00686EF0, (int) InterceptPaint8C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x00687056, (int) InterceptPaint8C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x006871C8, (int) InterceptPaint8C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x0068733C, (int) InterceptPaint8C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + + addhook(0x006874B0, (int) InterceptPaint9C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x00687618, (int) InterceptPaint9C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x0068778C, (int) InterceptPaint9C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x00687902, (int) InterceptPaint9C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + } + + static bool PaintWoodenSupports(uint8 function, int supportType, int special, int height, uint32 imageColourFlags, bool *underground) { + function_call call = { + .function = function, + .supports = { + .type = supportType, + .special = special, + .height = height, + .colour_flags = imageColourFlags, + } + }; + + _calls[_callCount] = call; + _callCount++; + + return _woodenSupports; + } + + static bool PaintMetalSupports(uint8 function, int supportType, uint8 segment, int special, int height, uint32 imageColourFlags) { + CheckSegmentSupportHeight(); + + function_call call = { + .function = function, + .supports = { + .type = supportType, + .segment = segment, + .special = special, + .height = height, + .colour_flags = imageColourFlags, + } + }; + + _calls[_callCount] = call; + _callCount++; + return false; + } + + static paint_struct *Paint6C( + uint32 imageID, + sint8 xOffset, sint8 yOffset, + sint16 boundBoxLengthX, sint16 boundBoxLengthY, sint8 boundBoxLengthZ, + sint16 zOffset, + uint32 rotation + ) { + function_call call = { + .function = PAINT_98196C, + .paint = { + .image_id = imageID, + .offset = {xOffset, yOffset}, + .bound_box_length = {boundBoxLengthX, boundBoxLengthY, boundBoxLengthZ}, + .z_offset = zOffset, + .rotation = rotation + }, + }; + + _calls[_callCount] = call; + _callCount++; + + return nullptr; + } + + static paint_struct *PaintFull( + uint8 function, + uint32 imageID, + sint8 xOffset, sint8 yOffset, + sint16 boundBoxLengthX, sint16 boundBoxLengthY, sint8 boundBoxLengthZ, + sint16 zOffset, + sint16 boundBoxOffsetX, sint16 boundBoxOffsetY, sint16 boundBoxOffsetZ, + uint32 rotation + ) { + function_call call = { + .function = function, + .paint = { + .image_id = imageID, + .offset = {xOffset, yOffset}, + .bound_box_length = {boundBoxLengthX, boundBoxLengthY, boundBoxLengthZ}, + .bound_box_offset = {boundBoxOffsetX, boundBoxOffsetY, boundBoxOffsetZ}, + .z_offset = zOffset, + .rotation = rotation + }, + }; + + _calls[_callCount] = call; + _callCount++; + + return nullptr; + } + + static void ClearCalls() { + _callCount = 0; + memset(_calls, 0, sizeof(_calls)); + } + + static int GetCalls(function_call *buffer) { + memcpy(buffer, _calls, _callCount * sizeof(function_call)); + return _callCount; + } + + static void SetSimulateWoodenSupports(bool enabled) { + _woodenSupports = enabled; + } + +private: + static bool _woodenSupports; + static uint8 _callCount; + static function_call _calls[256]; + + static uint32 InterceptMetalASupports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp) { + bool output = PaintMetalSupports(SUPPORTS_METAL_A, edi, ebx, (sint16) (eax & 0xFFFF), (edx & 0xFFFF), ebp); + + return output ? 1 : 0; + } + + static uint32 InterceptMetalBSupports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp) { + bool output = PaintMetalSupports(SUPPORTS_METAL_B, edi, ebx, (sint16) (eax & 0xFFFF), (edx & 0xFFFF), ebp); + + return output ? 1 : 0; + } + + static void CheckSegmentSupportHeight() { + // First get last known support height state + if (memcmp(gSupportSegments, &DefaultSegmentHeight, sizeof(support_height) * 9) == 0) { + // Nothing changed + return; + } + + + function_call call = { + .function = SET_SEGMENT_HEIGHT + }; + + _calls[_callCount] = call; + _callCount++; + } + + static uint32 InterceptWoodenASupports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp) { + bool output = PaintWoodenSupports(SUPPORTS_WOOD_A, edi, eax & 0xFFFF, edx & 0xFFFF, ebp, nullptr); + + return output ? 1 : 0; + } + + static uint32 InterceptWoodenBSupports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp) { + bool output = PaintWoodenSupports(SUPPORTS_WOOD_B, edi, eax & 0xFFFF, edx & 0xFFFF, ebp, nullptr); + + return output ? 1 : 0; + } + + static uint32 InterceptPaint6C(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp) { + if ((ebp & 0x03) != get_current_rotation()) { + // Log error + log_error("Ebp is different from current rotation"); + } + + return (uintptr_t) Paint6C( + ebx, + (sint8) (eax & 0xFF), (sint8) (ecx & 0xFF), + (sint16) (edi & 0xFFFF), (sint16) (esi & 0xFFFF), (sint8) ((eax >> 8) & 0xFF), + edx & 0xFFFF, + ebp & 0x03 + ); + } + + static uint32 InterceptPaint7C(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp) { + return InterceptPaintFull(PAINT_98197C, eax, ebx, ecx, edx, esi, edi, ebp); + } + + static uint32 InterceptPaint8C(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp) { + return InterceptPaintFull(PAINT_98198C, eax, ebx, ecx, edx, esi, edi, ebp); + } + + static uint32 InterceptPaint9C(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp) { + return InterceptPaintFull(PAINT_98199C, eax, ebx, ecx, edx, esi, edi, ebp); + } + + static uint32 InterceptPaintFull(uint8 function, uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp) { + if ((ebp & 0x03) != get_current_rotation()) { + // Log error + log_error("Ebp is different from current rotation"); + } + + rct_xyz16 boundOffset = { + RCT2_GLOBAL(RCT2_ADDRESS_PAINT_BOUNDBOX_OFFSET_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_PAINT_BOUNDBOX_OFFSET_Y, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_PAINT_BOUNDBOX_OFFSET_Z, sint16) + }; + + return (uintptr_t) PaintFull( + function, + ebx, + (sint8) (eax & 0xFF), (sint8) (ecx & 0xFF), + (sint16) (edi & 0xFFFF), (sint16) (esi & 0xFFFF), (sint8) ((eax >> 8) & 0xFF), + edx & 0xFFFF, + boundOffset.x, boundOffset.y, boundOffset.z, + ebp & 0x03 + ); + } +}; + +bool PaintInterceptor::_woodenSupports = false; +uint8 PaintInterceptor::_callCount = 0; +function_call PaintInterceptor::_calls[256] = {0}; + +extern "C" { +bool wooden_a_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, bool *underground) { + return PaintInterceptor::PaintWoodenSupports(SUPPORTS_WOOD_A, supportType, special, height, imageColourFlags, underground); +} + +bool wooden_b_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, bool *underground) { + return PaintInterceptor::PaintWoodenSupports(SUPPORTS_WOOD_B, supportType, special, height, imageColourFlags, underground); +} + +bool metal_a_supports_paint_setup(uint8 supportType, uint8 segment, int special, int height, uint32 imageColourFlags) { + return PaintInterceptor::PaintMetalSupports(SUPPORTS_METAL_A, supportType, segment, special, height, imageColourFlags); +} + +bool metal_b_supports_paint_setup(uint8 supportType, uint8 segment, int special, int height, uint32 imageColourFlags) { + return PaintInterceptor::PaintMetalSupports(SUPPORTS_METAL_B, supportType, segment, special, height, imageColourFlags); +} + +paint_struct *sub_98196C(uint32 image_id, sint8 x_offset, sint8 y_offset, sint16 bound_box_length_x, sint16 bound_box_length_y, sint8 bound_box_length_z, sint16 z_offset, uint32 rotation) { + return PaintInterceptor::Paint6C(image_id, x_offset, y_offset, bound_box_length_x, bound_box_length_y, bound_box_length_z, z_offset, rotation); +} + +paint_struct *sub_98197C( + uint32 image_id, + sint8 x_offset, sint8 y_offset, + sint16 bound_box_length_x, sint16 bound_box_length_y, sint8 bound_box_length_z, + sint16 z_offset, + sint16 bound_box_offset_x, sint16 bound_box_offset_y, sint16 bound_box_offset_z, + uint32 rotation +) { + return PaintInterceptor::PaintFull( + PAINT_98197C, + image_id, + x_offset, y_offset, + bound_box_length_x, bound_box_length_y, bound_box_length_z, + z_offset, + bound_box_offset_x, bound_box_offset_y, bound_box_offset_z, + rotation + ); +} + +paint_struct *sub_98198C( + uint32 image_id, + sint8 x_offset, sint8 y_offset, + sint16 bound_box_length_x, sint16 bound_box_length_y, sint8 bound_box_length_z, + sint16 z_offset, + sint16 bound_box_offset_x, sint16 bound_box_offset_y, sint16 bound_box_offset_z, + uint32 rotation +) { + return PaintInterceptor::PaintFull( + PAINT_98198C, + image_id, + x_offset, y_offset, + bound_box_length_x, bound_box_length_y, bound_box_length_z, + z_offset, + bound_box_offset_x, bound_box_offset_y, bound_box_offset_z, + rotation + ); +} + +paint_struct *sub_98199C( + uint32 image_id, + sint8 x_offset, sint8 y_offset, + sint16 bound_box_length_x, sint16 bound_box_length_y, sint8 bound_box_length_z, + sint16 z_offset, + sint16 bound_box_offset_x, sint16 bound_box_offset_y, sint16 bound_box_offset_z, + uint32 rotation +) { + return PaintInterceptor::PaintFull( + PAINT_98199C, + image_id, + x_offset, y_offset, + bound_box_length_x, bound_box_length_y, bound_box_length_z, + z_offset, + bound_box_offset_x, bound_box_offset_y, bound_box_offset_z, + rotation + ); +} + +bool paint_attach_to_previous_ps(uint32 image_id, uint16 x, uint16 y) { + return false; +} + +void intercept_clear_calls() { + PaintInterceptor::ClearCalls(); +} + +int intercept_get_calls(function_call *buffer) { + return PaintInterceptor::GetCalls(buffer); +} + +void intercept_simulate_wooden_supports(bool enabled) { + return PaintInterceptor::SetSimulateWoodenSupports(enabled); +} + +void initHooks() { + PaintInterceptor::InitHooks(); +} + +} diff --git a/test/testpaint/intercept.c b/test/testpaint/intercept.c index 12e546b2eb..f628050f9b 100644 --- a/test/testpaint/intercept.c +++ b/test/testpaint/intercept.c @@ -27,7 +27,7 @@ static const uint32 DEFAULT_SCHEME_MISC = COLOUR_DARK_PURPLE << 19 | COLOUR_LIGH static const uint32 DEFAULT_SCHEME_3 = COLOUR_BRIGHT_PURPLE << 19 | COLOUR_DARK_BLUE << 24 | 0xA0000000; #define BLANK_SUPPORT {.height = 0, .slope = 0xFF} -static const support_height DefaultSegmentHeight[9] = { +const support_height DefaultSegmentHeight[9] = { BLANK_SUPPORT, BLANK_SUPPORT, BLANK_SUPPORT, BLANK_SUPPORT, BLANK_SUPPORT, BLANK_SUPPORT, BLANK_SUPPORT, BLANK_SUPPORT, BLANK_SUPPORT @@ -37,218 +37,6 @@ extern const utf8string RideNames[91]; extern const utf8string TrackNames[256]; extern const utf8string FlatTrackNames[256]; -static bool _woodenSupports; -static uint8 callCount; -static function_call calls[256]; - -void intercept_clear_calls() -{ - callCount = 0; - memset(calls, 0, sizeof(calls)); -} - -int intercept_get_calls(function_call * buffer) -{ - memcpy(buffer, calls, 256); - return callCount; -} - -bool paint_attach_to_previous_ps(uint32 image_id, uint16 x, uint16 y) { - return false; -} - -paint_struct *sub_98196C( - uint32 image_id, - sint8 x_offset, sint8 y_offset, - sint16 bound_box_length_x, sint16 bound_box_length_y, sint8 bound_box_length_z, - sint16 z_offset, - uint32 rotation -) { - function_call call = { - .function = PAINT_98196C, - .paint = { - .image_id = image_id, - .offset = {x_offset, y_offset}, - .bound_box_length = {bound_box_length_x, bound_box_length_y, bound_box_length_z}, - .z_offset = z_offset, - .rotation = rotation - }, - }; - - calls[callCount] = call; - callCount++; - - return NULL; -} - -paint_struct *sub_98197C( - uint32 image_id, - sint8 x_offset, sint8 y_offset, - sint16 bound_box_length_x, sint16 bound_box_length_y, sint8 bound_box_length_z, - sint16 z_offset, - sint16 bound_box_offset_x, sint16 bound_box_offset_y, sint16 bound_box_offset_z, - uint32 rotation -) { - function_call call = { - .function = PAINT_98197C, - .paint = { - .image_id = image_id, - .offset = {x_offset, y_offset}, - .bound_box_length = {bound_box_length_x, bound_box_length_y, bound_box_length_z}, - .bound_box_offset = {bound_box_offset_x, bound_box_offset_y, bound_box_offset_z}, - .z_offset = z_offset, - .rotation = rotation, - }, - }; - - calls[callCount] = call; - callCount++; - - return NULL; -} - -paint_struct *sub_98198C( - uint32 image_id, - sint8 x_offset, sint8 y_offset, - sint16 bound_box_length_x, sint16 bound_box_length_y, sint8 bound_box_length_z, - sint16 z_offset, - sint16 bound_box_offset_x, sint16 bound_box_offset_y, sint16 bound_box_offset_z, - uint32 rotation -) { - function_call call = { - .function = PAINT_98198C, - .paint = { - .image_id = image_id, - .offset = {x_offset, y_offset}, - .bound_box_length = {bound_box_length_x, bound_box_length_y, bound_box_length_z}, - .bound_box_offset = {bound_box_offset_x, bound_box_offset_y, bound_box_offset_z}, - .z_offset = z_offset, - .rotation = rotation, - }, - }; - - calls[callCount] = call; - callCount++; - - return NULL; -} - -paint_struct *sub_98199C( - uint32 image_id, - sint8 x_offset, sint8 y_offset, - sint16 bound_box_length_x, sint16 bound_box_length_y, sint8 bound_box_length_z, - sint16 z_offset, - sint16 bound_box_offset_x, sint16 bound_box_offset_y, sint16 bound_box_offset_z, - uint32 rotation -) { - function_call call = { - .function = PAINT_98199C, - .paint = { - .image_id = image_id, - .offset = {x_offset, y_offset}, - .bound_box_length = {bound_box_length_x, bound_box_length_y, bound_box_length_z}, - .bound_box_offset = {bound_box_offset_x, bound_box_offset_y, bound_box_offset_z}, - .z_offset = z_offset, - .rotation = rotation, - }, - }; - - calls[callCount] = call; - callCount++; - - return NULL; -} - -bool wooden_a_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, bool *underground) { - - function_call call = { - .function = SUPPORTS_WOOD_A, - .supports = { - .type = supportType, - .special = special, - .height = height, - .colour_flags = imageColourFlags, - } - }; - - calls[callCount] = call; - callCount++; - return _woodenSupports; -} - -bool wooden_b_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, bool *underground) { - - function_call call = { - .function = SUPPORTS_WOOD_B, - .supports = { - .type = supportType, - .special = special, - .height = height, - .colour_flags = imageColourFlags, - } - }; - - calls[callCount] = call; - callCount++; - return _woodenSupports; -} - -static void check_support_height() -{ - // First get last known support height state - if (memcmp(gSupportSegments, &DefaultSegmentHeight, sizeof(support_height) * 9) == 0) { - // Nothing changed - return; - } - - function_call call = { - .function = SET_SEGMENT_HEIGHT - }; - - calls[callCount] = call; - callCount++; -} - -bool metal_a_supports_paint_setup(int supportType, int segment, int special, int height, uint32 imageColourFlags) { - - check_support_height(); - - function_call call = { - .function = SUPPORTS_METAL_A, - .supports = { - .type = supportType, - .segment = segment, - .special = special, - .height = height, - .colour_flags = imageColourFlags, - } - }; - - calls[callCount] = call; - callCount++; - return false; -} - -bool metal_b_supports_paint_setup(int supportType, uint8 segment, int special, int height, uint32 imageColourFlags) { - - check_support_height(); - - function_call call = { - .function = SUPPORTS_METAL_B, - .supports = { - .type = supportType, - .segment = segment, - .special = special, - .height = height, - .colour_flags = imageColourFlags, - } - }; - - calls[callCount] = call; - callCount++; - return false; -} - enum { SPRITEGROUP_NONE, @@ -257,7 +45,6 @@ enum { SPRITEGROUP_FENCE_SPIRAL_SLIDE, // 20564 SPRITEGROUP_FLOOR_CORK, // 22134 SPRITEGROUP_FENCE_ROPE, // 22138 - }; static int getSpriteGroup(uint16 spriteIndex) { @@ -524,6 +311,7 @@ extern bool testSupportSegments(uint8 rideType, uint8 trackType); extern bool testTunnels(uint8 rideType, uint8 trackType); extern bool testVerticalTunnels(uint8 rideType, uint8 trackType); + static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string error, size_t len) { if (rideType == RIDE_TYPE_CHAIRLIFT) { if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION || trackType == TRACK_ELEM_END_STATION) { @@ -573,9 +361,9 @@ static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string error, for (int supports = 0; supports < 2; supports++) { if (supports == 0) { - _woodenSupports = false; + intercept_simulate_wooden_supports(false); } else { - _woodenSupports = true; + intercept_simulate_wooden_supports(true); } for (int inverted = 0; inverted < 2; inverted++) { if (inverted == 0) { @@ -600,8 +388,7 @@ static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string error, gSurfaceElement = &surfaceElement; g141E9DB = G141E9DB_FLAG_1 | G141E9DB_FLAG_2; - callCount = 0; - memset(&calls, 0, sizeof(calls)); + intercept_clear_calls(); memcpy(gSupportSegments, DefaultSegmentHeight, sizeof(support_height) * 9); @@ -621,11 +408,10 @@ static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string error, // segment heights // tunnels - uint8 oldCallCount = callCount; function_call oldCalls[256]; - memcpy(&oldCalls, &calls, sizeof(calls)); + int oldCallCount = intercept_get_calls(oldCalls); - callCount = 0; + intercept_clear_calls(); testpaint_clear_ignore(); memcpy(gSupportSegments, DefaultSegmentHeight, sizeof(support_height) * 9); @@ -636,9 +422,8 @@ static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string error, continue; } - uint8 newCallCount = callCount; function_call newCalls[256]; - memcpy(&newCalls, &calls, sizeof(calls)); + int newCallCount = intercept_get_calls(newCalls); if (!assertFunctionCallArrayEquals(oldCalls, oldCallCount, newCalls, newCallCount)) { utf8string diff = malloc(2048); @@ -724,97 +509,3 @@ bool testTrackPainting(int rideType, int trackType) { return success; } - -static int intercept_draw_6c(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp) { - registers regs = {.eax =eax, .ebx = ebx, .ecx = ecx, .edx = edx, .esi = esi, .edi = edi, .ebp = ebp}; - if ((ebp & 0x03) != get_current_rotation()) { - // Log error - log_error("Ebp is different from current rotation"); - } - - return (int) sub_98196C(ebx, regs.al, regs.cl, regs.di, regs.si, regs.ah, regs.dx, regs.ebp & 0x03); -} - -static int intercept_draw_7c(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp) { - registers regs = {.eax =eax, .ebx = ebx, .ecx = ecx, .edx = edx, .esi = esi, .edi = edi, .ebp = ebp}; - if ((ebp & 0x03) != get_current_rotation()) { - // Log error - log_error("Ebp is different from current rotation"); - } - - rct_xyz16 boundOffset = { - RCT2_GLOBAL(RCT2_ADDRESS_PAINT_BOUNDBOX_OFFSET_X, sint16), - RCT2_GLOBAL(RCT2_ADDRESS_PAINT_BOUNDBOX_OFFSET_Y, sint16), - RCT2_GLOBAL(RCT2_ADDRESS_PAINT_BOUNDBOX_OFFSET_Z, sint16) - }; - - return (int) sub_98197C(ebx, regs.al, regs.cl, regs.di, regs.si, regs.ah, regs.dx, boundOffset.x, boundOffset.y, boundOffset.z, regs.ebp & 0x03); -} - -static int intercept_draw_9c(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp) { - registers regs = {.eax =eax, .ebx = ebx, .ecx = ecx, .edx = edx, .esi = esi, .edi = edi, .ebp = ebp}; - if ((ebp & 0x03) != get_current_rotation()) { - // Log error - log_error("Ebp is different from current rotation"); - } - - rct_xyz16 boundOffset = { - RCT2_GLOBAL(RCT2_ADDRESS_PAINT_BOUNDBOX_OFFSET_X, sint16), - RCT2_GLOBAL(RCT2_ADDRESS_PAINT_BOUNDBOX_OFFSET_Y, sint16), - RCT2_GLOBAL(RCT2_ADDRESS_PAINT_BOUNDBOX_OFFSET_Z, sint16) - }; - - return (int) sub_98199C(ebx, regs.al, regs.cl, regs.di, regs.si, regs.ah, regs.dx, boundOffset.x, boundOffset.y, boundOffset.z, regs.ebp & 0x03); -} - -static uint32 intercept_wooden_a_supports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp) { - registers regs = {.eax =eax, .ebx = ebx, .edx = edx, .edi = edi, .ebp = ebp}; - bool output = wooden_a_supports_paint_setup(regs.edi, (sint16) regs.ax, regs.dx, (uint32) regs.ebp, NULL); - - return output ? 1 : 0; -} - -static uint32 intercept_wooden_b_supports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp) { - registers regs = {.eax =eax, .ebx = ebx, .edx = edx, .edi = edi, .ebp = ebp}; - bool output = wooden_b_supports_paint_setup(regs.edi, (sint16) regs.ax, regs.dx, (uint32) regs.ebp, NULL); - - return output ? 1 : 0; -} - -static uint32 intercept_metal_a_supports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp) { - registers regs = {.eax =eax, .ebx = ebx, .edx = edx, .edi = edi, .ebp = ebp}; - metal_a_supports_paint_setup(regs.edi, regs.ebx, (sint16) regs.ax, regs.dx, (uint32) regs.ebp); - - return 0; -} - -static uint32 intercept_metal_b_supports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp) { - registers regs = {.eax =eax, .ebx = ebx, .edx = edx, .edi = edi, .ebp = ebp}; - metal_b_supports_paint_setup(regs.edi, regs.ebx, (sint16) regs.ax, regs.dx, (uint32) regs.ebp); - - return 0; -} - - -void initHooks() { - addhook(0x00686806, (int) intercept_draw_7c, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x006869B2, (int) intercept_draw_7c, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x00686B6F, (int) intercept_draw_7c, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x00686D31, (int) intercept_draw_7c, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - - addhook(0x006861AC, (int) intercept_draw_6c, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x00686337, (int) intercept_draw_6c, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x006864D0, (int) intercept_draw_6c, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x0068666B, (int) intercept_draw_6c, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - - addhook(0x006874B0, (int) intercept_draw_9c, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x00687618, (int) intercept_draw_9c, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x0068778C, (int) intercept_draw_9c, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x00687902, (int) intercept_draw_9c, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - - addhook(0x006629BC, (int) intercept_wooden_a_supports, 0, (int[]) {EAX, EBX, EDX, EDI, EBP, END}, 0, EAX); - addhook(0x00662D5C, (int) intercept_wooden_b_supports, 0, (int[]) {EAX, EBX, EDX, EDI, EBP, END}, 0, EAX); - - addhook(0x00663105, (int) intercept_metal_a_supports, 0, (int[]) {EAX, EBX, EDX, EDI, EBP, END}, 0, EAX); - addhook(0x00663584, (int) intercept_metal_b_supports, 0, (int[]) {EAX, EBX, EDX, EDI, EBP, END}, 0, EAX); -} diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index 7194042178..fef78af70d 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -85,9 +85,13 @@ extern "C" bool testVerticalTunnels(uint8 rideType, uint8 trackType); void intercept_clear_calls(); int intercept_get_calls(function_call * buffer); + void intercept_simulate_wooden_supports(bool enabled); bool assertFunctionCallEquals(function_call expected, function_call actual); int generatePaintCode(uint8 rideType); + + extern const support_height DefaultSegmentHeight[9]; + #ifdef __cplusplus } #endif From 6642dc534c15d5431713d58f0dc0a2a013ca896a Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sat, 15 Oct 2016 21:51:51 +0200 Subject: [PATCH 02/42] Update Project files --- OpenRCT2.xcodeproj/project.pbxproj | 4 ++++ test/testpaint/testpaint.vcxproj | 1 + 2 files changed, 5 insertions(+) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 8d99a054a8..0d2d58654d 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -114,6 +114,7 @@ C650B21A1CCABBDD00B4D91C /* tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C650B2171CCABBDD00B4D91C /* tables.cpp */; }; C650B21C1CCABC4400B4D91C /* ConvertCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C650B21B1CCABC4400B4D91C /* ConvertCommand.cpp */; }; C6575A371D46AFBA00C3E79F /* debug_paint.c in Sources */ = {isa = PBXBuildFile; fileRef = C6575A361D46AFBA00C3E79F /* debug_paint.c */; }; + C65A9EAF1DB2C01B003C3557 /* PaintIntercept.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C65A9EAE1DB2C01B003C3557 /* PaintIntercept.cpp */; }; C686F8AC1CDBC37E009F9BFC /* banner.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F8981CDBC37E009F9BFC /* banner.c */; }; C686F8AD1CDBC37E009F9BFC /* entrance.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F8991CDBC37E009F9BFC /* entrance.c */; }; C686F8AE1CDBC37E009F9BFC /* fence.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F89A1CDBC37E009F9BFC /* fence.c */; }; @@ -513,6 +514,7 @@ C650B2181CCABBDD00B4D91C /* Tables.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = Tables.h; sourceTree = ""; usesTabs = 0; }; C650B21B1CCABC4400B4D91C /* ConvertCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConvertCommand.cpp; sourceTree = ""; usesTabs = 0; }; C6575A361D46AFBA00C3E79F /* debug_paint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debug_paint.c; sourceTree = ""; }; + C65A9EAE1DB2C01B003C3557 /* PaintIntercept.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PaintIntercept.cpp; sourceTree = ""; }; C686F8981CDBC37E009F9BFC /* banner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = banner.c; sourceTree = ""; }; C686F8991CDBC37E009F9BFC /* entrance.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = entrance.c; sourceTree = ""; }; C686F89A1CDBC37E009F9BFC /* fence.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fence.c; sourceTree = ""; }; @@ -1175,6 +1177,7 @@ C64FDAC71D6DA72400F259B9 /* intercept.c */, 85AFA2101D7DB83E00221B42 /* intercept.h */, 85AFA20F1D7DB83E00221B42 /* main.cpp */, + C65A9EAE1DB2C01B003C3557 /* PaintIntercept.cpp */, ); name = Paint; path = test/testpaint; @@ -2444,6 +2447,7 @@ C64FDAAC1D6D9A2100F259B9 /* splash_boats.c in Sources */, C64FDAAD1D6D9A2100F259B9 /* submarine_ride.c in Sources */, C64FDAAE1D6D9A2100F259B9 /* water_coaster.c in Sources */, + C65A9EAF1DB2C01B003C3557 /* PaintIntercept.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/test/testpaint/testpaint.vcxproj b/test/testpaint/testpaint.vcxproj index 76e617c82a..999ff6c09b 100644 --- a/test/testpaint/testpaint.vcxproj +++ b/test/testpaint/testpaint.vcxproj @@ -99,6 +99,7 @@ + From a552a801657bf43c819505b4e3fd7c5d1db7228e Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 15:00:59 +0200 Subject: [PATCH 03/42] Attempt to fix msvc compatibility --- test/testpaint/PaintIntercept.cpp | 116 ++++++++++++++---------------- 1 file changed, 53 insertions(+), 63 deletions(-) diff --git a/test/testpaint/PaintIntercept.cpp b/test/testpaint/PaintIntercept.cpp index ebaa33cee3..ed6412d25c 100644 --- a/test/testpaint/PaintIntercept.cpp +++ b/test/testpaint/PaintIntercept.cpp @@ -26,43 +26,42 @@ extern "C" { class PaintInterceptor { public: static void InitHooks() { - addhook(0x006629BC, (int) InterceptWoodenASupports, 0, (int[]) {EAX, EBX, EDX, EDI, EBP, END}, 0, EAX); - addhook(0x00662D5C, (int) InterceptWoodenBSupports, 0, (int[]) {EAX, EBX, EDX, EDI, EBP, END}, 0, EAX); + int supportsRegisterArgs[] = {EAX, EBX, EDX, EDI, EBP, END}; + addhook(0x006629BC, (int) InterceptWoodenASupports, 0, supportsRegisterArgs, 0, EAX); + addhook(0x00662D5C, (int) InterceptWoodenBSupports, 0, supportsRegisterArgs, 0, EAX); - addhook(0x00663105, (int) InterceptMetalASupports, 0, (int[]) {EAX, EBX, EDX, EDI, EBP, END}, 0, EAX); - addhook(0x00663584, (int) InterceptMetalBSupports, 0, (int[]) {EAX, EBX, EDX, EDI, EBP, END}, 0, EAX); + addhook(0x00663105, (int) InterceptMetalASupports, 0, supportsRegisterArgs, 0, EAX); + addhook(0x00663584, (int) InterceptMetalBSupports, 0, supportsRegisterArgs, 0, EAX); - addhook(0x006861AC, (int) InterceptPaint6C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x00686337, (int) InterceptPaint6C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x006864D0, (int) InterceptPaint6C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x0068666B, (int) InterceptPaint6C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + int paintRegisterArgs[] = {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}; + addhook(0x006861AC, (int) InterceptPaint6C, 0, paintRegisterArgs, 0, EBP); + addhook(0x00686337, (int) InterceptPaint6C, 0, paintRegisterArgs, 0, EBP); + addhook(0x006864D0, (int) InterceptPaint6C, 0, paintRegisterArgs, 0, EBP); + addhook(0x0068666B, (int) InterceptPaint6C, 0, paintRegisterArgs, 0, EBP); - addhook(0x00686806, (int) InterceptPaint7C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x006869B2, (int) InterceptPaint7C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x00686B6F, (int) InterceptPaint7C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x00686D31, (int) InterceptPaint7C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x00686806, (int) InterceptPaint7C, 0, paintRegisterArgs, 0, EBP); + addhook(0x006869B2, (int) InterceptPaint7C, 0, paintRegisterArgs, 0, EBP); + addhook(0x00686B6F, (int) InterceptPaint7C, 0, paintRegisterArgs, 0, EBP); + addhook(0x00686D31, (int) InterceptPaint7C, 0, paintRegisterArgs, 0, EBP); - addhook(0x00686EF0, (int) InterceptPaint8C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x00687056, (int) InterceptPaint8C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x006871C8, (int) InterceptPaint8C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x0068733C, (int) InterceptPaint8C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x00686EF0, (int) InterceptPaint8C, 0, paintRegisterArgs, 0, EBP); + addhook(0x00687056, (int) InterceptPaint8C, 0, paintRegisterArgs, 0, EBP); + addhook(0x006871C8, (int) InterceptPaint8C, 0, paintRegisterArgs, 0, EBP); + addhook(0x0068733C, (int) InterceptPaint8C, 0, paintRegisterArgs, 0, EBP); - addhook(0x006874B0, (int) InterceptPaint9C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x00687618, (int) InterceptPaint9C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x0068778C, (int) InterceptPaint9C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); - addhook(0x00687902, (int) InterceptPaint9C, 0, (int[]) {EAX, EBX, ECX, EDX, ESI, EDI, EBP, END}, 0, EBP); + addhook(0x006874B0, (int) InterceptPaint9C, 0, paintRegisterArgs, 0, EBP); + addhook(0x00687618, (int) InterceptPaint9C, 0, paintRegisterArgs, 0, EBP); + addhook(0x0068778C, (int) InterceptPaint9C, 0, paintRegisterArgs, 0, EBP); + addhook(0x00687902, (int) InterceptPaint9C, 0, paintRegisterArgs, 0, EBP); } static bool PaintWoodenSupports(uint8 function, int supportType, int special, int height, uint32 imageColourFlags, bool *underground) { - function_call call = { - .function = function, - .supports = { - .type = supportType, - .special = special, - .height = height, - .colour_flags = imageColourFlags, - } - }; + function_call call = {0}; + call.function = function; + call.supports.type = supportType; + call.supports.special = special; + call.supports.height = height; + call.supports.colour_flags = imageColourFlags; _calls[_callCount] = call; _callCount++; @@ -73,19 +72,17 @@ public: static bool PaintMetalSupports(uint8 function, int supportType, uint8 segment, int special, int height, uint32 imageColourFlags) { CheckSegmentSupportHeight(); - function_call call = { - .function = function, - .supports = { - .type = supportType, - .segment = segment, - .special = special, - .height = height, - .colour_flags = imageColourFlags, - } - }; + function_call call = {0}; + call.function = function; + call.supports.type = supportType; + call.supports.segment = segment; + call.supports.special = special; + call.supports.height = height; + call.supports.colour_flags = imageColourFlags; _calls[_callCount] = call; _callCount++; + return false; } @@ -96,16 +93,13 @@ public: sint16 zOffset, uint32 rotation ) { - function_call call = { - .function = PAINT_98196C, - .paint = { - .image_id = imageID, - .offset = {xOffset, yOffset}, - .bound_box_length = {boundBoxLengthX, boundBoxLengthY, boundBoxLengthZ}, - .z_offset = zOffset, - .rotation = rotation - }, - }; + function_call call = {0}; + call.function = PAINT_98196C; + call.paint.image_id = imageID; + call.paint.offset = {xOffset, yOffset}; + call.paint.bound_box_length = {boundBoxLengthX, boundBoxLengthY, boundBoxLengthZ}; + call.paint.z_offset = zOffset; + call.paint.rotation = rotation; _calls[_callCount] = call; _callCount++; @@ -122,17 +116,14 @@ public: sint16 boundBoxOffsetX, sint16 boundBoxOffsetY, sint16 boundBoxOffsetZ, uint32 rotation ) { - function_call call = { - .function = function, - .paint = { - .image_id = imageID, - .offset = {xOffset, yOffset}, - .bound_box_length = {boundBoxLengthX, boundBoxLengthY, boundBoxLengthZ}, - .bound_box_offset = {boundBoxOffsetX, boundBoxOffsetY, boundBoxOffsetZ}, - .z_offset = zOffset, - .rotation = rotation - }, - }; + function_call call = {0}; + call.function = function; + call.paint.image_id = imageID; + call.paint.offset = {xOffset, yOffset}; + call.paint.bound_box_length = {boundBoxLengthX, boundBoxLengthY, boundBoxLengthZ}; + call.paint.bound_box_offset = {boundBoxOffsetX, boundBoxOffsetY, boundBoxOffsetZ}; + call.paint.z_offset = zOffset; + call.paint.rotation = rotation; _calls[_callCount] = call; _callCount++; @@ -179,9 +170,8 @@ private: } - function_call call = { - .function = SET_SEGMENT_HEIGHT - }; + function_call call = {0}; + call.function = SET_SEGMENT_HEIGHT; _calls[_callCount] = call; _callCount++; From 486d9da0a065a406ab22cb1e56849458dfcca181 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 15:49:04 +0200 Subject: [PATCH 04/42] Extract environment resetting --- test/testpaint/generate.cpp | 30 +--------- test/testpaint/intercept.c | 20 +------ test/testpaint/intercept.h | 1 + test/testpaint/intercept_2.cpp | 100 +++++++++++++-------------------- 4 files changed, 43 insertions(+), 108 deletions(-) diff --git a/test/testpaint/generate.cpp b/test/testpaint/generate.cpp index 417774d751..82ca6c5d69 100644 --- a/test/testpaint/generate.cpp +++ b/test/testpaint/generate.cpp @@ -1004,35 +1004,7 @@ private: void CallOriginal(int trackType, int direction, int trackSequence, int height, rct_map_element *mapElement) { - gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE; - gTrackColours[SCHEME_TRACK] = Intercept2::DEFAULT_SCHEME_TRACK; - gTrackColours[SCHEME_SUPPORTS] = Intercept2::DEFAULT_SCHEME_SUPPORTS; - gTrackColours[SCHEME_MISC] = Intercept2::DEFAULT_SCHEME_MISC; - gTrackColours[SCHEME_3] = Intercept2::DEFAULT_SCHEME_3; - - rct_drawpixelinfo dpi = { 0 }; - dpi.zoom_level = 1; - unk_140E9A8 = &dpi; - - rct_ride ride = {0}; - - rct_ride_entry rideEntry = {0}; - rct_ride_entry_vehicle vehicleEntry { 0 }; - vehicleEntry.base_image_id = 0x70000; - rideEntry.vehicles[0] = vehicleEntry; - - gRideList[0] = ride; - gRideEntries[0] = &rideEntry; - - for (int s = 0; s < 9; ++s) - { - gSupportSegments[s].height = 0; - gSupportSegments[s].slope = 0xFF; - } - - gSupport.height = 0; - gSupport.slope = 0xFF; - g141E9DB = G141E9DB_FLAG_1 | G141E9DB_FLAG_2; + intercept_reset_environment(); uint32 *trackDirectionList = (uint32 *)RideTypeTrackPaintFunctionsOld[_rideType][trackType]; // Have to call from this point as it pushes esi and expects callee to pop it diff --git a/test/testpaint/intercept.c b/test/testpaint/intercept.c index f628050f9b..85b99193fd 100644 --- a/test/testpaint/intercept.c +++ b/test/testpaint/intercept.c @@ -332,25 +332,7 @@ static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string error, surfaceElement.type = MAP_ELEMENT_TYPE_SURFACE; surfaceElement.base_height = 2; - gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE; - gTrackColours[SCHEME_TRACK] = DEFAULT_SCHEME_TRACK; - gTrackColours[SCHEME_SUPPORTS] = DEFAULT_SCHEME_SUPPORTS; - gTrackColours[SCHEME_MISC] = DEFAULT_SCHEME_MISC; - gTrackColours[SCHEME_3] = DEFAULT_SCHEME_3; - - rct_drawpixelinfo dpi = {.zoom_level = 1}; - unk_140E9A8 = &dpi; - - rct_ride ride = { 0 }; - ride.entrance_style = RIDE_ENTRANCE_STYLE_CANVAS_TENT; - - rct_ride_entry rideEntry = { 0 }; - rct_ride_entry_vehicle vehicleEntry = {.base_image_id = 0x70000}; - rideEntry.vehicles[0] = vehicleEntry; - - - gRideList[0] = ride; - gRideEntries[0] = &rideEntry; + intercept_reset_environment(); int height = 48; diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index fef78af70d..064c30f78c 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -85,6 +85,7 @@ extern "C" bool testVerticalTunnels(uint8 rideType, uint8 trackType); void intercept_clear_calls(); int intercept_get_calls(function_call * buffer); + void intercept_reset_environment(); void intercept_simulate_wooden_supports(bool enabled); bool assertFunctionCallEquals(function_call expected, function_call actual); diff --git a/test/testpaint/intercept_2.cpp b/test/testpaint/intercept_2.cpp index 3d087ff458..b27b80dca7 100644 --- a/test/testpaint/intercept_2.cpp +++ b/test/testpaint/intercept_2.cpp @@ -29,6 +29,39 @@ extern "C" { namespace Intercept2 { + static void ResetEnvironment() { + gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE; + gTrackColours[SCHEME_TRACK] = DEFAULT_SCHEME_TRACK; + gTrackColours[SCHEME_SUPPORTS] = DEFAULT_SCHEME_SUPPORTS; + gTrackColours[SCHEME_MISC] = DEFAULT_SCHEME_MISC; + gTrackColours[SCHEME_3] = DEFAULT_SCHEME_3; + + rct_drawpixelinfo dpi = { 0 }; + dpi.zoom_level = 1; + unk_140E9A8 = &dpi; + + rct_ride ride = {0}; + ride.entrance_style = RIDE_ENTRANCE_STYLE_PLAIN; + + rct_ride_entry rideEntry = {0}; + rct_ride_entry_vehicle vehicleEntry { 0 }; + vehicleEntry.base_image_id = 0x70000; + rideEntry.vehicles[0] = vehicleEntry; + + gRideList[0] = ride; + gRideEntries[0] = &rideEntry; + + for (int s = 0; s < 9; ++s) + { + gSupportSegments[s].height = 0; + gSupportSegments[s].slope = 0xFF; + } + + gSupport.height = 0; + gSupport.slope = 0xFF; + g141E9DB = G141E9DB_FLAG_1 | G141E9DB_FLAG_2; + } + static bool SortSegmentSupportCalls(SegmentSupportCall lhs, SegmentSupportCall rhs) { if (lhs.height != rhs.height) { @@ -297,26 +330,7 @@ namespace Intercept2 surfaceElement.type = MAP_ELEMENT_TYPE_SURFACE; surfaceElement.base_height = 2; - gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE; - gTrackColours[SCHEME_TRACK] = DEFAULT_SCHEME_TRACK; - gTrackColours[SCHEME_SUPPORTS] = DEFAULT_SCHEME_SUPPORTS; - gTrackColours[SCHEME_MISC] = DEFAULT_SCHEME_MISC; - gTrackColours[SCHEME_3] = DEFAULT_SCHEME_3; - - rct_drawpixelinfo dpi = { 0 }; - dpi.zoom_level = 1; - unk_140E9A8 = &dpi; - - rct_ride ride = {0}; - - rct_ride_entry rideEntry = {0}; - rct_ride_entry_vehicle vehicleEntry { 0 }; - vehicleEntry.base_image_id = 0x70000; - rideEntry.vehicles[0] = vehicleEntry; - - - gRideList[0] = ride; - gRideEntries[0] = &rideEntry; + ResetEnvironment(); int height = 48; @@ -497,26 +511,7 @@ namespace Intercept2 g_currently_drawn_item = &mapElement; - gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE; - gTrackColours[SCHEME_TRACK] = DEFAULT_SCHEME_TRACK; - gTrackColours[SCHEME_SUPPORTS] = DEFAULT_SCHEME_SUPPORTS; - gTrackColours[SCHEME_MISC] = DEFAULT_SCHEME_MISC; - gTrackColours[SCHEME_3] = DEFAULT_SCHEME_3; - - rct_drawpixelinfo dpi { 0 }; - dpi.zoom_level = 1; - unk_140E9A8 = &dpi; - - rct_ride ride = {0}; - - rct_ride_entry rideEntry = {0}; - rct_ride_entry_vehicle vehicleEntry { 0 }; - vehicleEntry.base_image_id = 0x70000; - rideEntry.vehicles[0] = vehicleEntry; - - - gRideList[0] = ride; - gRideEntries[0] = &rideEntry; + ResetEnvironment(); int height = 48; @@ -689,26 +684,7 @@ namespace Intercept2 g_currently_drawn_item = &mapElement; - gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE; - gTrackColours[SCHEME_TRACK] = DEFAULT_SCHEME_TRACK; - gTrackColours[SCHEME_SUPPORTS] = DEFAULT_SCHEME_SUPPORTS; - gTrackColours[SCHEME_MISC] = DEFAULT_SCHEME_MISC; - gTrackColours[SCHEME_3] = DEFAULT_SCHEME_3; - - rct_drawpixelinfo dpi = { 0 }; - dpi.zoom_level = 1; - unk_140E9A8 = &dpi; - - rct_ride ride = {0}; - - rct_ride_entry rideEntry = {0}; - rct_ride_entry_vehicle vehicleEntry = { 0 }; - vehicleEntry.base_image_id = 0x70000; - rideEntry.vehicles[0] = vehicleEntry; - - - gRideList[0] = ride; - gRideEntries[0] = &rideEntry; + ResetEnvironment(); int height = 48; @@ -869,4 +845,8 @@ extern "C" { return Intercept2::testIsIgnored(direction, trackSequence); } + + void intercept_reset_environment() { + Intercept2::ResetEnvironment(); + } } From 70654e9ee540617eb150fb7c8a956ae73e8b7e65 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 16:06:18 +0200 Subject: [PATCH 05/42] Extract tunnel/segment resetting --- src/paint/map_element/map_element.c | 4 +-- src/paint/map_element/map_element.h | 6 ++-- src/paint/map_element/surface.c | 24 +++++++------- test/testpaint/generate.cpp | 5 +-- test/testpaint/intercept.c | 7 ++--- test/testpaint/intercept.h | 2 ++ test/testpaint/intercept_2.cpp | 49 +++++++++++++++++++---------- 7 files changed, 58 insertions(+), 39 deletions(-) diff --git a/src/paint/map_element/map_element.c b/src/paint/map_element/map_element.c index ec1cfd940b..d6dccbfec6 100644 --- a/src/paint/map_element/map_element.c +++ b/src/paint/map_element/map_element.c @@ -38,9 +38,9 @@ uint16 gUnk141E9DC; rct_xy16 gPaintMapPosition; bool gDidPassSurface; rct_map_element * gSurfaceElement; -tunnel_entry gLeftTunnels[65]; +tunnel_entry gLeftTunnels[TUNNEL_MAX_COUNT]; uint8 gLeftTunnelCount; -tunnel_entry gRightTunnels[65]; +tunnel_entry gRightTunnels[TUNNEL_MAX_COUNT]; uint8 gRightTunnelCount; uint8 gVerticalTunnelHeight; #endif diff --git a/src/paint/map_element/map_element.h b/src/paint/map_element/map_element.h index d1065c32ad..e2e7580ec8 100644 --- a/src/paint/map_element/map_element.h +++ b/src/paint/map_element/map_element.h @@ -80,15 +80,17 @@ enum G141E9DB_FLAG_2 = 2, }; +#define TUNNEL_MAX_COUNT 65 + #ifdef NO_RCT2 extern uint8 g141E9DB; extern uint16 gUnk141E9DC; extern rct_xy16 gPaintMapPosition; extern bool gDidPassSurface; extern rct_map_element * gSurfaceElement; -extern tunnel_entry gLeftTunnels[65]; +extern tunnel_entry gLeftTunnels[TUNNEL_MAX_COUNT]; extern uint8 gLeftTunnelCount; -extern tunnel_entry gRightTunnels[65]; +extern tunnel_entry gRightTunnels[TUNNEL_MAX_COUNT]; extern uint8 gRightTunnelCount; extern uint8 gVerticalTunnelHeight; #else diff --git a/src/paint/map_element/surface.c b/src/paint/map_element/surface.c index e45e672984..0f9f9965d6 100644 --- a/src/paint/map_element/surface.c +++ b/src/paint/map_element/surface.c @@ -632,7 +632,7 @@ static void viewport_surface_draw_land_side_bottom(enum edge edge, uint8 height, // Normal walls while (curHeight > tunnelArray[0].height) { // TODO: Should probably be done by just keeping track of the current index - memmove(&tunnelArray[0], &tunnelArray[1], sizeof(tunnel_entry) * 64); + memmove(&tunnelArray[0], &tunnelArray[1], sizeof(tunnel_entry) * (TUNNEL_MAX_COUNT - 1)); } if (curHeight != tunnelArray[0].height) { @@ -680,7 +680,7 @@ static void viewport_surface_draw_land_side_bottom(enum edge edge, uint8 height, curHeight += stru_97B570[tunnelType][0]; // TODO: Should probably be done by just keeping track of the current index - memmove(&tunnelArray[0], &tunnelArray[1], sizeof(tunnel_entry) * 64); + memmove(&tunnelArray[0], &tunnelArray[1], sizeof(tunnel_entry) * (TUNNEL_MAX_COUNT - 1)); } } @@ -902,7 +902,7 @@ static void viewport_surface_draw_water_side_bottom(enum edge edge, uint8 height // Normal walls while (curHeight > tunnelArray[0].height) { // TODO: Should probably be done by just keeping track of the current index - memmove(&tunnelArray[0], &tunnelArray[1], sizeof(tunnel_entry) * 64); + memmove(&tunnelArray[0], &tunnelArray[1], sizeof(tunnel_entry) * (TUNNEL_MAX_COUNT - 1)); } sub_98196C(base_image_id, offset.x, offset.y, bounds.x, bounds.y, 15, curHeight * 16, rotation); @@ -948,7 +948,7 @@ static void viewport_surface_draw_water_side_bottom(enum edge edge, uint8 height curHeight += stru_97B570[tunnelType][0]; // TODO: Should probably be done by just keeping track of the current index - memmove(&tunnelArray[0], &tunnelArray[1], sizeof(tunnel_entry) * 64); + memmove(&tunnelArray[0], &tunnelArray[1], sizeof(tunnel_entry) * (TUNNEL_MAX_COUNT - 1)); } } @@ -1312,18 +1312,18 @@ void surface_paint(uint8 direction, uint16 height, rct_map_element * mapElement) log_verbose("eax: %d", eax); } - tunnel_entry backupLeftTunnels[65]; - tunnel_entry backupRightTunnels[65]; + tunnel_entry backupLeftTunnels[TUNNEL_MAX_COUNT]; + tunnel_entry backupRightTunnels[TUNNEL_MAX_COUNT]; #ifdef __MINGW32__ // The other code crashes mingw 4.8.2, as available on Travis - for (int i = 0; i < 65; i++) { + for (int i = 0; i < TUNNEL_MAX_COUNT; i++) { backupLeftTunnels[i] = gLeftTunnels[i]; backupRightTunnels[i] = gRightTunnels[i]; } #else - memcpy(backupLeftTunnels, gLeftTunnels, sizeof(tunnel_entry) * 65); - memcpy(backupRightTunnels, gRightTunnels, sizeof(tunnel_entry) * 65); + memcpy(backupLeftTunnels, gLeftTunnels, sizeof(tunnel_entry) * TUNNEL_MAX_COUNT); + memcpy(backupRightTunnels, gRightTunnels, sizeof(tunnel_entry) * TUNNEL_MAX_COUNT); #endif viewport_surface_draw_land_side_top(EDGE_TOPLEFT, height / 16, eax / 32, tileDescriptors[0], tileDescriptors[3]); @@ -1334,13 +1334,13 @@ void surface_paint(uint8 direction, uint16 height, rct_map_element * mapElement) #ifdef __MINGW32__ // The other code crashes mingw 4.8.2, as available on Travis - for (int i = 0; i < 65; i++) { + for (int i = 0; i < TUNNEL_MAX_COUNT; i++) { gLeftTunnels[i] = backupLeftTunnels[i]; gRightTunnels[i] = backupRightTunnels[i]; } #else - memcpy(gLeftTunnels, backupLeftTunnels, sizeof(tunnel_entry) * 65); - memcpy(gRightTunnels, backupRightTunnels, sizeof(tunnel_entry) * 65); + memcpy(gLeftTunnels, backupLeftTunnels, sizeof(tunnel_entry) * TUNNEL_MAX_COUNT); + memcpy(gRightTunnels, backupRightTunnels, sizeof(tunnel_entry) * TUNNEL_MAX_COUNT); #endif } diff --git a/test/testpaint/generate.cpp b/test/testpaint/generate.cpp index 82ca6c5d69..64265577b7 100644 --- a/test/testpaint/generate.cpp +++ b/test/testpaint/generate.cpp @@ -737,8 +737,8 @@ private: Intercept2::TunnelCall tileTunnelCalls[4][4], sint16 verticalTunnelHeights[4]) { - gLeftTunnelCount = 0; - gRightTunnelCount = 0; + intercept_reset_tunnels(); + for (int offset = -8; offset <= 8; offset += 8) { CallOriginal(trackType, direction, trackSequence, height + offset, mapElement); @@ -1005,6 +1005,7 @@ private: void CallOriginal(int trackType, int direction, int trackSequence, int height, rct_map_element *mapElement) { intercept_reset_environment(); + intercept_reset_segment_heights(); uint32 *trackDirectionList = (uint32 *)RideTypeTrackPaintFunctionsOld[_rideType][trackType]; // Have to call from this point as it pushes esi and expects callee to pop it diff --git a/test/testpaint/intercept.c b/test/testpaint/intercept.c index 85b99193fd..bdbc027f47 100644 --- a/test/testpaint/intercept.c +++ b/test/testpaint/intercept.c @@ -368,11 +368,9 @@ static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string error, RCT2_GLOBAL(0x009DE56E, sint16) = 64; // y gDidPassSurface = true; // Above surface gSurfaceElement = &surfaceElement; - g141E9DB = G141E9DB_FLAG_1 | G141E9DB_FLAG_2; intercept_clear_calls(); - - memcpy(gSupportSegments, DefaultSegmentHeight, sizeof(support_height) * 9); + intercept_reset_segment_heights(); uint32 *trackDirectionList = (uint32 *)RideTypeTrackPaintFunctionsOld[rideType][trackType]; @@ -396,7 +394,8 @@ static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string error, intercept_clear_calls(); testpaint_clear_ignore(); - memcpy(gSupportSegments, DefaultSegmentHeight, sizeof(support_height) * 9); + intercept_reset_segment_heights(); + newPaintFunction(rideIndex, trackSequence, direction, height, &mapElement); if (testpaint_is_ignored(direction, trackSequence)) { snprintf(error, len, "[ IGNORED ] [direction:%d trackSequence:%d chainLift:%d inverted:%d]\n", diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index 064c30f78c..6b5e9dbc51 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -86,6 +86,8 @@ extern "C" void intercept_clear_calls(); int intercept_get_calls(function_call * buffer); void intercept_reset_environment(); + void intercept_reset_segment_heights(); + void intercept_reset_tunnels(); void intercept_simulate_wooden_supports(bool enabled); bool assertFunctionCallEquals(function_call expected, function_call actual); diff --git a/test/testpaint/intercept_2.cpp b/test/testpaint/intercept_2.cpp index b27b80dca7..eb0c81b340 100644 --- a/test/testpaint/intercept_2.cpp +++ b/test/testpaint/intercept_2.cpp @@ -51,6 +51,23 @@ namespace Intercept2 gRideList[0] = ride; gRideEntries[0] = &rideEntry; + g141E9DB = G141E9DB_FLAG_1 | G141E9DB_FLAG_2; + } + + static void ResetTunnels() { + gLeftTunnelCount = 0; + gRightTunnelCount = 0; + + for (int i = 0; i < TUNNEL_MAX_COUNT; i++) { + gLeftTunnels[i] = (tunnel_entry) {0, 0}; + gRightTunnels[i] = (tunnel_entry) {0, 0}; + } + + gLeftTunnels[0] = (tunnel_entry) {0xFF, 0xFF}; + gRightTunnels[0] = (tunnel_entry) {0xFF, 0xFF}; + } + + static void ResetSegmentHeights() { for (int s = 0; s < 9; ++s) { gSupportSegments[s].height = 0; @@ -59,7 +76,6 @@ namespace Intercept2 gSupport.height = 0; gSupport.slope = 0xFF; - g141E9DB = G141E9DB_FLAG_1 | G141E9DB_FLAG_2; } static bool SortSegmentSupportCalls(SegmentSupportCall lhs, SegmentSupportCall rhs) @@ -331,6 +347,7 @@ namespace Intercept2 surfaceElement.base_height = 2; ResetEnvironment(); + ResetTunnels(); int height = 48; @@ -349,14 +366,7 @@ namespace Intercept2 SupportCall tileGeneralSupportCalls[4]; for (int direction = 0; direction < 4; direction++) { - for (int s = 0; s < 9; ++s) { - gSupportSegments[s].height = 0; - gSupportSegments[s].slope = 0xFF; - } - - gSupport.height = 0; - gSupport.slope = 0xFF; - g141E9DB = G141E9DB_FLAG_1 | G141E9DB_FLAG_2; + ResetSegmentHeights(); uint32 *trackDirectionList = (uint32 *)RideTypeTrackPaintFunctionsOld[rideType][trackType]; @@ -391,10 +401,7 @@ namespace Intercept2 } for (int direction = 0; direction < 4; direction++) { - for (int s = 0; s < 9; ++s) { - gSupportSegments[s].height = 0; - gSupportSegments[s].slope = 0xFF; - } + ResetSegmentHeights(); testpaint_clear_ignore(); TRACK_PAINT_FUNCTION newPaintFunction = newPaintGetter(trackType, direction); @@ -438,8 +445,7 @@ namespace Intercept2 for (int direction = 0; direction < 4; direction++) { - gSupport.height = 0; - gSupport.slope = 0xFF; + ResetSegmentHeights(); testpaint_clear_ignore(); TRACK_PAINT_FUNCTION newPaintFunction = newPaintGetter(trackType, direction); @@ -523,8 +529,7 @@ namespace Intercept2 TunnelCall tileTunnelCalls[4][4]; for (int direction = 0; direction < 4; direction++) { - gLeftTunnelCount = 0; - gRightTunnelCount = 0; + ResetTunnels(); uint32 *trackDirectionList = (uint32 *)RideTypeTrackPaintFunctionsOld[rideType][trackType]; @@ -849,4 +854,14 @@ extern "C" void intercept_reset_environment() { Intercept2::ResetEnvironment(); } + + void intercept_reset_segment_heights() { + Intercept2::ResetSegmentHeights(); + } + + void intercept_reset_tunnels() { + Intercept2::ResetTunnels(); + } + + } From d6772865f5353c6b43410088b36050d1c747f2dc Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 16:30:02 +0200 Subject: [PATCH 06/42] Use return codes for test results --- test/testpaint/intercept.c | 27 ++++++++++++++------------- test/testpaint/intercept.h | 8 +++++++- test/testpaint/main.cpp | 38 +++++++++++++++++++++++++++----------- 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/test/testpaint/intercept.c b/test/testpaint/intercept.c index bdbc027f47..14c22d5efd 100644 --- a/test/testpaint/intercept.c +++ b/test/testpaint/intercept.c @@ -312,14 +312,14 @@ extern bool testTunnels(uint8 rideType, uint8 trackType); extern bool testVerticalTunnels(uint8 rideType, uint8 trackType); -static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string error, size_t len) { +static uint8 testTrackElement(uint8 rideType, uint8 trackType, utf8string error, size_t len) { if (rideType == RIDE_TYPE_CHAIRLIFT) { if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION || trackType == TRACK_ELEM_END_STATION) { - // These rides chechk neighbouring tiles for tracks - snprintf(error, len, "Skipped"); - return false; + // These rides check neighbouring tiles for tracks + return TEST_SKIPPED; } } + uint8 rideIndex = 0; rct_map_element mapElement = { 0 }; mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; @@ -439,7 +439,7 @@ static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string error, free(diff); - return false; + return TEST_FAILED; } } @@ -451,19 +451,20 @@ static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string error, bool segmentSuccess = testSupportSegments(rideType, trackType); if (!segmentSuccess) { - return false; + return TEST_FAILED; } bool tunnelSuccess = testTunnels(rideType, trackType); if (!tunnelSuccess) { - return false; + return TEST_FAILED; } bool verticalTunnelSuccess = testVerticalTunnels(rideType, trackType); if (!verticalTunnelSuccess) { - return false; + return TEST_FAILED; } - return true; + + return TEST_SUCCESS; } bool rideIsImplemented(int rideType) { @@ -471,7 +472,7 @@ bool rideIsImplemented(int rideType) { return (newPaintGetter != 0); } -bool testTrackPainting(int rideType, int trackType) { +uint8 testTrackPainting(int rideType, int trackType) { TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; if (newPaintGetter == NULL) { return false; @@ -482,11 +483,11 @@ bool testTrackPainting(int rideType, int trackType) { } utf8string error = malloc(2048); - bool success = testTrackElement(rideType, trackType, error, 2048); - if (!success) { + int retVal = testTrackElement(rideType, trackType, error, 2048); + if (retVal != TEST_SUCCESS) { printf("%s\n", error); } free(error); - return success; + return retVal; } diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index 6b5e9dbc51..7662e4ce61 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -48,6 +48,12 @@ enum SET_SEGMENT_HEIGHT, }; +enum { + TEST_SUCCESS, + TEST_FAILED, + TEST_SKIPPED, +}; + typedef struct { uint8 function; @@ -79,7 +85,7 @@ extern "C" int getTrackSequenceCount(uint8 rideType, uint8 trackType); bool rideIsImplemented(int rideType); bool rideSupportsTrackType(int rideType, int trackType); - bool testTrackPainting(int rideType, int trackType); + uint8 testTrackPainting(int rideType, int trackType); bool testSupportSegments(uint8 rideType, uint8 trackType); bool testTunnels(uint8 rideType, uint8 trackType); bool testVerticalTunnels(uint8 rideType, uint8 trackType); diff --git a/test/testpaint/main.cpp b/test/testpaint/main.cpp index 6f23dbb827..03ad2e40ae 100644 --- a/test/testpaint/main.cpp +++ b/test/testpaint/main.cpp @@ -42,6 +42,7 @@ typedef struct { enum CLIColour { DEFAULT, RED, + YELLOW, GREEN, }; @@ -96,6 +97,8 @@ static const char* GetAnsiColorCode(CLIColour color) { switch (color) { case RED: return "1"; case GREEN: return "2"; + case YELLOW: + return "3"; default: return NULL; }; } @@ -114,6 +117,7 @@ static WORD GetWindowsConsoleAttribute(CLIColour color, WORD defaultAttr) switch (color) { case RED: return FOREGROUND_RED; case GREEN: return FOREGROUND_GREEN; + case YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; default: return defaultAttr; }; } @@ -444,18 +448,30 @@ int main(int argc, char *argv[]) { ColouredPrintF(CLIColour::GREEN, "[ RUN ] "); printf("%s.%s\n", rideTypeName, trackTypeName); - bool success = testTrackPainting(tc.rideType, trackType); - if (!success) { - utf8string testCaseName = new utf8[64]; - snprintf(testCaseName, 64, "%s.%s", rideTypeName, trackTypeName); + int retVal = testTrackPainting(tc.rideType, trackType); + switch (retVal) { + case TEST_SUCCESS: + ColouredPrintF(CLIColour::GREEN, "[ OK ] "); + printf("%s.%s (0 ms)\n", rideTypeName, trackTypeName); + successCount++; + break; - ColouredPrintF(CLIColour::RED, "[ FAILED ] "); - printf("%s (0 ms)\n", testCaseName); - failures.push_back(testCaseName); - } else { - ColouredPrintF(CLIColour::GREEN, "[ OK ] "); - printf("%s.%s (0 ms)\n", rideTypeName, trackTypeName); - successCount++; + case TEST_SKIPPED: + printf("Skipped\n"); + // Outputting this as OK because CLion only allows FAILED or OK + ColouredPrintF(CLIColour::YELLOW, "[ OK ] "); + printf("%s.%s (0 ms)\n", rideTypeName, trackTypeName); + successCount++; + break; + + case TEST_FAILED: + utf8string testCaseName = new utf8[64]; + snprintf(testCaseName, 64, "%s.%s", rideTypeName, trackTypeName); + + ColouredPrintF(CLIColour::RED, "[ FAILED ] "); + printf("%s (0 ms)\n", testCaseName); + failures.push_back(testCaseName); + break; } } From 28db02885de921d624358454d20bd2a9826466da Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 18:18:54 +0200 Subject: [PATCH 07/42] Extract function printing --- OpenRCT2.xcodeproj/project.pbxproj | 4 + test/testpaint/Printer.cpp | 150 +++++++++++++++++++++++++++++ test/testpaint/intercept.c | 107 +------------------- test/testpaint/intercept.h | 1 + test/testpaint/testpaint.vcxproj | 1 + 5 files changed, 160 insertions(+), 103 deletions(-) create mode 100644 test/testpaint/Printer.cpp diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 0d2d58654d..006a16790a 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -207,6 +207,7 @@ C686F9581CDBC4C7009F9BFC /* vehicle_paint.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F9561CDBC4C7009F9BFC /* vehicle_paint.c */; }; C6B5A7D41CDFE4CB00C9C006 /* S6Exporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6B5A7D01CDFE4CB00C9C006 /* S6Exporter.cpp */; }; C6B5A7D51CDFE4CB00C9C006 /* S6Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6B5A7D21CDFE4CB00C9C006 /* S6Importer.cpp */; }; + C6BDA02B1DB3DFD600271C0A /* Printer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6BDA0291DB3DFC900271C0A /* Printer.cpp */; }; D41B73EF1C2101890080A7B9 /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B73EE1C2101890080A7B9 /* libcurl.tbd */; }; D41B741D1C210A7A0080A7B9 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B741C1C210A7A0080A7B9 /* libiconv.tbd */; }; D41B74731C2125E50080A7B9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D41B74721C2125E50080A7B9 /* Assets.xcassets */; }; @@ -615,6 +616,7 @@ C6B5A7D11CDFE4CB00C9C006 /* S6Exporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = S6Exporter.h; sourceTree = ""; }; C6B5A7D21CDFE4CB00C9C006 /* S6Importer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = S6Importer.cpp; sourceTree = ""; }; C6B5A7D31CDFE4CB00C9C006 /* S6Importer.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = S6Importer.h; sourceTree = ""; }; + C6BDA0291DB3DFC900271C0A /* Printer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Printer.cpp; sourceTree = ""; }; D41B73EE1C2101890080A7B9 /* libcurl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.tbd; path = usr/lib/libcurl.tbd; sourceTree = SDKROOT; }; D41B741C1C210A7A0080A7B9 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; D41B74721C2125E50080A7B9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = distribution/macos/Assets.xcassets; sourceTree = SOURCE_ROOT; }; @@ -1178,6 +1180,7 @@ 85AFA2101D7DB83E00221B42 /* intercept.h */, 85AFA20F1D7DB83E00221B42 /* main.cpp */, C65A9EAE1DB2C01B003C3557 /* PaintIntercept.cpp */, + C6BDA0291DB3DFC900271C0A /* Printer.cpp */, ); name = Paint; path = test/testpaint; @@ -2393,6 +2396,7 @@ C64FDA7B1D6D9A2100F259B9 /* stand_up_roller_coaster.c in Sources */, C64FDA7C1D6D9A2100F259B9 /* steeplechase.c in Sources */, C64FDA7D1D6D9A2100F259B9 /* suspended_swinging_coaster.c in Sources */, + C6BDA02B1DB3DFD600271C0A /* Printer.cpp in Sources */, C64FDA7E1D6D9A2100F259B9 /* twister_roller_coaster.c in Sources */, C64FDA7F1D6D9A2100F259B9 /* vertical_drop_roller_coaster.c in Sources */, C64FDA801D6D9A2100F259B9 /* virginia_reel.c in Sources */, diff --git a/test/testpaint/Printer.cpp b/test/testpaint/Printer.cpp new file mode 100644 index 0000000000..94b565bd4f --- /dev/null +++ b/test/testpaint/Printer.cpp @@ -0,0 +1,150 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#include + +#include "Printer.h" + +class Printer { +public: + static std::string PrintFunction(function_call call, uint16 baseHeight) { + std::string imageId = GetImageIdString(call.paint.image_id); + + switch (call.function) { + case SUPPORTS_WOOD_A: + return StringFormat("wooden_a_supports_paint_setup(%d, %d, %s, %s)", call.supports.type, call.supports.special, + GetHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str()); + case SUPPORTS_WOOD_B: + return StringFormat("wooden_b_supports_paint_setup(%d, %d, %s, %s)", call.supports.type, call.supports.special, + call.supports.height, imageId.c_str()); + + case SUPPORTS_METAL_A: + return StringFormat("metal_a_supports_paint_setup(%d, %d, %d, %s, %s)", call.supports.type, + call.supports.segment, call.supports.special, GetHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str()); + case SUPPORTS_METAL_B: + return StringFormat("metal_b_supports_paint_setup(%d, %d, %d, %s, %s)", call.supports.type, + call.supports.segment, call.supports.special, GetHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str()); + + case SET_SEGMENT_HEIGHT: + return "paint_util_set_segment_support_height"; + } + + std::string functionCallName = "?"; + switch (call.function) { + case PAINT_98196C: + functionCallName = "sub_98196C"; + break; + case PAINT_98197C: + functionCallName = "sub_98197C"; + break; + case PAINT_98198C: + functionCallName = "sub_98198C"; + break; + case PAINT_98199C: + functionCallName = "sub_98199C"; + break; + } + + std::string s = StringFormat("%s(", functionCallName.c_str()); + + s += StringFormat("%s, ", imageId.c_str()); + s += StringFormat("%d, %d, ", call.paint.offset.x, call.paint.offset.y); + s += StringFormat( + "%d, %d, %d, ", + call.paint.bound_box_length.x, call.paint.bound_box_length.y, call.paint.bound_box_length.z + ); + s += StringFormat("%s, ", GetHeightOffset(call.paint.z_offset, baseHeight).c_str()); + + if (call.function != PAINT_98196C) { + s += StringFormat( + "%d, %d, %s, ", + call.paint.bound_box_offset.x, call.paint.bound_box_offset.y, GetHeightOffset(call.paint.bound_box_offset.z, baseHeight).c_str() + ); + } + + s += StringFormat("%d)", call.paint.rotation); + + + if (call.function != PAINT_98196C) { + s += StringFormat( + " = { %d, %d, %s }, { %d, %d, %s }, { %d, %d, %d }", + call.paint.offset.x, call.paint.offset.y, GetHeightOffset(call.paint.z_offset, baseHeight).c_str(), + call.paint.bound_box_offset.x, call.paint.bound_box_offset.y, + GetHeightOffset(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); + } + + return s; + } + +private: + static std::string GetImageIdString(uint32 imageId) + { + std::string result; + + uint32 image = imageId & 0x7FFFF; + uint32 palette = imageId & ~0x7FFFF; + + std::string paletteName; + if (palette == Intercept2::DEFAULT_SCHEME_TRACK) paletteName = "SCHEME_TRACK"; + else if (palette == Intercept2::DEFAULT_SCHEME_SUPPORTS) paletteName = "SCHEME_SUPPORTS"; + else if (palette == Intercept2::DEFAULT_SCHEME_MISC) paletteName = "SCHEME_MISC"; + else if (palette == Intercept2::DEFAULT_SCHEME_3) paletteName = "SCHEME_3"; + else { + paletteName = StringFormat("0x%08X", palette); + } + + if (image == 0) { + result = paletteName; + } else if (image & 0x70000) { + result = StringFormat("%s | vehicle.base_image_id + %d", paletteName.c_str(), image & ~0x70000); + } else { + result = StringFormat("%s | %d", paletteName.c_str(), image); + } + + return result; + } + + static std::string GetHeightOffset(uint16 height, uint16 baseHeight) { + int offset = height - baseHeight; + + return StringFormat("height%s", GetOffsetExpressionString(offset).c_str()); + } + + static std::string GetOffsetExpressionString(int offset) + { + if (offset < 0) return std::string(" - ") + std::to_string(-offset); + if (offset > 0) return std::string(" + ") + std::to_string(offset); + return std::string(); + } + + static std::string StringFormat(const char *format, ...) { + va_list args; + char buffer[512]; + + va_start(args, format); + vsnprintf(buffer, sizeof(buffer), format, args); + va_end(args); + + return std::string(buffer); + } +}; + +extern "C" { +void printFunctionCall(utf8string out, size_t len, function_call call, uint16 baseHeight) { + snprintf(out, len, "%s", Printer::PrintFunction(call, baseHeight).c_str()); +} +} diff --git a/test/testpaint/intercept.c b/test/testpaint/intercept.c index 14c22d5efd..575e167ad5 100644 --- a/test/testpaint/intercept.c +++ b/test/testpaint/intercept.c @@ -157,109 +157,10 @@ static bool assertFunctionCallArrayEquals(function_call expected[], uint8 expect return true; } -static void printImageId(uint32 input, utf8string out, size_t len) { - uint32 image = input & 0x7FFFF; - uint32 palette = input & ~0x7FFFF; - - utf8string paletteName; - if (palette == DEFAULT_SCHEME_TRACK)paletteName = "SCHEME_TRACK"; - else if (palette == DEFAULT_SCHEME_SUPPORTS)paletteName = "SCHEME_SUPPORTS"; - else if (palette == DEFAULT_SCHEME_MISC)paletteName = "SCHEME_MISC"; - else if (palette == DEFAULT_SCHEME_3)paletteName = "SCHEME_3"; - else { - paletteName = malloc(16); - snprintf(paletteName, 16, "0x%08X", palette); - } - - if (image == 0) { - snprintf(out, len, "%s", paletteName); - } else if (image & 0x70000) { - snprintf(out, len, "%s | vehicle.base_image_id + %d", paletteName, image & ~0x70000); - } else { - snprintf(out, len, "%s | %d", paletteName, image); - } -} - -static void printFunctionCall(utf8string out, size_t len, function_call call) { - utf8string imageId = malloc(64); - printImageId(call.supports.colour_flags, imageId, 64); - switch (call.function) { - case SUPPORTS_WOOD_A: - snprintf(out, len, "wooden_a_supports_paint_setup(%d, %d, %d, %s)", call.supports.type, call.supports.special, call.supports.height, imageId); - return; - case SUPPORTS_WOOD_B: - snprintf(out, len, "wooden_b_supports_paint_setup(%d, %d, %d, %s)", call.supports.type, call.supports.special, call.supports.height, imageId); - return; - - case SUPPORTS_METAL_A: - snprintf(out, len, "metal_a_supports_paint_setup(%d, %d, %d, %d, %s)", call.supports.type, call.supports.segment, call.supports.special, call.supports.height, imageId); - return; - case SUPPORTS_METAL_B: - snprintf(out, len, "metal_b_supports_paint_setup(%d, %d, %d, %d, %s)", call.supports.type, call.supports.segment, call.supports.special, call.supports.height, imageId); - return; - - case SET_SEGMENT_HEIGHT: - snprintf(out, len, "paint_util_set_segment_support_height"); - return; - } - - utf8string name = "_default"; - switch (call.function) { - case PAINT_98196C: - name = "sub_98196C"; - break; - case PAINT_98197C: - name = "sub_98197C"; - break; - case PAINT_98198C: - name = "sub_98198C"; - break; - case PAINT_98199C: - name = "sub_98199C"; - break; - } - - size_t slen; - - printImageId(call.paint.image_id, imageId, 64); - slen = snprintf( - out, - len, - "%s(%s, %d, %d, %d, %d, %d, %d, ", - name, - imageId, - call.paint.offset.x, call.paint.offset.y, - call.paint.bound_box_length.x, call.paint.bound_box_length.y, call.paint.bound_box_length.z, - call.paint.z_offset - ); - if (slen >= len) return; - - if (call.function != PAINT_98196C) { - if (slen < len) - slen += snprintf( - out + slen, - len - slen, - "%d, %d, %d, ", - call.paint.bound_box_offset.x, call.paint.bound_box_offset.y, call.paint.bound_box_offset.z - ); - } - - if (slen < len) - slen += snprintf(out + slen, len - slen, "%d)", call.paint.rotation); - - if (call.function != PAINT_98196C) { - if (slen < len) - snprintf(out + slen, len - slen, " = { %d, %d, %d }, { %d, %d, %d }, { %d, %d, %d }", - call.paint.offset.x, call.paint.offset.y, call.paint.z_offset - 48, - call.paint.bound_box_offset.x, call.paint.bound_box_offset.y, call.paint.bound_box_offset.z - 48, - call.paint.bound_box_length.x, call.paint.bound_box_length.y, call.paint.bound_box_length.z); - } -} - -static void printFunctionCallArray(utf8string out, size_t len, function_call calls[], uint8 count) { +static void printFunctionCallArray(utf8string out, size_t len, function_call calls[], uint8 count, uint16 baseHeight) { for (int i = 0; i < count; i++) { utf8string callOut = malloc(1024); - printFunctionCall(callOut, 1024, calls[i]); + printFunctionCall(callOut, 1024, calls[i], baseHeight); size_t slen = strlen(out); if (slen < len) snprintf(out + slen, len - slen, "%s\n", callOut); @@ -410,12 +311,12 @@ static uint8 testTrackElement(uint8 rideType, uint8 trackType, utf8string error, utf8string diff = malloc(2048); snprintf(diff, 2048, "<<< EXPECTED\n"); - printFunctionCallArray(diff, 2048, oldCalls, oldCallCount); + printFunctionCallArray(diff, 2048, oldCalls, oldCallCount, height); size_t slen = strlen(diff); if (slen < 2048) snprintf(diff + slen, 2048 - slen, "====\n"); - printFunctionCallArray(diff, 2048, newCalls, newCallCount); + printFunctionCallArray(diff, 2048, newCalls, newCallCount, height); slen = strlen(diff); if (slen < 2048) diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index 7662e4ce61..b8fd24c941 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -95,6 +95,7 @@ extern "C" void intercept_reset_segment_heights(); void intercept_reset_tunnels(); void intercept_simulate_wooden_supports(bool enabled); + void printFunctionCall(utf8string out, size_t len, function_call call, uint16 baseHeight); bool assertFunctionCallEquals(function_call expected, function_call actual); int generatePaintCode(uint8 rideType); diff --git a/test/testpaint/testpaint.vcxproj b/test/testpaint/testpaint.vcxproj index 999ff6c09b..44e80ad512 100644 --- a/test/testpaint/testpaint.vcxproj +++ b/test/testpaint/testpaint.vcxproj @@ -100,6 +100,7 @@ + From 3b19dc02d383ae40b715177acf1366a082fb3d5f Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 18:44:57 +0200 Subject: [PATCH 08/42] Extract utilty functions --- test/testpaint/Printer.cpp | 2 +- test/testpaint/Utils.cpp | 75 ++++++++++++++++++++++++++++++++++++++ test/testpaint/Utils.hpp | 25 +++++++++++++ test/testpaint/intercept.c | 45 ----------------------- test/testpaint/intercept.h | 3 -- test/testpaint/main.cpp | 7 ++-- 6 files changed, 105 insertions(+), 52 deletions(-) create mode 100644 test/testpaint/Utils.cpp create mode 100644 test/testpaint/Utils.hpp diff --git a/test/testpaint/Printer.cpp b/test/testpaint/Printer.cpp index 94b565bd4f..a742e58e90 100644 --- a/test/testpaint/Printer.cpp +++ b/test/testpaint/Printer.cpp @@ -16,7 +16,7 @@ #include -#include "Printer.h" +#include "intercept.h" class Printer { public: diff --git a/test/testpaint/Utils.cpp b/test/testpaint/Utils.cpp new file mode 100644 index 0000000000..6c3cd7a10a --- /dev/null +++ b/test/testpaint/Utils.cpp @@ -0,0 +1,75 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#include "Utils.hpp" + +extern "C" { + #include "../../src/ride/ride.h" + #include "../../src/ride/track.h" + #include "../../src/ride/track_data.h" +} + +namespace Utils { + int getTrackSequenceCount(uint8 rideType, uint8 trackType) { + int sequenceCount = 0; + const rct_preview_track **trackBlocks; + + if (ride_type_has_flag(rideType, RIDE_TYPE_FLAG_FLAT_RIDE)) { + trackBlocks = FlatRideTrackBlocks; + } else { + trackBlocks = TrackBlocks; + } + + for (int i = 0; i < 256; i++) { + if (trackBlocks[trackType][i].index == 0xFF) { + break; + } + + sequenceCount++; + } + + return sequenceCount; + } + + bool rideSupportsTrackType(uint8 rideType, uint8 trackType) { + TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; + + if (newPaintGetter == NULL) { + return false; + } + + if (newPaintGetter(trackType, 0) == NULL) { + return false; + } + + if (RideTypeTrackPaintFunctionsOld[rideType][trackType] == 0) { + return false; + } + + return true; + } + + bool rideIsImplemented(uint8 rideType) { + TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; + return (newPaintGetter != 0); + } +} + +extern "C" { + int getTrackSequenceCount(uint8 rideType, uint8 trackType) { + return Utils::getTrackSequenceCount(rideType, trackType); + } +} \ No newline at end of file diff --git a/test/testpaint/Utils.hpp b/test/testpaint/Utils.hpp new file mode 100644 index 0000000000..3aaaab09ce --- /dev/null +++ b/test/testpaint/Utils.hpp @@ -0,0 +1,25 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../../src/common.h" + +namespace Utils { + int getTrackSequenceCount(uint8 rideType, uint8 trackType); + bool rideSupportsTrackType(uint8 rideType, uint8 trackType); + bool rideIsImplemented(uint8 rideType); +} \ No newline at end of file diff --git a/test/testpaint/intercept.c b/test/testpaint/intercept.c index 575e167ad5..0f1e3f1037 100644 --- a/test/testpaint/intercept.c +++ b/test/testpaint/intercept.c @@ -167,46 +167,6 @@ static void printFunctionCallArray(utf8string out, size_t len, function_call cal } } -int getTrackSequenceCount(uint8 rideType, uint8 trackType) { - int sequenceCount = 0; - const rct_preview_track **trackBlocks; - - if (ride_type_has_flag(rideType, RIDE_TYPE_FLAG_FLAT_RIDE)) { - trackBlocks = FlatRideTrackBlocks; - } else { - trackBlocks = TrackBlocks; - } - - for (int i = 0; i < 256; i++) { - if (trackBlocks[trackType][i].index == 0xFF) { - break; - } - - sequenceCount++; - } - - return sequenceCount; -} - -bool rideSupportsTrackType(int rideType, int trackType) -{ - TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; - - if (newPaintGetter == NULL) { - return false; - } - - if (newPaintGetter(trackType, 0) == NULL) { - return false; - } - - if (RideTypeTrackPaintFunctionsOld[rideType][trackType] == 0) { - return false; - } - - return true; -} - extern bool testSupportSegments(uint8 rideType, uint8 trackType); extern bool testTunnels(uint8 rideType, uint8 trackType); @@ -368,11 +328,6 @@ static uint8 testTrackElement(uint8 rideType, uint8 trackType, utf8string error, return TEST_SUCCESS; } -bool rideIsImplemented(int rideType) { - TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; - return (newPaintGetter != 0); -} - uint8 testTrackPainting(int rideType, int trackType) { TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; if (newPaintGetter == NULL) { diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index b8fd24c941..07b32ab6a8 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -80,11 +80,8 @@ typedef struct extern "C" { #endif - bool testRide(int rideType); void initHooks(); int getTrackSequenceCount(uint8 rideType, uint8 trackType); - bool rideIsImplemented(int rideType); - bool rideSupportsTrackType(int rideType, int trackType); uint8 testTrackPainting(int rideType, int trackType); bool testSupportSegments(uint8 rideType, uint8 trackType); bool testTunnels(uint8 rideType, uint8 trackType); diff --git a/test/testpaint/main.cpp b/test/testpaint/main.cpp index 03ad2e40ae..269e2cfc3b 100644 --- a/test/testpaint/main.cpp +++ b/test/testpaint/main.cpp @@ -24,6 +24,7 @@ #endif // defined(__unix__) #include "intercept.h" +#include "Utils.hpp" extern "C" { #include "data.h" @@ -344,7 +345,7 @@ static void PrintRideTypes() { for (uint8 rideType = 0; rideType < 91; rideType++) { CLIColour colour = CLIColour::DEFAULT; - bool implemented = rideIsImplemented(rideType); + bool implemented = Utils::rideIsImplemented(rideType); const char * rideName = RideNames[rideType]; const char * status = ""; if (implemented) { @@ -397,7 +398,7 @@ int main(int argc, char *argv[]) { continue; } - if (!rideIsImplemented(rideType)) { + if (!Utils::rideIsImplemented(rideType)) { continue; } @@ -408,7 +409,7 @@ int main(int argc, char *argv[]) { testCase.trackTypes.push_back(RideConstructionDefaultTrackType[rideType]); } else { for (int trackType = 0; trackType < 256; trackType++) { - if (rideSupportsTrackType(rideType, trackType)) { + if (Utils::rideSupportsTrackType(rideType, trackType)) { testCase.trackTypes.push_back(trackType); } } From b8b3eb5af5939ac0c207de5bec6b76a4c7813599 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 19:10:55 +0200 Subject: [PATCH 09/42] Fix for msvc --- test/testpaint/intercept_2.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/testpaint/intercept_2.cpp b/test/testpaint/intercept_2.cpp index eb0c81b340..70f9cae0f3 100644 --- a/test/testpaint/intercept_2.cpp +++ b/test/testpaint/intercept_2.cpp @@ -59,12 +59,16 @@ namespace Intercept2 gRightTunnelCount = 0; for (int i = 0; i < TUNNEL_MAX_COUNT; i++) { - gLeftTunnels[i] = (tunnel_entry) {0, 0}; - gRightTunnels[i] = (tunnel_entry) {0, 0}; + gLeftTunnels[i].height = 0; + gLeftTunnels[i].type = 0; + gRightTunnels[i].height = 0; + gRightTunnels[i].type = 0; } - gLeftTunnels[0] = (tunnel_entry) {0xFF, 0xFF}; - gRightTunnels[0] = (tunnel_entry) {0xFF, 0xFF}; + gLeftTunnels[0].height = 0xFF; + gLeftTunnels[0].type = 0xFF; + gRightTunnels[0].height = 0xFF; + gRightTunnels[0].type = 0xFF; } static void ResetSegmentHeights() { From f813a2871b4c8edc1d8bd7dc08428e3becfaa3a6 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 19:22:02 +0200 Subject: [PATCH 10/42] Extract function comparison --- test/testpaint/FunctionCall.cpp | 129 ++++++++++++++++++++++++++++++++ test/testpaint/FunctionCall.hpp | 25 +++++++ test/testpaint/intercept.c | 101 ------------------------- 3 files changed, 154 insertions(+), 101 deletions(-) create mode 100644 test/testpaint/FunctionCall.cpp create mode 100644 test/testpaint/FunctionCall.hpp diff --git a/test/testpaint/FunctionCall.cpp b/test/testpaint/FunctionCall.cpp new file mode 100644 index 0000000000..b499a136be --- /dev/null +++ b/test/testpaint/FunctionCall.cpp @@ -0,0 +1,129 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#include "FunctionCall.hpp" + +enum SpriteGroup { + SPRITEGROUP_NONE, + + SPRITEGROUP_FENCE_METAL_A, // 14568 + SPRITEGROUP_FENCE_METAL_B, // 14990 + SPRITEGROUP_FENCE_SPIRAL_SLIDE, // 20564 + SPRITEGROUP_FLOOR_CORK, // 22134 + SPRITEGROUP_FENCE_ROPE, // 22138 +}; + +static void canonicalizeFunctionCall(function_call *call); +static SpriteGroup getSpriteGroup(uint16 spriteIndex); + +bool FunctionCall::AssertsEquals(function_call expected, function_call actual) { + canonicalizeFunctionCall(&actual); + canonicalizeFunctionCall(&expected); + + if (expected.function != actual.function) { + return false; + } + + uint8 function = expected.function; + + if (function == SUPPORTS_WOOD_A || function == SUPPORTS_WOOD_B) { + if (expected.supports.type != actual.supports.type) return false; + if (expected.supports.special != actual.supports.special) return false; + if (expected.supports.height != actual.supports.height) return false; + if (expected.supports.colour_flags != actual.supports.colour_flags) return false; + + return true; + } + + if (function == SUPPORTS_METAL_A || function == SUPPORTS_METAL_B) { + if (expected.supports.type != actual.supports.type) return false; + if (expected.supports.segment != actual.supports.segment) return false; + if (expected.supports.special != actual.supports.special) return false; + if (expected.supports.height != actual.supports.height) return false; + if (expected.supports.colour_flags != actual.supports.colour_flags) return false; + + return true; + } + + if (function == SET_SEGMENT_HEIGHT) { + return true; + } + + if (expected.paint.image_id != actual.paint.image_id) { + SpriteGroup expectedSpriteGroup = getSpriteGroup(expected.paint.image_id & 0x7FFFF); + SpriteGroup actualSpriteGroup = getSpriteGroup(actual.paint.image_id & 0x7FFFF); + + if (expectedSpriteGroup != actualSpriteGroup) return false; + + if (expectedSpriteGroup == SPRITEGROUP_NONE) return false; + + return true; + } + + if (expected.paint.offset.x != actual.paint.offset.x) return false; + if (expected.paint.offset.y != actual.paint.offset.y) return false; + if (expected.paint.bound_box_length.x != actual.paint.bound_box_length.x) return false; + if (expected.paint.bound_box_length.y != actual.paint.bound_box_length.y) return false; + if (expected.paint.bound_box_length.z != actual.paint.bound_box_length.z) return false; + if (function != PAINT_98196C) { + if (expected.paint.bound_box_offset.x != actual.paint.bound_box_offset.x) return false; + if (expected.paint.bound_box_offset.y != actual.paint.bound_box_offset.y) return false; + if (expected.paint.bound_box_offset.z != actual.paint.bound_box_offset.z) return false; + } + if (expected.paint.z_offset != actual.paint.z_offset) return false; + if (expected.paint.rotation != actual.paint.rotation) return false; + + return true; +} + +static void canonicalizeFunctionCall(function_call *call) { + if (call->function != PAINT_98197C) return; + if (call->paint.offset.x != call->paint.bound_box_offset.x) return; + if (call->paint.offset.y != call->paint.bound_box_offset.y) return; + if (call->paint.z_offset != call->paint.bound_box_offset.z) return; + + call->function = PAINT_98196C; +} + +static SpriteGroup getSpriteGroup(uint16 spriteIndex) { + if (spriteIndex >= 14568 && spriteIndex <= 14571) { + return SPRITEGROUP_FENCE_METAL_A; + } + + if (spriteIndex >= 14990 && spriteIndex <= 14993) { + return SPRITEGROUP_FENCE_METAL_B; + } + + if (spriteIndex >= 20564 && spriteIndex <= 20567) { + return SPRITEGROUP_FENCE_SPIRAL_SLIDE; + } + + if (spriteIndex >= 22134 && spriteIndex <= 22137) { + return SPRITEGROUP_FLOOR_CORK; + } + + if (spriteIndex >= 22138 && spriteIndex <= 22141) { + return SPRITEGROUP_FENCE_ROPE; + } + + return SPRITEGROUP_NONE; +} + +extern "C" { + bool assertFunctionCallEquals(function_call expected, function_call actual) { + return FunctionCall::AssertsEquals(expected, actual); + } +} \ No newline at end of file diff --git a/test/testpaint/FunctionCall.hpp b/test/testpaint/FunctionCall.hpp new file mode 100644 index 0000000000..c0225af9ac --- /dev/null +++ b/test/testpaint/FunctionCall.hpp @@ -0,0 +1,25 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../../src/common.h" +#include "intercept.h" + +class FunctionCall { +public: + static bool AssertsEquals(function_call expected, function_call actual); +}; diff --git a/test/testpaint/intercept.c b/test/testpaint/intercept.c index 0f1e3f1037..f912573e7b 100644 --- a/test/testpaint/intercept.c +++ b/test/testpaint/intercept.c @@ -37,108 +37,7 @@ extern const utf8string RideNames[91]; extern const utf8string TrackNames[256]; extern const utf8string FlatTrackNames[256]; -enum { - SPRITEGROUP_NONE, - SPRITEGROUP_FENCE_METAL_A, // 14568 - SPRITEGROUP_FENCE_METAL_B, // 14990 - SPRITEGROUP_FENCE_SPIRAL_SLIDE, // 20564 - SPRITEGROUP_FLOOR_CORK, // 22134 - SPRITEGROUP_FENCE_ROPE, // 22138 -}; - -static int getSpriteGroup(uint16 spriteIndex) { - if (spriteIndex >= 14568 && spriteIndex <= 14571) { - return SPRITEGROUP_FENCE_METAL_A; - } - - if (spriteIndex >= 14990 && spriteIndex <= 14993) { - return SPRITEGROUP_FENCE_METAL_B; - } - - if (spriteIndex >= 20564 && spriteIndex <= 20567) { - return SPRITEGROUP_FENCE_SPIRAL_SLIDE; - } - - if (spriteIndex >= 22134 && spriteIndex <= 22137) { - return SPRITEGROUP_FLOOR_CORK; - } - - if (spriteIndex >= 22138 && spriteIndex <= 22141) { - return SPRITEGROUP_FENCE_ROPE; - } - - return SPRITEGROUP_NONE; -} - -static void canonicalizeFunctionCall(function_call *call) { - if (call->function != PAINT_98197C) return; - if (call->paint.offset.x != call->paint.bound_box_offset.x) return; - if (call->paint.offset.y != call->paint.bound_box_offset.y) return; - if (call->paint.z_offset != call->paint.bound_box_offset.z) return; - - call->function = PAINT_98196C; -} - -bool assertFunctionCallEquals(function_call expected, function_call actual) { - canonicalizeFunctionCall(&actual); - canonicalizeFunctionCall(&expected); - - if (expected.function != actual.function) { - return false; - } - - uint8 function = expected.function; - - if (function == SUPPORTS_WOOD_A || function == SUPPORTS_WOOD_B) { - if (expected.supports.type != actual.supports.type) return false; - if (expected.supports.special != actual.supports.special) return false; - if (expected.supports.height != actual.supports.height) return false; - if (expected.supports.colour_flags != actual.supports.colour_flags) return false; - - return true; - } - - if (function == SUPPORTS_METAL_A || function == SUPPORTS_METAL_B) { - if (expected.supports.type != actual.supports.type) return false; - if (expected.supports.segment != actual.supports.segment) return false; - if (expected.supports.special != actual.supports.special) return false; - if (expected.supports.height != actual.supports.height) return false; - if (expected.supports.colour_flags != actual.supports.colour_flags) return false; - - return true; - } - - if (function == SET_SEGMENT_HEIGHT) { - return true; - } - - if (expected.paint.image_id != actual.paint.image_id) { - int expectedSpriteGroup = getSpriteGroup(expected.paint.image_id & 0x7FFFF); - int actualSpriteGroup = getSpriteGroup(actual.paint.image_id & 0x7FFFF); - - if (expectedSpriteGroup != actualSpriteGroup) return false; - - if (expectedSpriteGroup == SPRITEGROUP_NONE) return false; - - return true; - } - - if (expected.paint.offset.x != actual.paint.offset.x) return false; - if (expected.paint.offset.y != actual.paint.offset.y) return false; - if (expected.paint.bound_box_length.x != actual.paint.bound_box_length.x) return false; - if (expected.paint.bound_box_length.y != actual.paint.bound_box_length.y) return false; - if (expected.paint.bound_box_length.z != actual.paint.bound_box_length.z) return false; - if (function != PAINT_98196C) { - if (expected.paint.bound_box_offset.x != actual.paint.bound_box_offset.x) return false; - if (expected.paint.bound_box_offset.y != actual.paint.bound_box_offset.y) return false; - if (expected.paint.bound_box_offset.z != actual.paint.bound_box_offset.z) return false; - } - if (expected.paint.z_offset != actual.paint.z_offset) return false; - if (expected.paint.rotation != actual.paint.rotation) return false; - - return true; -} static bool assertFunctionCallArrayEquals(function_call expected[], uint8 expectedCount, function_call actual[], uint8 actualCount) { if (expectedCount != actualCount) { From 263dc9f189a686ce888d20d78a93028be5f8a728 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 19:25:41 +0200 Subject: [PATCH 11/42] Remove unneeded declarations from intercept --- test/testpaint/intercept.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/test/testpaint/intercept.c b/test/testpaint/intercept.c index f912573e7b..1a8ea16387 100644 --- a/test/testpaint/intercept.c +++ b/test/testpaint/intercept.c @@ -15,17 +15,13 @@ #pragma endregion #include "intercept.h" +#include "data.h" #include "../../src/paint/paint.h" #include "../../src/paint/supports.h" #include "../../src/ride/track_data.h" #include "../../src/interface/viewport.h" #include "../../src/hook.h" -static const uint32 DEFAULT_SCHEME_TRACK = COLOUR_GREY << 19 | COLOUR_WHITE << 24 | 0xA0000000; -static const uint32 DEFAULT_SCHEME_SUPPORTS = COLOUR_LIGHT_BLUE << 19 | COLOUR_ICY_BLUE << 24 | 0xA0000000; -static const uint32 DEFAULT_SCHEME_MISC = COLOUR_DARK_PURPLE << 19 | COLOUR_LIGHT_PURPLE << 24 | 0xA0000000; -static const uint32 DEFAULT_SCHEME_3 = COLOUR_BRIGHT_PURPLE << 19 | COLOUR_DARK_BLUE << 24 | 0xA0000000; - #define BLANK_SUPPORT {.height = 0, .slope = 0xFF} const support_height DefaultSegmentHeight[9] = { BLANK_SUPPORT, BLANK_SUPPORT, BLANK_SUPPORT, @@ -33,12 +29,6 @@ const support_height DefaultSegmentHeight[9] = { BLANK_SUPPORT, BLANK_SUPPORT, BLANK_SUPPORT }; -extern const utf8string RideNames[91]; -extern const utf8string TrackNames[256]; -extern const utf8string FlatTrackNames[256]; - - - static bool assertFunctionCallArrayEquals(function_call expected[], uint8 expectedCount, function_call actual[], uint8 actualCount) { if (expectedCount != actualCount) { return false; @@ -71,7 +61,6 @@ extern bool testSupportSegments(uint8 rideType, uint8 trackType); extern bool testTunnels(uint8 rideType, uint8 trackType); extern bool testVerticalTunnels(uint8 rideType, uint8 trackType); - static uint8 testTrackElement(uint8 rideType, uint8 trackType, utf8string error, size_t len) { if (rideType == RIDE_TYPE_CHAIRLIFT) { if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION || trackType == TRACK_ELEM_END_STATION) { From abe6b8ee9e1eda337413167fff5aba0321fa0598 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 19:26:57 +0200 Subject: [PATCH 12/42] Update VS project --- test/testpaint/testpaint.vcxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/testpaint/testpaint.vcxproj b/test/testpaint/testpaint.vcxproj index 44e80ad512..ca9561ec02 100644 --- a/test/testpaint/testpaint.vcxproj +++ b/test/testpaint/testpaint.vcxproj @@ -95,12 +95,14 @@ + + From 334b8cca057589cd17fafc664dfc6c75a95de004 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 21:15:40 +0200 Subject: [PATCH 13/42] Extract all of `intercept.c` to C++ --- OpenRCT2.xcodeproj/project.pbxproj | 94 +++++++----- test/testpaint/FunctionCall.cpp | 17 +++ test/testpaint/FunctionCall.hpp | 1 + test/testpaint/PaintIntercept.cpp | 11 +- test/testpaint/Printer.cpp | 116 +++++++------- test/testpaint/Printer.hpp | 27 ++++ test/testpaint/String.cpp | 32 ++++ test/testpaint/String.hpp | 23 +++ test/testpaint/TestTrack.cpp | 204 +++++++++++++++++++++++++ test/testpaint/TestTrack.hpp | 29 ++++ test/testpaint/generate.cpp | 35 ++--- test/testpaint/intercept.c | 237 ----------------------------- test/testpaint/intercept.h | 5 - test/testpaint/main.cpp | 3 +- test/testpaint/testpaint.vcxproj | 3 +- 15 files changed, 472 insertions(+), 365 deletions(-) create mode 100644 test/testpaint/Printer.hpp create mode 100644 test/testpaint/String.cpp create mode 100644 test/testpaint/String.hpp create mode 100644 test/testpaint/TestTrack.cpp create mode 100644 test/testpaint/TestTrack.hpp delete mode 100644 test/testpaint/intercept.c diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 006a16790a..b3952fc3af 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -19,10 +19,19 @@ 791166FB1D7486EF005912EA /* NetworkServerAdvertiser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 791166F91D7486EF005912EA /* NetworkServerAdvertiser.cpp */; }; 85060FD31D8C17CC00DFA2B3 /* track_data_old.c in Sources */ = {isa = PBXBuildFile; fileRef = 8594C05F1D885CF600235E93 /* track_data_old.c */; }; 8594C0601D885CF600235E93 /* track_data_old.c in Sources */ = {isa = PBXBuildFile; fileRef = 8594C05F1D885CF600235E93 /* track_data_old.c */; }; - 85AFA2111D7DB83E00221B42 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 85AFA20F1D7DB83E00221B42 /* main.cpp */; }; 85B468FC1D96822F000F1DB5 /* paint_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = 85B468FB1D96822F000F1DB5 /* paint_helpers.c */; }; 85B468FD1D96822F000F1DB5 /* paint_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = 85B468FB1D96822F000F1DB5 /* paint_helpers.c */; }; - 85B5C0B01D81D912001B99A8 /* intercept_2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 85B5C0AF1D81D912001B99A8 /* intercept_2.cpp */; }; + C606CCBE1DB4054000FE4015 /* compat.c in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAB1DB4054000FE4015 /* compat.c */; }; + C606CCBF1DB4054000FE4015 /* data.c in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAC1DB4054000FE4015 /* data.c */; }; + C606CCC01DB4054000FE4015 /* FunctionCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAE1DB4054000FE4015 /* FunctionCall.cpp */; }; + C606CCC11DB4054000FE4015 /* generate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB01DB4054000FE4015 /* generate.cpp */; }; + C606CCC21DB4054000FE4015 /* intercept_2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB11DB4054000FE4015 /* intercept_2.cpp */; }; + C606CCC41DB4054000FE4015 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB41DB4054000FE4015 /* main.cpp */; }; + C606CCC51DB4054000FE4015 /* PaintIntercept.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB51DB4054000FE4015 /* PaintIntercept.cpp */; }; + C606CCC61DB4054000FE4015 /* Printer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB61DB4054000FE4015 /* Printer.cpp */; }; + C606CCC71DB4054000FE4015 /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB81DB4054000FE4015 /* String.cpp */; }; + C606CCC81DB4054000FE4015 /* TestTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCBA1DB4054000FE4015 /* TestTrack.cpp */; }; + C606CCC91DB4054000FE4015 /* Utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCBC1DB4054000FE4015 /* Utils.cpp */; }; C612A8991D64825300B634CA /* vehicle_data.c in Sources */ = {isa = PBXBuildFile; fileRef = C612A8971D64825300B634CA /* vehicle_data.c */; }; C61FB7241CF86356004CE991 /* NetworkUser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61FB7221CF86356004CE991 /* NetworkUser.cpp */; }; C64FDA641D6D9A2100F259B9 /* air_powered_vertical_coaster.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F8BB1CDBC3B7009F9BFC /* air_powered_vertical_coaster.c */; }; @@ -106,15 +115,11 @@ C64FDAC01D6D9E3B00F259B9 /* track_data.c in Sources */ = {isa = PBXBuildFile; fileRef = D442717B1CC81B3200D84D28 /* track_data.c */; }; C64FDAC21D6DA0B800F259B9 /* diagnostic.c in Sources */ = {isa = PBXBuildFile; fileRef = D44270FE1CC81B3200D84D28 /* diagnostic.c */; }; C64FDAC31D6DA41000F259B9 /* track_paint.c in Sources */ = {isa = PBXBuildFile; fileRef = D442717D1CC81B3200D84D28 /* track_paint.c */; }; - C64FDAC51D6DA55E00F259B9 /* compat.c in Sources */ = {isa = PBXBuildFile; fileRef = C64FDAC41D6DA55E00F259B9 /* compat.c */; }; - C64FDAC81D6DA72400F259B9 /* intercept.c in Sources */ = {isa = PBXBuildFile; fileRef = C64FDAC71D6DA72400F259B9 /* intercept.c */; }; - C64FDACA1D6DA92D00F259B9 /* data.c in Sources */ = {isa = PBXBuildFile; fileRef = C64FDAC91D6DA92D00F259B9 /* data.c */; }; C64FDACB1D6DBCC700F259B9 /* hook.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271121CC81B3200D84D28 /* hook.c */; }; C650B2191CCABBDD00B4D91C /* S4Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C650B2151CCABBDD00B4D91C /* S4Importer.cpp */; }; C650B21A1CCABBDD00B4D91C /* tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C650B2171CCABBDD00B4D91C /* tables.cpp */; }; C650B21C1CCABC4400B4D91C /* ConvertCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C650B21B1CCABC4400B4D91C /* ConvertCommand.cpp */; }; C6575A371D46AFBA00C3E79F /* debug_paint.c in Sources */ = {isa = PBXBuildFile; fileRef = C6575A361D46AFBA00C3E79F /* debug_paint.c */; }; - C65A9EAF1DB2C01B003C3557 /* PaintIntercept.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C65A9EAE1DB2C01B003C3557 /* PaintIntercept.cpp */; }; C686F8AC1CDBC37E009F9BFC /* banner.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F8981CDBC37E009F9BFC /* banner.c */; }; C686F8AD1CDBC37E009F9BFC /* entrance.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F8991CDBC37E009F9BFC /* entrance.c */; }; C686F8AE1CDBC37E009F9BFC /* fence.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F89A1CDBC37E009F9BFC /* fence.c */; }; @@ -207,7 +212,6 @@ C686F9581CDBC4C7009F9BFC /* vehicle_paint.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F9561CDBC4C7009F9BFC /* vehicle_paint.c */; }; C6B5A7D41CDFE4CB00C9C006 /* S6Exporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6B5A7D01CDFE4CB00C9C006 /* S6Exporter.cpp */; }; C6B5A7D51CDFE4CB00C9C006 /* S6Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6B5A7D21CDFE4CB00C9C006 /* S6Importer.cpp */; }; - C6BDA02B1DB3DFD600271C0A /* Printer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6BDA0291DB3DFC900271C0A /* Printer.cpp */; }; D41B73EF1C2101890080A7B9 /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B73EE1C2101890080A7B9 /* libcurl.tbd */; }; D41B741D1C210A7A0080A7B9 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B741C1C210A7A0080A7B9 /* libiconv.tbd */; }; D41B74731C2125E50080A7B9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D41B74721C2125E50080A7B9 /* Assets.xcassets */; }; @@ -395,6 +399,7 @@ D44272A61CC81B3200D84D28 /* scenery.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271F01CC81B3200D84D28 /* scenery.c */; }; D44272A71CC81B3200D84D28 /* sprite.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271F21CC81B3200D84D28 /* sprite.c */; }; D452919B1DAA204200C11788 /* generate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D45291991DAA202C00C11788 /* generate.cpp */; }; + D45A38BB1CF3006400659A24 /* engines in Resources */ = {isa = PBXBuildFile; fileRef = D45A38B21CF3006400659A24 /* engines */; }; D45A38BC1CF3006400659A24 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38B31CF3006400659A24 /* libcrypto.dylib */; }; D45A38BE1CF3006400659A24 /* libjansson.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38B51CF3006400659A24 /* libjansson.dylib */; }; D45A38C01CF3006400659A24 /* libSDL2_ttf.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38B71CF3006400659A24 /* libSDL2_ttf.dylib */; }; @@ -496,26 +501,36 @@ 791166F91D7486EF005912EA /* NetworkServerAdvertiser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkServerAdvertiser.cpp; sourceTree = ""; }; 791166FA1D7486EF005912EA /* NetworkServerAdvertiser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkServerAdvertiser.h; sourceTree = ""; }; 8594C05F1D885CF600235E93 /* track_data_old.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_data_old.c; sourceTree = ""; }; - 85AFA20F1D7DB83E00221B42 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; - 85AFA2101D7DB83E00221B42 /* intercept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intercept.h; sourceTree = ""; }; - 85AFA2141D7DDFA100221B42 /* data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = data.h; sourceTree = ""; }; 85B468FB1D96822F000F1DB5 /* paint_helpers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = paint_helpers.c; sourceTree = ""; }; - 85B5C0AF1D81D912001B99A8 /* intercept_2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = intercept_2.cpp; sourceTree = ""; }; + C606CCAB1DB4054000FE4015 /* compat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = compat.c; sourceTree = ""; }; + C606CCAC1DB4054000FE4015 /* data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = data.c; sourceTree = ""; }; + C606CCAD1DB4054000FE4015 /* data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = data.h; sourceTree = ""; }; + C606CCAE1DB4054000FE4015 /* FunctionCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionCall.cpp; sourceTree = ""; }; + C606CCAF1DB4054000FE4015 /* FunctionCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FunctionCall.hpp; sourceTree = ""; }; + C606CCB01DB4054000FE4015 /* generate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = generate.cpp; sourceTree = ""; }; + C606CCB11DB4054000FE4015 /* intercept_2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = intercept_2.cpp; sourceTree = ""; }; + C606CCB31DB4054000FE4015 /* intercept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intercept.h; sourceTree = ""; }; + C606CCB41DB4054000FE4015 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + C606CCB51DB4054000FE4015 /* PaintIntercept.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PaintIntercept.cpp; sourceTree = ""; }; + C606CCB61DB4054000FE4015 /* Printer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Printer.cpp; sourceTree = ""; }; + C606CCB71DB4054000FE4015 /* Printer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Printer.hpp; sourceTree = ""; }; + C606CCB81DB4054000FE4015 /* String.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = String.cpp; sourceTree = ""; }; + C606CCB91DB4054000FE4015 /* String.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = String.hpp; sourceTree = ""; }; + C606CCBA1DB4054000FE4015 /* TestTrack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestTrack.cpp; sourceTree = ""; }; + C606CCBB1DB4054000FE4015 /* TestTrack.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TestTrack.hpp; sourceTree = ""; }; + C606CCBC1DB4054000FE4015 /* Utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utils.cpp; sourceTree = ""; }; + C606CCBD1DB4054000FE4015 /* Utils.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Utils.hpp; sourceTree = ""; }; C612A8971D64825300B634CA /* vehicle_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vehicle_data.c; sourceTree = ""; }; C612A8981D64825300B634CA /* vehicle_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vehicle_data.h; sourceTree = ""; }; C61FB7221CF86356004CE991 /* NetworkUser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkUser.cpp; sourceTree = ""; usesTabs = 0; }; C61FB7231CF86356004CE991 /* NetworkUser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = NetworkUser.h; sourceTree = ""; usesTabs = 0; }; C64FDA5D1D6D99F400F259B9 /* PaintTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = PaintTest; sourceTree = BUILT_PRODUCTS_DIR; }; - C64FDAC41D6DA55E00F259B9 /* compat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = compat.c; sourceTree = ""; }; - C64FDAC71D6DA72400F259B9 /* intercept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = intercept.c; sourceTree = ""; }; - C64FDAC91D6DA92D00F259B9 /* data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = data.c; sourceTree = ""; }; C650B2151CCABBDD00B4D91C /* S4Importer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = S4Importer.cpp; sourceTree = ""; usesTabs = 0; }; C650B2161CCABBDD00B4D91C /* S4Importer.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = S4Importer.h; sourceTree = ""; usesTabs = 0; }; C650B2171CCABBDD00B4D91C /* tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tables.cpp; sourceTree = ""; usesTabs = 0; }; C650B2181CCABBDD00B4D91C /* Tables.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = Tables.h; sourceTree = ""; usesTabs = 0; }; C650B21B1CCABC4400B4D91C /* ConvertCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConvertCommand.cpp; sourceTree = ""; usesTabs = 0; }; C6575A361D46AFBA00C3E79F /* debug_paint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debug_paint.c; sourceTree = ""; }; - C65A9EAE1DB2C01B003C3557 /* PaintIntercept.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PaintIntercept.cpp; sourceTree = ""; }; C686F8981CDBC37E009F9BFC /* banner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = banner.c; sourceTree = ""; }; C686F8991CDBC37E009F9BFC /* entrance.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = entrance.c; sourceTree = ""; }; C686F89A1CDBC37E009F9BFC /* fence.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fence.c; sourceTree = ""; }; @@ -616,7 +631,6 @@ C6B5A7D11CDFE4CB00C9C006 /* S6Exporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = S6Exporter.h; sourceTree = ""; }; C6B5A7D21CDFE4CB00C9C006 /* S6Importer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = S6Importer.cpp; sourceTree = ""; }; C6B5A7D31CDFE4CB00C9C006 /* S6Importer.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = S6Importer.h; sourceTree = ""; }; - C6BDA0291DB3DFC900271C0A /* Printer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Printer.cpp; sourceTree = ""; }; D41B73EE1C2101890080A7B9 /* libcurl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.tbd; path = usr/lib/libcurl.tbd; sourceTree = SDKROOT; }; D41B741C1C210A7A0080A7B9 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; D41B74721C2125E50080A7B9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = distribution/macos/Assets.xcassets; sourceTree = SOURCE_ROOT; }; @@ -913,6 +927,7 @@ D44271F31CC81B3200D84D28 /* sprite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sprite.h; sourceTree = ""; }; D44271F41CC81B3200D84D28 /* water.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = water.h; sourceTree = ""; }; D45291991DAA202C00C11788 /* generate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = generate.cpp; sourceTree = ""; }; + D45A38B21CF3006400659A24 /* engines */ = {isa = PBXFileReference; lastKnownFileType = folder; path = engines; sourceTree = ""; }; D45A38B31CF3006400659A24 /* libcrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libcrypto.dylib; sourceTree = ""; }; D45A38B41CF3006400659A24 /* libfreetype.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libfreetype.dylib; sourceTree = ""; }; D45A38B51CF3006400659A24 /* libjansson.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libjansson.dylib; sourceTree = ""; }; @@ -1171,16 +1186,24 @@ C64FDA5E1D6D99F400F259B9 /* Paint */ = { isa = PBXGroup; children = ( - C64FDAC41D6DA55E00F259B9 /* compat.c */, - C64FDAC91D6DA92D00F259B9 /* data.c */, - 85AFA2141D7DDFA100221B42 /* data.h */, - D45291991DAA202C00C11788 /* generate.cpp */, - 85B5C0AF1D81D912001B99A8 /* intercept_2.cpp */, - C64FDAC71D6DA72400F259B9 /* intercept.c */, - 85AFA2101D7DB83E00221B42 /* intercept.h */, - 85AFA20F1D7DB83E00221B42 /* main.cpp */, - C65A9EAE1DB2C01B003C3557 /* PaintIntercept.cpp */, - C6BDA0291DB3DFC900271C0A /* Printer.cpp */, + C606CCAB1DB4054000FE4015 /* compat.c */, + C606CCAC1DB4054000FE4015 /* data.c */, + C606CCAD1DB4054000FE4015 /* data.h */, + C606CCAE1DB4054000FE4015 /* FunctionCall.cpp */, + C606CCAF1DB4054000FE4015 /* FunctionCall.hpp */, + C606CCB01DB4054000FE4015 /* generate.cpp */, + C606CCB11DB4054000FE4015 /* intercept_2.cpp */, + C606CCB31DB4054000FE4015 /* intercept.h */, + C606CCB41DB4054000FE4015 /* main.cpp */, + C606CCB51DB4054000FE4015 /* PaintIntercept.cpp */, + C606CCB61DB4054000FE4015 /* Printer.cpp */, + C606CCB71DB4054000FE4015 /* Printer.hpp */, + C606CCB81DB4054000FE4015 /* String.cpp */, + C606CCB91DB4054000FE4015 /* String.hpp */, + C606CCBA1DB4054000FE4015 /* TestTrack.cpp */, + C606CCBB1DB4054000FE4015 /* TestTrack.hpp */, + C606CCBC1DB4054000FE4015 /* Utils.cpp */, + C606CCBD1DB4054000FE4015 /* Utils.hpp */, ); name = Paint; path = test/testpaint; @@ -2371,7 +2394,6 @@ C64FDA651D6D9A2100F259B9 /* bobsleigh_coaster.c in Sources */, C64FDA661D6D9A2100F259B9 /* compact_inverted_coaster.c in Sources */, C64FDA671D6D9A2100F259B9 /* corkscrew_roller_coaster.c in Sources */, - 85AFA2111D7DB83E00221B42 /* main.cpp in Sources */, C64FDA681D6D9A2100F259B9 /* flying_roller_coaster.c in Sources */, C64FDA691D6D9A2100F259B9 /* giga_coaster.c in Sources */, C64FDA6A1D6D9A2100F259B9 /* heartline_twister_coaster.c in Sources */, @@ -2382,25 +2404,26 @@ C64FDA6F1D6D9A2100F259B9 /* lay_down_roller_coaster.c in Sources */, C64FDA701D6D9A2100F259B9 /* lim_launched_roller_coaster.c in Sources */, C64FDA711D6D9A2100F259B9 /* looping_roller_coaster.c in Sources */, - C64FDAC81D6DA72400F259B9 /* intercept.c in Sources */, C64FDA721D6D9A2100F259B9 /* mine_ride.c in Sources */, C64FDA731D6D9A2100F259B9 /* mine_train_coaster.c in Sources */, C64FDA741D6D9A2100F259B9 /* mini_roller_coaster.c in Sources */, C64FDA751D6D9A2100F259B9 /* mini_suspended_coaster.c in Sources */, C64FDA761D6D9A2100F259B9 /* multi_dimension_roller_coaster.c in Sources */, C64FDA771D6D9A2100F259B9 /* reverse_freefall_coaster.c in Sources */, + C606CCBE1DB4054000FE4015 /* compat.c in Sources */, C64FDA781D6D9A2100F259B9 /* reverser_roller_coaster.c in Sources */, C64FDA791D6D9A2100F259B9 /* side_friction_roller_coaster.c in Sources */, - C64FDACA1D6DA92D00F259B9 /* data.c in Sources */, C64FDA7A1D6D9A2100F259B9 /* spiral_roller_coaster.c in Sources */, + C606CCC21DB4054000FE4015 /* intercept_2.cpp in Sources */, C64FDA7B1D6D9A2100F259B9 /* stand_up_roller_coaster.c in Sources */, + C606CCC61DB4054000FE4015 /* Printer.cpp in Sources */, C64FDA7C1D6D9A2100F259B9 /* steeplechase.c in Sources */, C64FDA7D1D6D9A2100F259B9 /* suspended_swinging_coaster.c in Sources */, - C6BDA02B1DB3DFD600271C0A /* Printer.cpp in Sources */, C64FDA7E1D6D9A2100F259B9 /* twister_roller_coaster.c in Sources */, C64FDA7F1D6D9A2100F259B9 /* vertical_drop_roller_coaster.c in Sources */, C64FDA801D6D9A2100F259B9 /* virginia_reel.c in Sources */, C64FDA811D6D9A2100F259B9 /* wild_mouse.c in Sources */, + C606CCC41DB4054000FE4015 /* main.cpp in Sources */, C64FDA821D6D9A2100F259B9 /* wooden_roller_coaster.c in Sources */, C64FDA831D6D9A2100F259B9 /* wooden_wild_mouse.c in Sources */, C64FDA841D6D9A2100F259B9 /* car_ride.c in Sources */, @@ -2409,26 +2432,28 @@ 85060FD31D8C17CC00DFA2B3 /* track_data_old.c in Sources */, C64FDA871D6D9A2100F259B9 /* dodgems.c in Sources */, C64FDA881D6D9A2100F259B9 /* ferris_wheel.c in Sources */, - D452919B1DAA204200C11788 /* generate.cpp in Sources */, C64FDA891D6D9A2100F259B9 /* flying_saucers.c in Sources */, + C606CCC11DB4054000FE4015 /* generate.cpp in Sources */, C64FDA8A1D6D9A2100F259B9 /* ghost_train.c in Sources */, + C606CCBF1DB4054000FE4015 /* data.c in Sources */, C64FDA8B1D6D9A2100F259B9 /* haunted_house.c in Sources */, C64FDA8C1D6D9A2100F259B9 /* maze.c in Sources */, C64FDA8D1D6D9A2100F259B9 /* merry_go_round.c in Sources */, C64FDA8E1D6D9A2100F259B9 /* mini_golf.c in Sources */, + C606CCC81DB4054000FE4015 /* TestTrack.cpp in Sources */, C64FDA8F1D6D9A2100F259B9 /* mini_helicopters.c in Sources */, + C606CCC51DB4054000FE4015 /* PaintIntercept.cpp in Sources */, C64FDA901D6D9A2100F259B9 /* monorail_cycles.c in Sources */, - 85B5C0B01D81D912001B99A8 /* intercept_2.cpp in Sources */, C64FDA911D6D9A2100F259B9 /* observation_tower.c in Sources */, C64FDA921D6D9A2100F259B9 /* space_rings.c in Sources */, C64FDA931D6D9A2100F259B9 /* spiral_slide.c in Sources */, C64FDA941D6D9A2100F259B9 /* facility.c in Sources */, - C64FDAC51D6DA55E00F259B9 /* compat.c in Sources */, C64FDA951D6D9A2100F259B9 /* misc.c in Sources */, C64FDA961D6D9A2100F259B9 /* shop.c in Sources */, C64FDA971D6D9A2100F259B9 /* 3d_cinema.c in Sources */, C64FDA981D6D9A2100F259B9 /* enterprise.c in Sources */, C64FDA991D6D9A2100F259B9 /* go_karts.c in Sources */, + C606CCC01DB4054000FE4015 /* FunctionCall.cpp in Sources */, C64FDA9A1D6D9A2100F259B9 /* launched_freefall.c in Sources */, C64FDA9B1D6D9A2100F259B9 /* magic_carpet.c in Sources */, C64FDA9C1D6D9A2100F259B9 /* motion_simulator.c in Sources */, @@ -2438,6 +2463,7 @@ C64FDAA01D6D9A2100F259B9 /* top_spin.c in Sources */, C64FDAA11D6D9A2100F259B9 /* twist.c in Sources */, C64FDAA21D6D9A2100F259B9 /* chairlift.c in Sources */, + C606CCC71DB4054000FE4015 /* String.cpp in Sources */, C64FDAA31D6D9A2100F259B9 /* lift.c in Sources */, C64FDAA41D6D9A2100F259B9 /* miniature_railway.c in Sources */, C64FDAA51D6D9A2100F259B9 /* monorail.c in Sources */, @@ -2447,11 +2473,11 @@ C64FDAA81D6D9A2100F259B9 /* dingy_slide.c in Sources */, C64FDAA91D6D9A2100F259B9 /* log_flume.c in Sources */, C64FDAAA1D6D9A2100F259B9 /* river_rafts.c in Sources */, + C606CCC91DB4054000FE4015 /* Utils.cpp in Sources */, C64FDAAB1D6D9A2100F259B9 /* river_rapids.c in Sources */, C64FDAAC1D6D9A2100F259B9 /* splash_boats.c in Sources */, C64FDAAD1D6D9A2100F259B9 /* submarine_ride.c in Sources */, C64FDAAE1D6D9A2100F259B9 /* water_coaster.c in Sources */, - C65A9EAF1DB2C01B003C3557 /* PaintIntercept.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/test/testpaint/FunctionCall.cpp b/test/testpaint/FunctionCall.cpp index b499a136be..c0074f34c9 100644 --- a/test/testpaint/FunctionCall.cpp +++ b/test/testpaint/FunctionCall.cpp @@ -29,6 +29,23 @@ enum SpriteGroup { static void canonicalizeFunctionCall(function_call *call); static SpriteGroup getSpriteGroup(uint16 spriteIndex); +bool FunctionCall::AssertsEquals(std::vector expected, std::vector actual) { + if (expected.size() != actual.size()) { + return false; + } + + for (int i = 0; i < expected.size(); i++) { + function_call expectedCall = expected[i]; + function_call actualCall = actual[i]; + + if (!AssertsEquals(expectedCall, actualCall)) { + return false; + } + } + + return true; +} + bool FunctionCall::AssertsEquals(function_call expected, function_call actual) { canonicalizeFunctionCall(&actual); canonicalizeFunctionCall(&expected); diff --git a/test/testpaint/FunctionCall.hpp b/test/testpaint/FunctionCall.hpp index c0225af9ac..aabe4e565e 100644 --- a/test/testpaint/FunctionCall.hpp +++ b/test/testpaint/FunctionCall.hpp @@ -22,4 +22,5 @@ class FunctionCall { public: static bool AssertsEquals(function_call expected, function_call actual); + static bool AssertsEquals(std::vector expected, std::vector actual); }; diff --git a/test/testpaint/PaintIntercept.cpp b/test/testpaint/PaintIntercept.cpp index ed6412d25c..a56564b662 100644 --- a/test/testpaint/PaintIntercept.cpp +++ b/test/testpaint/PaintIntercept.cpp @@ -163,12 +163,15 @@ private: } static void CheckSegmentSupportHeight() { - // First get last known support height state - if (memcmp(gSupportSegments, &DefaultSegmentHeight, sizeof(support_height) * 9) == 0) { - // Nothing changed - return; + bool hasChanged = false; + for (int i = 0; i < 9; i++) { + if (gSupportSegments[i].height != 0) hasChanged = true; + if (gSupportSegments[i].slope != 0xFF) hasChanged = true; } + if (!hasChanged) { + return; + } function_call call = {0}; call.function = SET_SEGMENT_HEIGHT; diff --git a/test/testpaint/Printer.cpp b/test/testpaint/Printer.cpp index a742e58e90..bd3d8fb8b2 100644 --- a/test/testpaint/Printer.cpp +++ b/test/testpaint/Printer.cpp @@ -14,72 +14,86 @@ *****************************************************************************/ #pragma endregion -#include - +#include "Printer.hpp" +#include "String.hpp" #include "intercept.h" -class Printer { -public: - static std::string PrintFunction(function_call call, uint16 baseHeight) { - std::string imageId = GetImageIdString(call.paint.image_id); +namespace Printer { + + static const char *functionNames[] = { + "sub_98196C", + "sub_98197C", + "sub_98198C", + "sub_98199C", + "metal_a_supports_paint_setup", + "metal_b_supports_paint_setup", + "wooden_a_supports_paint_setup", + "wooden_b_supports_paint_setup", + }; + + static std::string GetImageIdString(uint32 imageId); + + static std::string GetHeightOffset(uint16 height, uint16 baseHeight); + + static std::string GetOffsetExpressionString(int offset); + + std::string PrintFunctionCalls(std::vector calls, uint16 baseHeight) { + std::string out; + + for (auto &&call : calls) { + out += PrintFunctionCall(call, baseHeight).c_str(); + out += "\n"; + } + + return out; + } + + std::string PrintFunctionCall(function_call call, uint16 baseHeight) { + std::string imageId = GetImageIdString(call.supports.colour_flags); + const char *functionName = functionNames[call.function]; switch (call.function) { case SUPPORTS_WOOD_A: - return StringFormat("wooden_a_supports_paint_setup(%d, %d, %s, %s)", call.supports.type, call.supports.special, - GetHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str()); case SUPPORTS_WOOD_B: - return StringFormat("wooden_b_supports_paint_setup(%d, %d, %s, %s)", call.supports.type, call.supports.special, - call.supports.height, imageId.c_str()); + return String::Format( + "%s(%d, %d, %s, %s)", functionName, call.supports.type, call.supports.special, + GetHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str() + ); case SUPPORTS_METAL_A: - return StringFormat("metal_a_supports_paint_setup(%d, %d, %d, %s, %s)", call.supports.type, - call.supports.segment, call.supports.special, GetHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str()); case SUPPORTS_METAL_B: - return StringFormat("metal_b_supports_paint_setup(%d, %d, %d, %s, %s)", call.supports.type, - call.supports.segment, call.supports.special, GetHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str()); + return String::Format( + "%s(%d, %d, %d, %s, %s)", functionName, call.supports.type, call.supports.segment, call.supports.special, + GetHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str() + ); case SET_SEGMENT_HEIGHT: return "paint_util_set_segment_support_height"; } - std::string functionCallName = "?"; - switch (call.function) { - case PAINT_98196C: - functionCallName = "sub_98196C"; - break; - case PAINT_98197C: - functionCallName = "sub_98197C"; - break; - case PAINT_98198C: - functionCallName = "sub_98198C"; - break; - case PAINT_98199C: - functionCallName = "sub_98199C"; - break; - } + std::string s = String::Format("%s(", functionName); - std::string s = StringFormat("%s(", functionCallName.c_str()); - - s += StringFormat("%s, ", imageId.c_str()); - s += StringFormat("%d, %d, ", call.paint.offset.x, call.paint.offset.y); - s += StringFormat( + imageId = GetImageIdString(call.paint.image_id); + s += String::Format("%s, ", imageId.c_str()); + s += String::Format("%d, %d, ", call.paint.offset.x, call.paint.offset.y); + s += String::Format( "%d, %d, %d, ", call.paint.bound_box_length.x, call.paint.bound_box_length.y, call.paint.bound_box_length.z ); - s += StringFormat("%s, ", GetHeightOffset(call.paint.z_offset, baseHeight).c_str()); + s += String::Format("%s, ", GetHeightOffset(call.paint.z_offset, baseHeight).c_str()); if (call.function != PAINT_98196C) { - s += StringFormat( + s += String::Format( "%d, %d, %s, ", call.paint.bound_box_offset.x, call.paint.bound_box_offset.y, GetHeightOffset(call.paint.bound_box_offset.z, baseHeight).c_str() ); } - s += StringFormat("%d)", call.paint.rotation); + s += String::Format("%d)", call.paint.rotation); if (call.function != PAINT_98196C) { - s += StringFormat( + s += String::Format( " = { %d, %d, %s }, { %d, %d, %s }, { %d, %d, %d }", call.paint.offset.x, call.paint.offset.y, GetHeightOffset(call.paint.z_offset, baseHeight).c_str(), call.paint.bound_box_offset.x, call.paint.bound_box_offset.y, @@ -90,7 +104,6 @@ public: return s; } -private: static std::string GetImageIdString(uint32 imageId) { std::string result; @@ -104,15 +117,15 @@ private: else if (palette == Intercept2::DEFAULT_SCHEME_MISC) paletteName = "SCHEME_MISC"; else if (palette == Intercept2::DEFAULT_SCHEME_3) paletteName = "SCHEME_3"; else { - paletteName = StringFormat("0x%08X", palette); + paletteName = String::Format("0x%08X", palette); } if (image == 0) { result = paletteName; } else if (image & 0x70000) { - result = StringFormat("%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 { - result = StringFormat("%s | %d", paletteName.c_str(), image); + result = String::Format("%s | %d", paletteName.c_str(), image); } return result; @@ -121,7 +134,7 @@ private: static std::string GetHeightOffset(uint16 height, uint16 baseHeight) { int offset = height - baseHeight; - return StringFormat("height%s", GetOffsetExpressionString(offset).c_str()); + return String::Format("height%s", GetOffsetExpressionString(offset).c_str()); } static std::string GetOffsetExpressionString(int offset) @@ -130,21 +143,4 @@ private: if (offset > 0) return std::string(" + ") + std::to_string(offset); return std::string(); } - - static std::string StringFormat(const char *format, ...) { - va_list args; - char buffer[512]; - - va_start(args, format); - vsnprintf(buffer, sizeof(buffer), format, args); - va_end(args); - - return std::string(buffer); - } }; - -extern "C" { -void printFunctionCall(utf8string out, size_t len, function_call call, uint16 baseHeight) { - snprintf(out, len, "%s", Printer::PrintFunction(call, baseHeight).c_str()); -} -} diff --git a/test/testpaint/Printer.hpp b/test/testpaint/Printer.hpp new file mode 100644 index 0000000000..d8815bdee0 --- /dev/null +++ b/test/testpaint/Printer.hpp @@ -0,0 +1,27 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include +#include + +#include "intercept.h" + +namespace Printer { + std::string PrintFunctionCall(function_call call, uint16 baseHeight); + std::string PrintFunctionCalls(std::vector calls, uint16 baseHeight); +} diff --git a/test/testpaint/String.cpp b/test/testpaint/String.cpp new file mode 100644 index 0000000000..0189d9cd5a --- /dev/null +++ b/test/testpaint/String.cpp @@ -0,0 +1,32 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#include "String.hpp" + +namespace String { + std::string Format(const char * format, ...) + { + va_list args; + char buffer[512]; + + va_start(args, format); + vsnprintf(buffer, sizeof(buffer), format, args); + va_end(args); + + return std::string(buffer); + } +}; + diff --git a/test/testpaint/String.hpp b/test/testpaint/String.hpp new file mode 100644 index 0000000000..67c232530a --- /dev/null +++ b/test/testpaint/String.hpp @@ -0,0 +1,23 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include + +namespace String { + std::string Format(const char *format, ...); +} diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp new file mode 100644 index 0000000000..bb90af069c --- /dev/null +++ b/test/testpaint/TestTrack.cpp @@ -0,0 +1,204 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#include +#include + +#include "intercept.h" +#include "Printer.hpp" +#include "String.hpp" +#include "TestTrack.hpp" +#include "Utils.hpp" +#include "FunctionCall.hpp" + +extern "C" { +#include "../../src/ride/ride.h" +#include "../../src/ride/track.h" +#include "../../src/ride/track_data.h" +} + +static void CallOriginal( + uint8 rideType, + uint8 trackType, + uint8 direction, + uint8 trackSequence, + uint16 height, + rct_map_element *mapElement +) { + uint32 *trackDirectionList = (uint32 *) RideTypeTrackPaintFunctionsOld[rideType][trackType]; + const uint8 rideIndex = 0; + + // Have to call from this point as it pushes esi and expects callee to pop it + RCT2_CALLPROC_X( + 0x006C4934, + rideType, + (int) trackDirectionList, + direction, + height, + (int) &mapElement, + rideIndex * sizeof(rct_ride), + trackSequence + ); +} + +static void CallNew( + uint8 rideType, + uint8 trackType, + uint8 direction, + uint8 trackSequence, + uint16 height, + rct_map_element *mapElement +) { + TRACK_PAINT_FUNCTION_GETTER newPaintFunctionGetter = RideTypeTrackPaintFunctions[rideType]; + TRACK_PAINT_FUNCTION newPaintFunction = newPaintFunctionGetter(trackType, direction); + + newPaintFunction(0, trackSequence, direction, height, mapElement); +} + +uint8 TestTrack::TestPaintTrackElement(uint8 rideType, uint8 trackType) { + if (!Utils::rideSupportsTrackType(rideType, trackType)) { + return TEST_FAILED; + } + + + std::string error = ""; + uint8 retVal = TestPaintTrackElementCalls(rideType, trackType, &error); + + if (retVal != TEST_SUCCESS) { + printf("%s\n", error.c_str()); + } + + return retVal; +} + +uint8 TestTrack::TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std::string *error) { + if (rideType == RIDE_TYPE_CHAIRLIFT) { + if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION || + trackType == TRACK_ELEM_END_STATION) { + // These rides check neighbouring tiles for tracks + return TEST_SKIPPED; + } + } + + uint8 rideIndex = 0; + uint16 height = 3 * 16; + + rct_map_element mapElement = {0}; + mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; + mapElement.properties.track.type = trackType; + mapElement.base_height = height / 16; + g_currently_drawn_item = &mapElement; + + rct_map_element surfaceElement = {0}; + surfaceElement.type = MAP_ELEMENT_TYPE_SURFACE; + surfaceElement.base_height = 2; + gSurfaceElement = &surfaceElement; + gDidPassSurface = true; + + intercept_reset_environment(); + + int sequenceCount = getTrackSequenceCount(rideType, trackType); + + *error += String::Format("rct2: 0x%08X\n", RideTypeTrackPaintFunctionsOld[rideType][trackType]); + + function_call callBuffer[256] = {0}; + int callCount = 0; + + int chainLift = 0; + int inverted = 0; + + // TODO: test chainlift + // TODO: test inverted + // TODO: test supports + // TODO: test entrance styles + + for (int currentRotation = 0; currentRotation < 4; currentRotation++) { + gCurrentRotation = currentRotation; + for (int direction = 0; direction < 4; direction++) { + for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { + RCT2_GLOBAL(0x009DE56A, sint16) = 64; // x + RCT2_GLOBAL(0x009DE56E, sint16) = 64; // y + + std::string caseName = String::Format( + "[direction:%d trackSequence:%d chainLift:%d inverted:%d]", + direction, trackSequence, chainLift, inverted + ); + + intercept_clear_calls(); + intercept_reset_segment_heights(); + + CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); + + callCount = intercept_get_calls(callBuffer); + std::vector oldCalls; + oldCalls.insert(oldCalls.begin(), callBuffer, callBuffer + callCount); + + intercept_clear_calls(); + testpaint_clear_ignore(); + intercept_reset_segment_heights(); + + CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); + + if (testpaint_is_ignored(direction, trackSequence)) { + *error += String::Format("[ IGNORED ] %s\n", caseName.c_str()); + continue; + } + + callCount = intercept_get_calls(callBuffer); + std::vector newCalls; + newCalls.insert(newCalls.begin(), callBuffer, callBuffer + callCount); + + bool sucess = true; + if (oldCalls.size() != newCalls.size()) { + *error += String::Format( + "Call counts don't match (was %d, expected %d). %s\n", + newCalls.size(), oldCalls.size(), caseName.c_str() + ); + sucess = false; + } else if (!FunctionCall::AssertsEquals(oldCalls, newCalls)) { + *error += String::Format("Calls don't match. %s\n", caseName.c_str()); + sucess = false; + } + + if (!sucess) { + *error += " Expected:\n"; + *error += Printer::PrintFunctionCalls(oldCalls, height); + *error += " Actual:\n"; + *error += Printer::PrintFunctionCalls(newCalls, height); + + return TEST_FAILED; + } + } + } + } + + bool segmentSuccess = testSupportSegments(rideType, trackType); + if (!segmentSuccess) { + return TEST_FAILED; + } + + bool tunnelSuccess = testTunnels(rideType, trackType); + if (!tunnelSuccess) { + return TEST_FAILED; + } + + bool verticalTunnelSuccess = testVerticalTunnels(rideType, trackType); + if (!verticalTunnelSuccess) { + return TEST_FAILED; + } + + return TEST_SUCCESS; +} \ No newline at end of file diff --git a/test/testpaint/TestTrack.hpp b/test/testpaint/TestTrack.hpp new file mode 100644 index 0000000000..7f049766aa --- /dev/null +++ b/test/testpaint/TestTrack.hpp @@ -0,0 +1,29 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include + +#include "../../src/common.h" + +class TestTrack { +public: + static uint8 TestPaintTrackElement(uint8 rideType, uint8 trackType); + +private: + static uint8 TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std::string * error); +}; diff --git a/test/testpaint/generate.cpp b/test/testpaint/generate.cpp index 64265577b7..615692f9ef 100644 --- a/test/testpaint/generate.cpp +++ b/test/testpaint/generate.cpp @@ -19,6 +19,7 @@ #include #include "intercept.h" +#include "String.hpp" extern "C" { @@ -630,17 +631,17 @@ private: { const char * funcName = GetFunctionCallName(call.function); std::string imageId = GetImageIdString(call.paint.image_id); - std::string s = StringFormat("%s_rotated(direction, %s, ", funcName, imageId.c_str()); + std::string s = String::Format("%s_rotated(direction, %s, ", funcName, imageId.c_str()); s += FormatXYSwap(call.paint.offset.x, call.paint.offset.y, direction); s += ", "; s += FormatXYSwap(call.paint.bound_box_length.x, call.paint.bound_box_length.y, direction); - s += StringFormat(", %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) { s += ", "; s += FormatXYSwap(call.paint.bound_box_offset.x, call.paint.bound_box_offset.y, direction); - s += StringFormat(", height%s", GetOffsetExpressionString(call.paint.bound_box_offset.z - height).c_str()); + s += String::Format(", height%s", GetOffsetExpressionString(call.paint.bound_box_offset.z - height).c_str()); } s += ");"; @@ -651,11 +652,11 @@ private: { if (direction & 1) { - return StringFormat("%d, %d", y, x); + return String::Format("%d, %d", y, x); } else { - return StringFormat("%d, %d", x, y); + return String::Format("%d, %d", x, y); } } @@ -912,12 +913,12 @@ private: if (ssh.height == 0xFFFF) { szCall += "0xFFFF"; - szCall += StringFormat(", 0);", ssh.slope); + szCall += String::Format(", 0);", ssh.slope); } else { szCall += std::to_string(ssh.height); - szCall += StringFormat(", 0x%02X);", ssh.slope); + szCall += String::Format(", 0x%02X);", ssh.slope); } WriteLine(tabs, szCall); } @@ -953,15 +954,15 @@ private: else if (palette == Intercept2::DEFAULT_SCHEME_MISC) paletteName = "gTrackColours[SCHEME_MISC]"; else if (palette == Intercept2::DEFAULT_SCHEME_3) paletteName = "gTrackColours[SCHEME_3]"; else { - paletteName = StringFormat("0x%08X", palette); + paletteName = String::Format("0x%08X", palette); } if (image == 0) { result = paletteName; } else if (image & 0x70000) { - result = StringFormat("%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 { - result = StringFormat("%s | %d", paletteName.c_str(), image); + result = String::Format("%s | %d", paletteName.c_str(), image); } return result; } @@ -982,7 +983,7 @@ private: if (segmentsPrinted > 0) { s += " | "; } - s += StringFormat("SEGMENT_%02X", 0xB4 + 4 * i); + s += String::Format("SEGMENT_%02X", 0xB4 + 4 * i); segmentsPrinted++; } } @@ -1093,18 +1094,6 @@ private: } fprintf(_file, "%s\n", s.c_str()); } - - static std::string StringFormat(const char * format, ...) - { - va_list args; - char buffer[512]; - - va_start(args, format); - vsnprintf(buffer, sizeof(buffer), format, args); - va_end(args); - - return std::string(buffer); - } }; extern "C" diff --git a/test/testpaint/intercept.c b/test/testpaint/intercept.c deleted file mode 100644 index 1a8ea16387..0000000000 --- a/test/testpaint/intercept.c +++ /dev/null @@ -1,237 +0,0 @@ -#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers -/***************************************************************************** - * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. - * - * OpenRCT2 is the work of many authors, a full list can be found in contributors.md - * For more information, visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * A full copy of the GNU General Public License can be found in licence.txt - *****************************************************************************/ -#pragma endregion - -#include "intercept.h" -#include "data.h" -#include "../../src/paint/paint.h" -#include "../../src/paint/supports.h" -#include "../../src/ride/track_data.h" -#include "../../src/interface/viewport.h" -#include "../../src/hook.h" - -#define BLANK_SUPPORT {.height = 0, .slope = 0xFF} -const support_height DefaultSegmentHeight[9] = { - BLANK_SUPPORT, BLANK_SUPPORT, BLANK_SUPPORT, - BLANK_SUPPORT, BLANK_SUPPORT, BLANK_SUPPORT, - BLANK_SUPPORT, BLANK_SUPPORT, BLANK_SUPPORT -}; - -static bool assertFunctionCallArrayEquals(function_call expected[], uint8 expectedCount, function_call actual[], uint8 actualCount) { - if (expectedCount != actualCount) { - return false; - } - - for (int i = 0; i < expectedCount; i++) { - function_call expectedCall = expected[i]; - function_call actualCall = actual[i]; - - if (!assertFunctionCallEquals(expectedCall, actualCall)) { - return false; - } - } - - return true; -} - -static void printFunctionCallArray(utf8string out, size_t len, function_call calls[], uint8 count, uint16 baseHeight) { - for (int i = 0; i < count; i++) { - utf8string callOut = malloc(1024); - printFunctionCall(callOut, 1024, calls[i], baseHeight); - size_t slen = strlen(out); - if (slen < len) - snprintf(out + slen, len - slen, "%s\n", callOut); - } -} - - -extern bool testSupportSegments(uint8 rideType, uint8 trackType); -extern bool testTunnels(uint8 rideType, uint8 trackType); -extern bool testVerticalTunnels(uint8 rideType, uint8 trackType); - -static uint8 testTrackElement(uint8 rideType, uint8 trackType, utf8string error, size_t len) { - if (rideType == RIDE_TYPE_CHAIRLIFT) { - if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION || trackType == TRACK_ELEM_END_STATION) { - // These rides check neighbouring tiles for tracks - return TEST_SKIPPED; - } - } - - uint8 rideIndex = 0; - rct_map_element mapElement = { 0 }; - mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; - mapElement.properties.track.type = trackType; - mapElement.base_height = 3; - - g_currently_drawn_item = &mapElement; - - rct_map_element surfaceElement = { 0 }; - surfaceElement.type = MAP_ELEMENT_TYPE_SURFACE; - surfaceElement.base_height = 2; - - intercept_reset_environment(); - - int height = 48; - - snprintf(error, len, "rct2: 0x%08X\n", RideTypeTrackPaintFunctionsOld[rideType][trackType]); - - TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; - int sequenceCount = getTrackSequenceCount(rideType, trackType); - - for (int supports = 0; supports < 2; supports++) { - if (supports == 0) { - intercept_simulate_wooden_supports(false); - } else { - intercept_simulate_wooden_supports(true); - } - for (int inverted = 0; inverted < 2; inverted++) { - if (inverted == 0) { - mapElement.properties.track.colour &= ~TRACK_ELEMENT_COLOUR_FLAG_INVERTED; - } else { - mapElement.properties.track.colour |= TRACK_ELEMENT_COLOUR_FLAG_INVERTED; - } - for (int chainLift = 0; chainLift < 2; chainLift++) { - if (chainLift == 0) { - mapElement.type &= ~0x80; - } else { - mapElement.type |= 0x80; - } - for (int currentRotation = 0; currentRotation < 4; currentRotation++) { - gCurrentRotation = currentRotation; - for (int direction = 0; direction < 4; direction++) { - TRACK_PAINT_FUNCTION newPaintFunction = newPaintGetter(trackType, direction); - for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { - RCT2_GLOBAL(0x009DE56A, sint16) = 64; // x - RCT2_GLOBAL(0x009DE56E, sint16) = 64; // y - gDidPassSurface = true; // Above surface - gSurfaceElement = &surfaceElement; - - intercept_clear_calls(); - intercept_reset_segment_heights(); - - uint32 *trackDirectionList = (uint32 *)RideTypeTrackPaintFunctionsOld[rideType][trackType]; - - // Have to call from this point as it pushes esi and expects callee to pop it - RCT2_CALLPROC_X( - 0x006C4934, - rideType, - (int) trackDirectionList, - direction, - height, - (int) &mapElement, - rideIndex * sizeof(rct_ride), - trackSequence - ); - // segment heights - // tunnels - - function_call oldCalls[256]; - int oldCallCount = intercept_get_calls(oldCalls); - - intercept_clear_calls(); - - testpaint_clear_ignore(); - intercept_reset_segment_heights(); - - newPaintFunction(rideIndex, trackSequence, direction, height, &mapElement); - if (testpaint_is_ignored(direction, trackSequence)) { - snprintf(error, len, "[ IGNORED ] [direction:%d trackSequence:%d chainLift:%d inverted:%d]\n", - direction, trackSequence, chainLift, inverted); - continue; - } - - function_call newCalls[256]; - int newCallCount = intercept_get_calls(newCalls); - - if (!assertFunctionCallArrayEquals(oldCalls, oldCallCount, newCalls, newCallCount)) { - utf8string diff = malloc(2048); - - snprintf(diff, 2048, "<<< EXPECTED\n"); - printFunctionCallArray(diff, 2048, oldCalls, oldCallCount, height); - - size_t slen = strlen(diff); - if (slen < 2048) - snprintf(diff + slen, 2048 - slen, "====\n"); - printFunctionCallArray(diff, 2048, newCalls, newCallCount, height); - - slen = strlen(diff); - if (slen < 2048) - snprintf(diff + slen, 2048 - slen, ">>> ACTUAL\n"); - - if (oldCallCount != newCallCount) { - slen = strlen(error); - if (slen < len) - snprintf(error + slen, len - slen, "Call counts don't match (was %d, expected %d) [direction:%d trackSequence:%d chainLift:%d inverted:%d]", - newCallCount, oldCallCount, direction, trackSequence, chainLift, inverted); - } else { - slen = strlen(error); - if (slen < len) - snprintf(error + slen, len - slen, "Calls don't match [direction:%d trackSequence:%d chainLift:%d inverted:%d]", - direction, trackSequence, chainLift, inverted); - } - - slen = strlen(error); - if (slen < len) - snprintf(error + slen, len - slen, "\n%s", diff); - - free(diff); - - return TEST_FAILED; - } - - } - } - } - } - } - } - - bool segmentSuccess = testSupportSegments(rideType, trackType); - if (!segmentSuccess) { - return TEST_FAILED; - } - - bool tunnelSuccess = testTunnels(rideType, trackType); - if (!tunnelSuccess) { - return TEST_FAILED; - } - - bool verticalTunnelSuccess = testVerticalTunnels(rideType, trackType); - if (!verticalTunnelSuccess) { - return TEST_FAILED; - } - - return TEST_SUCCESS; -} - -uint8 testTrackPainting(int rideType, int trackType) { - TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; - if (newPaintGetter == NULL) { - return false; - } - - if (newPaintGetter(trackType, 0) == NULL) { - return false; - } - - utf8string error = malloc(2048); - int retVal = testTrackElement(rideType, trackType, error, 2048); - if (retVal != TEST_SUCCESS) { - printf("%s\n", error); - } - free(error); - - return retVal; -} diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index 07b32ab6a8..b63ee38f6e 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -82,7 +82,6 @@ extern "C" #endif void initHooks(); int getTrackSequenceCount(uint8 rideType, uint8 trackType); - uint8 testTrackPainting(int rideType, int trackType); bool testSupportSegments(uint8 rideType, uint8 trackType); bool testTunnels(uint8 rideType, uint8 trackType); bool testVerticalTunnels(uint8 rideType, uint8 trackType); @@ -91,14 +90,10 @@ extern "C" void intercept_reset_environment(); void intercept_reset_segment_heights(); void intercept_reset_tunnels(); - void intercept_simulate_wooden_supports(bool enabled); - void printFunctionCall(utf8string out, size_t len, function_call call, uint16 baseHeight); bool assertFunctionCallEquals(function_call expected, function_call actual); int generatePaintCode(uint8 rideType); - extern const support_height DefaultSegmentHeight[9]; - #ifdef __cplusplus } #endif diff --git a/test/testpaint/main.cpp b/test/testpaint/main.cpp index 269e2cfc3b..78383d4482 100644 --- a/test/testpaint/main.cpp +++ b/test/testpaint/main.cpp @@ -24,6 +24,7 @@ #endif // defined(__unix__) #include "intercept.h" +#include "TestTrack.hpp" #include "Utils.hpp" extern "C" { @@ -449,7 +450,7 @@ int main(int argc, char *argv[]) { ColouredPrintF(CLIColour::GREEN, "[ RUN ] "); printf("%s.%s\n", rideTypeName, trackTypeName); - int retVal = testTrackPainting(tc.rideType, trackType); + int retVal = TestTrack::TestPaintTrackElement(tc.rideType, trackType); switch (retVal) { case TEST_SUCCESS: ColouredPrintF(CLIColour::GREEN, "[ OK ] "); diff --git a/test/testpaint/testpaint.vcxproj b/test/testpaint/testpaint.vcxproj index ca9561ec02..5ecb055bdc 100644 --- a/test/testpaint/testpaint.vcxproj +++ b/test/testpaint/testpaint.vcxproj @@ -97,11 +97,12 @@ - + + From 6c54bba6f6b0a7daa97a38b9829a978620d12804 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 21:22:18 +0200 Subject: [PATCH 14/42] Fix MSVC --- test/testpaint/FunctionCall.cpp | 2 +- test/testpaint/String.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/test/testpaint/FunctionCall.cpp b/test/testpaint/FunctionCall.cpp index c0074f34c9..8d7973b8c7 100644 --- a/test/testpaint/FunctionCall.cpp +++ b/test/testpaint/FunctionCall.cpp @@ -34,7 +34,7 @@ bool FunctionCall::AssertsEquals(std::vector expected, std::vecto return false; } - for (int i = 0; i < expected.size(); i++) { + for (size_t i = 0; i < expected.size(); i++) { function_call expectedCall = expected[i]; function_call actualCall = actual[i]; diff --git a/test/testpaint/String.cpp b/test/testpaint/String.cpp index 0189d9cd5a..6260e2870d 100644 --- a/test/testpaint/String.cpp +++ b/test/testpaint/String.cpp @@ -14,6 +14,8 @@ *****************************************************************************/ #pragma endregion +#include + #include "String.hpp" namespace String { @@ -21,11 +23,11 @@ namespace String { { va_list args; char buffer[512]; - + va_start(args, format); vsnprintf(buffer, sizeof(buffer), format, args); va_end(args); - + return std::string(buffer); } }; From 7d69446464240d235f93bf62afad91a6d65817cf Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 16 Oct 2016 21:41:20 +0200 Subject: [PATCH 15/42] Attempt to fix GCC --- test/testpaint/PaintIntercept.cpp | 5 +---- test/testpaint/TestTrack.cpp | 2 +- test/testpaint/Utils.cpp | 6 ------ test/testpaint/Utils.hpp | 2 +- test/testpaint/generate.cpp | 3 ++- test/testpaint/intercept.h | 1 - test/testpaint/intercept_2.cpp | 7 ++++--- 7 files changed, 9 insertions(+), 17 deletions(-) diff --git a/test/testpaint/PaintIntercept.cpp b/test/testpaint/PaintIntercept.cpp index a56564b662..5ee804d6ae 100644 --- a/test/testpaint/PaintIntercept.cpp +++ b/test/testpaint/PaintIntercept.cpp @@ -21,6 +21,7 @@ extern "C" { #include "../../src/common.h" #include "../../src/hook.h" #include "../../src/interface/viewport.h" +#include "../../src/paint/supports.h" } class PaintInterceptor { @@ -337,10 +338,6 @@ int intercept_get_calls(function_call *buffer) { return PaintInterceptor::GetCalls(buffer); } -void intercept_simulate_wooden_supports(bool enabled) { - return PaintInterceptor::SetSimulateWoodenSupports(enabled); -} - void initHooks() { PaintInterceptor::InitHooks(); } diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index bb90af069c..6adca06ad7 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -110,7 +110,7 @@ uint8 TestTrack::TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std intercept_reset_environment(); - int sequenceCount = getTrackSequenceCount(rideType, trackType); + int sequenceCount = Utils::getTrackSequenceCount(rideType, trackType); *error += String::Format("rct2: 0x%08X\n", RideTypeTrackPaintFunctionsOld[rideType][trackType]); diff --git a/test/testpaint/Utils.cpp b/test/testpaint/Utils.cpp index 6c3cd7a10a..344a408b3d 100644 --- a/test/testpaint/Utils.cpp +++ b/test/testpaint/Utils.cpp @@ -67,9 +67,3 @@ namespace Utils { return (newPaintGetter != 0); } } - -extern "C" { - int getTrackSequenceCount(uint8 rideType, uint8 trackType) { - return Utils::getTrackSequenceCount(rideType, trackType); - } -} \ No newline at end of file diff --git a/test/testpaint/Utils.hpp b/test/testpaint/Utils.hpp index 3aaaab09ce..9ced7e4a2c 100644 --- a/test/testpaint/Utils.hpp +++ b/test/testpaint/Utils.hpp @@ -22,4 +22,4 @@ namespace Utils { int getTrackSequenceCount(uint8 rideType, uint8 trackType); bool rideSupportsTrackType(uint8 rideType, uint8 trackType); bool rideIsImplemented(uint8 rideType); -} \ No newline at end of file +} diff --git a/test/testpaint/generate.cpp b/test/testpaint/generate.cpp index 615692f9ef..253e3cd8f8 100644 --- a/test/testpaint/generate.cpp +++ b/test/testpaint/generate.cpp @@ -20,6 +20,7 @@ #include "intercept.h" #include "String.hpp" +#include "Utils.hpp" extern "C" { @@ -173,7 +174,7 @@ private: void GenerateTrackFunctionBody(int tabs, int trackType) { - int numSequences = getTrackSequenceCount(_rideType, trackType); + int numSequences = Utils::getTrackSequenceCount(_rideType, trackType); if (numSequences > 1) { WriteLine(tabs, "switch (trackSequence) {"); diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index b63ee38f6e..1f1655ad97 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -81,7 +81,6 @@ extern "C" { #endif void initHooks(); - int getTrackSequenceCount(uint8 rideType, uint8 trackType); bool testSupportSegments(uint8 rideType, uint8 trackType); bool testTunnels(uint8 rideType, uint8 trackType); bool testVerticalTunnels(uint8 rideType, uint8 trackType); diff --git a/test/testpaint/intercept_2.cpp b/test/testpaint/intercept_2.cpp index 70f9cae0f3..a8fff99c51 100644 --- a/test/testpaint/intercept_2.cpp +++ b/test/testpaint/intercept_2.cpp @@ -18,6 +18,7 @@ #include #include "intercept.h" +#include "Utils.hpp" extern "C" { #include "../../src/paint/paint.h" @@ -356,7 +357,7 @@ namespace Intercept2 int height = 48; TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; - int sequenceCount = getTrackSequenceCount(rideType, trackType); + int sequenceCount = Utils::getTrackSequenceCount(rideType, trackType); for (int chainLift = 0; chainLift < 2; chainLift++) { if (chainLift == 0) { @@ -526,7 +527,7 @@ namespace Intercept2 int height = 48; TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; - int sequenceCount = getTrackSequenceCount(rideType, trackType); + int sequenceCount = Utils::getTrackSequenceCount(rideType, trackType); for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { @@ -698,7 +699,7 @@ namespace Intercept2 int height = 48; TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; - int sequenceCount = getTrackSequenceCount(rideType, trackType); + int sequenceCount = Utils::getTrackSequenceCount(rideType, trackType); for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { From deb266c4432c10efa661b7476e6989b5e5f54f11 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 00:13:46 +0200 Subject: [PATCH 16/42] Extract SupportHeightCalls --- OpenRCT2.xcodeproj/project.pbxproj | 12 ++ test/testpaint/GeneralSupportHeightCall.cpp | 76 +++++++++ test/testpaint/GeneralSupportHeightCall.hpp | 52 ++++++ test/testpaint/Printer.cpp | 38 ++++- test/testpaint/Printer.hpp | 3 + test/testpaint/SegmentSupportHeightCall.cpp | 112 +++++++++++++ test/testpaint/SegmentSupportHeightCall.hpp | 36 +++++ test/testpaint/generate.cpp | 7 +- test/testpaint/intercept.h | 14 -- test/testpaint/intercept_2.cpp | 171 ++++---------------- test/testpaint/main.cpp | 33 ++++ test/testpaint/testpaint.vcxproj | 2 + 12 files changed, 394 insertions(+), 162 deletions(-) create mode 100644 test/testpaint/GeneralSupportHeightCall.cpp create mode 100644 test/testpaint/GeneralSupportHeightCall.hpp create mode 100644 test/testpaint/SegmentSupportHeightCall.cpp create mode 100644 test/testpaint/SegmentSupportHeightCall.hpp diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index b3952fc3af..a73bf33186 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -32,6 +32,8 @@ C606CCC71DB4054000FE4015 /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB81DB4054000FE4015 /* String.cpp */; }; C606CCC81DB4054000FE4015 /* TestTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCBA1DB4054000FE4015 /* TestTrack.cpp */; }; C606CCC91DB4054000FE4015 /* Utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCBC1DB4054000FE4015 /* Utils.cpp */; }; + C606CCCE1DB427A000FE4015 /* GeneralSupportHeightCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCCA1DB427A000FE4015 /* GeneralSupportHeightCall.cpp */; }; + C606CCCF1DB427A000FE4015 /* SegmentSupportHeightCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCCC1DB427A000FE4015 /* SegmentSupportHeightCall.cpp */; }; C612A8991D64825300B634CA /* vehicle_data.c in Sources */ = {isa = PBXBuildFile; fileRef = C612A8971D64825300B634CA /* vehicle_data.c */; }; C61FB7241CF86356004CE991 /* NetworkUser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61FB7221CF86356004CE991 /* NetworkUser.cpp */; }; C64FDA641D6D9A2100F259B9 /* air_powered_vertical_coaster.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F8BB1CDBC3B7009F9BFC /* air_powered_vertical_coaster.c */; }; @@ -520,6 +522,10 @@ C606CCBB1DB4054000FE4015 /* TestTrack.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TestTrack.hpp; sourceTree = ""; }; C606CCBC1DB4054000FE4015 /* Utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utils.cpp; sourceTree = ""; }; C606CCBD1DB4054000FE4015 /* Utils.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Utils.hpp; sourceTree = ""; }; + C606CCCA1DB427A000FE4015 /* GeneralSupportHeightCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GeneralSupportHeightCall.cpp; sourceTree = ""; }; + C606CCCB1DB427A000FE4015 /* GeneralSupportHeightCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = GeneralSupportHeightCall.hpp; sourceTree = ""; }; + C606CCCC1DB427A000FE4015 /* SegmentSupportHeightCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SegmentSupportHeightCall.cpp; sourceTree = ""; }; + C606CCCD1DB427A000FE4015 /* SegmentSupportHeightCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SegmentSupportHeightCall.hpp; sourceTree = ""; }; C612A8971D64825300B634CA /* vehicle_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vehicle_data.c; sourceTree = ""; }; C612A8981D64825300B634CA /* vehicle_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vehicle_data.h; sourceTree = ""; }; C61FB7221CF86356004CE991 /* NetworkUser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkUser.cpp; sourceTree = ""; usesTabs = 0; }; @@ -1191,6 +1197,8 @@ C606CCAD1DB4054000FE4015 /* data.h */, C606CCAE1DB4054000FE4015 /* FunctionCall.cpp */, C606CCAF1DB4054000FE4015 /* FunctionCall.hpp */, + C606CCCA1DB427A000FE4015 /* GeneralSupportHeightCall.cpp */, + C606CCCB1DB427A000FE4015 /* GeneralSupportHeightCall.hpp */, C606CCB01DB4054000FE4015 /* generate.cpp */, C606CCB11DB4054000FE4015 /* intercept_2.cpp */, C606CCB31DB4054000FE4015 /* intercept.h */, @@ -1198,6 +1206,8 @@ C606CCB51DB4054000FE4015 /* PaintIntercept.cpp */, C606CCB61DB4054000FE4015 /* Printer.cpp */, C606CCB71DB4054000FE4015 /* Printer.hpp */, + C606CCCC1DB427A000FE4015 /* SegmentSupportHeightCall.cpp */, + C606CCCD1DB427A000FE4015 /* SegmentSupportHeightCall.hpp */, C606CCB81DB4054000FE4015 /* String.cpp */, C606CCB91DB4054000FE4015 /* String.hpp */, C606CCBA1DB4054000FE4015 /* TestTrack.cpp */, @@ -2401,6 +2411,7 @@ C64FDA6C1D6D9A2100F259B9 /* inverted_impulse_coaster.c in Sources */, C64FDA6D1D6D9A2100F259B9 /* inverted_roller_coaster.c in Sources */, C64FDA6E1D6D9A2100F259B9 /* junior_roller_coaster.c in Sources */, + C606CCCF1DB427A000FE4015 /* SegmentSupportHeightCall.cpp in Sources */, C64FDA6F1D6D9A2100F259B9 /* lay_down_roller_coaster.c in Sources */, C64FDA701D6D9A2100F259B9 /* lim_launched_roller_coaster.c in Sources */, C64FDA711D6D9A2100F259B9 /* looping_roller_coaster.c in Sources */, @@ -2444,6 +2455,7 @@ C64FDA8F1D6D9A2100F259B9 /* mini_helicopters.c in Sources */, C606CCC51DB4054000FE4015 /* PaintIntercept.cpp in Sources */, C64FDA901D6D9A2100F259B9 /* monorail_cycles.c in Sources */, + C606CCCE1DB427A000FE4015 /* GeneralSupportHeightCall.cpp in Sources */, C64FDA911D6D9A2100F259B9 /* observation_tower.c in Sources */, C64FDA921D6D9A2100F259B9 /* space_rings.c in Sources */, C64FDA931D6D9A2100F259B9 /* spiral_slide.c in Sources */, diff --git a/test/testpaint/GeneralSupportHeightCall.cpp b/test/testpaint/GeneralSupportHeightCall.cpp new file mode 100644 index 0000000000..774414371b --- /dev/null +++ b/test/testpaint/GeneralSupportHeightCall.cpp @@ -0,0 +1,76 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#include + +#include "GeneralSupportHeightCall.hpp" + +bool GeneralSupportHeightCall::CallsMatch(SupportCall tileSupportCalls[4]) { + SupportCall baseCall = tileSupportCalls[0]; + for (int i = 1; i < 4; i++) { + if (tileSupportCalls[i] != baseCall) return false; + } + + return true; +} + +SupportCall *GeneralSupportHeightCall::FindMostCommonSupportCall(SupportCall calls[4]) { + std::map map; + + for (int i = 0; i < 4; ++i) { + if (map.count(calls[i]) == 0) { + map[calls[i]] = 1; + } else { + map[calls[i]] += 1; + } + } + + if (map.size() == 1) { + return &calls[0]; + } + + if (map.size() == 2) { + for (auto &&item : map) { + if (item.second == 3) { + return (SupportCall *)&item.first; + } + } + + return nullptr; + } + + if (map.size() == 3) { + for (auto &&item : map) { + if (item.second == 2) { + return (SupportCall *)&item.first; + } + } + + return nullptr; + } + + return nullptr; +} + +bool GeneralSupportHeightCall::AssertEquals(const SupportCall *lhs, const SupportCall *rhs) { + if (lhs == nullptr && rhs == nullptr) return true; + if (lhs == nullptr || rhs == nullptr) return false; + + if (lhs->height != rhs->height) return false; + if (lhs->slope != rhs->slope) return false; + + return true; +} diff --git a/test/testpaint/GeneralSupportHeightCall.hpp b/test/testpaint/GeneralSupportHeightCall.hpp new file mode 100644 index 0000000000..3127c634d8 --- /dev/null +++ b/test/testpaint/GeneralSupportHeightCall.hpp @@ -0,0 +1,52 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../../src/common.h" + +struct SupportCall { + sint32 height; + sint16 slope; + + friend bool operator==(const SupportCall& lhs, const SupportCall& rhs) { + if (lhs.height != rhs.height) return false; + if (lhs.slope != rhs.slope) return false; + + return true; + } + + bool operator!=(const SupportCall &other) const { + return !(*this == other); + } + + bool operator<(const SupportCall &other) const { + if (height != other.height) { + return height < other.height; + } + + return slope < other.slope; + } +}; + +class GeneralSupportHeightCall { +public: + static bool CallsMatch(SupportCall tileSupportCalls[4]); + + static SupportCall *FindMostCommonSupportCall(SupportCall calls[4]); + + static bool AssertEquals(const SupportCall *lhs, const SupportCall *rhs); +}; diff --git a/test/testpaint/Printer.cpp b/test/testpaint/Printer.cpp index bd3d8fb8b2..d59271556b 100644 --- a/test/testpaint/Printer.cpp +++ b/test/testpaint/Printer.cpp @@ -16,7 +16,6 @@ #include "Printer.hpp" #include "String.hpp" -#include "intercept.h" namespace Printer { @@ -37,6 +36,8 @@ namespace Printer { static std::string GetOffsetExpressionString(int offset); + static std::string PrintSegmentSupportHeightCall(SegmentSupportCall call); + std::string PrintFunctionCalls(std::vector calls, uint16 baseHeight) { std::string out; @@ -104,6 +105,41 @@ namespace Printer { return s; } + std::string PrintSegmentSupportHeightCalls(std::vector calls) { + std::string out = ""; + + for (auto &&call : calls) { + out += PrintSegmentSupportHeightCall(call); + } + + return out; + } + + static std::string PrintSegmentSupportHeightCall(SegmentSupportCall call) { + std::string out = ""; + + int segmentsPrinted = 0; + for (int i = 0; i < 9; i++) { + if (call.segments & segment_offsets[i]) { + if (segmentsPrinted > 0) { + out += " | "; + } + out += String::Format("SEGMENT_%02X", 0xB4 + 4 * i); + segmentsPrinted++; + } + } + + if (call.height == 0xFFFF) { + out += ", 0xFFFF"; + } else { + out += String::Format(", %d", call.height); + } + + out += String::Format(", 0x%02X\n", call.slope); + + return out; + } + static std::string GetImageIdString(uint32 imageId) { std::string result; diff --git a/test/testpaint/Printer.hpp b/test/testpaint/Printer.hpp index d8815bdee0..032aee77f7 100644 --- a/test/testpaint/Printer.hpp +++ b/test/testpaint/Printer.hpp @@ -20,8 +20,11 @@ #include #include "intercept.h" +#include "SegmentSupportHeightCall.hpp" namespace Printer { std::string PrintFunctionCall(function_call call, uint16 baseHeight); std::string PrintFunctionCalls(std::vector calls, uint16 baseHeight); + + std::string PrintSegmentSupportHeightCalls(std::vector calls); } diff --git a/test/testpaint/SegmentSupportHeightCall.cpp b/test/testpaint/SegmentSupportHeightCall.cpp new file mode 100644 index 0000000000..6bb5fcadc4 --- /dev/null +++ b/test/testpaint/SegmentSupportHeightCall.cpp @@ -0,0 +1,112 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#include "SegmentSupportHeightCall.hpp" + +extern "C" { +#include "../../src/paint/map_element/map_element.h" +} + +static bool SortSegmentSupportCalls(SegmentSupportCall lhs, SegmentSupportCall rhs) +{ + if (lhs.height != rhs.height) { + return lhs.height < rhs.height; + } + + if (lhs.slope != rhs.slope) { + return lhs.slope < rhs.slope; + } + + return lhs.segments < rhs.segments; +} + +std::vector SegmentSupportHeightCall::getSegmentCalls(support_height *supports, uint8 rotation) { + uint16 positionsRemaining = SEGMENTS_ALL; + + for (int i = 0; i < 9; i++) { + if (supports[i].height == 0 && supports[i].slope == 0xFF) { + positionsRemaining &= ~segment_offsets[i]; + } + } + + std::vector calls; + + while (positionsRemaining != 0) { + SegmentSupportCall call = {0}; + call.height = -1; + call.slope = -1; + + support_height referenceSupport = { 0 }; + + for (int i = 0; i < 9; i++) { + if (positionsRemaining & segment_offsets[i]) { + referenceSupport = supports[i]; + if (supports[i].height != 0) { + call.height = supports[i].height; + } + if (supports[i].slope != 0xFF) { + call.slope = supports[i].slope; + } + break; + } + } + + uint16 positionsMatched = 0; + for (int i = 0; i < 9; i++) { + if (supports[i].height == referenceSupport.height && supports[i].slope == referenceSupport.slope) { + positionsMatched |= segment_offsets[i]; + } + } + positionsRemaining &= ~positionsMatched; + + call.segments = paint_util_rotate_segments(positionsMatched, (4 - rotation) % 4); + + calls.push_back(call); + } + + if (calls.size() > 1) { + std::sort(calls.begin(), calls.end(), SortSegmentSupportCalls); + } + + return calls; +} + +bool SegmentSupportHeightCall::CallsMatch(std::vector tileSegmentSupportCalls[4]) +{ + std::vector baseCallList = tileSegmentSupportCalls[0]; + for (int i = 1; i < 4; i++) { + if (!CallsEqual(baseCallList, tileSegmentSupportCalls[i])) { + return false; + } + } + + return true; +} + +bool SegmentSupportHeightCall::CallsEqual(std::vector lhs, std::vector rhs) +{ + if (lhs.size() != rhs.size()) return false; + for (size_t i = 0; i < lhs.size(); ++i) { + if (lhs[i].segments != rhs[i].segments) + return false; + if (lhs[i].height != rhs[i].height) + return false; + if (lhs[i].slope != rhs[i].slope) + return false; + } + + return true; +} diff --git a/test/testpaint/SegmentSupportHeightCall.hpp b/test/testpaint/SegmentSupportHeightCall.hpp new file mode 100644 index 0000000000..5a87709967 --- /dev/null +++ b/test/testpaint/SegmentSupportHeightCall.hpp @@ -0,0 +1,36 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include + +#include "../../src/common.h" +#include "../../src/paint/paint.h" + +struct SegmentSupportCall +{ + uint16 segments; + sint32 height; + sint16 slope; +}; + +class SegmentSupportHeightCall { +public: + static std::vector getSegmentCalls(support_height supports[9], uint8 rotation); + static bool CallsMatch(std::vector tileSegmentSupportCalls[4]); + static bool CallsEqual(std::vector lhs, std::vector rhs); +}; diff --git a/test/testpaint/generate.cpp b/test/testpaint/generate.cpp index 253e3cd8f8..3f5a5a7507 100644 --- a/test/testpaint/generate.cpp +++ b/test/testpaint/generate.cpp @@ -19,6 +19,7 @@ #include #include "intercept.h" +#include "SegmentSupportHeightCall.hpp" #include "String.hpp" #include "Utils.hpp" @@ -401,7 +402,7 @@ private: std::vector calls[4], chainLiftCalls[4], cableLiftCalls[4]; Intercept2::TunnelCall tileTunnelCalls[4][4]; sint16 verticalTunnelHeights[4]; - std::vector segmentSupportCalls[4]; + std::vector segmentSupportCalls[4]; support_height generalSupports[4] = { 0 }; for (int direction = 0; direction < 4; direction++) { rct_map_element mapElement = { 0 }; @@ -431,7 +432,7 @@ private: } } - segmentSupportCalls[direction] = Intercept2::getSegmentCalls(gSupportSegments, direction); + segmentSupportCalls[direction] = SegmentSupportHeightCall::getSegmentCalls(gSupportSegments, direction); generalSupports[direction] = gSupport; if (gSupport.slope != 0xFF && gSupport.height != 0) { @@ -894,7 +895,7 @@ private: WriteLine(tabs, "paint_util_push_tunnel_rotated(direction, height%s, TUNNEL_%d);", GetOffsetExpressionString(offset).c_str(), type); } - void GenerateSegmentSupportCall(int tabs, std::vector segmentSupportCalls[4]) + void GenerateSegmentSupportCall(int tabs, std::vector segmentSupportCalls[4]) { for (size_t i = 0; i < segmentSupportCalls[0].size(); i++) { diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index 1f1655ad97..581482bae7 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -108,19 +108,6 @@ namespace Intercept2 static const uint32 DEFAULT_SCHEME_MISC = COLOUR_DARK_PURPLE << 19 | COLOUR_LIGHT_PURPLE << 24 | 0xA0000000; static const uint32 DEFAULT_SCHEME_3 = COLOUR_BRIGHT_PURPLE << 19 | COLOUR_DARK_BLUE << 24 | 0xA0000000; - struct SegmentSupportCall - { - uint16 segments; - sint32 height; - sint16 slope; - }; - - struct SupportCall - { - sint32 height; - sint16 slope; - }; - enum { TUNNELCALL_SKIPPED, TUNNELCALL_NONE, @@ -134,7 +121,6 @@ namespace Intercept2 }; sint16 getTunnelOffset(uint32 baseHeight, tunnel_entry calls[3]); - std::vector getSegmentCalls(support_height supports[9], uint8 rotation); } #endif diff --git a/test/testpaint/intercept_2.cpp b/test/testpaint/intercept_2.cpp index a8fff99c51..c972b32bbc 100644 --- a/test/testpaint/intercept_2.cpp +++ b/test/testpaint/intercept_2.cpp @@ -18,6 +18,9 @@ #include #include "intercept.h" +#include "GeneralSupportHeightCall.hpp" +#include "Printer.hpp" +#include "SegmentSupportHeightCall.hpp" #include "Utils.hpp" extern "C" { @@ -83,141 +86,9 @@ namespace Intercept2 gSupport.slope = 0xFF; } - static bool SortSegmentSupportCalls(SegmentSupportCall lhs, SegmentSupportCall rhs) - { - if (lhs.height != rhs.height) { - return lhs.height < rhs.height; - } - - if (lhs.slope != rhs.slope) { - return lhs.slope < rhs.slope; - } - - return lhs.segments < rhs.segments; - } - - std::vector getSegmentCalls(support_height supports[9], uint8 rotation) - { - uint16 positionsRemaining = SEGMENTS_ALL; - - for (int i = 0; i < 9; i++) { - if (supports[i].height == 0 && supports[i].slope == 0xFF) { - positionsRemaining &= ~segment_offsets[i]; - } - } - - std::vector calls; - - while (positionsRemaining != 0) { - SegmentSupportCall call = {0}; - call.height = -1; - call.slope = -1; - - support_height referenceSupport = { 0 }; - - for (int i = 0; i < 9; i++) { - if (positionsRemaining & segment_offsets[i]) { - referenceSupport = supports[i]; - if (supports[i].height != 0) { - call.height = supports[i].height; - } - if (supports[i].slope != 0xFF) { - call.slope = supports[i].slope; - } - break; - } - } - - uint16 positionsMatched = 0; - for (int i = 0; i < 9; i++) { - if (supports[i].height == referenceSupport.height && supports[i].slope == referenceSupport.slope) { - positionsMatched |= segment_offsets[i]; - } - } - positionsRemaining &= ~positionsMatched; - - call.segments = paint_util_rotate_segments(positionsMatched, (4 - rotation) % 4); - - calls.push_back(call); - } - - if (calls.size() > 1) { - std::sort(calls.begin(), calls.end(), SortSegmentSupportCalls); - } - - return calls; - } - - static bool SegmentCallEquals(std::vector lhs, std::vector rhs) - { - if (lhs.size() != rhs.size()) return false; - for (size_t i = 0; i < lhs.size(); ++i) { - if (lhs[i].segments != rhs[i].segments) - return false; - if (lhs[i].height != rhs[i].height) - return false; - if (lhs[i].slope != rhs[i].slope) - return false; - } - - return true; - } - - static bool segmentCallsMatch(std::vector tileSegmentSupportCalls[4]) - { - std::vector baseCallList = tileSegmentSupportCalls[0]; - for (int i = 1; i < 4; i++) { - if (!SegmentCallEquals(baseCallList, tileSegmentSupportCalls[i])) { - return false; - } - } - - return true; - } - - static bool supportCallsMatch(SupportCall tileSupportCalls[4]) - { - SupportCall baseCall = tileSupportCalls[0]; - for (int i = 1; i < 4; i++) { - if (tileSupportCalls[i].height != baseCall.height) return false; - if (tileSupportCalls[i].slope != baseCall.slope) return false; - } - - return true; - } - static void printSegmentSupports(utf8string out, size_t len, std::vector segmentCalls) { - for (auto &&call : segmentCalls) { - int segmentsPrinted = 0; - for (int i = 0; i < 9; i++) { - if (call.segments & segment_offsets[i]) { - if (segmentsPrinted > 0) { - size_t slen = strlen(out); - if (slen < len) - snprintf(out + slen, len - slen, " | "); - } - size_t slen = strlen(out); - if (slen < len) - snprintf(out + slen, slen - len, "SEGMENT_%02X", 0xB4 + 4 * i); - segmentsPrinted++; - } - } - - if (call.height == 0xFFFF) { - size_t slen = strlen(out); - if (slen < len) - snprintf(out + slen, len - slen, ", 0xFFFF"); - } else { - size_t slen = strlen(out); - if (slen < len) - snprintf(out + slen, len - slen, ", %d", call.height); - } - - size_t slen = strlen(out); - if (slen < len) - snprintf(out + slen, len - slen, ", 0x%02X\n", call.slope); - } + snprintf(out, len, "%s", Printer::PrintSegmentSupportHeightCalls(segmentCalls).c_str()); } static bool tunnelCallsLineUp(TunnelCall tunnelCalls[4][4]) @@ -387,7 +258,7 @@ namespace Intercept2 trackSequence ); - tileSegmentSupportCalls[direction] = getSegmentCalls(gSupportSegments, direction); + tileSegmentSupportCalls[direction] = SegmentSupportHeightCall::getSegmentCalls(gSupportSegments, direction); tileGeneralSupportCalls[direction].height = -1; tileGeneralSupportCalls[direction].slope = -1; @@ -395,13 +266,16 @@ namespace Intercept2 tileGeneralSupportCalls[direction].height = gSupport.height; } if (gSupport.slope != 0xFF) { - tileGeneralSupportCalls[direction].height = gSupport.height; + tileGeneralSupportCalls[direction].slope = gSupport.slope; } } - if (!segmentCallsMatch(tileSegmentSupportCalls)) { + if (!SegmentSupportHeightCall::CallsMatch(tileSegmentSupportCalls)) { // TODO: if 3 directions do share the same mask, use that call list as a reference. printf("Original segment calls didn't match. [trackSequence:%d chainLift:%d]\n", trackSequence, chainLift); + for (int i = 0; i < 4; i++) { + printf("# %d\n%s", i, Printer::PrintSegmentSupportHeightCalls(tileSegmentSupportCalls[i]).c_str()); + } continue; } @@ -415,9 +289,10 @@ namespace Intercept2 continue; } - std::vector newCalls = getSegmentCalls(gSupportSegments, direction); + std::vector newCalls = SegmentSupportHeightCall::getSegmentCalls(gSupportSegments, + direction); - if (!SegmentCallEquals(tileSegmentSupportCalls[0], newCalls)) { + if (!SegmentSupportHeightCall::CallsEqual(tileSegmentSupportCalls[0], newCalls)) { // TODO put this into *error utf8string diff = new utf8[2048]; snprintf(diff, 2048, "<<< EXPECTED\n"); @@ -440,14 +315,22 @@ namespace Intercept2 } } - if (!supportCallsMatch(tileGeneralSupportCalls)) { - // TODO: if 3 directions do share the output, use that. - printf("Original support calls didn't match. [trackSequence:%d chainLift:%d]\n", trackSequence, chainLift); - continue; - } - SupportCall referenceGeneralSupportCall = tileGeneralSupportCalls[0]; + if (!GeneralSupportHeightCall::CallsMatch(tileGeneralSupportCalls)) { + SupportCall *found = GeneralSupportHeightCall::FindMostCommonSupportCall(tileGeneralSupportCalls); + if (found == nullptr) { + // TODO: if 3 directions do share the output, use that. + printf("Original support calls didn't match. [trackSequence:%d chainLift:%d]\n", trackSequence, chainLift); + for (int i = 0; i < 4; ++i) { + printf("[%d, 0x%02X] ", tileGeneralSupportCalls[i].height, tileGeneralSupportCalls[i].slope); + } + printf("\n"); + continue; + } + referenceGeneralSupportCall = *found; + } + for (int direction = 0; direction < 4; direction++) { ResetSegmentHeights(); diff --git a/test/testpaint/main.cpp b/test/testpaint/main.cpp index 78383d4482..68bac9d702 100644 --- a/test/testpaint/main.cpp +++ b/test/testpaint/main.cpp @@ -358,7 +358,40 @@ static void PrintRideTypes() } } +#import "GeneralSupportHeightCall.hpp" + +static void TestGeneralSupportHeightCall() { + SupportCall callA = {16, 0x20}; + SupportCall callB = {32, 0x20}; + SupportCall callC = {48, 0x20}; + SupportCall callD = {48, 0x1F}; + + SupportCall *result; + + SupportCall groupA[4] = {callA, callA, callA, callA}; + result = GeneralSupportHeightCall::FindMostCommonSupportCall(groupA); + assert(GeneralSupportHeightCall::AssertEquals(result, &callA)); + + SupportCall groupB[4] = {callB, callA, callA, callA}; + result = GeneralSupportHeightCall::FindMostCommonSupportCall(groupB); + assert(GeneralSupportHeightCall::AssertEquals(result, &callA)); + + SupportCall groupC[4] = {callB, callA, callB, callA}; + result = GeneralSupportHeightCall::FindMostCommonSupportCall(groupC); + assert(GeneralSupportHeightCall::AssertEquals(result, nullptr)); + + SupportCall groupD[4] = {callB, callC, callB, callA}; + result = GeneralSupportHeightCall::FindMostCommonSupportCall(groupD); + assert(GeneralSupportHeightCall::AssertEquals(result, &callB)); + + SupportCall groupE[4] = {callD, callC, callB, callA}; + result = GeneralSupportHeightCall::FindMostCommonSupportCall(groupE); + assert(GeneralSupportHeightCall::AssertEquals(result, nullptr)); +} + int main(int argc, char *argv[]) { + TestGeneralSupportHeightCall(); + std::vector testCases; bool generate = false; diff --git a/test/testpaint/testpaint.vcxproj b/test/testpaint/testpaint.vcxproj index 5ecb055bdc..1a99508a9e 100644 --- a/test/testpaint/testpaint.vcxproj +++ b/test/testpaint/testpaint.vcxproj @@ -96,11 +96,13 @@ + + From 1bd87537ebbc8d99f34f66fb4a0eca41e59f5ee6 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 00:31:53 +0200 Subject: [PATCH 17/42] Attempt to fix automatic segment heights --- test/testpaint/SegmentSupportHeightCall.cpp | 40 +++++++++++++++++++++ test/testpaint/SegmentSupportHeightCall.hpp | 13 +++++++ test/testpaint/intercept_2.cpp | 17 +++++---- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/test/testpaint/SegmentSupportHeightCall.cpp b/test/testpaint/SegmentSupportHeightCall.cpp index 6bb5fcadc4..c769021d92 100644 --- a/test/testpaint/SegmentSupportHeightCall.cpp +++ b/test/testpaint/SegmentSupportHeightCall.cpp @@ -14,6 +14,8 @@ *****************************************************************************/ #pragma endregion +#include + #include "SegmentSupportHeightCall.hpp" extern "C" { @@ -110,3 +112,41 @@ bool SegmentSupportHeightCall::CallsEqual(std::vector lhs, s return true; } + +std::vector* SegmentSupportHeightCall::FindMostCommonSupportCall(std::vector *calls) { + std::map, int> map; + + for (int i = 0; i < 4; ++i) { + if (map.count(calls[i]) == 0) { + map[calls[i]] = 1; + } else { + map[calls[i]] += 1; + } + } + + if (map.size() == 1) { + return &calls[0]; + } + + if (map.size() == 2) { + for (auto &&item : map) { + if (item.second == 3) { + return (std::vector *)&item.first; + } + } + + return nullptr; + } + + if (map.size() == 3) { + for (auto &&item : map) { + if (item.second == 2) { + return (std::vector *)&item.first; + } + } + + return nullptr; + } + + return nullptr; +} diff --git a/test/testpaint/SegmentSupportHeightCall.hpp b/test/testpaint/SegmentSupportHeightCall.hpp index 5a87709967..bc7d159b2c 100644 --- a/test/testpaint/SegmentSupportHeightCall.hpp +++ b/test/testpaint/SegmentSupportHeightCall.hpp @@ -26,6 +26,18 @@ struct SegmentSupportCall uint16 segments; sint32 height; sint16 slope; + + bool operator<(const SegmentSupportCall &other) const { + if (height != other.height) { + return height < other.height; + } + + if (segments != other.segments) { + return segments < other.segments; + } + + return slope < other.slope; + } }; class SegmentSupportHeightCall { @@ -33,4 +45,5 @@ public: static std::vector getSegmentCalls(support_height supports[9], uint8 rotation); static bool CallsMatch(std::vector tileSegmentSupportCalls[4]); static bool CallsEqual(std::vector lhs, std::vector rhs); + static std::vector * FindMostCommonSupportCall(std::vector calls[4]); }; diff --git a/test/testpaint/intercept_2.cpp b/test/testpaint/intercept_2.cpp index c972b32bbc..8fdd7cbba7 100644 --- a/test/testpaint/intercept_2.cpp +++ b/test/testpaint/intercept_2.cpp @@ -270,13 +270,19 @@ namespace Intercept2 } } + std::vector referenceCalls = tileSegmentSupportCalls[0]; + if (!SegmentSupportHeightCall::CallsMatch(tileSegmentSupportCalls)) { - // TODO: if 3 directions do share the same mask, use that call list as a reference. - printf("Original segment calls didn't match. [trackSequence:%d chainLift:%d]\n", trackSequence, chainLift); - for (int i = 0; i < 4; i++) { - printf("# %d\n%s", i, Printer::PrintSegmentSupportHeightCalls(tileSegmentSupportCalls[i]).c_str()); + std::vector *found = SegmentSupportHeightCall::FindMostCommonSupportCall(tileSegmentSupportCalls); + if (found != nullptr) { + referenceCalls = *found; + } else { + printf("Original segment calls didn't match. [trackSequence:%d chainLift:%d]\n", trackSequence, chainLift); + for (int i = 0; i < 4; i++) { + printf("# %d\n%s", i, Printer::PrintSegmentSupportHeightCalls(tileSegmentSupportCalls[i]).c_str()); + } + continue; } - continue; } for (int direction = 0; direction < 4; direction++) { @@ -320,7 +326,6 @@ namespace Intercept2 if (!GeneralSupportHeightCall::CallsMatch(tileGeneralSupportCalls)) { SupportCall *found = GeneralSupportHeightCall::FindMostCommonSupportCall(tileGeneralSupportCalls); if (found == nullptr) { - // TODO: if 3 directions do share the output, use that. printf("Original support calls didn't match. [trackSequence:%d chainLift:%d]\n", trackSequence, chainLift); for (int i = 0; i < 4; ++i) { printf("[%d, 0x%02X] ", tileGeneralSupportCalls[i].height, tileGeneralSupportCalls[i].slope); From cb4519e9c5848ca1cc000efd883e40fa5c21be8f Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 10:21:53 +0200 Subject: [PATCH 18/42] Move support height testing --- test/testpaint/TestTrack.cpp | 332 +++++++++++++++++++++++++-------- test/testpaint/TestTrack.hpp | 3 - test/testpaint/intercept.h | 5 +- test/testpaint/intercept_2.cpp | 183 +----------------- 4 files changed, 263 insertions(+), 260 deletions(-) diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index 6adca06ad7..6f975a5337 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -18,11 +18,13 @@ #include #include "intercept.h" +#include "FunctionCall.hpp" +#include "GeneralSupportHeightCall.hpp" #include "Printer.hpp" +#include "SegmentSupportHeightCall.hpp" #include "String.hpp" #include "TestTrack.hpp" #include "Utils.hpp" -#include "FunctionCall.hpp" extern "C" { #include "../../src/ride/ride.h" @@ -68,23 +70,19 @@ static void CallNew( newPaintFunction(0, trackSequence, direction, height, mapElement); } +typedef uint8 (*TestFunction)(uint8, uint8, uint8, std::string *); + +static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error); + +static uint8 TestTrackElementSegmentSupportHeight(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error); + +static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error); + uint8 TestTrack::TestPaintTrackElement(uint8 rideType, uint8 trackType) { if (!Utils::rideSupportsTrackType(rideType, trackType)) { return TEST_FAILED; } - - std::string error = ""; - uint8 retVal = TestPaintTrackElementCalls(rideType, trackType, &error); - - if (retVal != TEST_SUCCESS) { - printf("%s\n", error.c_str()); - } - - return retVal; -} - -uint8 TestTrack::TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std::string *error) { if (rideType == RIDE_TYPE_CHAIRLIFT) { if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION || trackType == TRACK_ELEM_END_STATION) { @@ -93,6 +91,32 @@ uint8 TestTrack::TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std } } + int sequenceCount = Utils::getTrackSequenceCount(rideType, trackType); + std::string error = String::Format("rct2: 0x%08X\n", RideTypeTrackPaintFunctionsOld[rideType][trackType]); + + uint8 retVal = TEST_SUCCESS; + + static TestFunction functions[] = { + TestTrackElementPaintCalls, + TestTrackElementSegmentSupportHeight, + TestTrackElementGeneralSupportHeight + }; + + for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { + for (auto &&function : functions) { + retVal = function(rideType, trackType, trackSequence, &error); + } + + if (retVal != TEST_SUCCESS) { + printf("%s\n", error.c_str()); + return retVal; + } + } + + return retVal; +} + +static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error) { uint8 rideIndex = 0; uint16 height = 3 * 16; @@ -108,11 +132,8 @@ uint8 TestTrack::TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std gSurfaceElement = &surfaceElement; gDidPassSurface = true; - intercept_reset_environment(); - - int sequenceCount = Utils::getTrackSequenceCount(rideType, trackType); - - *error += String::Format("rct2: 0x%08X\n", RideTypeTrackPaintFunctionsOld[rideType][trackType]); + Intercept2::ResetEnvironment(); + Intercept2::ResetTunnels(); function_call callBuffer[256] = {0}; int callCount = 0; @@ -128,77 +149,234 @@ uint8 TestTrack::TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std for (int currentRotation = 0; currentRotation < 4; currentRotation++) { gCurrentRotation = currentRotation; for (int direction = 0; direction < 4; direction++) { - for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { - RCT2_GLOBAL(0x009DE56A, sint16) = 64; // x - RCT2_GLOBAL(0x009DE56E, sint16) = 64; // y + RCT2_GLOBAL(0x009DE56A, sint16) = 64; // x + RCT2_GLOBAL(0x009DE56E, sint16) = 64; // y - std::string caseName = String::Format( - "[direction:%d trackSequence:%d chainLift:%d inverted:%d]", - direction, trackSequence, chainLift, inverted + std::string caseName = String::Format( + "[direction:%d trackSequence:%d chainLift:%d inverted:%d]", + direction, trackSequence, chainLift, inverted + ); + + intercept_clear_calls(); + Intercept2::ResetSupportHeights(); + + CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); + + callCount = intercept_get_calls(callBuffer); + std::vector oldCalls; + oldCalls.insert(oldCalls.begin(), callBuffer, callBuffer + callCount); + + intercept_clear_calls(); + testpaint_clear_ignore(); + Intercept2::ResetSupportHeights(); + + CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); + + if (testpaint_is_ignored(direction, trackSequence)) { + *error += String::Format("[ IGNORED ] %s\n", caseName.c_str()); + continue; + } + + callCount = intercept_get_calls(callBuffer); + std::vector newCalls; + newCalls.insert(newCalls.begin(), callBuffer, callBuffer + callCount); + + bool sucess = true; + if (oldCalls.size() != newCalls.size()) { + *error += String::Format( + "Call counts don't match (was %d, expected %d). %s\n", + newCalls.size(), oldCalls.size(), caseName.c_str() ); + sucess = false; + } else if (!FunctionCall::AssertsEquals(oldCalls, newCalls)) { + *error += String::Format("Calls don't match. %s\n", caseName.c_str()); + sucess = false; + } - intercept_clear_calls(); - intercept_reset_segment_heights(); + if (!sucess) { + *error += " Expected:\n"; + *error += Printer::PrintFunctionCalls(oldCalls, height); + *error += " Actual:\n"; + *error += Printer::PrintFunctionCalls(newCalls, height); - CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); - - callCount = intercept_get_calls(callBuffer); - std::vector oldCalls; - oldCalls.insert(oldCalls.begin(), callBuffer, callBuffer + callCount); - - intercept_clear_calls(); - testpaint_clear_ignore(); - intercept_reset_segment_heights(); - - CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); - - if (testpaint_is_ignored(direction, trackSequence)) { - *error += String::Format("[ IGNORED ] %s\n", caseName.c_str()); - continue; - } - - callCount = intercept_get_calls(callBuffer); - std::vector newCalls; - newCalls.insert(newCalls.begin(), callBuffer, callBuffer + callCount); - - bool sucess = true; - if (oldCalls.size() != newCalls.size()) { - *error += String::Format( - "Call counts don't match (was %d, expected %d). %s\n", - newCalls.size(), oldCalls.size(), caseName.c_str() - ); - sucess = false; - } else if (!FunctionCall::AssertsEquals(oldCalls, newCalls)) { - *error += String::Format("Calls don't match. %s\n", caseName.c_str()); - sucess = false; - } - - if (!sucess) { - *error += " Expected:\n"; - *error += Printer::PrintFunctionCalls(oldCalls, height); - *error += " Actual:\n"; - *error += Printer::PrintFunctionCalls(newCalls, height); - - return TEST_FAILED; - } + return TEST_FAILED; } } } - bool segmentSuccess = testSupportSegments(rideType, trackType); - if (!segmentSuccess) { - return TEST_FAILED; + return TEST_SUCCESS; +} + +static uint8 TestTrackElementSegmentSupportHeight(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error) { + uint8 rideIndex = 0; + uint16 height = 3 * 16; + + rct_map_element mapElement = {0}; + mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; + mapElement.properties.track.type = trackType; + mapElement.base_height = height / 16; + g_currently_drawn_item = &mapElement; + + rct_map_element surfaceElement = {0}; + surfaceElement.type = MAP_ELEMENT_TYPE_SURFACE; + surfaceElement.base_height = 2; + gSurfaceElement = &surfaceElement; + gDidPassSurface = true; + + Intercept2::ResetEnvironment(); + Intercept2::ResetTunnels(); + + // TODO: Test Chainlift + // TODO: Test Maze + // TODO: Allow skip + + std::string state = String::Format("[trackSequence:%d chainLift:%d]", trackSequence, 0); + + std::vector tileSegmentSupportCalls[4]; + + for (int direction = 0; direction < 4; direction++) { + Intercept2::ResetSupportHeights(); + + CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); + + tileSegmentSupportCalls[direction] = SegmentSupportHeightCall::getSegmentCalls(gSupportSegments, direction); } - bool tunnelSuccess = testTunnels(rideType, trackType); - if (!tunnelSuccess) { - return TEST_FAILED; + std::vector referenceCalls = tileSegmentSupportCalls[0]; + + if (!SegmentSupportHeightCall::CallsMatch(tileSegmentSupportCalls)) { + std::vector *found = SegmentSupportHeightCall::FindMostCommonSupportCall( + tileSegmentSupportCalls); + if (found != nullptr) { + referenceCalls = *found; + } else { + *error += String::Format("Original segment calls didn't match. %s\n", state.c_str()); + for (int direction = 0; direction < 4; direction++) { + *error += String::Format("# %d\n", direction); + *error += Printer::PrintSegmentSupportHeightCalls(tileSegmentSupportCalls[direction]); + } + return TEST_FAILED; + } } - bool verticalTunnelSuccess = testVerticalTunnels(rideType, trackType); - if (!verticalTunnelSuccess) { - return TEST_FAILED; + for (int direction = 0; direction < 4; direction++) { + Intercept2::ResetSupportHeights(); + + testpaint_clear_ignore(); + CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); + if (testpaint_is_ignored(direction, trackSequence)) { + continue; + } + + std::vector newCalls = SegmentSupportHeightCall::getSegmentCalls(gSupportSegments, + direction); + if (!SegmentSupportHeightCall::CallsEqual(referenceCalls, newCalls)) { + *error += String::Format( + "Segment support heights didn't match. [direction:%d] %s\n", + direction, state.c_str() + ); + *error += " Expected:\n"; + *error += Printer::PrintSegmentSupportHeightCalls(referenceCalls); + *error += " Actual:\n"; + *error += Printer::PrintSegmentSupportHeightCalls(newCalls); + + return TEST_FAILED; + } } return TEST_SUCCESS; -} \ No newline at end of file +} + +static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error) { + uint8 rideIndex = 0; + uint16 height = 3 * 16; + + rct_map_element mapElement = {0}; + mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; + mapElement.properties.track.type = trackType; + mapElement.base_height = height / 16; + g_currently_drawn_item = &mapElement; + + rct_map_element surfaceElement = {0}; + surfaceElement.type = MAP_ELEMENT_TYPE_SURFACE; + surfaceElement.base_height = 2; + gSurfaceElement = &surfaceElement; + gDidPassSurface = true; + + Intercept2::ResetEnvironment(); + Intercept2::ResetTunnels(); + + // TODO: Test Chainlift + // TODO: Test Maze + // TODO: Allow skip + + std::string state = String::Format("[trackSequence:%d chainLift:%d]", trackSequence, 0); + + SupportCall tileGeneralSupportCalls[4]; + for (int direction = 0; direction < 4; direction++) { + Intercept2::ResetSupportHeights(); + + CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); + + tileGeneralSupportCalls[direction].height = -1; + tileGeneralSupportCalls[direction].slope = -1; + if (gSupport.height != 0) { + tileGeneralSupportCalls[direction].height = gSupport.height; + } + if (gSupport.slope != 0xFF) { + tileGeneralSupportCalls[direction].slope = gSupport.slope; + } + } + + SupportCall referenceGeneralSupportCall = tileGeneralSupportCalls[0]; + if (!GeneralSupportHeightCall::CallsMatch(tileGeneralSupportCalls)) { + SupportCall *found = GeneralSupportHeightCall::FindMostCommonSupportCall(tileGeneralSupportCalls); + if (found == nullptr) { + *error += String::Format("Original support calls didn't match. %s\n", state.c_str()); + for (int i = 0; i < 4; ++i) { + *error += String::Format("[%d, 0x%02X] ", tileGeneralSupportCalls[i].height, tileGeneralSupportCalls[i].slope); + } + *error += "\n"; + return TEST_FAILED; + } + referenceGeneralSupportCall = *found; + } + + for (int direction = 0; direction < 4; direction++) { + Intercept2::ResetSupportHeights(); + + testpaint_clear_ignore(); + CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); + if (testpaint_is_ignored(direction, trackSequence)) { + continue; + } + + + if (referenceGeneralSupportCall.height != -1) { + if (gSupport.height != referenceGeneralSupportCall.height) { + *error += String::Format( + "General support heights didn't match. (expected height + %d, actual: height + %d) [direction:%d] %s\n", + referenceGeneralSupportCall.height - height, + gSupport.height - height, + direction, + state.c_str() + ); + return TEST_FAILED; + } + } + if (referenceGeneralSupportCall.slope != -1) { + if (gSupport.slope != referenceGeneralSupportCall.slope) { + *error += String::Format( + "General support slopes didn't match. (expected 0x%02X, actual: 0x%02X) [direction:%d] %s\n", + referenceGeneralSupportCall.slope, + gSupport.slope, + direction, + state.c_str() + ); + return TEST_FAILED; + } + } + } + + return TEST_SUCCESS; +} diff --git a/test/testpaint/TestTrack.hpp b/test/testpaint/TestTrack.hpp index 7f049766aa..7eb3ff1d07 100644 --- a/test/testpaint/TestTrack.hpp +++ b/test/testpaint/TestTrack.hpp @@ -23,7 +23,4 @@ class TestTrack { public: static uint8 TestPaintTrackElement(uint8 rideType, uint8 trackType); - -private: - static uint8 TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std::string * error); }; diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index 581482bae7..0aed39fcf7 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -81,7 +81,6 @@ extern "C" { #endif void initHooks(); - bool testSupportSegments(uint8 rideType, uint8 trackType); bool testTunnels(uint8 rideType, uint8 trackType); bool testVerticalTunnels(uint8 rideType, uint8 trackType); void intercept_clear_calls(); @@ -121,6 +120,10 @@ namespace Intercept2 }; sint16 getTunnelOffset(uint32 baseHeight, tunnel_entry calls[3]); + + void ResetEnvironment(); + void ResetTunnels(); + void ResetSupportHeights(); } #endif diff --git a/test/testpaint/intercept_2.cpp b/test/testpaint/intercept_2.cpp index 8fdd7cbba7..2673b0cb36 100644 --- a/test/testpaint/intercept_2.cpp +++ b/test/testpaint/intercept_2.cpp @@ -33,7 +33,7 @@ extern "C" { namespace Intercept2 { - static void ResetEnvironment() { + void ResetEnvironment() { gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE; gTrackColours[SCHEME_TRACK] = DEFAULT_SCHEME_TRACK; gTrackColours[SCHEME_SUPPORTS] = DEFAULT_SCHEME_SUPPORTS; @@ -58,7 +58,7 @@ namespace Intercept2 g141E9DB = G141E9DB_FLAG_1 | G141E9DB_FLAG_2; } - static void ResetTunnels() { + void ResetTunnels() { gLeftTunnelCount = 0; gRightTunnelCount = 0; @@ -75,7 +75,7 @@ namespace Intercept2 gRightTunnels[0].type = 0xFF; } - static void ResetSegmentHeights() { + void ResetSupportHeights() { for (int s = 0; s < 9; ++s) { gSupportSegments[s].height = 0; @@ -86,11 +86,6 @@ namespace Intercept2 gSupport.slope = 0xFF; } - static void printSegmentSupports(utf8string out, size_t len, std::vector segmentCalls) - { - snprintf(out, len, "%s", Printer::PrintSegmentSupportHeightCalls(segmentCalls).c_str()); - } - static bool tunnelCallsLineUp(TunnelCall tunnelCalls[4][4]) { for (int side = 0; side < 4; ++side) { @@ -207,171 +202,6 @@ namespace Intercept2 printf("\n"); } - static bool testSupportSegments(uint8 rideType, uint8 trackType) - { - uint8 rideIndex = 0; - rct_map_element mapElement = {0}; - mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; - mapElement.properties.track.type = trackType; - mapElement.base_height = 3; - - g_currently_drawn_item = &mapElement; - - rct_map_element surfaceElement = {0}; - surfaceElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; - surfaceElement.type = MAP_ELEMENT_TYPE_SURFACE; - surfaceElement.base_height = 2; - - ResetEnvironment(); - ResetTunnels(); - - int height = 48; - - TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; - int sequenceCount = Utils::getTrackSequenceCount(rideType, trackType); - - for (int chainLift = 0; chainLift < 2; chainLift++) { - if (chainLift == 0) { - mapElement.type &= ~0x80; - } else { - mapElement.type |= 0x80; - } - - for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { - std::vector tileSegmentSupportCalls[4]; - SupportCall tileGeneralSupportCalls[4]; - - for (int direction = 0; direction < 4; direction++) { - ResetSegmentHeights(); - - uint32 *trackDirectionList = (uint32 *)RideTypeTrackPaintFunctionsOld[rideType][trackType]; - - // Have to call from this point as it pushes esi and expects callee to pop it - RCT2_CALLPROC_X( - 0x006C4934, - rideType, - (int) trackDirectionList, - direction, - height, - (int) &mapElement, - rideIndex * sizeof(rct_ride), - trackSequence - ); - - tileSegmentSupportCalls[direction] = SegmentSupportHeightCall::getSegmentCalls(gSupportSegments, direction); - - tileGeneralSupportCalls[direction].height = -1; - tileGeneralSupportCalls[direction].slope = -1; - if (gSupport.height != 0) { - tileGeneralSupportCalls[direction].height = gSupport.height; - } - if (gSupport.slope != 0xFF) { - tileGeneralSupportCalls[direction].slope = gSupport.slope; - } - } - - std::vector referenceCalls = tileSegmentSupportCalls[0]; - - if (!SegmentSupportHeightCall::CallsMatch(tileSegmentSupportCalls)) { - std::vector *found = SegmentSupportHeightCall::FindMostCommonSupportCall(tileSegmentSupportCalls); - if (found != nullptr) { - referenceCalls = *found; - } else { - printf("Original segment calls didn't match. [trackSequence:%d chainLift:%d]\n", trackSequence, chainLift); - for (int i = 0; i < 4; i++) { - printf("# %d\n%s", i, Printer::PrintSegmentSupportHeightCalls(tileSegmentSupportCalls[i]).c_str()); - } - continue; - } - } - - for (int direction = 0; direction < 4; direction++) { - ResetSegmentHeights(); - - testpaint_clear_ignore(); - TRACK_PAINT_FUNCTION newPaintFunction = newPaintGetter(trackType, direction); - newPaintFunction(rideIndex, trackSequence, direction, height, &mapElement); - if (testpaint_is_ignored(direction, trackSequence)) { - continue; - } - - std::vector newCalls = SegmentSupportHeightCall::getSegmentCalls(gSupportSegments, - direction); - - if (!SegmentSupportHeightCall::CallsEqual(tileSegmentSupportCalls[0], newCalls)) { - // TODO put this into *error - utf8string diff = new utf8[2048]; - snprintf(diff, 2048, "<<< EXPECTED\n"); - printSegmentSupports(diff, 2048, tileSegmentSupportCalls[0]); - - size_t slen = strlen(diff); - if (slen < 2048) - snprintf(diff + slen, 2048 - slen, "====\n"); - printSegmentSupports(diff, 2048, newCalls); - - slen = strlen(diff); - if (slen < 2048) - snprintf(diff + strlen(diff), 2048 - slen, ">>> ACTUAL\n"); - - printf("Segment support heights didn't match. [direction:%d trackSequence:%d chainLift:%d]\n", direction, - trackSequence, chainLift); - printf("%s", diff); - delete[] diff; - return false; - } - } - - SupportCall referenceGeneralSupportCall = tileGeneralSupportCalls[0]; - - if (!GeneralSupportHeightCall::CallsMatch(tileGeneralSupportCalls)) { - SupportCall *found = GeneralSupportHeightCall::FindMostCommonSupportCall(tileGeneralSupportCalls); - if (found == nullptr) { - printf("Original support calls didn't match. [trackSequence:%d chainLift:%d]\n", trackSequence, chainLift); - for (int i = 0; i < 4; ++i) { - printf("[%d, 0x%02X] ", tileGeneralSupportCalls[i].height, tileGeneralSupportCalls[i].slope); - } - printf("\n"); - continue; - } - referenceGeneralSupportCall = *found; - } - - - for (int direction = 0; direction < 4; direction++) { - ResetSegmentHeights(); - - testpaint_clear_ignore(); - TRACK_PAINT_FUNCTION newPaintFunction = newPaintGetter(trackType, direction); - newPaintFunction(rideIndex, trackSequence, direction, height, &mapElement); - if (testpaint_is_ignored(direction, trackSequence)) { - continue; - } - - if (referenceGeneralSupportCall.height != -1) { - if (gSupport.height != referenceGeneralSupportCall.height) { - printf("General support heights didn't match. (expected height + %d, actual: height + %d) [direction:%d trackSequence:%d chainLift:%d]\n", - referenceGeneralSupportCall.height - height, - gSupport.height - height, - direction, - trackSequence, - chainLift); - return false; - } - } - if (referenceGeneralSupportCall.slope != -1) { - if (gSupport.slope != referenceGeneralSupportCall.slope) { - printf("General support slopes didn't match. [direction:%d trackSequence:%d chainLift:%d]\n", direction, - trackSequence, chainLift); - return false; - } - } - } - - } - } - return true; - } - static bool tunnelPatternsMatch(TunnelCall expected[4], TunnelCall actual[4]) { for (int side = 0; side < 4; side++) { @@ -709,11 +539,6 @@ namespace Intercept2 extern "C" { - bool testSupportSegments(uint8 rideType, uint8 trackType) - { - return Intercept2::testSupportSegments(rideType, trackType); - } - bool testTunnels(uint8 rideType, uint8 trackType) { return Intercept2::testTunnels(rideType, trackType); @@ -749,7 +574,7 @@ extern "C" } void intercept_reset_segment_heights() { - Intercept2::ResetSegmentHeights(); + Intercept2::ResetSupportHeights(); } void intercept_reset_tunnels() { From 9efb41a13f5f428d3402a7e8233ec3750bfd9760 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 11:57:41 +0200 Subject: [PATCH 19/42] Extract Side tunnels --- OpenRCT2.xcodeproj/project.pbxproj | 6 + test/testpaint/Printer.cpp | 69 +++++++ test/testpaint/Printer.hpp | 3 + test/testpaint/SideTunnelCall.cpp | 106 +++++++++++ test/testpaint/SideTunnelCall.hpp | 44 +++++ test/testpaint/TestTrack.cpp | 120 +++++++++++- test/testpaint/generate.cpp | 25 +-- test/testpaint/intercept.h | 12 -- test/testpaint/intercept_2.cpp | 294 ----------------------------- test/testpaint/testpaint.vcxproj | 1 + 10 files changed, 361 insertions(+), 319 deletions(-) create mode 100644 test/testpaint/SideTunnelCall.cpp create mode 100644 test/testpaint/SideTunnelCall.hpp diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index a73bf33186..6340354d87 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -34,6 +34,7 @@ C606CCC91DB4054000FE4015 /* Utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCBC1DB4054000FE4015 /* Utils.cpp */; }; C606CCCE1DB427A000FE4015 /* GeneralSupportHeightCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCCA1DB427A000FE4015 /* GeneralSupportHeightCall.cpp */; }; C606CCCF1DB427A000FE4015 /* SegmentSupportHeightCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCCC1DB427A000FE4015 /* SegmentSupportHeightCall.cpp */; }; + C606CCD21DB4D7C800FE4015 /* SideTunnelCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCD01DB4D7C800FE4015 /* SideTunnelCall.cpp */; }; C612A8991D64825300B634CA /* vehicle_data.c in Sources */ = {isa = PBXBuildFile; fileRef = C612A8971D64825300B634CA /* vehicle_data.c */; }; C61FB7241CF86356004CE991 /* NetworkUser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61FB7221CF86356004CE991 /* NetworkUser.cpp */; }; C64FDA641D6D9A2100F259B9 /* air_powered_vertical_coaster.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F8BB1CDBC3B7009F9BFC /* air_powered_vertical_coaster.c */; }; @@ -526,6 +527,8 @@ C606CCCB1DB427A000FE4015 /* GeneralSupportHeightCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = GeneralSupportHeightCall.hpp; sourceTree = ""; }; C606CCCC1DB427A000FE4015 /* SegmentSupportHeightCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SegmentSupportHeightCall.cpp; sourceTree = ""; }; C606CCCD1DB427A000FE4015 /* SegmentSupportHeightCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SegmentSupportHeightCall.hpp; sourceTree = ""; }; + C606CCD01DB4D7C800FE4015 /* SideTunnelCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SideTunnelCall.cpp; sourceTree = ""; }; + C606CCD11DB4D7C800FE4015 /* SideTunnelCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SideTunnelCall.hpp; sourceTree = ""; }; C612A8971D64825300B634CA /* vehicle_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vehicle_data.c; sourceTree = ""; }; C612A8981D64825300B634CA /* vehicle_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vehicle_data.h; sourceTree = ""; }; C61FB7221CF86356004CE991 /* NetworkUser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkUser.cpp; sourceTree = ""; usesTabs = 0; }; @@ -1208,6 +1211,8 @@ C606CCB71DB4054000FE4015 /* Printer.hpp */, C606CCCC1DB427A000FE4015 /* SegmentSupportHeightCall.cpp */, C606CCCD1DB427A000FE4015 /* SegmentSupportHeightCall.hpp */, + C606CCD01DB4D7C800FE4015 /* SideTunnelCall.cpp */, + C606CCD11DB4D7C800FE4015 /* SideTunnelCall.hpp */, C606CCB81DB4054000FE4015 /* String.cpp */, C606CCB91DB4054000FE4015 /* String.hpp */, C606CCBA1DB4054000FE4015 /* TestTrack.cpp */, @@ -2399,6 +2404,7 @@ C64FDAC01D6D9E3B00F259B9 /* track_data.c in Sources */, C64FDABF1D6D9CEA00F259B9 /* map_element.c in Sources */, C64FDABE1D6D9CD900F259B9 /* ride_data.c in Sources */, + C606CCD21DB4D7C800FE4015 /* SideTunnelCall.cpp in Sources */, C64FDABC1D6D9C8800F259B9 /* addresses.c in Sources */, C64FDA641D6D9A2100F259B9 /* air_powered_vertical_coaster.c in Sources */, C64FDA651D6D9A2100F259B9 /* bobsleigh_coaster.c in Sources */, diff --git a/test/testpaint/Printer.cpp b/test/testpaint/Printer.cpp index d59271556b..d90c8cb885 100644 --- a/test/testpaint/Printer.cpp +++ b/test/testpaint/Printer.cpp @@ -38,6 +38,8 @@ namespace Printer { static std::string PrintSegmentSupportHeightCall(SegmentSupportCall call); + static std::string PrintSideTunnelEdge(TunnelCall edge); + std::string PrintFunctionCalls(std::vector calls, uint16 baseHeight) { std::string out; @@ -140,6 +142,73 @@ namespace Printer { return out; } + std::string PrintSideTunnelCalls(TunnelCall tunnelCalls[4][4]) { + std::string s; + + for (int direction = 0; direction < 4; ++direction) { + s += " + "; + } + s += "\n"; + + for (int direction = 0; direction < 4; ++direction) { + std::string leftEdge = PrintSideTunnelEdge(tunnelCalls[direction][2]); + std::string rightEdge = PrintSideTunnelEdge(tunnelCalls[direction][3]); + s += String::Format(" %s %s ", leftEdge.c_str(), rightEdge.c_str()); + } + s += "\n"; + + for (int direction = 0; direction < 4; ++direction) { + printf(" + + "); + } + s += "\n"; + + for (int direction = 0; direction < 4; ++direction) { + std::string leftEdge = PrintSideTunnelEdge(tunnelCalls[direction][0]); + std::string rightEdge = PrintSideTunnelEdge(tunnelCalls[direction][1]); + s += String::Format(" %s %s ", leftEdge.c_str(), rightEdge.c_str()); + } + s += "\n"; + + for (int direction = 0; direction < 4; ++direction) { + s += " + "; + } + s += "\n"; + + for (int direction = 0; direction < 4; ++direction) { + s += String::Format(" direction %d ", direction); + } + s += "\n"; + + return s; + } + + static std::string PrintSideTunnelEdge(TunnelCall edge) { + std::string s; + + switch (edge.call) { + case TUNNELCALL_SKIPPED: + s = " "; + break; + + case TUNNELCALL_NONE: + s = " - "; + break; + + case TUNNELCALL_CALL: + std::string offset; + + if (edge.offset <= 0) { + offset = String::Format("%d", edge.offset); + } else { + offset = String::Format("+%d", edge.offset); + } + s = String::Format("%3s/%X ", offset.c_str(), edge.type); + break; + } + + return s; + } + static std::string GetImageIdString(uint32 imageId) { std::string result; diff --git a/test/testpaint/Printer.hpp b/test/testpaint/Printer.hpp index 032aee77f7..f9b59a4100 100644 --- a/test/testpaint/Printer.hpp +++ b/test/testpaint/Printer.hpp @@ -20,6 +20,7 @@ #include #include "intercept.h" +#include "SideTunnelCall.hpp" #include "SegmentSupportHeightCall.hpp" namespace Printer { @@ -27,4 +28,6 @@ namespace Printer { std::string PrintFunctionCalls(std::vector calls, uint16 baseHeight); std::string PrintSegmentSupportHeightCalls(std::vector calls); + + std::string PrintSideTunnelCalls(TunnelCall tunnelCalls[4][4]); } diff --git a/test/testpaint/SideTunnelCall.cpp b/test/testpaint/SideTunnelCall.cpp new file mode 100644 index 0000000000..cca3c35a44 --- /dev/null +++ b/test/testpaint/SideTunnelCall.cpp @@ -0,0 +1,106 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#include "SideTunnelCall.hpp" + +sint16 SideTunnelCall::GetTunnelOffset(uint32 baseHeight, tunnel_entry calls[3]) { + for (sint16 offset = -56; offset <= 56; offset += 8) { + if (calls[0].height != (baseHeight - 8 + offset) / 16) continue; + if (calls[1].height != (baseHeight + 0 + offset) / 16) continue; + if (calls[2].height != (baseHeight + 8 + offset) / 16) continue; + + return offset; + } + + log_error("Unknown tunnel height. (%d, %d, %d)", calls[0].height, calls[1].height, calls[2].height); + return 0; +} + + +TunnelCall SideTunnelCall::ExtractTunnelCalls(tunnel_entry *calls, uint8 count, uint16 baseHeight, bool *error) { + TunnelCall tunnelCall = {0}; + + if (count == 0) { + tunnelCall.call = TUNNELCALL_NONE; + return tunnelCall; + } + + if (count == 3) { + tunnelCall.call = TUNNELCALL_CALL; + tunnelCall.offset = GetTunnelOffset(baseHeight, calls); + tunnelCall.type = calls[0].type; + return tunnelCall; + } + + *error = true; + return tunnelCall; +} + + +bool SideTunnelCall::TunnelCallsLineUp(TunnelCall tunnelCalls[4][4]) +{ + for (int side = 0; side < 4; ++side) { + TunnelCall * referenceCall = nullptr; + for (int direction = 0; direction < 4; ++direction) { + if (tunnelCalls[direction][side].call == TUNNELCALL_SKIPPED) { + continue; + } + + if (referenceCall == nullptr) { + referenceCall = &tunnelCalls[direction][side]; + continue; + } + + if (referenceCall->call != tunnelCalls[direction][side].call) return false; + + if (referenceCall->call == TUNNELCALL_CALL) { + if (referenceCall->type != tunnelCalls[direction][side].type) return false; + if (referenceCall->offset != tunnelCalls[direction][side].offset) return false; + } + } + } + + return true; +} + +void SideTunnelCall::GetTunnelCallReferencePattern(TunnelCall tunnelCalls[4][4], TunnelCall (*out)[4]) +{ + for (int side = 0; side < 4; ++side) { + for (int direction = 0; direction < 4; ++direction) { + if (tunnelCalls[direction][side].call == TUNNELCALL_SKIPPED) { + continue; + } + + (*out)[side].call = tunnelCalls[direction][side].call; + (*out)[side].type = tunnelCalls[direction][side].type; + (*out)[side].offset = tunnelCalls[direction][side].offset; + } + } +} + +bool SideTunnelCall::TunnelPatternsMatch(TunnelCall expected[4], TunnelCall actual[4]) +{ + for (int side = 0; side < 4; side++) { + if (expected[side].call != actual[side].call) return false; + + if (expected[side].call == TUNNELCALL_CALL) { + if (expected[side].type != actual[side].type) return false; + if (expected[side].offset != actual[side].offset) return false; + } + } + + return true; +} diff --git a/test/testpaint/SideTunnelCall.hpp b/test/testpaint/SideTunnelCall.hpp new file mode 100644 index 0000000000..0c585516e6 --- /dev/null +++ b/test/testpaint/SideTunnelCall.hpp @@ -0,0 +1,44 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../../src/common.h" + +extern "C" { +#include "../../src/paint/map_element/map_element.h" +} + +enum { + TUNNELCALL_SKIPPED, + TUNNELCALL_NONE, + TUNNELCALL_CALL, +}; + +struct TunnelCall { + uint8 call; + sint16 offset; + uint8 type; +}; + +namespace SideTunnelCall { + sint16 GetTunnelOffset(uint32 baseHeight, tunnel_entry calls[3]); + TunnelCall ExtractTunnelCalls(tunnel_entry * list, uint8 count, uint16 baseHeight, bool * error); + + bool TunnelPatternsMatch(TunnelCall expected[4], TunnelCall actual[4]); + void GetTunnelCallReferencePattern(TunnelCall tunnelCalls[4][4], TunnelCall (*out)[4]); + bool TunnelCallsLineUp(TunnelCall tunnelCalls[4][4]); +}; diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index 6f975a5337..af66c79a42 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -22,6 +22,7 @@ #include "GeneralSupportHeightCall.hpp" #include "Printer.hpp" #include "SegmentSupportHeightCall.hpp" +#include "SideTunnelCall.hpp" #include "String.hpp" #include "TestTrack.hpp" #include "Utils.hpp" @@ -78,6 +79,8 @@ static uint8 TestTrackElementSegmentSupportHeight(uint8 rideType, uint8 trackTyp static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error); +static uint8 TestTrackElementSideTunnels(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error); + uint8 TestTrack::TestPaintTrackElement(uint8 rideType, uint8 trackType) { if (!Utils::rideSupportsTrackType(rideType, trackType)) { return TEST_FAILED; @@ -99,7 +102,8 @@ uint8 TestTrack::TestPaintTrackElement(uint8 rideType, uint8 trackType) { static TestFunction functions[] = { TestTrackElementPaintCalls, TestTrackElementSegmentSupportHeight, - TestTrackElementGeneralSupportHeight + TestTrackElementGeneralSupportHeight, + TestTrackElementSideTunnels, }; for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { @@ -380,3 +384,117 @@ static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackTyp return TEST_SUCCESS; } + +static uint8 TestTrackElementSideTunnels(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error) { + uint8 rideIndex = 0; + uint16 height = 3 * 16; + + rct_map_element mapElement = {0}; + mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; + mapElement.properties.track.type = trackType; + mapElement.base_height = height / 16; + g_currently_drawn_item = &mapElement; + + rct_map_element surfaceElement = {0}; + surfaceElement.type = MAP_ELEMENT_TYPE_SURFACE; + surfaceElement.base_height = 2; + gSurfaceElement = &surfaceElement; + gDidPassSurface = true; + + Intercept2::ResetEnvironment(); + Intercept2::ResetTunnels(); + + TunnelCall tileTunnelCalls[4][4]; + + for (int direction = 0; direction < 4; direction++) { + Intercept2::ResetTunnels(); + + for (sint8 offset = -8; offset <= 8; offset += 8) { + CallOriginal(rideType, trackType, direction, trackSequence, height + offset, &mapElement); + } + + uint8 rightIndex = (4 - direction) % 4; + uint8 leftIndex = (rightIndex + 1) % 4; + + for (int i = 0; i < 4; ++i) { + tileTunnelCalls[direction][i].call = TUNNELCALL_SKIPPED; + } + + bool err = false; + tileTunnelCalls[direction][rightIndex] = SideTunnelCall::ExtractTunnelCalls(gRightTunnels, gRightTunnelCount, height, + &err); + + tileTunnelCalls[direction][leftIndex] = SideTunnelCall::ExtractTunnelCalls(gLeftTunnels, gLeftTunnelCount, height, + &err); + + if (err) { + *error += "Multiple tunnels on one side aren't supported.\n"; + return TEST_FAILED; + } + } + + TunnelCall newTileTunnelCalls[4][4]; + for (int direction = 0; direction < 4; direction++) { + Intercept2::ResetTunnels(); + + testpaint_clear_ignore(); + + for (sint8 offset = -8; offset <= 8; offset += 8) { + // TODO: move tunnel pushing to interface so we don't have to check the output 3 times + CallNew(rideType, trackType, direction, trackSequence, height + offset, &mapElement); + } + + uint8 rightIndex = (4 - direction) % 4; + uint8 leftIndex = (rightIndex + 1) % 4; + + for (int i = 0; i < 4; ++i) { + newTileTunnelCalls[direction][i].call = TUNNELCALL_SKIPPED; + } + + bool err = false; + newTileTunnelCalls[direction][rightIndex] = SideTunnelCall::ExtractTunnelCalls(gRightTunnels, gRightTunnelCount, height, + &err); + + newTileTunnelCalls[direction][leftIndex] = SideTunnelCall::ExtractTunnelCalls(gLeftTunnels, gLeftTunnelCount, height, + &err); + + if (err) { + *error += "Multiple tunnels on one side aren't supported.\n"; + return TEST_FAILED; + } + } + + + if (!SideTunnelCall::TunnelCallsLineUp(tileTunnelCalls)) { + *error += String::Format( + "Original tunnel calls don\'t line up. Skipping tunnel validation [trackSequence:%d].\n", + trackSequence + ); + *error += Printer::PrintSideTunnelCalls(tileTunnelCalls); + + if (!SideTunnelCall::TunnelCallsLineUp(newTileTunnelCalls)) { + *error += String::Format("Decompiled tunnel calls don\'t line up. [trackSequence:%d].\n", trackSequence); + *error += Printer::PrintSideTunnelCalls(newTileTunnelCalls); + return TEST_FAILED; + } + + return TEST_SUCCESS; + } + + TunnelCall referencePattern[4]; + SideTunnelCall::GetTunnelCallReferencePattern(tileTunnelCalls, &referencePattern); + + TunnelCall actualPattern[4]; + SideTunnelCall::GetTunnelCallReferencePattern(newTileTunnelCalls, &actualPattern); + + if (!SideTunnelCall::TunnelPatternsMatch(referencePattern, actualPattern)) { + *error += String::Format("Tunnel calls don't match expected pattern. [trackSequence:%d]\n", trackSequence); + *error += " Expected:\n"; + *error += Printer::PrintSideTunnelCalls(tileTunnelCalls); + *error += " Actual:\n"; + *error += Printer::PrintSideTunnelCalls(newTileTunnelCalls); + return TEST_FAILED; + } + + return TEST_SUCCESS; +} \ No newline at end of file diff --git a/test/testpaint/generate.cpp b/test/testpaint/generate.cpp index 3f5a5a7507..b4205cba30 100644 --- a/test/testpaint/generate.cpp +++ b/test/testpaint/generate.cpp @@ -20,6 +20,7 @@ #include "intercept.h" #include "SegmentSupportHeightCall.hpp" +#include "SideTunnelCall.hpp" #include "String.hpp" #include "Utils.hpp" @@ -400,7 +401,7 @@ private: bool blockSegmentsBeforeSupports = false; std::vector calls[4], chainLiftCalls[4], cableLiftCalls[4]; - Intercept2::TunnelCall tileTunnelCalls[4][4]; + TunnelCall tileTunnelCalls[4][4]; sint16 verticalTunnelHeights[4]; std::vector segmentSupportCalls[4]; support_height generalSupports[4] = { 0 }; @@ -737,7 +738,7 @@ private: int trackSequence, int height, rct_map_element * mapElement, - Intercept2::TunnelCall tileTunnelCalls[4][4], + TunnelCall tileTunnelCalls[4][4], sint16 verticalTunnelHeights[4]) { intercept_reset_tunnels(); @@ -751,13 +752,13 @@ private: uint8 leftIndex = (rightIndex + 1) % 4; for (int i = 0; i < 4; ++i) { - tileTunnelCalls[direction][i].call = Intercept2::TUNNELCALL_SKIPPED; + tileTunnelCalls[direction][i].call = TUNNELCALL_SKIPPED; } if (gRightTunnelCount == 0) { - tileTunnelCalls[direction][rightIndex].call = Intercept2::TUNNELCALL_NONE; + tileTunnelCalls[direction][rightIndex].call = TUNNELCALL_NONE; } else if (gRightTunnelCount == 3) { - tileTunnelCalls[direction][rightIndex].call = Intercept2::TUNNELCALL_CALL; - tileTunnelCalls[direction][rightIndex].offset = Intercept2::getTunnelOffset(height, gRightTunnels); + tileTunnelCalls[direction][rightIndex].call = TUNNELCALL_CALL; + tileTunnelCalls[direction][rightIndex].offset = SideTunnelCall::GetTunnelOffset(height, gRightTunnels); tileTunnelCalls[direction][rightIndex].type = gRightTunnels[0].type; } else { printf("Multiple tunnels on one side aren't supported.\n"); @@ -765,10 +766,10 @@ private: } if (gLeftTunnelCount == 0) { - tileTunnelCalls[direction][leftIndex].call = Intercept2::TUNNELCALL_NONE; + tileTunnelCalls[direction][leftIndex].call = TUNNELCALL_NONE; } else if (gLeftTunnelCount == 3) { - tileTunnelCalls[direction][leftIndex].call = Intercept2::TUNNELCALL_CALL; - tileTunnelCalls[direction][leftIndex].offset = Intercept2::getTunnelOffset(height, gLeftTunnels); + tileTunnelCalls[direction][leftIndex].call = TUNNELCALL_CALL; + tileTunnelCalls[direction][leftIndex].offset = SideTunnelCall::GetTunnelOffset(height, gLeftTunnels); tileTunnelCalls[direction][leftIndex].type = gLeftTunnels[0].type; } else { printf("Multiple tunnels on one side aren't supported.\n"); @@ -788,7 +789,7 @@ private: return true; } - void GenerateTunnelCall(int tabs, Intercept2::TunnelCall tileTunnelCalls[4][4], sint16 verticalTunnelHeights[4]) + void GenerateTunnelCall(int tabs, TunnelCall tileTunnelCalls[4][4], sint16 verticalTunnelHeights[4]) { constexpr uint8 TunnelLeft = 0; constexpr uint8 TunnelRight = 1; @@ -809,7 +810,7 @@ private: for (int side = 0; side < 4; side++) { auto tunnel = tileTunnelCalls[direction][side]; - if (tunnel.call == Intercept2::TUNNELCALL_CALL) + if (tunnel.call == TUNNELCALL_CALL) { tunnelOffset[direction] = tunnel.offset; tunnelType[direction] = tunnel.type; @@ -857,7 +858,7 @@ private: WriteLine(tabs, "case %d:", i); for (int side = 0; side < 4; side++) { - if (tileTunnelCalls[i][side].call == Intercept2::TUNNELCALL_CALL) + if (tileTunnelCalls[i][side].call == TUNNELCALL_CALL) { GenerateTunnelCall(tabs + 1, tileTunnelCalls[i][side].offset, tileTunnelCalls[i][side].type, dsToWay[i][side]); } diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index 0aed39fcf7..6dcdad474b 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -107,19 +107,7 @@ namespace Intercept2 static const uint32 DEFAULT_SCHEME_MISC = COLOUR_DARK_PURPLE << 19 | COLOUR_LIGHT_PURPLE << 24 | 0xA0000000; static const uint32 DEFAULT_SCHEME_3 = COLOUR_BRIGHT_PURPLE << 19 | COLOUR_DARK_BLUE << 24 | 0xA0000000; - enum { - TUNNELCALL_SKIPPED, - TUNNELCALL_NONE, - TUNNELCALL_CALL, - }; - struct TunnelCall { - uint8 call; - sint16 offset; - uint8 type; - }; - - sint16 getTunnelOffset(uint32 baseHeight, tunnel_entry calls[3]); void ResetEnvironment(); void ResetTunnels(); diff --git a/test/testpaint/intercept_2.cpp b/test/testpaint/intercept_2.cpp index 2673b0cb36..b98be2fd35 100644 --- a/test/testpaint/intercept_2.cpp +++ b/test/testpaint/intercept_2.cpp @@ -86,295 +86,6 @@ namespace Intercept2 gSupport.slope = 0xFF; } - static bool tunnelCallsLineUp(TunnelCall tunnelCalls[4][4]) - { - for (int side = 0; side < 4; ++side) { - TunnelCall * referenceCall = nullptr; - for (int direction = 0; direction < 4; ++direction) { - if (tunnelCalls[direction][side].call == TUNNELCALL_SKIPPED) { - continue; - } - - if (referenceCall == nullptr) { - referenceCall = &tunnelCalls[direction][side]; - continue; - } - - if (referenceCall->call != tunnelCalls[direction][side].call) return false; - - if (referenceCall->call == TUNNELCALL_CALL) { - if (referenceCall->type != tunnelCalls[direction][side].type) return false; - if (referenceCall->offset != tunnelCalls[direction][side].offset) return false; - } - } - } - - return true; - } - - static void getTunnelCallReferencePattern(TunnelCall tunnelCalls[4][4], TunnelCall (*out)[4]) - { - for (int side = 0; side < 4; ++side) { - for (int direction = 0; direction < 4; ++direction) { - if (tunnelCalls[direction][side].call == TUNNELCALL_SKIPPED) { - continue; - } - - (*out)[side].call = tunnelCalls[direction][side].call; - (*out)[side].type = tunnelCalls[direction][side].type; - (*out)[side].offset = tunnelCalls[direction][side].offset; - } - } - } - - static utf8string getTunnelEdgeString(TunnelCall edge) - { - utf8string out = new utf8[32]; - - switch (edge.call) { - case TUNNELCALL_SKIPPED: - snprintf(out, 32, "%s", " "); - break; - - case TUNNELCALL_NONE: - snprintf(out, 32, "%s", " - "); - break; - - case TUNNELCALL_CALL: - if (edge.offset == 0) { - snprintf(out, 32, " 0/%X ", edge.type); - } else { - utf8string offset = new utf8[16]; - if (edge.offset < 0) { - snprintf(offset, 16, "%d", edge.offset); - } else { - snprintf(offset, 16, "+%d", edge.offset); - } - - snprintf(out, 32, "%3s/%X ", offset, edge.type); - - delete[] offset; - } - break; - } - - return out; - } - - static void printTunnelCalls(TunnelCall tunnelCalls[4][4]) - { - for (int direction = 0; direction < 4; ++direction) { - printf(" + "); - } - printf("\n"); - - for (int direction = 0; direction < 4; ++direction) { - utf8string tlEdge = getTunnelEdgeString(tunnelCalls[direction][2]); - utf8string trEdge = getTunnelEdgeString(tunnelCalls[direction][3]); - printf(" %s %s ", tlEdge, trEdge); - delete [] tlEdge; - delete [] trEdge; - } - printf("\n"); - - for (int direction = 0; direction < 4; ++direction) { - printf(" + + "); - } - printf("\n"); - - for (int direction = 0; direction < 4; ++direction) { - utf8string brEdge = getTunnelEdgeString(tunnelCalls[direction][0]); - utf8string blEdge = getTunnelEdgeString(tunnelCalls[direction][1]); - printf(" %s %s ", blEdge, brEdge); - delete [] blEdge; - delete [] brEdge; - } - printf("\n"); - - for (int direction = 0; direction < 4; ++direction) { - printf(" + "); - } - printf("\n"); - - for (int direction = 0; direction < 4; ++direction) { - printf(" direction %d ", direction); - } - printf("\n"); - } - - static bool tunnelPatternsMatch(TunnelCall expected[4], TunnelCall actual[4]) - { - for (int side = 0; side < 4; side++) { - if (expected[side].call != actual[side].call) return false; - - if (expected[side].call == TUNNELCALL_CALL) { - if (expected[side].type != actual[side].type) return false; - if (expected[side].offset != actual[side].offset) return false; - } - } - - return true; - } - - sint16 getTunnelOffset(uint32 baseHeight, tunnel_entry calls[3]) - { - for (sint16 offset = -56; offset <= 56; offset += 8) { - if (calls[0].height != (baseHeight - 8 + offset) / 16) continue; - if (calls[1].height != (baseHeight + 0 + offset) / 16) continue; - if (calls[2].height != (baseHeight + 8 + offset) / 16) continue; - - return offset; - } - - log_error("Unknown tunnel height. (%d, %d, %d)", calls[0].height, calls[1].height, calls[2].height); - return 0; - } - - static bool testTunnels(uint8 rideType, uint8 trackType) - { - uint8 rideIndex = 0; - rct_map_element mapElement = {0}; - mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; - mapElement.properties.track.type = trackType; - mapElement.base_height = 3; - - g_currently_drawn_item = &mapElement; - - ResetEnvironment(); - - int height = 48; - - TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; - int sequenceCount = Utils::getTrackSequenceCount(rideType, trackType); - - - for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { - TunnelCall tileTunnelCalls[4][4]; - - for (int direction = 0; direction < 4; direction++) { - ResetTunnels(); - - uint32 *trackDirectionList = (uint32 *)RideTypeTrackPaintFunctionsOld[rideType][trackType]; - - for (int offset = -8; offset <= 8; offset += 8) { - // Have to call from this point as it pushes esi and expects callee to pop it - RCT2_CALLPROC_X( - 0x006C4934, - rideType, - (int) trackDirectionList, - direction, - height + offset, - (int) &mapElement, - rideIndex * sizeof(rct_ride), - trackSequence - ); - } - - uint8 rightIndex = (4 - direction) % 4; - uint8 leftIndex = (rightIndex + 1) % 4; - - for (int i = 0; i < 4; ++i) { - tileTunnelCalls[direction][i].call = TUNNELCALL_SKIPPED; - } - if (gRightTunnelCount == 0) { - tileTunnelCalls[direction][rightIndex].call = TUNNELCALL_NONE; - } else if (gRightTunnelCount == 3) { - tileTunnelCalls[direction][rightIndex].call = TUNNELCALL_CALL; - tileTunnelCalls[direction][rightIndex].offset = getTunnelOffset(height, gRightTunnels); - tileTunnelCalls[direction][rightIndex].type = gRightTunnels[0].type; - } else { - printf("Multiple tunnels on one side aren't supported.\n"); - return false; - } - - if (gLeftTunnelCount == 0) { - tileTunnelCalls[direction][leftIndex].call = TUNNELCALL_NONE; - } else if (gLeftTunnelCount == 3) { - tileTunnelCalls[direction][leftIndex].call = TUNNELCALL_CALL; - tileTunnelCalls[direction][leftIndex].offset = getTunnelOffset(height, gLeftTunnels); - tileTunnelCalls[direction][leftIndex].type = gLeftTunnels[0].type; - } else { - printf("Multiple tunnels on one side aren't supported.\n"); - return false; - } - } - - TunnelCall newTileTunnelCalls[4][4]; - for (int direction = 0; direction < 4; direction++) { - gLeftTunnelCount = 0; - gRightTunnelCount = 0; - - testpaint_clear_ignore(); - TRACK_PAINT_FUNCTION newPaintFunction = newPaintGetter(trackType, direction); - - for (int offset = -8; offset <= 8; offset += 8) { - // TODO: move tunnel pushing to interface so we don't have to check the output 3 times - newPaintFunction(rideIndex, trackSequence, direction, height + offset, &mapElement); - } - - uint8 rightIndex = (4 - direction) % 4; - uint8 leftIndex = (rightIndex + 1) % 4; - - for (int i = 0; i < 4; ++i) { - newTileTunnelCalls[direction][i].call = TUNNELCALL_SKIPPED; - } - - if (gRightTunnelCount == 0) { - newTileTunnelCalls[direction][rightIndex].call = TUNNELCALL_NONE; - } else if (gRightTunnelCount == 3) { - newTileTunnelCalls[direction][rightIndex].call = TUNNELCALL_CALL; - newTileTunnelCalls[direction][rightIndex].offset = getTunnelOffset(height, gRightTunnels); - newTileTunnelCalls[direction][rightIndex].type = gRightTunnels[0].type; - } else { - printf("Multiple tunnels on one side aren't supported.\n"); - return false; - } - - if (gLeftTunnelCount == 0) { - newTileTunnelCalls[direction][leftIndex].call = TUNNELCALL_NONE; - } else if (gLeftTunnelCount == 3) { - newTileTunnelCalls[direction][leftIndex].call = TUNNELCALL_CALL; - newTileTunnelCalls[direction][leftIndex].offset = getTunnelOffset(height, gLeftTunnels); - newTileTunnelCalls[direction][leftIndex].type = gLeftTunnels[0].type; - } else { - printf("Multiple tunnels on one side aren't supported.\n"); - return false; - } - } - - - if (!tunnelCallsLineUp(tileTunnelCalls)) { - printf("Original tunnel calls don\'t line up. Skipping tunnel validation [trackSequence:%d].\n", - trackSequence); - printTunnelCalls(tileTunnelCalls); - - if (!tunnelCallsLineUp(newTileTunnelCalls)) { - printf("Decompiled tunnel calls don\'t line up. [trackSequence:%d].\n", trackSequence); - printTunnelCalls(newTileTunnelCalls); - return false; - } - continue; - } - - TunnelCall referencePattern[4] = { 0 }; - getTunnelCallReferencePattern(tileTunnelCalls, &referencePattern); - - TunnelCall actualPattern[4] = { 0 }; - getTunnelCallReferencePattern(newTileTunnelCalls, &actualPattern); - - if (!tunnelPatternsMatch(referencePattern, actualPattern)) { - printf("Tunnel calls don't match expected pattern. [trackSequence:%d]\n", trackSequence); - printf("expected:\n"); - printTunnelCalls(tileTunnelCalls); - printf("actual:\n"); - printTunnelCalls(newTileTunnelCalls); - return false; - } - - } - return true; - } - static bool verticalTunnelHeightIsConsistent(uint8 heights[4]) { for (int i = 1; i < 4; ++i) { @@ -539,11 +250,6 @@ namespace Intercept2 extern "C" { - bool testTunnels(uint8 rideType, uint8 trackType) - { - return Intercept2::testTunnels(rideType, trackType); - } - bool testVerticalTunnels(uint8 rideType, uint8 trackType) { return Intercept2::testVerticalTunnels(rideType, trackType); diff --git a/test/testpaint/testpaint.vcxproj b/test/testpaint/testpaint.vcxproj index 1a99508a9e..5cb14b45ac 100644 --- a/test/testpaint/testpaint.vcxproj +++ b/test/testpaint/testpaint.vcxproj @@ -103,6 +103,7 @@ + From d3ce7d1d75ba719405694e87c5902c77dedd05d0 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 12:22:15 +0200 Subject: [PATCH 20/42] Extract vertical tunnel testing --- OpenRCT2.xcodeproj/project.pbxproj | 6 ++ test/testpaint/Printer.cpp | 17 ++-- test/testpaint/Printer.hpp | 2 + test/testpaint/TestTrack.cpp | 76 ++++++++++++++- test/testpaint/VerticalTunnelCall.cpp | 25 +++++ test/testpaint/VerticalTunnelCall.hpp | 23 +++++ test/testpaint/intercept_2.cpp | 127 -------------------------- test/testpaint/testpaint.vcxproj | 1 + 8 files changed, 140 insertions(+), 137 deletions(-) create mode 100644 test/testpaint/VerticalTunnelCall.cpp create mode 100644 test/testpaint/VerticalTunnelCall.hpp diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 6340354d87..3775dd0bbc 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -35,6 +35,7 @@ C606CCCE1DB427A000FE4015 /* GeneralSupportHeightCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCCA1DB427A000FE4015 /* GeneralSupportHeightCall.cpp */; }; C606CCCF1DB427A000FE4015 /* SegmentSupportHeightCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCCC1DB427A000FE4015 /* SegmentSupportHeightCall.cpp */; }; C606CCD21DB4D7C800FE4015 /* SideTunnelCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCD01DB4D7C800FE4015 /* SideTunnelCall.cpp */; }; + C606CCD51DB4DD6C00FE4015 /* VerticalTunnelCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCD31DB4DD6C00FE4015 /* VerticalTunnelCall.cpp */; }; C612A8991D64825300B634CA /* vehicle_data.c in Sources */ = {isa = PBXBuildFile; fileRef = C612A8971D64825300B634CA /* vehicle_data.c */; }; C61FB7241CF86356004CE991 /* NetworkUser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61FB7221CF86356004CE991 /* NetworkUser.cpp */; }; C64FDA641D6D9A2100F259B9 /* air_powered_vertical_coaster.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F8BB1CDBC3B7009F9BFC /* air_powered_vertical_coaster.c */; }; @@ -529,6 +530,8 @@ C606CCCD1DB427A000FE4015 /* SegmentSupportHeightCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SegmentSupportHeightCall.hpp; sourceTree = ""; }; C606CCD01DB4D7C800FE4015 /* SideTunnelCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SideTunnelCall.cpp; sourceTree = ""; }; C606CCD11DB4D7C800FE4015 /* SideTunnelCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SideTunnelCall.hpp; sourceTree = ""; }; + C606CCD31DB4DD6C00FE4015 /* VerticalTunnelCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VerticalTunnelCall.cpp; sourceTree = ""; }; + C606CCD41DB4DD6C00FE4015 /* VerticalTunnelCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VerticalTunnelCall.hpp; sourceTree = ""; }; C612A8971D64825300B634CA /* vehicle_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vehicle_data.c; sourceTree = ""; }; C612A8981D64825300B634CA /* vehicle_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vehicle_data.h; sourceTree = ""; }; C61FB7221CF86356004CE991 /* NetworkUser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkUser.cpp; sourceTree = ""; usesTabs = 0; }; @@ -1219,6 +1222,8 @@ C606CCBB1DB4054000FE4015 /* TestTrack.hpp */, C606CCBC1DB4054000FE4015 /* Utils.cpp */, C606CCBD1DB4054000FE4015 /* Utils.hpp */, + C606CCD31DB4DD6C00FE4015 /* VerticalTunnelCall.cpp */, + C606CCD41DB4DD6C00FE4015 /* VerticalTunnelCall.hpp */, ); name = Paint; path = test/testpaint; @@ -2407,6 +2412,7 @@ C606CCD21DB4D7C800FE4015 /* SideTunnelCall.cpp in Sources */, C64FDABC1D6D9C8800F259B9 /* addresses.c in Sources */, C64FDA641D6D9A2100F259B9 /* air_powered_vertical_coaster.c in Sources */, + C606CCD51DB4DD6C00FE4015 /* VerticalTunnelCall.cpp in Sources */, C64FDA651D6D9A2100F259B9 /* bobsleigh_coaster.c in Sources */, C64FDA661D6D9A2100F259B9 /* compact_inverted_coaster.c in Sources */, C64FDA671D6D9A2100F259B9 /* corkscrew_roller_coaster.c in Sources */, diff --git a/test/testpaint/Printer.cpp b/test/testpaint/Printer.cpp index d90c8cb885..87882dbbda 100644 --- a/test/testpaint/Printer.cpp +++ b/test/testpaint/Printer.cpp @@ -32,8 +32,6 @@ namespace Printer { static std::string GetImageIdString(uint32 imageId); - static std::string GetHeightOffset(uint16 height, uint16 baseHeight); - static std::string GetOffsetExpressionString(int offset); static std::string PrintSegmentSupportHeightCall(SegmentSupportCall call); @@ -60,14 +58,14 @@ namespace Printer { case SUPPORTS_WOOD_B: return String::Format( "%s(%d, %d, %s, %s)", functionName, call.supports.type, call.supports.special, - GetHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str() + PrintHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str() ); case SUPPORTS_METAL_A: case SUPPORTS_METAL_B: return String::Format( "%s(%d, %d, %d, %s, %s)", functionName, call.supports.type, call.supports.segment, call.supports.special, - GetHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str() + PrintHeightOffset(call.supports.height, baseHeight).c_str(), imageId.c_str() ); case SET_SEGMENT_HEIGHT: @@ -83,12 +81,13 @@ namespace Printer { "%d, %d, %d, ", call.paint.bound_box_length.x, call.paint.bound_box_length.y, call.paint.bound_box_length.z ); - s += String::Format("%s, ", GetHeightOffset(call.paint.z_offset, baseHeight).c_str()); + s += String::Format("%s, ", PrintHeightOffset(call.paint.z_offset, baseHeight).c_str()); if (call.function != PAINT_98196C) { s += String::Format( "%d, %d, %s, ", - call.paint.bound_box_offset.x, call.paint.bound_box_offset.y, GetHeightOffset(call.paint.bound_box_offset.z, baseHeight).c_str() + call.paint.bound_box_offset.x, call.paint.bound_box_offset.y, + PrintHeightOffset(call.paint.bound_box_offset.z, baseHeight).c_str() ); } @@ -98,9 +97,9 @@ namespace Printer { if (call.function != PAINT_98196C) { s += String::Format( " = { %d, %d, %s }, { %d, %d, %s }, { %d, %d, %d }", - call.paint.offset.x, call.paint.offset.y, GetHeightOffset(call.paint.z_offset, baseHeight).c_str(), + call.paint.offset.x, call.paint.offset.y, PrintHeightOffset(call.paint.z_offset, baseHeight).c_str(), call.paint.bound_box_offset.x, call.paint.bound_box_offset.y, - GetHeightOffset(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); } @@ -236,7 +235,7 @@ namespace Printer { return result; } - static std::string GetHeightOffset(uint16 height, uint16 baseHeight) { + std::string PrintHeightOffset(uint16 height, uint16 baseHeight) { int offset = height - baseHeight; return String::Format("height%s", GetOffsetExpressionString(offset).c_str()); diff --git a/test/testpaint/Printer.hpp b/test/testpaint/Printer.hpp index f9b59a4100..30b0749adf 100644 --- a/test/testpaint/Printer.hpp +++ b/test/testpaint/Printer.hpp @@ -30,4 +30,6 @@ namespace Printer { std::string PrintSegmentSupportHeightCalls(std::vector calls); std::string PrintSideTunnelCalls(TunnelCall tunnelCalls[4][4]); + + std::string PrintHeightOffset(uint16 height, uint16 baseHeight); } diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index af66c79a42..524d0d794c 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -26,6 +26,7 @@ #include "String.hpp" #include "TestTrack.hpp" #include "Utils.hpp" +#include "VerticalTunnelCall.hpp" extern "C" { #include "../../src/ride/ride.h" @@ -81,6 +82,8 @@ static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackTyp static uint8 TestTrackElementSideTunnels(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error); +static uint8 TestTrackElementVerticalTunnels(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error); + uint8 TestTrack::TestPaintTrackElement(uint8 rideType, uint8 trackType) { if (!Utils::rideSupportsTrackType(rideType, trackType)) { return TEST_FAILED; @@ -104,6 +107,7 @@ uint8 TestTrack::TestPaintTrackElement(uint8 rideType, uint8 trackType) { TestTrackElementSegmentSupportHeight, TestTrackElementGeneralSupportHeight, TestTrackElementSideTunnels, + TestTrackElementVerticalTunnels, }; for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { @@ -497,4 +501,74 @@ static uint8 TestTrackElementSideTunnels(uint8 rideType, uint8 trackType, uint8 } return TEST_SUCCESS; -} \ No newline at end of file +} + +static uint8 TestTrackElementVerticalTunnels(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error) { + uint8 rideIndex = 0; + uint16 height = 3 * 16; + + rct_map_element mapElement = {0}; + mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; + mapElement.properties.track.type = trackType; + mapElement.base_height = height / 16; + g_currently_drawn_item = &mapElement; + + rct_map_element surfaceElement = {0}; + surfaceElement.type = MAP_ELEMENT_TYPE_SURFACE; + surfaceElement.base_height = 2; + gSurfaceElement = &surfaceElement; + gDidPassSurface = true; + + Intercept2::ResetEnvironment(); + Intercept2::ResetTunnels(); + + uint8 verticalTunnelHeight[4]; + + for (int direction = 0; direction < 4; direction++) { + gVerticalTunnelHeight = 0; + CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); + verticalTunnelHeight[direction] = gVerticalTunnelHeight; + } + + if (!VerticalTunnelCall::HeightIsConsistent(verticalTunnelHeight)) { + *error += String::Format( + "Original vertical tunnel height is inconsistent, skipping test. [trackSequence:%d]\n", + trackSequence + ); + return TEST_SUCCESS; + } + + uint8 referenceHeight = verticalTunnelHeight[0]; + + for (int direction = 0; direction < 4; direction++) { + gVerticalTunnelHeight = 0; + + testpaint_clear_ignore(); + CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); + if (testpaint_is_ignored(direction, trackSequence)) { + continue; + } + + if (gVerticalTunnelHeight != referenceHeight) { + if (gVerticalTunnelHeight == 0) { + *error += String::Format( + "Expected no tunnel. Actual: %d [trackSequence:%d]\n", + gVerticalTunnelHeight, trackSequence + ); + return TEST_FAILED; + } + + *error += String::Format( + "Expected vertical tunnel height to be `%s`, was `%s`. [trackSequence:%d direction:%d]\n", + Printer::PrintHeightOffset((referenceHeight * 16), height).c_str(), + Printer::PrintHeightOffset((gVerticalTunnelHeight * 16), height).c_str(), + trackSequence, + direction + ); + + return TEST_FAILED; + } + } + + return TEST_SUCCESS; +} diff --git a/test/testpaint/VerticalTunnelCall.cpp b/test/testpaint/VerticalTunnelCall.cpp new file mode 100644 index 0000000000..e989febe4b --- /dev/null +++ b/test/testpaint/VerticalTunnelCall.cpp @@ -0,0 +1,25 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#include "VerticalTunnelCall.hpp" + +bool VerticalTunnelCall::HeightIsConsistent(uint8 heights[4]) { + for (int i = 1; i < 4; ++i) { + if (heights[i] != heights[0]) return false; + } + + return true; +} diff --git a/test/testpaint/VerticalTunnelCall.hpp b/test/testpaint/VerticalTunnelCall.hpp new file mode 100644 index 0000000000..b72c4cd41d --- /dev/null +++ b/test/testpaint/VerticalTunnelCall.hpp @@ -0,0 +1,23 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../../src/common.h" + +namespace VerticalTunnelCall { + bool HeightIsConsistent(uint8 heights[4]); +}; diff --git a/test/testpaint/intercept_2.cpp b/test/testpaint/intercept_2.cpp index b98be2fd35..8695423ea1 100644 --- a/test/testpaint/intercept_2.cpp +++ b/test/testpaint/intercept_2.cpp @@ -86,128 +86,6 @@ namespace Intercept2 gSupport.slope = 0xFF; } - static bool verticalTunnelHeightIsConsistent(uint8 heights[4]) - { - for (int i = 1; i < 4; ++i) { - if (heights[i] != heights[0]) return false; - } - - return true; - } - - static void printRelativeHeight(utf8string out, size_t len, sint16 height) - { - if (height == 0) { - snprintf(out, len, "height"); - return; - } - - if (height > 0) { - snprintf(out, len, "height + %d", height); - return; - } - - if (height < 0) { - snprintf(out, len, "height - %d", int(abs(height))); - return; - } - } - - static bool testVerticalTunnels(uint8 rideType, uint8 trackType) - { - uint8 rideIndex = 0; - rct_map_element mapElement = {0}; - mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; - mapElement.properties.track.type = trackType; - mapElement.base_height = 3; - - g_currently_drawn_item = &mapElement; - - ResetEnvironment(); - - int height = 48; - - TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; - int sequenceCount = Utils::getTrackSequenceCount(rideType, trackType); - - - for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { - uint8 verticalTunnelHeight[4]; - - for (int direction = 0; direction < 4; direction++) { - gVerticalTunnelHeight = 0; - - uint32 *trackDirectionList = (uint32 *)RideTypeTrackPaintFunctionsOld[rideType][trackType]; - - // Have to call from this point as it pushes esi and expects callee to pop it - RCT2_CALLPROC_X( - 0x006C4934, - rideType, - (int) trackDirectionList, - direction, - height, - (int) &mapElement, - rideIndex * sizeof(rct_ride), - trackSequence - ); - - verticalTunnelHeight[direction] = gVerticalTunnelHeight; - } - - if (!verticalTunnelHeightIsConsistent(verticalTunnelHeight)) { - printf( - "Original vertical tunnel height is inconsistent, skipping test. [trackSequence:%d]\n", - trackSequence - ); - continue; - } - - uint8 referenceHeight = verticalTunnelHeight[0]; - for (int direction = 0; direction < 4; direction++) { - gVerticalTunnelHeight = 0; - - testpaint_clear_ignore(); - TRACK_PAINT_FUNCTION newPaintFunction = newPaintGetter(trackType, direction); - newPaintFunction(rideIndex, trackSequence, direction, height, &mapElement); - if (testpaint_is_ignored(direction, trackSequence)) { - continue; - } - - if (gVerticalTunnelHeight != referenceHeight) { - if (referenceHeight == 0) { - printf( - "Expected no vertical tunnel. [trackSequence:%d direction:%d]\n", - trackSequence, - direction - ); - - return false; - } - - utf8string strExpectedTunnelHeight = new utf8[16]; - utf8string strActualTunnelHeight = new utf8[16]; - printRelativeHeight(strExpectedTunnelHeight, 16, (referenceHeight * 16) - 48); - printRelativeHeight(strActualTunnelHeight, 16, (gVerticalTunnelHeight * 16) - 48); - - printf( - "Expected vertical tunnel height to be `%s`, was `%s`. [trackSequence:%d direction:%d]\n", - strExpectedTunnelHeight, - strActualTunnelHeight, - trackSequence, - direction - ); - - delete []strExpectedTunnelHeight; - delete []strActualTunnelHeight; - - return false; - } - } - } - - return true; - } - struct IgnoredEntry { uint8 Direction; @@ -250,11 +128,6 @@ namespace Intercept2 extern "C" { - bool testVerticalTunnels(uint8 rideType, uint8 trackType) - { - return Intercept2::testVerticalTunnels(rideType, trackType); - } - void testpaint_clear_ignore() { Intercept2::testClearIgnore(); diff --git a/test/testpaint/testpaint.vcxproj b/test/testpaint/testpaint.vcxproj index 5cb14b45ac..c3d28cd492 100644 --- a/test/testpaint/testpaint.vcxproj +++ b/test/testpaint/testpaint.vcxproj @@ -107,6 +107,7 @@ + From 18d9b1e91e98d08569ec7ea465d0fed5ce05297f Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 12:42:59 +0200 Subject: [PATCH 21/42] Don't use C for PaintIntercept functions --- OpenRCT2.xcodeproj/project.pbxproj | 2 + test/testpaint/FunctionCall.hpp | 37 ++++++++++++++++ test/testpaint/PaintIntercept.cpp | 68 ++++++++++++++---------------- test/testpaint/PaintIntercept.hpp | 29 +++++++++++++ test/testpaint/Printer.hpp | 2 +- test/testpaint/TestTrack.cpp | 9 ++-- test/testpaint/generate.cpp | 21 ++++----- test/testpaint/intercept.h | 41 ------------------ test/testpaint/main.cpp | 6 +-- 9 files changed, 119 insertions(+), 96 deletions(-) create mode 100644 test/testpaint/PaintIntercept.hpp diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 3775dd0bbc..23a7d8e3f0 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -532,6 +532,7 @@ C606CCD11DB4D7C800FE4015 /* SideTunnelCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SideTunnelCall.hpp; sourceTree = ""; }; C606CCD31DB4DD6C00FE4015 /* VerticalTunnelCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VerticalTunnelCall.cpp; sourceTree = ""; }; C606CCD41DB4DD6C00FE4015 /* VerticalTunnelCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VerticalTunnelCall.hpp; sourceTree = ""; }; + C606CCD61DB4E1CD00FE4015 /* PaintIntercept.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PaintIntercept.hpp; sourceTree = ""; }; C612A8971D64825300B634CA /* vehicle_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vehicle_data.c; sourceTree = ""; }; C612A8981D64825300B634CA /* vehicle_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vehicle_data.h; sourceTree = ""; }; C61FB7221CF86356004CE991 /* NetworkUser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkUser.cpp; sourceTree = ""; usesTabs = 0; }; @@ -1210,6 +1211,7 @@ C606CCB31DB4054000FE4015 /* intercept.h */, C606CCB41DB4054000FE4015 /* main.cpp */, C606CCB51DB4054000FE4015 /* PaintIntercept.cpp */, + C606CCD61DB4E1CD00FE4015 /* PaintIntercept.hpp */, C606CCB61DB4054000FE4015 /* Printer.cpp */, C606CCB71DB4054000FE4015 /* Printer.hpp */, C606CCCC1DB427A000FE4015 /* SegmentSupportHeightCall.cpp */, diff --git a/test/testpaint/FunctionCall.hpp b/test/testpaint/FunctionCall.hpp index aabe4e565e..52e9980665 100644 --- a/test/testpaint/FunctionCall.hpp +++ b/test/testpaint/FunctionCall.hpp @@ -19,6 +19,43 @@ #include "../../src/common.h" #include "intercept.h" +enum +{ + PAINT_98196C, + PAINT_98197C, + PAINT_98198C, + PAINT_98199C, + + SUPPORTS_METAL_A, + SUPPORTS_METAL_B, + SUPPORTS_WOOD_A, + SUPPORTS_WOOD_B, + + SET_SEGMENT_HEIGHT, +}; + +typedef struct +{ + uint8 function; + struct paint + { + uint32 image_id; + rct_xy16 offset; + rct_xyz16 bound_box_length; + sint16 z_offset; + rct_xyz16 bound_box_offset; + uint32 rotation; + } paint; + struct supports + { + int type; + uint8 segment; + int special; + int height; + uint32 colour_flags; + } supports; +} function_call; + class FunctionCall { public: static bool AssertsEquals(function_call expected, function_call actual); diff --git a/test/testpaint/PaintIntercept.cpp b/test/testpaint/PaintIntercept.cpp index 5ee804d6ae..92a7b90eae 100644 --- a/test/testpaint/PaintIntercept.cpp +++ b/test/testpaint/PaintIntercept.cpp @@ -15,7 +15,7 @@ #pragma endregion -#include "intercept.h" +#include "PaintIntercept.hpp" extern "C" { #include "../../src/common.h" @@ -24,9 +24,23 @@ extern "C" { #include "../../src/paint/supports.h" } -class PaintInterceptor { -public: - static void InitHooks() { +static bool _woodenSupports = false; +static uint8 _callCount = 0; +static function_call _calls[256] = {0}; + +namespace PaintIntercept { + static uint32 InterceptWoodenASupports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp); + static uint32 InterceptWoodenBSupports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp); + static uint32 InterceptMetalASupports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp); + static uint32 InterceptMetalBSupports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp); + static uint32 InterceptPaint6C(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp); + static uint32 InterceptPaint7C(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp); + static uint32 InterceptPaint8C(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp); + static uint32 InterceptPaint9C(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp); + static uint32 InterceptPaintFull(uint8 function, uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp); + static void CheckSegmentSupportHeight(); + + void InitHooks() { int supportsRegisterArgs[] = {EAX, EBX, EDX, EDI, EBP, END}; addhook(0x006629BC, (int) InterceptWoodenASupports, 0, supportsRegisterArgs, 0, EAX); addhook(0x00662D5C, (int) InterceptWoodenBSupports, 0, supportsRegisterArgs, 0, EAX); @@ -56,7 +70,7 @@ public: addhook(0x00687902, (int) InterceptPaint9C, 0, paintRegisterArgs, 0, EBP); } - static bool PaintWoodenSupports(uint8 function, int supportType, int special, int height, uint32 imageColourFlags, bool *underground) { + bool PaintWoodenSupports(uint8 function, int supportType, int special, int height, uint32 imageColourFlags, bool *underground) { function_call call = {0}; call.function = function; call.supports.type = supportType; @@ -70,7 +84,7 @@ public: return _woodenSupports; } - static bool PaintMetalSupports(uint8 function, int supportType, uint8 segment, int special, int height, uint32 imageColourFlags) { + bool PaintMetalSupports(uint8 function, int supportType, uint8 segment, int special, int height, uint32 imageColourFlags) { CheckSegmentSupportHeight(); function_call call = {0}; @@ -132,25 +146,20 @@ public: return nullptr; } - static void ClearCalls() { + void ClearCalls() { _callCount = 0; memset(_calls, 0, sizeof(_calls)); } - static int GetCalls(function_call *buffer) { + int GetCalls(function_call *buffer) { memcpy(buffer, _calls, _callCount * sizeof(function_call)); return _callCount; } - static void SetSimulateWoodenSupports(bool enabled) { + void SetSimulateWoodenSupports(bool enabled) { _woodenSupports = enabled; } -private: - static bool _woodenSupports; - static uint8 _callCount; - static function_call _calls[256]; - static uint32 InterceptMetalASupports(uint32 eax, uint32 ebx, uint32 edx, uint32 edi, uint32 ebp) { bool output = PaintMetalSupports(SUPPORTS_METAL_A, edi, ebx, (sint16) (eax & 0xFFFF), (edx & 0xFFFF), ebp); @@ -244,29 +253,26 @@ private: } }; -bool PaintInterceptor::_woodenSupports = false; -uint8 PaintInterceptor::_callCount = 0; -function_call PaintInterceptor::_calls[256] = {0}; extern "C" { bool wooden_a_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, bool *underground) { - return PaintInterceptor::PaintWoodenSupports(SUPPORTS_WOOD_A, supportType, special, height, imageColourFlags, underground); + return PaintIntercept::PaintWoodenSupports(SUPPORTS_WOOD_A, supportType, special, height, imageColourFlags, underground); } bool wooden_b_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, bool *underground) { - return PaintInterceptor::PaintWoodenSupports(SUPPORTS_WOOD_B, supportType, special, height, imageColourFlags, underground); + return PaintIntercept::PaintWoodenSupports(SUPPORTS_WOOD_B, supportType, special, height, imageColourFlags, underground); } bool metal_a_supports_paint_setup(uint8 supportType, uint8 segment, int special, int height, uint32 imageColourFlags) { - return PaintInterceptor::PaintMetalSupports(SUPPORTS_METAL_A, supportType, segment, special, height, imageColourFlags); + return PaintIntercept::PaintMetalSupports(SUPPORTS_METAL_A, supportType, segment, special, height, imageColourFlags); } bool metal_b_supports_paint_setup(uint8 supportType, uint8 segment, int special, int height, uint32 imageColourFlags) { - return PaintInterceptor::PaintMetalSupports(SUPPORTS_METAL_B, supportType, segment, special, height, imageColourFlags); + return PaintIntercept::PaintMetalSupports(SUPPORTS_METAL_B, supportType, segment, special, height, imageColourFlags); } paint_struct *sub_98196C(uint32 image_id, sint8 x_offset, sint8 y_offset, sint16 bound_box_length_x, sint16 bound_box_length_y, sint8 bound_box_length_z, sint16 z_offset, uint32 rotation) { - return PaintInterceptor::Paint6C(image_id, x_offset, y_offset, bound_box_length_x, bound_box_length_y, bound_box_length_z, z_offset, rotation); + return PaintIntercept::Paint6C(image_id, x_offset, y_offset, bound_box_length_x, bound_box_length_y, bound_box_length_z, z_offset, rotation); } paint_struct *sub_98197C( @@ -277,7 +283,7 @@ paint_struct *sub_98197C( sint16 bound_box_offset_x, sint16 bound_box_offset_y, sint16 bound_box_offset_z, uint32 rotation ) { - return PaintInterceptor::PaintFull( + return PaintIntercept::PaintFull( PAINT_98197C, image_id, x_offset, y_offset, @@ -296,7 +302,7 @@ paint_struct *sub_98198C( sint16 bound_box_offset_x, sint16 bound_box_offset_y, sint16 bound_box_offset_z, uint32 rotation ) { - return PaintInterceptor::PaintFull( + return PaintIntercept::PaintFull( PAINT_98198C, image_id, x_offset, y_offset, @@ -315,7 +321,7 @@ paint_struct *sub_98199C( sint16 bound_box_offset_x, sint16 bound_box_offset_y, sint16 bound_box_offset_z, uint32 rotation ) { - return PaintInterceptor::PaintFull( + return PaintIntercept::PaintFull( PAINT_98199C, image_id, x_offset, y_offset, @@ -330,16 +336,4 @@ bool paint_attach_to_previous_ps(uint32 image_id, uint16 x, uint16 y) { return false; } -void intercept_clear_calls() { - PaintInterceptor::ClearCalls(); -} - -int intercept_get_calls(function_call *buffer) { - return PaintInterceptor::GetCalls(buffer); -} - -void initHooks() { - PaintInterceptor::InitHooks(); -} - } diff --git a/test/testpaint/PaintIntercept.hpp b/test/testpaint/PaintIntercept.hpp new file mode 100644 index 0000000000..32ee986583 --- /dev/null +++ b/test/testpaint/PaintIntercept.hpp @@ -0,0 +1,29 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../../src/common.h" +#include "FunctionCall.hpp" + +namespace PaintIntercept { + void InitHooks(); + + void ClearCalls(); + int GetCalls(function_call *buffer); + + void SetSimulateWoodenSupports(bool enabled); +}; diff --git a/test/testpaint/Printer.hpp b/test/testpaint/Printer.hpp index 30b0749adf..f387f6adfa 100644 --- a/test/testpaint/Printer.hpp +++ b/test/testpaint/Printer.hpp @@ -19,7 +19,7 @@ #include #include -#include "intercept.h" +#include "FunctionCall.hpp" #include "SideTunnelCall.hpp" #include "SegmentSupportHeightCall.hpp" diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index 524d0d794c..5c1dd2b98f 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -20,6 +20,7 @@ #include "intercept.h" #include "FunctionCall.hpp" #include "GeneralSupportHeightCall.hpp" +#include "PaintIntercept.hpp" #include "Printer.hpp" #include "SegmentSupportHeightCall.hpp" #include "SideTunnelCall.hpp" @@ -165,16 +166,16 @@ static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 t direction, trackSequence, chainLift, inverted ); - intercept_clear_calls(); + PaintIntercept::ClearCalls(); Intercept2::ResetSupportHeights(); CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); - callCount = intercept_get_calls(callBuffer); + callCount = PaintIntercept::GetCalls(callBuffer); std::vector oldCalls; oldCalls.insert(oldCalls.begin(), callBuffer, callBuffer + callCount); - intercept_clear_calls(); + PaintIntercept::ClearCalls(); testpaint_clear_ignore(); Intercept2::ResetSupportHeights(); @@ -185,7 +186,7 @@ static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 t continue; } - callCount = intercept_get_calls(callBuffer); + callCount = PaintIntercept::GetCalls(callBuffer); std::vector newCalls; newCalls.insert(newCalls.begin(), callBuffer, callBuffer + callCount); diff --git a/test/testpaint/generate.cpp b/test/testpaint/generate.cpp index b4205cba30..4db4f30950 100644 --- a/test/testpaint/generate.cpp +++ b/test/testpaint/generate.cpp @@ -18,7 +18,8 @@ #include #include -#include "intercept.h" +#include "FunctionCall.hpp" +#include "PaintIntercept.hpp" #include "SegmentSupportHeightCall.hpp" #include "SideTunnelCall.hpp" #include "String.hpp" @@ -421,9 +422,9 @@ private: RCT2_GLOBAL(0x009DE56E, sint16) = 64; function_call callBuffer[256] = { 0 }; - intercept_clear_calls(); + PaintIntercept::ClearCalls(); CallOriginal(trackType, direction, trackSequence, height, &mapElement); - int numCalls = intercept_get_calls(callBuffer); + int numCalls = PaintIntercept::GetCalls(callBuffer); calls[direction].insert(calls[direction].begin(), callBuffer, callBuffer + numCalls); for (auto &&call : calls[direction]) { @@ -442,9 +443,9 @@ private: // Get chain lift calls mapElement.type |= 0x80; - intercept_clear_calls(); + PaintIntercept::ClearCalls(); CallOriginal(trackType, direction, trackSequence, height, &mapElement); - numCalls = intercept_get_calls(callBuffer); + numCalls = PaintIntercept::GetCalls(callBuffer); chainLiftCalls[direction].insert(chainLiftCalls[direction].begin(), callBuffer, callBuffer + numCalls); // Get cable lift calls (giga coaster only) @@ -452,9 +453,9 @@ private: { mapElement.type = 0; mapElement.properties.track.colour |= TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT; - intercept_clear_calls(); + PaintIntercept::ClearCalls(); CallOriginal(trackType, direction, trackSequence, height, &mapElement); - numCalls = intercept_get_calls(callBuffer); + numCalls = PaintIntercept::GetCalls(callBuffer); cableLiftCalls[direction].insert(cableLiftCalls[direction].begin(), callBuffer, callBuffer + numCalls); } @@ -465,9 +466,9 @@ private: RCT2_GLOBAL(0x009DE56E, sint16) = 64; mapElement.type = 0; mapElement.properties.track.colour &= ~TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT; - intercept_clear_calls(); + PaintIntercept::ClearCalls(); CallOriginal(trackType, direction, trackSequence, height, &mapElement); - numCalls = intercept_get_calls(callBuffer); + numCalls = PaintIntercept::GetCalls(callBuffer); std::vector checkCalls = std::vector(callBuffer, callBuffer + numCalls); if (!CompareFunctionCalls(checkCalls, calls[direction])) { @@ -715,7 +716,7 @@ private: bool CompareFunctionCall(const function_call a, const function_call &b) { - return assertFunctionCallEquals(a, b); + return FunctionCall::AssertsEquals(a, b); } const char * GetFunctionCallName(int function) diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index 6dcdad474b..f0e75dd040 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -33,20 +33,7 @@ extern "C" #define gRideEntries RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, rct_ride_entry*) #define gCurrentRotation RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8) -enum -{ - PAINT_98196C, - PAINT_98197C, - PAINT_98198C, - PAINT_98199C, - SUPPORTS_METAL_A, - SUPPORTS_METAL_B, - SUPPORTS_WOOD_A, - SUPPORTS_WOOD_B, - - SET_SEGMENT_HEIGHT, -}; enum { TEST_SUCCESS, @@ -54,41 +41,13 @@ enum { TEST_SKIPPED, }; -typedef struct -{ - uint8 function; - struct paint - { - uint32 image_id; - rct_xy16 offset; - rct_xyz16 bound_box_length; - sint16 z_offset; - rct_xyz16 bound_box_offset; - uint32 rotation; - } paint; - struct supports - { - int type; - uint8 segment; - int special; - int height; - uint32 colour_flags; - } supports; -} function_call; - #ifdef __cplusplus extern "C" { #endif - void initHooks(); - bool testTunnels(uint8 rideType, uint8 trackType); - bool testVerticalTunnels(uint8 rideType, uint8 trackType); - void intercept_clear_calls(); - int intercept_get_calls(function_call * buffer); void intercept_reset_environment(); void intercept_reset_segment_heights(); void intercept_reset_tunnels(); - bool assertFunctionCallEquals(function_call expected, function_call actual); int generatePaintCode(uint8 rideType); diff --git a/test/testpaint/main.cpp b/test/testpaint/main.cpp index 68bac9d702..03a3371028 100644 --- a/test/testpaint/main.cpp +++ b/test/testpaint/main.cpp @@ -23,7 +23,7 @@ #include #endif // defined(__unix__) -#include "intercept.h" +#include "PaintIntercept.hpp" #include "TestTrack.hpp" #include "Utils.hpp" @@ -422,7 +422,7 @@ int main(int argc, char *argv[]) { } openrct2_setup_rct2_segment(); - initHooks(); + PaintIntercept::InitHooks(); return generatePaintCode(specificRideType); } @@ -464,7 +464,7 @@ int main(int argc, char *argv[]) { ColouredPrintF(CLIColour::GREEN, "[----------] "); printf("Global test environment set-up.\n"); openrct2_setup_rct2_segment(); - initHooks(); + PaintIntercept::InitHooks(); int successCount = 0; std::vector failures; From 455080d8b819c7c86a3359fe07c69914f27060ef Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 15:15:40 +0200 Subject: [PATCH 22/42] Fix MSVC --- test/testpaint/GeneralSupportHeightCall.hpp | 9 ++++----- test/testpaint/SegmentSupportHeightCall.cpp | 1 + test/testpaint/main.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/testpaint/GeneralSupportHeightCall.hpp b/test/testpaint/GeneralSupportHeightCall.hpp index 3127c634d8..9187ebaa62 100644 --- a/test/testpaint/GeneralSupportHeightCall.hpp +++ b/test/testpaint/GeneralSupportHeightCall.hpp @@ -42,11 +42,10 @@ struct SupportCall { } }; -class GeneralSupportHeightCall { -public: - static bool CallsMatch(SupportCall tileSupportCalls[4]); +namespace GeneralSupportHeightCall { + bool CallsMatch(SupportCall tileSupportCalls[4]); - static SupportCall *FindMostCommonSupportCall(SupportCall calls[4]); + SupportCall *FindMostCommonSupportCall(SupportCall calls[4]); - static bool AssertEquals(const SupportCall *lhs, const SupportCall *rhs); + bool AssertEquals(const SupportCall *lhs, const SupportCall *rhs); }; diff --git a/test/testpaint/SegmentSupportHeightCall.cpp b/test/testpaint/SegmentSupportHeightCall.cpp index c769021d92..05f3fbf906 100644 --- a/test/testpaint/SegmentSupportHeightCall.cpp +++ b/test/testpaint/SegmentSupportHeightCall.cpp @@ -15,6 +15,7 @@ #pragma endregion #include +#include #include "SegmentSupportHeightCall.hpp" diff --git a/test/testpaint/main.cpp b/test/testpaint/main.cpp index 03a3371028..5be202c211 100644 --- a/test/testpaint/main.cpp +++ b/test/testpaint/main.cpp @@ -358,7 +358,7 @@ static void PrintRideTypes() } } -#import "GeneralSupportHeightCall.hpp" +#include "GeneralSupportHeightCall.hpp" static void TestGeneralSupportHeightCall() { SupportCall callA = {16, 0x20}; From d05dfbe5dc00d1474ffaab2d8a1de95b0b7e9796 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 16:06:05 +0200 Subject: [PATCH 23/42] Rename intercept2 to TestPaint --- OpenRCT2.xcodeproj/project.pbxproj | 16 +++---- test/testpaint/FunctionCall.hpp | 2 +- test/testpaint/Printer.cpp | 8 ++-- .../{intercept_2.cpp => TestPaint.cpp} | 25 +++-------- test/testpaint/{intercept.h => TestPaint.hpp} | 42 ++++--------------- test/testpaint/TestTrack.cpp | 38 ++++++++--------- test/testpaint/generate.cpp | 14 +++---- test/testpaint/testpaint.vcxproj | 2 +- 8 files changed, 53 insertions(+), 94 deletions(-) rename test/testpaint/{intercept_2.cpp => TestPaint.cpp} (88%) rename test/testpaint/{intercept.h => TestPaint.hpp} (75%) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 23a7d8e3f0..5f221925e4 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -25,7 +25,6 @@ C606CCBF1DB4054000FE4015 /* data.c in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAC1DB4054000FE4015 /* data.c */; }; C606CCC01DB4054000FE4015 /* FunctionCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAE1DB4054000FE4015 /* FunctionCall.cpp */; }; C606CCC11DB4054000FE4015 /* generate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB01DB4054000FE4015 /* generate.cpp */; }; - C606CCC21DB4054000FE4015 /* intercept_2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB11DB4054000FE4015 /* intercept_2.cpp */; }; C606CCC41DB4054000FE4015 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB41DB4054000FE4015 /* main.cpp */; }; C606CCC51DB4054000FE4015 /* PaintIntercept.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB51DB4054000FE4015 /* PaintIntercept.cpp */; }; C606CCC61DB4054000FE4015 /* Printer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB61DB4054000FE4015 /* Printer.cpp */; }; @@ -36,6 +35,7 @@ C606CCCF1DB427A000FE4015 /* SegmentSupportHeightCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCCC1DB427A000FE4015 /* SegmentSupportHeightCall.cpp */; }; C606CCD21DB4D7C800FE4015 /* SideTunnelCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCD01DB4D7C800FE4015 /* SideTunnelCall.cpp */; }; C606CCD51DB4DD6C00FE4015 /* VerticalTunnelCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCD31DB4DD6C00FE4015 /* VerticalTunnelCall.cpp */; }; + C606CD261DB5120C00FE4015 /* TestPaint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CD231DB5120900FE4015 /* TestPaint.cpp */; }; C612A8991D64825300B634CA /* vehicle_data.c in Sources */ = {isa = PBXBuildFile; fileRef = C612A8971D64825300B634CA /* vehicle_data.c */; }; C61FB7241CF86356004CE991 /* NetworkUser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61FB7221CF86356004CE991 /* NetworkUser.cpp */; }; C64FDA641D6D9A2100F259B9 /* air_powered_vertical_coaster.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F8BB1CDBC3B7009F9BFC /* air_powered_vertical_coaster.c */; }; @@ -402,8 +402,6 @@ D44272A51CC81B3200D84D28 /* particle.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271EF1CC81B3200D84D28 /* particle.c */; }; D44272A61CC81B3200D84D28 /* scenery.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271F01CC81B3200D84D28 /* scenery.c */; }; D44272A71CC81B3200D84D28 /* sprite.c in Sources */ = {isa = PBXBuildFile; fileRef = D44271F21CC81B3200D84D28 /* sprite.c */; }; - D452919B1DAA204200C11788 /* generate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D45291991DAA202C00C11788 /* generate.cpp */; }; - D45A38BB1CF3006400659A24 /* engines in Resources */ = {isa = PBXBuildFile; fileRef = D45A38B21CF3006400659A24 /* engines */; }; D45A38BC1CF3006400659A24 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38B31CF3006400659A24 /* libcrypto.dylib */; }; D45A38BE1CF3006400659A24 /* libjansson.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38B51CF3006400659A24 /* libjansson.dylib */; }; D45A38C01CF3006400659A24 /* libSDL2_ttf.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38B71CF3006400659A24 /* libSDL2_ttf.dylib */; }; @@ -512,8 +510,6 @@ C606CCAE1DB4054000FE4015 /* FunctionCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionCall.cpp; sourceTree = ""; }; C606CCAF1DB4054000FE4015 /* FunctionCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FunctionCall.hpp; sourceTree = ""; }; C606CCB01DB4054000FE4015 /* generate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = generate.cpp; sourceTree = ""; }; - C606CCB11DB4054000FE4015 /* intercept_2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = intercept_2.cpp; sourceTree = ""; }; - C606CCB31DB4054000FE4015 /* intercept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intercept.h; sourceTree = ""; }; C606CCB41DB4054000FE4015 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; C606CCB51DB4054000FE4015 /* PaintIntercept.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PaintIntercept.cpp; sourceTree = ""; }; C606CCB61DB4054000FE4015 /* Printer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Printer.cpp; sourceTree = ""; }; @@ -533,6 +529,8 @@ C606CCD31DB4DD6C00FE4015 /* VerticalTunnelCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VerticalTunnelCall.cpp; sourceTree = ""; }; C606CCD41DB4DD6C00FE4015 /* VerticalTunnelCall.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VerticalTunnelCall.hpp; sourceTree = ""; }; C606CCD61DB4E1CD00FE4015 /* PaintIntercept.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PaintIntercept.hpp; sourceTree = ""; }; + C606CD231DB5120900FE4015 /* TestPaint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestPaint.cpp; sourceTree = ""; }; + C606CD241DB5120900FE4015 /* TestPaint.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TestPaint.hpp; sourceTree = ""; }; C612A8971D64825300B634CA /* vehicle_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vehicle_data.c; sourceTree = ""; }; C612A8981D64825300B634CA /* vehicle_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vehicle_data.h; sourceTree = ""; }; C61FB7221CF86356004CE991 /* NetworkUser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkUser.cpp; sourceTree = ""; usesTabs = 0; }; @@ -939,8 +937,6 @@ D44271F21CC81B3200D84D28 /* sprite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sprite.c; sourceTree = ""; }; D44271F31CC81B3200D84D28 /* sprite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sprite.h; sourceTree = ""; }; D44271F41CC81B3200D84D28 /* water.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = water.h; sourceTree = ""; }; - D45291991DAA202C00C11788 /* generate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = generate.cpp; sourceTree = ""; }; - D45A38B21CF3006400659A24 /* engines */ = {isa = PBXFileReference; lastKnownFileType = folder; path = engines; sourceTree = ""; }; D45A38B31CF3006400659A24 /* libcrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libcrypto.dylib; sourceTree = ""; }; D45A38B41CF3006400659A24 /* libfreetype.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libfreetype.dylib; sourceTree = ""; }; D45A38B51CF3006400659A24 /* libjansson.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libjansson.dylib; sourceTree = ""; }; @@ -1207,8 +1203,6 @@ C606CCCA1DB427A000FE4015 /* GeneralSupportHeightCall.cpp */, C606CCCB1DB427A000FE4015 /* GeneralSupportHeightCall.hpp */, C606CCB01DB4054000FE4015 /* generate.cpp */, - C606CCB11DB4054000FE4015 /* intercept_2.cpp */, - C606CCB31DB4054000FE4015 /* intercept.h */, C606CCB41DB4054000FE4015 /* main.cpp */, C606CCB51DB4054000FE4015 /* PaintIntercept.cpp */, C606CCD61DB4E1CD00FE4015 /* PaintIntercept.hpp */, @@ -1220,6 +1214,8 @@ C606CCD11DB4D7C800FE4015 /* SideTunnelCall.hpp */, C606CCB81DB4054000FE4015 /* String.cpp */, C606CCB91DB4054000FE4015 /* String.hpp */, + C606CD231DB5120900FE4015 /* TestPaint.cpp */, + C606CD241DB5120900FE4015 /* TestPaint.hpp */, C606CCBA1DB4054000FE4015 /* TestTrack.cpp */, C606CCBB1DB4054000FE4015 /* TestTrack.hpp */, C606CCBC1DB4054000FE4015 /* Utils.cpp */, @@ -2439,7 +2435,6 @@ C64FDA781D6D9A2100F259B9 /* reverser_roller_coaster.c in Sources */, C64FDA791D6D9A2100F259B9 /* side_friction_roller_coaster.c in Sources */, C64FDA7A1D6D9A2100F259B9 /* spiral_roller_coaster.c in Sources */, - C606CCC21DB4054000FE4015 /* intercept_2.cpp in Sources */, C64FDA7B1D6D9A2100F259B9 /* stand_up_roller_coaster.c in Sources */, C606CCC61DB4054000FE4015 /* Printer.cpp in Sources */, C64FDA7C1D6D9A2100F259B9 /* steeplechase.c in Sources */, @@ -2488,6 +2483,7 @@ C64FDA9F1D6D9A2100F259B9 /* swinging_inverter_ship.c in Sources */, C64FDAA01D6D9A2100F259B9 /* top_spin.c in Sources */, C64FDAA11D6D9A2100F259B9 /* twist.c in Sources */, + C606CD261DB5120C00FE4015 /* TestPaint.cpp in Sources */, C64FDAA21D6D9A2100F259B9 /* chairlift.c in Sources */, C606CCC71DB4054000FE4015 /* String.cpp in Sources */, C64FDAA31D6D9A2100F259B9 /* lift.c in Sources */, diff --git a/test/testpaint/FunctionCall.hpp b/test/testpaint/FunctionCall.hpp index 52e9980665..10c1c4d18c 100644 --- a/test/testpaint/FunctionCall.hpp +++ b/test/testpaint/FunctionCall.hpp @@ -17,7 +17,7 @@ #pragma once #include "../../src/common.h" -#include "intercept.h" +#include "TestPaint.hpp" enum { diff --git a/test/testpaint/Printer.cpp b/test/testpaint/Printer.cpp index 87882dbbda..77915fc4b2 100644 --- a/test/testpaint/Printer.cpp +++ b/test/testpaint/Printer.cpp @@ -216,10 +216,10 @@ namespace Printer { uint32 palette = imageId & ~0x7FFFF; std::string paletteName; - if (palette == Intercept2::DEFAULT_SCHEME_TRACK) paletteName = "SCHEME_TRACK"; - else if (palette == Intercept2::DEFAULT_SCHEME_SUPPORTS) paletteName = "SCHEME_SUPPORTS"; - else if (palette == Intercept2::DEFAULT_SCHEME_MISC) paletteName = "SCHEME_MISC"; - else if (palette == Intercept2::DEFAULT_SCHEME_3) paletteName = "SCHEME_3"; + if (palette == TestPaint::DEFAULT_SCHEME_TRACK) paletteName = "SCHEME_TRACK"; + else if (palette == TestPaint::DEFAULT_SCHEME_SUPPORTS) paletteName = "SCHEME_SUPPORTS"; + else if (palette == TestPaint::DEFAULT_SCHEME_MISC) paletteName = "SCHEME_MISC"; + else if (palette == TestPaint::DEFAULT_SCHEME_3) paletteName = "SCHEME_3"; else { paletteName = String::Format("0x%08X", palette); } diff --git a/test/testpaint/intercept_2.cpp b/test/testpaint/TestPaint.cpp similarity index 88% rename from test/testpaint/intercept_2.cpp rename to test/testpaint/TestPaint.cpp index 8695423ea1..a5a74ce3b0 100644 --- a/test/testpaint/intercept_2.cpp +++ b/test/testpaint/TestPaint.cpp @@ -17,7 +17,7 @@ #include #include -#include "intercept.h" +#include "TestPaint.hpp" #include "GeneralSupportHeightCall.hpp" #include "Printer.hpp" #include "SegmentSupportHeightCall.hpp" @@ -31,7 +31,7 @@ extern "C" { #include "../../src/hook.h" } -namespace Intercept2 +namespace TestPaint { void ResetEnvironment() { gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE; @@ -130,35 +130,22 @@ extern "C" { void testpaint_clear_ignore() { - Intercept2::testClearIgnore(); + TestPaint::testClearIgnore(); } void testpaint_ignore(uint8 direction, uint8 trackSequence) { - Intercept2::testIgnore(direction, trackSequence); + TestPaint::testIgnore(direction, trackSequence); } void testpaint_ignore_all() { - Intercept2::testIgnoreAll(); + TestPaint::testIgnoreAll(); } bool testpaint_is_ignored(uint8 direction, uint8 trackSequence) { - return Intercept2::testIsIgnored(direction, trackSequence); + return TestPaint::testIsIgnored(direction, trackSequence); } - void intercept_reset_environment() { - Intercept2::ResetEnvironment(); - } - - void intercept_reset_segment_heights() { - Intercept2::ResetSupportHeights(); - } - - void intercept_reset_tunnels() { - Intercept2::ResetTunnels(); - } - - } diff --git a/test/testpaint/intercept.h b/test/testpaint/TestPaint.hpp similarity index 75% rename from test/testpaint/intercept.h rename to test/testpaint/TestPaint.hpp index f0e75dd040..b0ff7d78de 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/TestPaint.hpp @@ -14,65 +14,41 @@ *****************************************************************************/ #pragma endregion -#ifndef _TEST_PAINT_INTERCEPT_H_ -#define _TEST_PAINT_INTERCEPT_H_ +#pragma once + +#include #include "../../src/common.h" -#ifdef __cplusplus extern "C" { -#endif #include "../../src/interface/colour.h" #include "../../src/paint/paint.h" #include "../../src/paint/map_element/map_element.h" -#ifdef __cplusplus } -#endif -#define gRideEntries RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, rct_ride_entry*) +#define gRideEntries RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, rct_ride_entry*) #define gCurrentRotation RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8) - - enum { TEST_SUCCESS, TEST_FAILED, TEST_SKIPPED, }; -#ifdef __cplusplus -extern "C" -{ -#endif - void intercept_reset_environment(); - void intercept_reset_segment_heights(); - void intercept_reset_tunnels(); - - int generatePaintCode(uint8 rideType); - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus - -#include - -namespace Intercept2 +namespace TestPaint { static const uint32 DEFAULT_SCHEME_TRACK = COLOUR_GREY << 19 | COLOUR_WHITE << 24 | 0xA0000000; static const uint32 DEFAULT_SCHEME_SUPPORTS = COLOUR_LIGHT_BLUE << 19 | COLOUR_ICY_BLUE << 24 | 0xA0000000; static const uint32 DEFAULT_SCHEME_MISC = COLOUR_DARK_PURPLE << 19 | COLOUR_LIGHT_PURPLE << 24 | 0xA0000000; static const uint32 DEFAULT_SCHEME_3 = COLOUR_BRIGHT_PURPLE << 19 | COLOUR_DARK_BLUE << 24 | 0xA0000000; - - void ResetEnvironment(); void ResetTunnels(); void ResetSupportHeights(); } -#endif - -#endif // #endif _TEST_PAINT_INTERCEPT_H_ +extern "C" +{ +int generatePaintCode(uint8 rideType); +} diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index 5c1dd2b98f..498da4fc85 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -17,7 +17,7 @@ #include #include -#include "intercept.h" +#include "TestPaint.hpp" #include "FunctionCall.hpp" #include "GeneralSupportHeightCall.hpp" #include "PaintIntercept.hpp" @@ -141,8 +141,8 @@ static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 t gSurfaceElement = &surfaceElement; gDidPassSurface = true; - Intercept2::ResetEnvironment(); - Intercept2::ResetTunnels(); + TestPaint::ResetEnvironment(); + TestPaint::ResetTunnels(); function_call callBuffer[256] = {0}; int callCount = 0; @@ -167,7 +167,7 @@ static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 t ); PaintIntercept::ClearCalls(); - Intercept2::ResetSupportHeights(); + TestPaint::ResetSupportHeights(); CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); @@ -177,7 +177,7 @@ static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 t PaintIntercept::ClearCalls(); testpaint_clear_ignore(); - Intercept2::ResetSupportHeights(); + TestPaint::ResetSupportHeights(); CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); @@ -232,8 +232,8 @@ static uint8 TestTrackElementSegmentSupportHeight(uint8 rideType, uint8 trackTyp gSurfaceElement = &surfaceElement; gDidPassSurface = true; - Intercept2::ResetEnvironment(); - Intercept2::ResetTunnels(); + TestPaint::ResetEnvironment(); + TestPaint::ResetTunnels(); // TODO: Test Chainlift // TODO: Test Maze @@ -244,7 +244,7 @@ static uint8 TestTrackElementSegmentSupportHeight(uint8 rideType, uint8 trackTyp std::vector tileSegmentSupportCalls[4]; for (int direction = 0; direction < 4; direction++) { - Intercept2::ResetSupportHeights(); + TestPaint::ResetSupportHeights(); CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); @@ -269,7 +269,7 @@ static uint8 TestTrackElementSegmentSupportHeight(uint8 rideType, uint8 trackTyp } for (int direction = 0; direction < 4; direction++) { - Intercept2::ResetSupportHeights(); + TestPaint::ResetSupportHeights(); testpaint_clear_ignore(); CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); @@ -312,8 +312,8 @@ static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackTyp gSurfaceElement = &surfaceElement; gDidPassSurface = true; - Intercept2::ResetEnvironment(); - Intercept2::ResetTunnels(); + TestPaint::ResetEnvironment(); + TestPaint::ResetTunnels(); // TODO: Test Chainlift // TODO: Test Maze @@ -323,7 +323,7 @@ static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackTyp SupportCall tileGeneralSupportCalls[4]; for (int direction = 0; direction < 4; direction++) { - Intercept2::ResetSupportHeights(); + TestPaint::ResetSupportHeights(); CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); @@ -352,7 +352,7 @@ static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackTyp } for (int direction = 0; direction < 4; direction++) { - Intercept2::ResetSupportHeights(); + TestPaint::ResetSupportHeights(); testpaint_clear_ignore(); CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); @@ -406,13 +406,13 @@ static uint8 TestTrackElementSideTunnels(uint8 rideType, uint8 trackType, uint8 gSurfaceElement = &surfaceElement; gDidPassSurface = true; - Intercept2::ResetEnvironment(); - Intercept2::ResetTunnels(); + TestPaint::ResetEnvironment(); + TestPaint::ResetTunnels(); TunnelCall tileTunnelCalls[4][4]; for (int direction = 0; direction < 4; direction++) { - Intercept2::ResetTunnels(); + TestPaint::ResetTunnels(); for (sint8 offset = -8; offset <= 8; offset += 8) { CallOriginal(rideType, trackType, direction, trackSequence, height + offset, &mapElement); @@ -440,7 +440,7 @@ static uint8 TestTrackElementSideTunnels(uint8 rideType, uint8 trackType, uint8 TunnelCall newTileTunnelCalls[4][4]; for (int direction = 0; direction < 4; direction++) { - Intercept2::ResetTunnels(); + TestPaint::ResetTunnels(); testpaint_clear_ignore(); @@ -520,8 +520,8 @@ static uint8 TestTrackElementVerticalTunnels(uint8 rideType, uint8 trackType, ui gSurfaceElement = &surfaceElement; gDidPassSurface = true; - Intercept2::ResetEnvironment(); - Intercept2::ResetTunnels(); + TestPaint::ResetEnvironment(); + TestPaint::ResetTunnels(); uint8 verticalTunnelHeight[4]; diff --git a/test/testpaint/generate.cpp b/test/testpaint/generate.cpp index 4db4f30950..e3be70c09d 100644 --- a/test/testpaint/generate.cpp +++ b/test/testpaint/generate.cpp @@ -742,7 +742,7 @@ private: TunnelCall tileTunnelCalls[4][4], sint16 verticalTunnelHeights[4]) { - intercept_reset_tunnels(); + TestPaint::ResetTunnels(); for (int offset = -8; offset <= 8; offset += 8) { @@ -953,10 +953,10 @@ private: uint32 palette = imageId & ~0x7FFFF; std::string paletteName; - if (palette == Intercept2::DEFAULT_SCHEME_TRACK) paletteName = "gTrackColours[SCHEME_TRACK]"; - else if (palette == Intercept2::DEFAULT_SCHEME_SUPPORTS) paletteName = "gTrackColours[SCHEME_SUPPORTS]"; - else if (palette == Intercept2::DEFAULT_SCHEME_MISC) paletteName = "gTrackColours[SCHEME_MISC]"; - else if (palette == Intercept2::DEFAULT_SCHEME_3) paletteName = "gTrackColours[SCHEME_3]"; + if (palette == TestPaint::DEFAULT_SCHEME_TRACK) paletteName = "gTrackColours[SCHEME_TRACK]"; + else if (palette == TestPaint::DEFAULT_SCHEME_SUPPORTS) paletteName = "gTrackColours[SCHEME_SUPPORTS]"; + else if (palette == TestPaint::DEFAULT_SCHEME_MISC) paletteName = "gTrackColours[SCHEME_MISC]"; + else if (palette == TestPaint::DEFAULT_SCHEME_3) paletteName = "gTrackColours[SCHEME_3]"; else { paletteName = String::Format("0x%08X", palette); } @@ -1009,8 +1009,8 @@ private: void CallOriginal(int trackType, int direction, int trackSequence, int height, rct_map_element *mapElement) { - intercept_reset_environment(); - intercept_reset_segment_heights(); + TestPaint::ResetEnvironment(); + TestPaint::ResetSupportHeights(); uint32 *trackDirectionList = (uint32 *)RideTypeTrackPaintFunctionsOld[_rideType][trackType]; // Have to call from this point as it pushes esi and expects callee to pop it diff --git a/test/testpaint/testpaint.vcxproj b/test/testpaint/testpaint.vcxproj index c3d28cd492..09b27dffd4 100644 --- a/test/testpaint/testpaint.vcxproj +++ b/test/testpaint/testpaint.vcxproj @@ -98,13 +98,13 @@ - + From e1c4e3e8f26e4e63e534983f6e470f62bf65dd45 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 16:07:32 +0200 Subject: [PATCH 24/42] Remove more C bridging code --- test/testpaint/FunctionCall.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/testpaint/FunctionCall.cpp b/test/testpaint/FunctionCall.cpp index 8d7973b8c7..b120f5b2f7 100644 --- a/test/testpaint/FunctionCall.cpp +++ b/test/testpaint/FunctionCall.cpp @@ -138,9 +138,3 @@ static SpriteGroup getSpriteGroup(uint16 spriteIndex) { return SPRITEGROUP_NONE; } - -extern "C" { - bool assertFunctionCallEquals(function_call expected, function_call actual) { - return FunctionCall::AssertsEquals(expected, actual); - } -} \ No newline at end of file From 7d126126ed349a803aa1896fc364ba43628e59e7 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 17:59:51 +0200 Subject: [PATCH 25/42] Add filters --- test/testpaint/TestTrack.cpp | 189 ++++++++++++++++++++++++++++++++++- 1 file changed, 184 insertions(+), 5 deletions(-) diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index 498da4fc85..7cdad8ed73 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -35,6 +35,136 @@ extern "C" { #include "../../src/ride/track_data.h" } +interface ITestTrackFilter { +public: + virtual ~ITestTrackFilter() {} + + virtual bool AppliesTo(uint8 rideType, uint8 trackType) abstract; + + virtual int Variations(uint8 rideType, uint8 trackType) abstract; + + virtual std::string VariantName(uint8 rideType, uint8 trackType, int variant) abstract; + + virtual void ApplyTo(uint8 rideType, uint8 trackType, int variant, + rct_map_element *mapElement, rct_map_element *surfaceElement, + rct_ride *ride, rct_ride_entry *rideEntry + ) abstract; +}; + +class CableLiftFilter : public ITestTrackFilter { +public: + bool AppliesTo(uint8 rideType, uint8 trackType) { + return rideType == RIDE_TYPE_GIGA_COASTER; + } + + int Variations(uint8 rideType, uint8 trackType) { + return 2; + } + + std::string VariantName(uint8 rideType, uint8 trackType, int variant) { + return String::Format("cableLift:%d", variant); + } + + virtual void ApplyTo(uint8 rideType, uint8 trackType, int variant, + rct_map_element *mapElement, rct_map_element *surfaceElement, + rct_ride *ride, rct_ride_entry *rideEntry + ) { + if (variant == 0) { + mapElement->properties.track.colour &= ~TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT; + } else { + mapElement->properties.track.colour |= TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT; + } + } +}; + +class ChainLiftFilter : public ITestTrackFilter { +public: + bool AppliesTo(uint8 rideType, uint8 trackType) { + return !ride_type_has_flag(rideType, RIDE_TYPE_FLAG_FLAT_RIDE); + } + + int Variations(uint8 rideType, uint8 trackType) { + return 2; + } + + std::string VariantName(uint8 rideType, uint8 trackType, int variant) { + return String::Format("chainLift:%d", variant); + } + + virtual void ApplyTo(uint8 rideType, uint8 trackType, int variant, + rct_map_element *mapElement, rct_map_element *surfaceElement, + rct_ride *ride, rct_ride_entry *rideEntry + ) { + if (variant == 0) { + mapElement->type &= ~0x80; + } else { + mapElement->type |= 0x80; + } + } +}; + +class InvertedFilter : public ITestTrackFilter { +public: + bool AppliesTo(uint8 rideType, uint8 trackType) { + if (rideType == RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER || + rideType == RIDE_TYPE_FLYING_ROLLER_COASTER || + rideType == RIDE_TYPE_LAY_DOWN_ROLLER_COASTER) { + return true; + } + + return false; + } + + int Variations(uint8 rideType, uint8 trackType) { + return 2; + } + + std::string VariantName(uint8 rideType, uint8 trackType, int variant) { + return String::Format("inverted:%d", variant); + } + + virtual void ApplyTo(uint8 rideType, uint8 trackType, int variant, + rct_map_element *mapElement, rct_map_element *surfaceElement, + rct_ride *ride, rct_ride_entry *rideEntry + ) { + if (variant == 0) { + mapElement->properties.track.colour &= ~TRACK_ELEMENT_COLOUR_FLAG_INVERTED; + } else { + mapElement->properties.track.colour |= TRACK_ELEMENT_COLOUR_FLAG_INVERTED; + } + } +}; + +class EntranceStyleFilter : public ITestTrackFilter { +public: + bool AppliesTo(uint8 rideType, uint8 trackType) { + if (trackType == TRACK_ELEM_BEGIN_STATION || + trackType == TRACK_ELEM_MIDDLE_STATION || + trackType == TRACK_ELEM_END_STATION) { + return true; + } + + return false; + } + + int Variations(uint8 rideType, uint8 trackType) { + return RIDE_ENTRANCE_STYLE_COUNT - 1; + } + + std::string VariantName(uint8 rideType, uint8 trackType, int variant) { + return String::Format("entranceStyle:%d", variant); + } + + virtual void ApplyTo(uint8 rideType, uint8 trackType, int variant, + rct_map_element *mapElement, rct_map_element *surfaceElement, + rct_ride *ride, rct_ride_entry *rideEntry + ) { + ride->entrance_style = variant; + } +}; + + + static void CallOriginal( uint8 rideType, uint8 trackType, @@ -147,14 +277,62 @@ static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 t function_call callBuffer[256] = {0}; int callCount = 0; - int chainLift = 0; - int inverted = 0; - // TODO: test chainlift // TODO: test inverted // TODO: test supports // TODO: test entrance styles + std::vector filters; + filters.push_back(new CableLiftFilter()); + filters.push_back(new ChainLiftFilter()); + filters.push_back(new InvertedFilter()); + filters.push_back(new EntranceStyleFilter()); + + std::vector activeFilters; + + for (auto &&filter : filters) { + if (filter->AppliesTo(rideType, trackType)) { + activeFilters.push_back(filter); + } + } + + // Add an element so there's always something to add to + std::vector filler; + filler.push_back(0); + + std::vector> argumentPermutations; + argumentPermutations.push_back(filler); + for (int filterIndex = 0; filterIndex < activeFilters.size(); ++filterIndex) { + ITestTrackFilter *filter = activeFilters[filterIndex]; + uint8 variantCount = filter->Variations(rideType, trackType); + + std::vector> newArgumentPermutations; + for (int variant = 0; variant < variantCount; variant++) { + for (auto &&oldPermutation : argumentPermutations) { + std::vector permutation; + permutation.insert(permutation.begin(), oldPermutation.begin(), oldPermutation.end()); + permutation.push_back(variant); + newArgumentPermutations.push_back(permutation); + } + } + + argumentPermutations.clear(); + argumentPermutations.insert(argumentPermutations.begin(), newArgumentPermutations.begin(), + newArgumentPermutations.end()); + } + + for (auto &&arguments : argumentPermutations) { + std::string baseCaseName = "["; + + for (int filterIndex = 0; filterIndex < activeFilters.size(); ++filterIndex) { + uint8 &variant = arguments[1 + filterIndex]; + baseCaseName += activeFilters[filterIndex]->VariantName(rideType, trackType, variant); + baseCaseName += " "; + + activeFilters[filterIndex]->ApplyTo(rideType, trackType, variant, &mapElement, &surfaceElement, &(gRideList[0]), gRideEntries[0]); + } + + for (int currentRotation = 0; currentRotation < 4; currentRotation++) { gCurrentRotation = currentRotation; for (int direction = 0; direction < 4; direction++) { @@ -162,8 +340,8 @@ static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 t RCT2_GLOBAL(0x009DE56E, sint16) = 64; // y std::string caseName = String::Format( - "[direction:%d trackSequence:%d chainLift:%d inverted:%d]", - direction, trackSequence, chainLift, inverted + "%srotation:%d direction:%d trackSequence:%d]", + baseCaseName.c_str(), currentRotation, direction, trackSequence ); PaintIntercept::ClearCalls(); @@ -212,6 +390,7 @@ static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 t } } } + } return TEST_SUCCESS; } From ba986f14aeb6c1c679e606a7c23e47c6e2c3f520 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 18:04:12 +0200 Subject: [PATCH 26/42] Actually return after failed test --- test/testpaint/TestTrack.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index 7cdad8ed73..b965cf0959 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -244,11 +244,11 @@ uint8 TestTrack::TestPaintTrackElement(uint8 rideType, uint8 trackType) { for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { for (auto &&function : functions) { retVal = function(rideType, trackType, trackSequence, &error); - } - if (retVal != TEST_SUCCESS) { - printf("%s\n", error.c_str()); - return retVal; + if (retVal != TEST_SUCCESS) { + printf("%s\n", error.c_str()); + return retVal; + } } } From 54964857daa439391f3522271669bdc2bdee16aa Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 19:15:57 +0200 Subject: [PATCH 27/42] Indent call test --- test/testpaint/TestTrack.cpp | 106 +++++++++++++++++------------------ 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index b965cf0959..7014c18030 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -96,9 +96,9 @@ public: rct_ride *ride, rct_ride_entry *rideEntry ) { if (variant == 0) { - mapElement->type &= ~0x80; + mapElement->type &= ~TRACK_ELEMENT_FLAG_CHAIN_LIFT; } else { - mapElement->type |= 0x80; + mapElement->type |= TRACK_ELEMENT_FLAG_CHAIN_LIFT; } } }; @@ -333,64 +333,64 @@ static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 t } - for (int currentRotation = 0; currentRotation < 4; currentRotation++) { - gCurrentRotation = currentRotation; - for (int direction = 0; direction < 4; direction++) { - RCT2_GLOBAL(0x009DE56A, sint16) = 64; // x - RCT2_GLOBAL(0x009DE56E, sint16) = 64; // y + for (int currentRotation = 0; currentRotation < 4; currentRotation++) { + gCurrentRotation = currentRotation; + for (int direction = 0; direction < 4; direction++) { + RCT2_GLOBAL(0x009DE56A, sint16) = 64; // x + RCT2_GLOBAL(0x009DE56E, sint16) = 64; // y - std::string caseName = String::Format( - "%srotation:%d direction:%d trackSequence:%d]", - baseCaseName.c_str(), currentRotation, direction, trackSequence - ); - - PaintIntercept::ClearCalls(); - TestPaint::ResetSupportHeights(); - - CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); - - callCount = PaintIntercept::GetCalls(callBuffer); - std::vector oldCalls; - oldCalls.insert(oldCalls.begin(), callBuffer, callBuffer + callCount); - - PaintIntercept::ClearCalls(); - testpaint_clear_ignore(); - TestPaint::ResetSupportHeights(); - - CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); - - if (testpaint_is_ignored(direction, trackSequence)) { - *error += String::Format("[ IGNORED ] %s\n", caseName.c_str()); - continue; - } - - callCount = PaintIntercept::GetCalls(callBuffer); - std::vector newCalls; - newCalls.insert(newCalls.begin(), callBuffer, callBuffer + callCount); - - bool sucess = true; - if (oldCalls.size() != newCalls.size()) { - *error += String::Format( - "Call counts don't match (was %d, expected %d). %s\n", - newCalls.size(), oldCalls.size(), caseName.c_str() + std::string caseName = String::Format( + "%srotation:%d direction:%d trackSequence:%d]", + baseCaseName.c_str(), currentRotation, direction, trackSequence ); - sucess = false; - } else if (!FunctionCall::AssertsEquals(oldCalls, newCalls)) { - *error += String::Format("Calls don't match. %s\n", caseName.c_str()); - sucess = false; - } - if (!sucess) { - *error += " Expected:\n"; - *error += Printer::PrintFunctionCalls(oldCalls, height); - *error += " Actual:\n"; - *error += Printer::PrintFunctionCalls(newCalls, height); + PaintIntercept::ClearCalls(); + TestPaint::ResetSupportHeights(); - return TEST_FAILED; + CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); + + callCount = PaintIntercept::GetCalls(callBuffer); + std::vector oldCalls; + oldCalls.insert(oldCalls.begin(), callBuffer, callBuffer + callCount); + + PaintIntercept::ClearCalls(); + testpaint_clear_ignore(); + TestPaint::ResetSupportHeights(); + + CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); + + if (testpaint_is_ignored(direction, trackSequence)) { + *error += String::Format("[ IGNORED ] %s\n", caseName.c_str()); + continue; + } + + callCount = PaintIntercept::GetCalls(callBuffer); + std::vector newCalls; + newCalls.insert(newCalls.begin(), callBuffer, callBuffer + callCount); + + bool sucess = true; + if (oldCalls.size() != newCalls.size()) { + *error += String::Format( + "Call counts don't match (was %d, expected %d). %s\n", + newCalls.size(), oldCalls.size(), caseName.c_str() + ); + sucess = false; + } else if (!FunctionCall::AssertsEquals(oldCalls, newCalls)) { + *error += String::Format("Calls don't match. %s\n", caseName.c_str()); + sucess = false; + } + + if (!sucess) { + *error += " Expected:\n"; + *error += Printer::PrintFunctionCalls(oldCalls, height); + *error += " Actual:\n"; + *error += Printer::PrintFunctionCalls(newCalls, height); + + return TEST_FAILED; + } } } } - } return TEST_SUCCESS; } From 58e5df75f0b1ff8f74b9013091e07860d7e27d48 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 19:16:53 +0200 Subject: [PATCH 28/42] Fix MSVC --- test/testpaint/TestTrack.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index 7014c18030..cf79e8a7a8 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -302,7 +302,7 @@ static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 t std::vector> argumentPermutations; argumentPermutations.push_back(filler); - for (int filterIndex = 0; filterIndex < activeFilters.size(); ++filterIndex) { + for (size_t filterIndex = 0; filterIndex < activeFilters.size(); ++filterIndex) { ITestTrackFilter *filter = activeFilters[filterIndex]; uint8 variantCount = filter->Variations(rideType, trackType); @@ -324,7 +324,7 @@ static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 t for (auto &&arguments : argumentPermutations) { std::string baseCaseName = "["; - for (int filterIndex = 0; filterIndex < activeFilters.size(); ++filterIndex) { + for (size_t filterIndex = 0; filterIndex < activeFilters.size(); ++filterIndex) { uint8 &variant = arguments[1 + filterIndex]; baseCaseName += activeFilters[filterIndex]->VariantName(rideType, trackType, variant); baseCaseName += " "; From ed9f67cc466dea2ed4204531ac690e3162516a57 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 19:56:26 +0200 Subject: [PATCH 29/42] Fix original call --- test/testpaint/TestTrack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index cf79e8a7a8..1f9e194c17 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -183,7 +183,7 @@ static void CallOriginal( (int) trackDirectionList, direction, height, - (int) &mapElement, + (int) mapElement, rideIndex * sizeof(rct_ride), trackSequence ); From a93e12b5d9beb5e1496e7b049716b807d0c8ddb5 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 20:04:13 +0200 Subject: [PATCH 30/42] Add silent mode --- test/testpaint/main.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/test/testpaint/main.cpp b/test/testpaint/main.cpp index 5be202c211..985e680c31 100644 --- a/test/testpaint/main.cpp +++ b/test/testpaint/main.cpp @@ -394,6 +394,7 @@ int main(int argc, char *argv[]) { std::vector testCases; + bool silent = false; bool generate = false; uint8 specificRideType = 0xFF; for (int i = 0; i < argc; ++i) { @@ -401,6 +402,9 @@ int main(int argc, char *argv[]) { if (strcmp(arg, "--gtest_color=no") == 0) { gTestColor = false; } + else if (strcmp(arg, "--silent") == 0) { + silent = true; + } else if (strcmp(arg, "--ride-type") == 0) { if (i + 1 < argc) { i++; @@ -481,13 +485,18 @@ int main(int argc, char *argv[]) { trackTypeName = TrackNames[trackType]; } - ColouredPrintF(CLIColour::GREEN, "[ RUN ] "); - printf("%s.%s\n", rideTypeName, trackTypeName); + + if (!silent) { + ColouredPrintF(CLIColour::GREEN, "[ RUN ] "); + printf("%s.%s\n", rideTypeName, trackTypeName); + } int retVal = TestTrack::TestPaintTrackElement(tc.rideType, trackType); switch (retVal) { case TEST_SUCCESS: - ColouredPrintF(CLIColour::GREEN, "[ OK ] "); - printf("%s.%s (0 ms)\n", rideTypeName, trackTypeName); + if (!silent) { + ColouredPrintF(CLIColour::GREEN, "[ OK ] "); + printf("%s.%s (0 ms)\n", rideTypeName, trackTypeName); + } successCount++; break; @@ -500,6 +509,10 @@ int main(int argc, char *argv[]) { break; case TEST_FAILED: + if (silent) { + ColouredPrintF(CLIColour::GREEN, "[ RUN ] "); + printf("%s.%s\n", rideTypeName, trackTypeName); + } utf8string testCaseName = new utf8[64]; snprintf(testCaseName, 64, "%s.%s", rideTypeName, trackTypeName); From c150c968bf4c78ddee61032bd3787c7d94f9631d Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 20:04:24 +0200 Subject: [PATCH 31/42] Remove `printf` call --- test/testpaint/Printer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testpaint/Printer.cpp b/test/testpaint/Printer.cpp index 77915fc4b2..03966d128c 100644 --- a/test/testpaint/Printer.cpp +++ b/test/testpaint/Printer.cpp @@ -157,7 +157,7 @@ namespace Printer { s += "\n"; for (int direction = 0; direction < 4; ++direction) { - printf(" + + "); + s += " + + "; } s += "\n"; From a6173425191ce6ad74bcd998fa466c06fce1b1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sat, 15 Oct 2016 23:45:11 +0200 Subject: [PATCH 32/42] Make 32 build also do `testpaint` target --- scripts/linux/build.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/linux/build.sh b/scripts/linux/build.sh index 8b9a629648..72b87202ce 100755 --- a/scripts/linux/build.sh +++ b/scripts/linux/build.sh @@ -69,6 +69,13 @@ pushd build chmod g+s $(pwd) # CMAKE and MAKE opts from environment docker run -v $PARENT:/work/openrct2 -w /work/openrct2/build -i -t openrct2/openrct2:64bit-only bash -c "cmake ../ $OPENRCT2_CMAKE_OPTS && make $OPENRCT_MAKE_OPTS" + elif [[ $TARGET == "linux" ]] + then + cmake $OPENRCT2_CMAKE_OPTS .. + # NOT the same variable as above + # this target also includes building & running of testpaint + make $OPENRCT2_MAKE_OPTS testpaint + ./testpaint else cmake $OPENRCT2_CMAKE_OPTS .. # NOT the same variable as above From 5f422905b6018f54a64b2bb1022b1b12702b9fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sun, 16 Oct 2016 00:04:01 +0200 Subject: [PATCH 33/42] Allow testpaint's tests to pass a build This will not pass a segfault, though. --- scripts/linux/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/linux/build.sh b/scripts/linux/build.sh index 72b87202ce..51a23a9d2f 100755 --- a/scripts/linux/build.sh +++ b/scripts/linux/build.sh @@ -76,6 +76,7 @@ pushd build # this target also includes building & running of testpaint make $OPENRCT2_MAKE_OPTS testpaint ./testpaint + if [[ $? == 1 ]] ; then echo Allowing failed tests to pass ; fi else cmake $OPENRCT2_CMAKE_OPTS .. # NOT the same variable as above From 8eac13b8671685c02150928bb98869838c315bf3 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 21:13:10 +0200 Subject: [PATCH 34/42] Run testpaint slightly more silent on Travis --- scripts/linux/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/linux/build.sh b/scripts/linux/build.sh index 51a23a9d2f..64b778a7c7 100755 --- a/scripts/linux/build.sh +++ b/scripts/linux/build.sh @@ -75,7 +75,7 @@ pushd build # NOT the same variable as above # this target also includes building & running of testpaint make $OPENRCT2_MAKE_OPTS testpaint - ./testpaint + ./testpaint --silent if [[ $? == 1 ]] ; then echo Allowing failed tests to pass ; fi else cmake $OPENRCT2_CMAKE_OPTS .. From d7f27cff72c8dc6c8a330b39d4f5360ad7c624d2 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 21:28:27 +0200 Subject: [PATCH 35/42] Fix GCC --- test/testpaint/PaintIntercept.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/testpaint/PaintIntercept.cpp b/test/testpaint/PaintIntercept.cpp index 92a7b90eae..10d3c03280 100644 --- a/test/testpaint/PaintIntercept.cpp +++ b/test/testpaint/PaintIntercept.cpp @@ -38,6 +38,8 @@ namespace PaintIntercept { static uint32 InterceptPaint8C(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp); static uint32 InterceptPaint9C(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp); static uint32 InterceptPaintFull(uint8 function, uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp); + bool PaintMetalSupports(uint8 function, int supportType, uint8 segment, int special, int height, uint32 imageColourFlags); + bool PaintWoodenSupports(uint8 function, int supportType, int special, int height, uint32 imageColourFlags, bool *underground); static void CheckSegmentSupportHeight(); void InitHooks() { From 871857ee24d882f2727603f07db6989440995637 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 21:30:01 +0200 Subject: [PATCH 36/42] Use debug build for Travis testpaint --- scripts/linux/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/linux/build.sh b/scripts/linux/build.sh index 64b778a7c7..2907f71d5b 100755 --- a/scripts/linux/build.sh +++ b/scripts/linux/build.sh @@ -71,7 +71,7 @@ pushd build docker run -v $PARENT:/work/openrct2 -w /work/openrct2/build -i -t openrct2/openrct2:64bit-only bash -c "cmake ../ $OPENRCT2_CMAKE_OPTS && make $OPENRCT_MAKE_OPTS" elif [[ $TARGET == "linux" ]] then - cmake $OPENRCT2_CMAKE_OPTS .. + cmake $OPENRCT2_CMAKE_OPTS .. -DCMAKE_BUILD_TYPE=debug # NOT the same variable as above # this target also includes building & running of testpaint make $OPENRCT2_MAKE_OPTS testpaint From 262655e2e0ca1b5a7404e6983f2e98b19944badb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sun, 16 Oct 2016 22:22:03 +0200 Subject: [PATCH 37/42] Validate access to functionNames # Conflicts: # test/testpaint/Printer.cpp --- test/testpaint/Printer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/testpaint/Printer.cpp b/test/testpaint/Printer.cpp index 03966d128c..31d5d75e09 100644 --- a/test/testpaint/Printer.cpp +++ b/test/testpaint/Printer.cpp @@ -16,6 +16,7 @@ #include "Printer.hpp" #include "String.hpp" +#include "../../src/core/Util.hpp" namespace Printer { @@ -28,6 +29,7 @@ namespace Printer { "metal_b_supports_paint_setup", "wooden_a_supports_paint_setup", "wooden_b_supports_paint_setup", + "paint_util_set_segment_support_height", }; static std::string GetImageIdString(uint32 imageId); @@ -51,6 +53,7 @@ namespace Printer { std::string PrintFunctionCall(function_call call, uint16 baseHeight) { std::string imageId = GetImageIdString(call.supports.colour_flags); + assert(call.function < Util::CountOf(functionNames)); const char *functionName = functionNames[call.function]; switch (call.function) { From 4f10555002215f621b1ed8a6d02857093ad24d36 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 21:43:31 +0200 Subject: [PATCH 38/42] Move include to extern C --- test/testpaint/SegmentSupportHeightCall.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/testpaint/SegmentSupportHeightCall.hpp b/test/testpaint/SegmentSupportHeightCall.hpp index bc7d159b2c..c095a9d1ba 100644 --- a/test/testpaint/SegmentSupportHeightCall.hpp +++ b/test/testpaint/SegmentSupportHeightCall.hpp @@ -19,7 +19,10 @@ #include #include "../../src/common.h" -#include "../../src/paint/paint.h" + +extern "C" { + #include "../../src/paint/paint.h" +} struct SegmentSupportCall { From a44745e2fae25fa3ec5a2d439016943245bcbf15 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 23:12:54 +0200 Subject: [PATCH 39/42] Fix General/SegmentSupportHeightCalls --- test/testpaint/GeneralSupportHeightCall.cpp | 19 ++++++++------- test/testpaint/GeneralSupportHeightCall.hpp | 2 +- test/testpaint/SegmentSupportHeightCall.cpp | 23 +++++++++--------- test/testpaint/SegmentSupportHeightCall.hpp | 2 +- test/testpaint/TestTrack.cpp | 26 +++++++++------------ test/testpaint/main.cpp | 26 ++++++++++++--------- 6 files changed, 50 insertions(+), 48 deletions(-) diff --git a/test/testpaint/GeneralSupportHeightCall.cpp b/test/testpaint/GeneralSupportHeightCall.cpp index 774414371b..87a75ff973 100644 --- a/test/testpaint/GeneralSupportHeightCall.cpp +++ b/test/testpaint/GeneralSupportHeightCall.cpp @@ -27,7 +27,7 @@ bool GeneralSupportHeightCall::CallsMatch(SupportCall tileSupportCalls[4]) { return true; } -SupportCall *GeneralSupportHeightCall::FindMostCommonSupportCall(SupportCall calls[4]) { +bool GeneralSupportHeightCall::FindMostCommonSupportCall(SupportCall calls[4], SupportCall *out) { std::map map; for (int i = 0; i < 4; ++i) { @@ -39,30 +39,33 @@ SupportCall *GeneralSupportHeightCall::FindMostCommonSupportCall(SupportCall cal } if (map.size() == 1) { - return &calls[0]; + (*out) = calls[0]; + return true; } if (map.size() == 2) { for (auto &&item : map) { if (item.second == 3) { - return (SupportCall *)&item.first; + (*out) = item.first; + return true; } } - return nullptr; + return false; } if (map.size() == 3) { for (auto &&item : map) { - if (item.second == 2) { - return (SupportCall *)&item.first; + if (item.second == 2) { + (*out) = item.first; + return true; } } - return nullptr; + return false; } - return nullptr; + return false; } bool GeneralSupportHeightCall::AssertEquals(const SupportCall *lhs, const SupportCall *rhs) { diff --git a/test/testpaint/GeneralSupportHeightCall.hpp b/test/testpaint/GeneralSupportHeightCall.hpp index 9187ebaa62..919c43529e 100644 --- a/test/testpaint/GeneralSupportHeightCall.hpp +++ b/test/testpaint/GeneralSupportHeightCall.hpp @@ -45,7 +45,7 @@ struct SupportCall { namespace GeneralSupportHeightCall { bool CallsMatch(SupportCall tileSupportCalls[4]); - SupportCall *FindMostCommonSupportCall(SupportCall calls[4]); + bool FindMostCommonSupportCall(SupportCall calls[4], SupportCall *out); bool AssertEquals(const SupportCall *lhs, const SupportCall *rhs); }; diff --git a/test/testpaint/SegmentSupportHeightCall.cpp b/test/testpaint/SegmentSupportHeightCall.cpp index 05f3fbf906..082df5665c 100644 --- a/test/testpaint/SegmentSupportHeightCall.cpp +++ b/test/testpaint/SegmentSupportHeightCall.cpp @@ -114,40 +114,39 @@ bool SegmentSupportHeightCall::CallsEqual(std::vector lhs, s return true; } -std::vector* SegmentSupportHeightCall::FindMostCommonSupportCall(std::vector *calls) { +bool SegmentSupportHeightCall::FindMostCommonSupportCall(std::vector calls[4], std::vector *out) { std::map, int> map; for (int i = 0; i < 4; ++i) { - if (map.count(calls[i]) == 0) { - map[calls[i]] = 1; - } else { - map[calls[i]] += 1; - } + map[calls[i]] += 1; } if (map.size() == 1) { - return &calls[0]; + (*out) = calls[0]; + return true; } if (map.size() == 2) { for (auto &&item : map) { if (item.second == 3) { - return (std::vector *)&item.first; + (*out) = item.first; + return true; } } - return nullptr; + return false; } if (map.size() == 3) { for (auto &&item : map) { if (item.second == 2) { - return (std::vector *)&item.first; + (*out) = item.first; + return true; } } - return nullptr; + return false; } - return nullptr; + return false; } diff --git a/test/testpaint/SegmentSupportHeightCall.hpp b/test/testpaint/SegmentSupportHeightCall.hpp index c095a9d1ba..6b3c9728c2 100644 --- a/test/testpaint/SegmentSupportHeightCall.hpp +++ b/test/testpaint/SegmentSupportHeightCall.hpp @@ -48,5 +48,5 @@ public: static std::vector getSegmentCalls(support_height supports[9], uint8 rotation); static bool CallsMatch(std::vector tileSegmentSupportCalls[4]); static bool CallsEqual(std::vector lhs, std::vector rhs); - static std::vector * FindMostCommonSupportCall(std::vector calls[4]); + static bool FindMostCommonSupportCall(std::vector calls[4], std::vector * out); }; diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index 1f9e194c17..2534c0d79d 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -433,11 +433,8 @@ static uint8 TestTrackElementSegmentSupportHeight(uint8 rideType, uint8 trackTyp std::vector referenceCalls = tileSegmentSupportCalls[0]; if (!SegmentSupportHeightCall::CallsMatch(tileSegmentSupportCalls)) { - std::vector *found = SegmentSupportHeightCall::FindMostCommonSupportCall( - tileSegmentSupportCalls); - if (found != nullptr) { - referenceCalls = *found; - } else { + bool success = SegmentSupportHeightCall::FindMostCommonSupportCall(tileSegmentSupportCalls, &referenceCalls); + if (!success) { *error += String::Format("Original segment calls didn't match. %s\n", state.c_str()); for (int direction = 0; direction < 4; direction++) { *error += String::Format("# %d\n", direction); @@ -516,10 +513,10 @@ static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackTyp } } - SupportCall referenceGeneralSupportCall = tileGeneralSupportCalls[0]; + SupportCall referenceCall = tileGeneralSupportCalls[0]; if (!GeneralSupportHeightCall::CallsMatch(tileGeneralSupportCalls)) { - SupportCall *found = GeneralSupportHeightCall::FindMostCommonSupportCall(tileGeneralSupportCalls); - if (found == nullptr) { + bool success = GeneralSupportHeightCall::FindMostCommonSupportCall(tileGeneralSupportCalls, &referenceCall); + if (!success) { *error += String::Format("Original support calls didn't match. %s\n", state.c_str()); for (int i = 0; i < 4; ++i) { *error += String::Format("[%d, 0x%02X] ", tileGeneralSupportCalls[i].height, tileGeneralSupportCalls[i].slope); @@ -527,7 +524,6 @@ static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackTyp *error += "\n"; return TEST_FAILED; } - referenceGeneralSupportCall = *found; } for (int direction = 0; direction < 4; direction++) { @@ -540,11 +536,11 @@ static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackTyp } - if (referenceGeneralSupportCall.height != -1) { - if (gSupport.height != referenceGeneralSupportCall.height) { + if (referenceCall.height != -1) { + if (gSupport.height != referenceCall.height) { *error += String::Format( "General support heights didn't match. (expected height + %d, actual: height + %d) [direction:%d] %s\n", - referenceGeneralSupportCall.height - height, + referenceCall.height - height, gSupport.height - height, direction, state.c_str() @@ -552,11 +548,11 @@ static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackTyp return TEST_FAILED; } } - if (referenceGeneralSupportCall.slope != -1) { - if (gSupport.slope != referenceGeneralSupportCall.slope) { + if (referenceCall.slope != -1) { + if (gSupport.slope != referenceCall.slope) { *error += String::Format( "General support slopes didn't match. (expected 0x%02X, actual: 0x%02X) [direction:%d] %s\n", - referenceGeneralSupportCall.slope, + referenceCall.slope, gSupport.slope, direction, state.c_str() diff --git a/test/testpaint/main.cpp b/test/testpaint/main.cpp index 985e680c31..ad1363762b 100644 --- a/test/testpaint/main.cpp +++ b/test/testpaint/main.cpp @@ -366,27 +366,31 @@ static void TestGeneralSupportHeightCall() { SupportCall callC = {48, 0x20}; SupportCall callD = {48, 0x1F}; - SupportCall *result; + SupportCall out = {0,0}; + bool success; SupportCall groupA[4] = {callA, callA, callA, callA}; - result = GeneralSupportHeightCall::FindMostCommonSupportCall(groupA); - assert(GeneralSupportHeightCall::AssertEquals(result, &callA)); + success = GeneralSupportHeightCall::FindMostCommonSupportCall(groupA, &out); + assert(success); + assert(out == callA); SupportCall groupB[4] = {callB, callA, callA, callA}; - result = GeneralSupportHeightCall::FindMostCommonSupportCall(groupB); - assert(GeneralSupportHeightCall::AssertEquals(result, &callA)); + success = GeneralSupportHeightCall::FindMostCommonSupportCall(groupB, &out); + assert(success); + assert(out == callA); SupportCall groupC[4] = {callB, callA, callB, callA}; - result = GeneralSupportHeightCall::FindMostCommonSupportCall(groupC); - assert(GeneralSupportHeightCall::AssertEquals(result, nullptr)); + success = GeneralSupportHeightCall::FindMostCommonSupportCall(groupC, &out); + assert(!success); SupportCall groupD[4] = {callB, callC, callB, callA}; - result = GeneralSupportHeightCall::FindMostCommonSupportCall(groupD); - assert(GeneralSupportHeightCall::AssertEquals(result, &callB)); + success = GeneralSupportHeightCall::FindMostCommonSupportCall(groupD, &out); + assert(success); + assert(out == callB); SupportCall groupE[4] = {callD, callC, callB, callA}; - result = GeneralSupportHeightCall::FindMostCommonSupportCall(groupE); - assert(GeneralSupportHeightCall::AssertEquals(result, nullptr)); + success = GeneralSupportHeightCall::FindMostCommonSupportCall(groupE, &out); + assert(!success); } int main(int argc, char *argv[]) { From 3dcebfc97f2dc5d78c286ec9830ff8faf3e36267 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Tue, 18 Oct 2016 19:35:22 +0200 Subject: [PATCH 40/42] Update TODOs --- test/testpaint/TestTrack.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index 2534c0d79d..cec12af3c7 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -277,10 +277,11 @@ static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 t function_call callBuffer[256] = {0}; int callCount = 0; - // TODO: test chainlift - // TODO: test inverted // TODO: test supports - // TODO: test entrance styles + // TODO: test flat rides + // TODO: test mazes + // TODO: test underground (Wooden RC) + // TODO: test station fences std::vector filters; filters.push_back(new CableLiftFilter()); From cdffaa071229272f3ce5ee5965a796fb01dceeb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Tue, 18 Oct 2016 22:14:44 +0200 Subject: [PATCH 41/42] Fix travis runs of testpaint `build.sh` script has `set -e` in the invocation, it fails the script before we have a chance to inspect exit code of `testpaint`. This melds checking of exit status into one command, so bash won't fail it early. --- scripts/linux/build.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/linux/build.sh b/scripts/linux/build.sh index 2907f71d5b..019366c749 100755 --- a/scripts/linux/build.sh +++ b/scripts/linux/build.sh @@ -75,8 +75,7 @@ pushd build # NOT the same variable as above # this target also includes building & running of testpaint make $OPENRCT2_MAKE_OPTS testpaint - ./testpaint --silent - if [[ $? == 1 ]] ; then echo Allowing failed tests to pass ; fi + ./testpaint --silent || if [[ $? -eq 1 ]] ; then echo Allowing failed tests to pass ; else false; fi else cmake $OPENRCT2_CMAKE_OPTS .. # NOT the same variable as above From 1be2dd996c04f59e8a8d5a3d80e0d016e7e6e2a6 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Wed, 19 Oct 2016 01:55:18 +0200 Subject: [PATCH 42/42] Make testpaint a lot more quiet --- scripts/linux/build.sh | 2 +- test/testpaint/TestPaint.hpp | 5 ++ test/testpaint/TestTrack.cpp | 4 +- test/testpaint/TestTrack.hpp | 2 +- test/testpaint/main.cpp | 116 +++++++++++++++++++++-------------- 5 files changed, 79 insertions(+), 50 deletions(-) diff --git a/scripts/linux/build.sh b/scripts/linux/build.sh index 019366c749..c07b28687e 100755 --- a/scripts/linux/build.sh +++ b/scripts/linux/build.sh @@ -75,7 +75,7 @@ pushd build # NOT the same variable as above # this target also includes building & running of testpaint make $OPENRCT2_MAKE_OPTS testpaint - ./testpaint --silent || if [[ $? -eq 1 ]] ; then echo Allowing failed tests to pass ; else false; fi + ./testpaint --quiet || if [[ $? -eq 1 ]] ; then echo Allowing failed tests to pass ; else false; fi else cmake $OPENRCT2_CMAKE_OPTS .. # NOT the same variable as above diff --git a/test/testpaint/TestPaint.hpp b/test/testpaint/TestPaint.hpp index b0ff7d78de..f5e4f3de89 100644 --- a/test/testpaint/TestPaint.hpp +++ b/test/testpaint/TestPaint.hpp @@ -48,6 +48,11 @@ namespace TestPaint void ResetSupportHeights(); } +enum Verbosity { + QUIET, + NORMAL, +}; + extern "C" { int generatePaintCode(uint8 rideType); diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index cec12af3c7..c067779e43 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -215,7 +215,7 @@ static uint8 TestTrackElementSideTunnels(uint8 rideType, uint8 trackType, uint8 static uint8 TestTrackElementVerticalTunnels(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error); -uint8 TestTrack::TestPaintTrackElement(uint8 rideType, uint8 trackType) { +uint8 TestTrack::TestPaintTrackElement(uint8 rideType, uint8 trackType, std::string *out) { if (!Utils::rideSupportsTrackType(rideType, trackType)) { return TEST_FAILED; } @@ -246,7 +246,7 @@ uint8 TestTrack::TestPaintTrackElement(uint8 rideType, uint8 trackType) { retVal = function(rideType, trackType, trackSequence, &error); if (retVal != TEST_SUCCESS) { - printf("%s\n", error.c_str()); + *out += error + "\n"; return retVal; } } diff --git a/test/testpaint/TestTrack.hpp b/test/testpaint/TestTrack.hpp index 7eb3ff1d07..811cb2cfe3 100644 --- a/test/testpaint/TestTrack.hpp +++ b/test/testpaint/TestTrack.hpp @@ -22,5 +22,5 @@ class TestTrack { public: - static uint8 TestPaintTrackElement(uint8 rideType, uint8 trackType); + static uint8 TestPaintTrackElement(uint8 rideType, uint8 trackType, std::string *out); }; diff --git a/test/testpaint/main.cpp b/test/testpaint/main.cpp index ad1363762b..d99a3e73bd 100644 --- a/test/testpaint/main.cpp +++ b/test/testpaint/main.cpp @@ -49,6 +49,7 @@ enum CLIColour { }; bool gTestColor = true; +Verbosity _verbosity = NORMAL; static bool CStringEquals(const char *lhs, const char *rhs) { if (lhs == NULL) return rhs == NULL; @@ -126,10 +127,9 @@ static WORD GetWindowsConsoleAttribute(CLIColour color, WORD defaultAttr) #endif -static void ColouredPrintF(CLIColour colour, const char* fmt, ...) +static void Write_VA(Verbosity verbosity, CLIColour colour, const char *fmt, va_list args) { - va_list args; - va_start(args, fmt); + if (_verbosity < verbosity) return; COLOUR_METHOD colourMethod = GetColourMethod(); @@ -148,6 +148,37 @@ static void ColouredPrintF(CLIColour colour, const char* fmt, ...) SetConsoleTextAttribute(hStdOut, defaultAttr); #endif } +} + +static void Write(Verbosity verbosity, CLIColour colour, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Write_VA(verbosity, colour, fmt, args); + va_end(args); +} + +static void Write(Verbosity verbosity, const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + Write_VA(verbosity, DEFAULT, fmt, args); + va_end(args); +} + +static void Write(CLIColour colour, const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + Write_VA(NORMAL, colour, fmt, args); + va_end(args); +} + +static void Write(const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + Write_VA(NORMAL, DEFAULT, fmt, args); va_end(args); } @@ -354,7 +385,7 @@ static void PrintRideTypes() colour = CLIColour::GREEN; } - ColouredPrintF(colour, "%2d: %-30s%s\n", rideType, rideName, status); + Write(colour, "%2d: %-30s%s\n", rideType, rideName, status); } } @@ -398,7 +429,6 @@ int main(int argc, char *argv[]) { std::vector testCases; - bool silent = false; bool generate = false; uint8 specificRideType = 0xFF; for (int i = 0; i < argc; ++i) { @@ -406,8 +436,8 @@ int main(int argc, char *argv[]) { if (strcmp(arg, "--gtest_color=no") == 0) { gTestColor = false; } - else if (strcmp(arg, "--silent") == 0) { - silent = true; + else if (strcmp(arg, "--quiet") == 0) { + _verbosity = Verbosity::QUIET; } else if (strcmp(arg, "--ride-type") == 0) { if (i + 1 < argc) { @@ -466,11 +496,11 @@ int main(int argc, char *argv[]) { testCount += tc.trackTypes.size(); } - ColouredPrintF(CLIColour::GREEN, "[==========] "); - printf("Running %d tests from %d test cases.\n", testCount, testCaseCount); + Write(CLIColour::GREEN, "[==========] "); + Write("Running %d tests from %d test cases.\n", testCount, testCaseCount); - ColouredPrintF(CLIColour::GREEN, "[----------] "); - printf("Global test environment set-up.\n"); + Write(CLIColour::GREEN, "[----------] "); + Write("Global test environment set-up.\n"); openrct2_setup_rct2_segment(); PaintIntercept::InitHooks(); @@ -478,8 +508,8 @@ int main(int argc, char *argv[]) { std::vector failures; for (auto &&tc : testCases) { const utf8string rideTypeName = RideNames[tc.rideType]; - ColouredPrintF(CLIColour::GREEN, "[----------] "); - printf("%d tests from %s\n", (int)tc.trackTypes.size(), rideTypeName); + Write(CLIColour::GREEN, "[----------] "); + Write("%d tests from %s\n", (int)tc.trackTypes.size(), rideTypeName); for (auto &&trackType : tc.trackTypes) { utf8string trackTypeName; @@ -489,71 +519,65 @@ int main(int argc, char *argv[]) { trackTypeName = TrackNames[trackType]; } + Write(CLIColour::GREEN, "[ RUN ] "); + Write("%s.%s\n", rideTypeName, trackTypeName); - if (!silent) { - ColouredPrintF(CLIColour::GREEN, "[ RUN ] "); - printf("%s.%s\n", rideTypeName, trackTypeName); - } - int retVal = TestTrack::TestPaintTrackElement(tc.rideType, trackType); + std::string out; + int retVal = TestTrack::TestPaintTrackElement(tc.rideType, trackType, &out); + Write("%s", out.c_str()); switch (retVal) { case TEST_SUCCESS: - if (!silent) { - ColouredPrintF(CLIColour::GREEN, "[ OK ] "); - printf("%s.%s (0 ms)\n", rideTypeName, trackTypeName); - } + Write(CLIColour::GREEN, "[ OK ] "); + Write("%s.%s (0 ms)\n", rideTypeName, trackTypeName); successCount++; break; case TEST_SKIPPED: - printf("Skipped\n"); + Write("Skipped\n"); // Outputting this as OK because CLion only allows FAILED or OK - ColouredPrintF(CLIColour::YELLOW, "[ OK ] "); - printf("%s.%s (0 ms)\n", rideTypeName, trackTypeName); + Write(CLIColour::YELLOW, "[ OK ] "); + Write("%s.%s (0 ms)\n", rideTypeName, trackTypeName); successCount++; break; case TEST_FAILED: - if (silent) { - ColouredPrintF(CLIColour::GREEN, "[ RUN ] "); - printf("%s.%s\n", rideTypeName, trackTypeName); - } utf8string testCaseName = new utf8[64]; snprintf(testCaseName, 64, "%s.%s", rideTypeName, trackTypeName); - ColouredPrintF(CLIColour::RED, "[ FAILED ] "); - printf("%s (0 ms)\n", testCaseName); + Write(CLIColour::RED, "[ FAILED ] "); + Write("%s (0 ms)\n", testCaseName); failures.push_back(testCaseName); break; } } - ColouredPrintF(CLIColour::GREEN, "[----------] "); - printf("%d tests from %s (0 ms total)\n", (int)tc.trackTypes.size(), rideTypeName); + Write(CLIColour::GREEN, "[----------] "); + Write("%d tests from %s (0 ms total)\n", (int)tc.trackTypes.size(), rideTypeName); } - printf("\n"); + Write("\n"); - ColouredPrintF(CLIColour::GREEN, "[----------] "); - printf("Global test environment tear-down\n"); + Write(CLIColour::GREEN, "[----------] "); + Write("Global test environment tear-down\n"); - ColouredPrintF(CLIColour::GREEN, "[==========] "); - printf("%d tests from %d test cases ran. (0 ms total).\n", testCount, testCaseCount); + Write(CLIColour::GREEN, "[==========] "); + Write("%d tests from %d test cases ran. (0 ms total).\n", testCount, testCaseCount); - ColouredPrintF(CLIColour::GREEN, "[ PASSED ] "); - printf("%d tests.\n", successCount); + Write(Verbosity::QUIET, CLIColour::GREEN, "[ PASSED ] "); + Write(Verbosity::QUIET, "%d tests.\n", successCount); if (failures.size() > 0) { - ColouredPrintF(CLIColour::RED, "[ FAILED ] "); - printf("%d tests, listed below:\n", (int)failures.size()); + Write(Verbosity::QUIET, CLIColour::RED, "[ FAILED ] "); + Write(Verbosity::QUIET, "%d tests, listed below:\n", (int)failures.size()); for (auto &&failure : failures) { - ColouredPrintF(CLIColour::RED, "[ FAILED ] "); - printf("%s\n", failure); + Write(Verbosity::QUIET, CLIColour::RED, "[ FAILED ] "); + Write(Verbosity::QUIET, "%s\n", failure); delete [] failure; } - printf("\n"); + Write(Verbosity::QUIET, "\n"); - printf("%d FAILED TESTS\n", (int)failures.size()); + Write(Verbosity::QUIET, "%d FAILED TESTS\n", (int)failures.size()); return 1; }