mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-06 06:32:56 +01:00
Add rough version of support segment checking
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
791166FB1D7486EF005912EA /* NetworkServerAdvertiser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 791166F91D7486EF005912EA /* NetworkServerAdvertiser.cpp */; };
|
||||
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 */; };
|
||||
85B5C0B01D81D912001B99A8 /* intercept_2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 85B5C0AF1D81D912001B99A8 /* intercept_2.cpp */; };
|
||||
C612A8991D64825300B634CA /* vehicle_data.c in Sources */ = {isa = PBXBuildFile; fileRef = C612A8971D64825300B634CA /* vehicle_data.c */; };
|
||||
C61FB7201CF6180C004CE991 /* libssl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38BA1CF3006400659A24 /* libssl.dylib */; };
|
||||
C61FB7211CF618BA004CE991 /* libssl.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38BA1CF3006400659A24 /* libssl.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
@@ -495,6 +496,7 @@
|
||||
85AFA20F1D7DB83E00221B42 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
|
||||
85AFA2101D7DB83E00221B42 /* intercept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intercept.h; sourceTree = "<group>"; };
|
||||
85AFA2141D7DDFA100221B42 /* data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = data.h; sourceTree = "<group>"; };
|
||||
85B5C0AF1D81D912001B99A8 /* intercept_2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = intercept_2.cpp; sourceTree = "<group>"; };
|
||||
C612A8971D64825300B634CA /* vehicle_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vehicle_data.c; sourceTree = "<group>"; };
|
||||
C612A8981D64825300B634CA /* vehicle_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vehicle_data.h; sourceTree = "<group>"; };
|
||||
C61FB7221CF86356004CE991 /* NetworkUser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkUser.cpp; sourceTree = "<group>"; usesTabs = 0; };
|
||||
@@ -1165,6 +1167,7 @@
|
||||
C64FDAC41D6DA55E00F259B9 /* compat.c */,
|
||||
C64FDAC91D6DA92D00F259B9 /* data.c */,
|
||||
85AFA2141D7DDFA100221B42 /* data.h */,
|
||||
85B5C0AF1D81D912001B99A8 /* intercept_2.cpp */,
|
||||
C64FDAC71D6DA72400F259B9 /* intercept.c */,
|
||||
85AFA2101D7DB83E00221B42 /* intercept.h */,
|
||||
85AFA20F1D7DB83E00221B42 /* main.cpp */,
|
||||
@@ -2417,6 +2420,7 @@
|
||||
C64FDA8E1D6D9A2100F259B9 /* mini_golf.c in Sources */,
|
||||
C64FDA8F1D6D9A2100F259B9 /* mini_helicopters.c 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 */,
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#include "../../src/interface/viewport.h"
|
||||
#include "../../src/hook.h"
|
||||
|
||||
#define gRideEntries RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, rct_ride_entry*)
|
||||
#define gCurrentRotation RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)
|
||||
|
||||
static const uint32 PALETTE_98 = COLOUR_GREY << 19 | COLOUR_WHITE << 24 | 0xA0000000;
|
||||
static const uint32 PALETTE_9C = COLOUR_LIGHT_BLUE << 19 | COLOUR_ICY_BLUE << 24 | 0xA0000000;
|
||||
@@ -446,7 +444,7 @@ static void printFunctionCallArray(utf8string *out, function_call calls[], uint8
|
||||
}
|
||||
}
|
||||
|
||||
static int getTrackSequenceCount(uint8 rideType, uint8 trackType) {
|
||||
int getTrackSequenceCount(uint8 rideType, uint8 trackType) {
|
||||
int sequenceCount = 0;
|
||||
const rct_preview_track **trackBlocks;
|
||||
|
||||
@@ -479,6 +477,9 @@ bool rideSupportsTrackType(int rideType, int trackType) {
|
||||
return supportsTrackType;
|
||||
}
|
||||
|
||||
|
||||
extern bool testSupportSegments(uint8 rideType, uint8 trackType);
|
||||
|
||||
static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string *error) {
|
||||
if (rideType == RIDE_TYPE_CHAIRLIFT) {
|
||||
if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION || trackType == TRACK_ELEM_END_STATION) {
|
||||
@@ -590,6 +591,11 @@ static bool testTrackElement(uint8 rideType, uint8 trackType, utf8string *error)
|
||||
}
|
||||
}
|
||||
|
||||
bool segmentSuccess = testSupportSegments(rideType, trackType);
|
||||
if (!segmentSuccess) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,12 @@
|
||||
|
||||
#include "../../src/common.h"
|
||||
|
||||
#define gRideEntries RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, rct_ride_entry*)
|
||||
#define gCurrentRotation RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)
|
||||
|
||||
bool testRide(int rideType);
|
||||
void initHooks();
|
||||
int getTrackSequenceCount(uint8 rideType, uint8 trackType);
|
||||
bool rideIsImplemented(int rideType);
|
||||
bool rideSupportsTrackType(int rideType, int trackType);
|
||||
bool testTrackPainting(int rideType, int trackType);
|
||||
|
||||
271
test/testpaint/intercept_2.cpp
Normal file
271
test/testpaint/intercept_2.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
#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 <vector>
|
||||
|
||||
extern "C" {
|
||||
#include "intercept.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"
|
||||
}
|
||||
|
||||
namespace Intercept2
|
||||
{
|
||||
|
||||
static const uint32 PALETTE_98 = COLOUR_GREY << 19 | COLOUR_WHITE << 24 | 0xA0000000;
|
||||
static const uint32 PALETTE_9C = COLOUR_LIGHT_BLUE << 19 | COLOUR_ICY_BLUE << 24 | 0xA0000000;
|
||||
static const uint32 PALETTE_A0 = COLOUR_DARK_PURPLE << 19 | COLOUR_LIGHT_PURPLE << 24 | 0xA0000000;
|
||||
static const uint32 PALETTE_A4 = COLOUR_BRIGHT_PURPLE << 19 | COLOUR_DARK_BLUE << 24 | 0xA0000000;
|
||||
|
||||
struct SegmentSupportCall
|
||||
{
|
||||
uint16 segments;
|
||||
sint32 height;
|
||||
sint16 slope;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static std::vector<SegmentSupportCall> 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<SegmentSupportCall> calls;
|
||||
|
||||
while (positionsRemaining != 0) {
|
||||
SegmentSupportCall call = {0};
|
||||
call.height = -1;
|
||||
call.slope = -1;
|
||||
|
||||
support_height referenceSupport;
|
||||
|
||||
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<SegmentSupportCall> lhs, std::vector<SegmentSupportCall> rhs)
|
||||
{
|
||||
if (lhs.size() != rhs.size()) return false;
|
||||
for (int 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<SegmentSupportCall> tileSegmentSupportCalls[4])
|
||||
{
|
||||
std::vector<SegmentSupportCall> baseCallList = tileSegmentSupportCalls[0];
|
||||
for (int i = 1; i < 4; i++) {
|
||||
if (!SegmentCallEquals(baseCallList, tileSegmentSupportCalls[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void printSegmentSupports(utf8string * out, std::vector<SegmentSupportCall> segmentCalls)
|
||||
{
|
||||
for (auto &&call : segmentCalls) {
|
||||
int segmentsPrinted = 0;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
if (call.segments & segment_offsets[i]) {
|
||||
if (segmentsPrinted > 0) {
|
||||
sprintf(*out + strlen(*out), " | ");
|
||||
}
|
||||
sprintf(*out + strlen(*out), "SEGMENT_%02X", 0xB4 + 4 * i);
|
||||
segmentsPrinted++;
|
||||
}
|
||||
}
|
||||
|
||||
if (call.height == 0xFFFF) {
|
||||
sprintf(*out + strlen(*out), ", 0xFFFF");
|
||||
} else {
|
||||
sprintf(*out + strlen(*out), ", %d", call.height);
|
||||
}
|
||||
|
||||
sprintf(*out + strlen(*out), ", 0x%02X\n", call.slope);
|
||||
}
|
||||
}
|
||||
|
||||
static bool testSupportSegments(uint8 rideType, uint8 trackType)
|
||||
{
|
||||
uint8 rideIndex = 0;
|
||||
rct_map_element mapElement = {0};
|
||||
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;
|
||||
|
||||
gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE;
|
||||
RCT2_GLOBAL(0x00F44198, uint32) = PALETTE_98;
|
||||
RCT2_GLOBAL(0x00F441A0, uint32) = PALETTE_A0;
|
||||
RCT2_GLOBAL(0x00F441A4, uint32) = PALETTE_A4;
|
||||
RCT2_GLOBAL(0x00F4419C, uint32) = PALETTE_9C;
|
||||
|
||||
rct_drawpixelinfo dpi = {.zoom_level = 1};
|
||||
unk_140E9A8 = &dpi;
|
||||
|
||||
rct_vehicle vehicle = {0};
|
||||
rct_ride ride = {0};
|
||||
|
||||
rct_ride_entry rideEntry = {0};
|
||||
rct_ride_entry_vehicle vehicleEntry = {.base_image_id = 0x70000};
|
||||
rideEntry.vehicles[0] = vehicleEntry;
|
||||
|
||||
|
||||
gRideList[0] = ride;
|
||||
gRideEntries[0] = &rideEntry;
|
||||
|
||||
int height = 48;
|
||||
|
||||
TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType];
|
||||
int sequenceCount = getTrackSequenceCount(rideType, trackType);
|
||||
|
||||
|
||||
for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) {
|
||||
std::vector<SegmentSupportCall> tileSegmentSupportCalls[4];
|
||||
|
||||
for (int direction = 0; direction < 4; direction++) {
|
||||
for (int s = 0; s < 9; ++s) {
|
||||
gSupportSegments[s].height = 0;
|
||||
gSupportSegments[s].slope = 0xFF;
|
||||
}
|
||||
|
||||
TRACK_PAINT_FUNCTION ** trackTypeList = (TRACK_PAINT_FUNCTION **) RideTypeTrackPaintFunctionsOld[rideType];
|
||||
uint32 * trackDirectionList = (uint32 *) trackTypeList[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] = getSegmentCalls(gSupportSegments, direction);
|
||||
}
|
||||
|
||||
if (!segmentCallsMatch(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]\n", trackSequence);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int direction = 0; direction < 4; direction++) {
|
||||
for (int s = 0; s < 9; ++s) {
|
||||
gSupportSegments[s].height = 0;
|
||||
gSupportSegments[s].slope = 0xFF;
|
||||
}
|
||||
|
||||
TRACK_PAINT_FUNCTION newPaintFunction = newPaintGetter(trackType, direction);
|
||||
newPaintFunction(rideIndex, trackSequence, direction, height, &mapElement);
|
||||
|
||||
std::vector<SegmentSupportCall> newCalls = getSegmentCalls(gSupportSegments, direction);
|
||||
|
||||
if (!SegmentCallEquals(tileSegmentSupportCalls[0], newCalls)) {
|
||||
// TODO put this into *error
|
||||
utf8string diff = new utf8[2048];
|
||||
sprintf(diff, "<<< EXPECTED\n");
|
||||
printSegmentSupports(&diff, tileSegmentSupportCalls[0]);
|
||||
sprintf(diff + strlen(diff), "====\n");
|
||||
printSegmentSupports(&diff, newCalls);
|
||||
sprintf(diff + strlen(diff), ">>> ACTUAL\n");
|
||||
|
||||
printf("Segment support heights didn't match. [direction:%d trackSequence:%d]\n", direction,
|
||||
trackSequence);
|
||||
printf("%s", diff);
|
||||
delete[] diff;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
bool testSupportSegments(uint8 rideType, uint8 trackType)
|
||||
{
|
||||
return Intercept2::testSupportSegments(rideType, trackType);
|
||||
}
|
||||
}
|
||||
@@ -84,6 +84,7 @@
|
||||
<ClCompile Include="compat.c" />
|
||||
<ClCompile Include="data.c" />
|
||||
<ClCompile Include="intercept.c" />
|
||||
<ClCompile Include="intercept_2.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="..\..\src\addresses.c" />
|
||||
<ClCompile Include="..\..\src\diagnostic.c" />
|
||||
|
||||
Reference in New Issue
Block a user