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] 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 @@ +