From de12a8dda1204e0dc110ab3e769b83eab80e29cb Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Tue, 13 Nov 2018 21:48:20 +0100 Subject: [PATCH] Import S4 elements property-by-property --- src/openrct2/rct1/RCT1.h | 2 +- src/openrct2/rct1/S4Importer.cpp | 407 ++++++++++++++++--------------- src/openrct2/rct12/RCT12.cpp | 5 + src/openrct2/rct12/RCT12.h | 1 + src/openrct2/world/TileElement.h | 1 + src/openrct2/world/Wall.cpp | 7 + 6 files changed, 229 insertions(+), 194 deletions(-) diff --git a/src/openrct2/rct1/RCT1.h b/src/openrct2/rct1/RCT1.h index 70ad36076e..f941c3a513 100644 --- a/src/openrct2/rct1/RCT1.h +++ b/src/openrct2/rct1/RCT1.h @@ -610,7 +610,7 @@ struct rct1_s4 uint32_t ticks; uint32_t random_a; uint32_t random_b; - TileElement tile_elements[RCT1_MAX_TILE_ELEMENTS]; + RCT12TileElement tile_elements[RCT1_MAX_TILE_ELEMENTS]; uint32_t unk_counter; rct1_sprite sprites[RCT1_MAX_SPRITES]; uint16_t next_sprite_index; diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 79ff894c23..166b971f35 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -470,7 +470,7 @@ private: { size_t maxTiles = 128 * 128; size_t tileIndex = 0; - TileElement* tileElement = _s4.tile_elements; + RCT12TileElement* tileElement = _s4.tile_elements; while (tileIndex < maxTiles) { @@ -1955,16 +1955,222 @@ private: void ImportTileElements() { - std::copy(std::begin(_s4.tile_elements), std::end(_s4.tile_elements), gTileElements); + gMapBaseZ = 7; + + for (uint32_t index = 0, dstOffset = 0; index < RCT1_MAX_TILE_ELEMENTS; index++) + { + auto src = &_s4.tile_elements[index]; + auto dst = &gTileElements[index + dstOffset]; + if (src->base_height == 0xFF) + { + memcpy(dst, src, sizeof(*src)); + } + else + { + ImportTileElement(dst, src); + } + } + ClearExtraTileEntries(); - FixSceneryColours(); - FixTileElementZ(); - FixPaths(); FixWalls(); - FixBanners(); - FixTerrain(); FixEntrancePositions(); - FixTileElementEntryTypes(); + } + + void ImportTileElement(TileElement* dst, const RCT12TileElement* src) + { + // Todo: allow for changing defition of OpenRCT2 tile element types - replace with a map + uint8_t tileElementType = src->GetType(); + dst->ClearAs(tileElementType); + dst->SetDirection(src->GetDirection()); + dst->flags = src->flags; + dst->base_height = src->base_height / 2; + dst->clearance_height = src->clearance_height / 2; + + switch (tileElementType) + { + case TILE_ELEMENT_TYPE_SURFACE: + { + auto dst2 = dst->AsSurface(); + auto src2 = src->AsSurface(); + + dst2->SetSlope(src2->GetSlope()); + dst2->SetSurfaceStyle(RCT1::GetTerrain(src2->GetSurfaceStyle())); + dst2->SetEdgeStyle(RCT1::GetTerrainEdge(src2->GetEdgeStyle())); + dst2->SetGrassLength(src2->GetGrassLength()); + dst2->SetOwnership(src2->GetOwnership()); + dst2->SetParkFences(src2->GetParkFences()); + dst2->SetWaterHeight(src2->GetWaterHeight()); + dst2->SetHasTrackThatNeedsWater(src2->HasTrackThatNeedsWater()); + + break; + } + case TILE_ELEMENT_TYPE_PATH: + { + auto dst2 = dst->AsPath(); + auto src2 = src->AsPath(); + + dst2->SetQueueBannerDirection(src2->GetQueueBannerDirection()); + dst2->SetSloped(src2->IsSloped()); + dst2->SetSlopeDirection(src2->GetSlopeDirection()); + dst2->SetRideIndex(src2->GetRideIndex()); + dst2->SetStationIndex(src2->GetStationIndex()); + dst2->SetWide(src2->IsWide()); + dst2->SetHasQueueBanner(src2->HasQueueBanner()); + dst2->SetEdges(src2->GetEdges()); + dst2->SetCorners(src2->GetCorners()); + dst2->SetAddition(src2->GetAddition()); + dst2->SetAdditionIsGhost(false); + dst2->SetAdditionStatus(src2->GetAdditionStatus()); + + // Type + uint8_t pathType = src2->GetRCT1PathType(); + uint8_t entryIndex = _pathTypeToEntryMap[pathType]; + + dst2->SetDirection(0); + dst2->flags &= ~(TILE_ELEMENT_FLAG_BROKEN | TILE_ELEMENT_FLAG_INDESTRUCTIBLE_TRACK_PIECE); + + dst2->SetEntryIndex(entryIndex); + if (RCT1::PathIsQueue(pathType)) + { + dst2->SetIsQueue(true); + } + + // Additions + uint8_t additionType = dst2->GetAddition(); + if (additionType != RCT1_PATH_ADDITION_NONE) + { + uint8_t normalisedType = RCT1::NormalisePathAddition(additionType); + entryIndex = _pathAdditionTypeToEntryMap[normalisedType]; + if (additionType != normalisedType) + { + dst2->flags |= TILE_ELEMENT_FLAG_BROKEN; + } + dst2->SetAddition(entryIndex + 1); + } + break; + } + case TILE_ELEMENT_TYPE_TRACK: + { + auto dst2 = dst->AsTrack(); + auto src2 = src->AsTrack(); + + dst2->SetTrackType(src2->GetTrackType()); + dst2->SetSequenceIndex(src2->GetSequenceIndex()); + dst2->SetRideIndex(src2->GetRideIndex()); + dst2->SetColourScheme(src2->GetColourScheme()); + dst2->SetStationIndex(src2->GetStationIndex()); + dst2->SetHasChain(src2->HasChain()); + dst2->SetHasCableLift(false); + dst2->SetInverted(src2->IsInverted()); + dst2->SetBrakeBoosterSpeed(src2->GetBrakeBoosterSpeed()); + dst2->SetHasGreenLight(src2->HasGreenLight()); + dst2->SetSeatRotation(4); + dst2->SetMazeEntry(src2->GetMazeEntry()); + dst2->SetPhotoTimeout(src2->GetPhotoTimeout()); + // Skipping IsHighlighted() + + // TODO: Import Door A and Door B states. + + break; + } + case TILE_ELEMENT_TYPE_SMALL_SCENERY: + { + auto dst2 = dst->AsSmallScenery(); + auto src2 = src->AsSmallScenery(); + + uint8_t entryIndex = _smallSceneryTypeToEntryMap[src2->GetEntryIndex()]; + dst2->SetEntryIndex(entryIndex); + dst2->SetAge(src2->GetAge()); + dst2->SetSceneryQuadrant(src2->GetSceneryQuadrant()); + dst2->SetPrimaryColour(RCT1::GetColour(src2->GetPrimaryColour())); + if (src2->NeedsSupports()) + dst2->SetNeedsSupports(); + + // Copied from [rct2: 0x006A2956] + switch (src2->GetEntryIndex()) + { + case RCT1_SCENERY_GEOMETRIC_SCULPTURE_1: + case RCT1_SCENERY_GEOMETRIC_SCULPTURE_2: + case RCT1_SCENERY_GEOMETRIC_SCULPTURE_3: + case RCT1_SCENERY_GEOMETRIC_SCULPTURE_4: + case RCT1_SCENERY_GEOMETRIC_SCULPTURE_5: + dst2->SetSecondaryColour(COLOUR_WHITE); + break; + case RCT1_SCENERY_TULIPS_1: + case RCT1_SCENERY_TULIPS_2: + dst2->SetPrimaryColour(COLOUR_BRIGHT_RED); + dst2->SetSecondaryColour(COLOUR_YELLOW); + } + + break; + } + case TILE_ELEMENT_TYPE_ENTRANCE: + { + auto dst2 = dst->AsEntrance(); + auto src2 = src->AsEntrance(); + + dst2->SetEntranceType(src2->GetEntranceType()); + dst2->SetRideIndex(src2->GetRideIndex()); + dst2->SetStationIndex(src2->GetStationIndex()); + dst2->SetSequenceIndex(src2->GetSequenceIndex()); + + if (src2->GetEntranceType() == ENTRANCE_TYPE_PARK_ENTRANCE) + { + uint8_t pathType = src2->GetPathType(); + if (pathType == 0) + { + pathType = RCT1_FOOTPATH_TYPE_TARMAC_GRAY; + } + uint8_t entryIndex = _pathTypeToEntryMap[pathType]; + dst2->SetPathType(entryIndex & 0x7F); + } + + break; + } + case TILE_ELEMENT_TYPE_WALL: + { + auto dst2 = dst->AsWall(); + auto src2 = src->AsWall(); + + dst2->SetEntryIndex(src2->GetEntryIndex()); + dst2->SetSlope(src2->GetSlope()); + dst2->SetPrimaryColour(RCT1::GetColour(src2->GetRCT1WallColour())); + dst2->SetRawRCT1Data(src2->GetRawRCT1WallTypeData()); + + break; + } + case TILE_ELEMENT_TYPE_LARGE_SCENERY: + { + auto dst2 = dst->AsLargeScenery(); + auto src2 = src->AsLargeScenery(); + + uint8_t type = src2->GetEntryIndex(); + dst2->SetEntryIndex(_largeSceneryTypeToEntryMap[type]); + dst2->SetSequenceIndex(src2->GetSequenceIndex()); + dst2->SetPrimaryColour(RCT1::GetColour(src2->GetPrimaryColour())); + dst2->SetSecondaryColour(RCT1::GetColour(src2->GetSecondaryColour())); + + break; + } + case TILE_ELEMENT_TYPE_BANNER: + { + auto dst2 = dst->AsBanner(); + auto src2 = src->AsBanner(); + + uint8_t index = src2->GetIndex(); + dst2->SetIndex(index); + dst2->SetPosition(src2->GetPosition()); + dst2->SetAllowedEdges(src2->GetAllowedEdges()); + + rct_banner* srcBanner = &_s4.banners[index]; + rct_banner* dstBanner = &gBanners[index]; + ImportBanner(dstBanner, srcBanner); + + break; + } + default: + assert(false); + } } void ImportResearch() @@ -2429,121 +2635,6 @@ private: gNextFreeTileElement = nextFreeTileElement; } - void FixSceneryColours() - { - colour_t colour; - TileElement* tileElement = gTileElements; - while (tileElement < gNextFreeTileElement) - { - if (tileElement->base_height != 255) - { - // This skips walls, which are fixed later. - switch (tileElement->GetType()) - { - case TILE_ELEMENT_TYPE_SMALL_SCENERY: - colour = RCT1::GetColour(tileElement->AsSmallScenery()->GetPrimaryColour()); - tileElement->AsSmallScenery()->SetPrimaryColour(colour); - - // Copied from [rct2: 0x006A2956] - switch (tileElement->AsSmallScenery()->GetEntryIndex()) - { - case RCT1_SCENERY_GEOMETRIC_SCULPTURE_1: - case RCT1_SCENERY_GEOMETRIC_SCULPTURE_2: - case RCT1_SCENERY_GEOMETRIC_SCULPTURE_3: - case RCT1_SCENERY_GEOMETRIC_SCULPTURE_4: - case RCT1_SCENERY_GEOMETRIC_SCULPTURE_5: - tileElement->AsSmallScenery()->SetSecondaryColour(COLOUR_WHITE); - break; - case RCT1_SCENERY_TULIPS_1: - case RCT1_SCENERY_TULIPS_2: - tileElement->AsSmallScenery()->SetPrimaryColour(COLOUR_BRIGHT_RED); - tileElement->AsSmallScenery()->SetSecondaryColour(COLOUR_YELLOW); - } - break; - case TILE_ELEMENT_TYPE_LARGE_SCENERY: - colour = RCT1::GetColour(tileElement->AsLargeScenery()->GetPrimaryColour()); - tileElement->AsLargeScenery()->SetPrimaryColour(colour); - - colour = RCT1::GetColour(tileElement->AsLargeScenery()->GetSecondaryColour()); - tileElement->AsLargeScenery()->SetSecondaryColour(colour); - - break; - } - } - tileElement++; - } - } - - void FixTileElementZ() - { - TileElement* tileElement = gTileElements; - while (tileElement < gNextFreeTileElement) - { - if (tileElement->base_height != 255) - { - tileElement->base_height /= 2; - tileElement->clearance_height /= 2; - } - tileElement++; - } - gMapBaseZ = 7; - } - - void FixPaths() - { - TileElement* tileElement = gTileElements; - while (tileElement < gNextFreeTileElement) - { - switch (tileElement->GetType()) - { - case TILE_ELEMENT_TYPE_PATH: - { - // Type - uint8_t pathType = tileElement->AsPath()->GetRCT1PathType(); - uint8_t entryIndex = _pathTypeToEntryMap[pathType]; - - tileElement->SetDirection(0); - tileElement->flags &= ~(TILE_ELEMENT_FLAG_BROKEN | TILE_ELEMENT_FLAG_INDESTRUCTIBLE_TRACK_PIECE); - - tileElement->AsPath()->SetEntryIndex(entryIndex); - if (RCT1::PathIsQueue(pathType)) - { - tileElement->AsPath()->SetIsQueue(true); - } - - tileElement->AsPath()->SetAdditionIsGhost(false); - - // Additions - uint8_t additionType = tileElement->AsPath()->GetAddition(); - if (additionType != RCT1_PATH_ADDITION_NONE) - { - uint8_t normalisedType = RCT1::NormalisePathAddition(additionType); - entryIndex = _pathAdditionTypeToEntryMap[normalisedType]; - if (additionType != normalisedType) - { - tileElement->flags |= TILE_ELEMENT_FLAG_BROKEN; - } - tileElement->AsPath()->SetAddition(entryIndex + 1); - } - break; - } - case TILE_ELEMENT_TYPE_ENTRANCE: - if (tileElement->AsEntrance()->GetEntranceType() == ENTRANCE_TYPE_PARK_ENTRANCE) - { - uint8_t pathType = tileElement->AsEntrance()->GetPathType(); - if (pathType == 0) - { - pathType = RCT1_FOOTPATH_TYPE_TARMAC_GRAY; - } - uint8_t entryIndex = _pathTypeToEntryMap[pathType]; - tileElement->AsEntrance()->SetPathType(entryIndex & 0x7F); - } - break; - } - tileElement++; - } - } - void FixWalls() { // The user might attempt to load a save while in pause mode. @@ -2627,27 +2718,6 @@ private: } } - void FixBanners() - { - for (int32_t x = 0; x < RCT1_MAX_MAP_SIZE; x++) - { - for (int32_t y = 0; y < RCT1_MAX_MAP_SIZE; y++) - { - TileElement* tileElement = map_get_first_element_at(x, y); - do - { - if (tileElement->GetType() == TILE_ELEMENT_TYPE_BANNER) - { - uint8_t index = tileElement->AsBanner()->GetIndex(); - rct_banner* src = &_s4.banners[index]; - rct_banner* dst = &gBanners[index]; - ImportBanner(dst, src); - } - } while (!(tileElement++)->IsLastForTile()); - } - } - } - void ImportBanner(rct_banner* dst, rct_banner* src) { *dst = *src; @@ -2668,21 +2738,6 @@ private: } } - void FixTerrain() - { - tile_element_iterator it; - tile_element_iterator_begin(&it); - while (tile_element_iterator_next(&it)) - { - TileElement* element = it.element; - if (element->GetType() == TILE_ELEMENT_TYPE_SURFACE) - { - element->AsSurface()->SetSurfaceStyle(RCT1::GetTerrain(element->AsSurface()->GetSurfaceStyle())); - element->AsSurface()->SetEdgeStyle(RCT1::GetTerrainEdge(element->AsSurface()->GetEdgeStyle())); - } - } - } - void FixEntrancePositions() { for (size_t i = 0; i < Util::CountOf(gParkEntrances); i++) @@ -2713,31 +2768,6 @@ private: } } - void FixTileElementEntryTypes() - { - tile_element_iterator it; - tile_element_iterator_begin(&it); - while (tile_element_iterator_next(&it)) - { - TileElement* tileElement = it.element; - switch (tileElement->GetType()) - { - case TILE_ELEMENT_TYPE_SMALL_SCENERY: - { - uint8_t entryIndex = _smallSceneryTypeToEntryMap[tileElement->AsSmallScenery()->GetEntryIndex()]; - tileElement->AsSmallScenery()->SetEntryIndex(entryIndex); - break; - } - case TILE_ELEMENT_TYPE_LARGE_SCENERY: - { - uint8_t type = tileElement->AsLargeScenery()->GetEntryIndex(); - tileElement->AsLargeScenery()->SetEntryIndex(_largeSceneryTypeToEntryMap[type]); - break; - } - } - } - } - EntryList* GetEntryList(uint8_t objectType) { switch (objectType) @@ -2878,15 +2908,6 @@ void load_from_sc4(const utf8* path) s4Importer->Import(); } -uint8_t PathElement::GetRCT1PathType() const -{ - uint8_t pathColour = type & 3; - uint8_t pathType2 = (entryIndex & FOOTPATH_PROPERTIES_TYPE_MASK) >> 2; - - pathType2 = pathType2 | pathColour; - return pathType2; -} - int32_t WallElement::GetRCT1WallType(int32_t edge) const { uint8_t var_05 = colour_3; diff --git a/src/openrct2/rct12/RCT12.cpp b/src/openrct2/rct12/RCT12.cpp index 36e0e8ef33..d142b07b47 100644 --- a/src/openrct2/rct12/RCT12.cpp +++ b/src/openrct2/rct12/RCT12.cpp @@ -332,6 +332,11 @@ bool RCT12WallElement::AnimationIsBackwards() const return (animation & WALL_ANIMATION_FLAG_DIRECTION_BACKWARD) != 0; } +uint32_t RCT12WallElement::GetRawRCT1WallTypeData() const +{ + return colour_3 | (colour_1 << 8) | (animation << 16); +} + int32_t RCT12WallElement::GetRCT1WallType(int32_t edge) const { uint8_t var_05 = colour_3; diff --git a/src/openrct2/rct12/RCT12.h b/src/openrct2/rct12/RCT12.h index fe860ac651..8ffc1f8e8d 100644 --- a/src/openrct2/rct12/RCT12.h +++ b/src/openrct2/rct12/RCT12.h @@ -310,6 +310,7 @@ public: BannerIndex GetBannerIndex() const; bool IsAcrossTrack() const; bool AnimationIsBackwards() const; + uint32_t GetRawRCT1WallTypeData() const; int32_t GetRCT1WallType(int32_t edge) const; colour_t GetRCT1WallColour() const; }; diff --git a/src/openrct2/world/TileElement.h b/src/openrct2/world/TileElement.h index 1f1dc98dd5..a477acf96f 100644 --- a/src/openrct2/world/TileElement.h +++ b/src/openrct2/world/TileElement.h @@ -390,6 +390,7 @@ public: bool AnimationIsBackwards() const; void SetAnimationIsBackwards(bool isBackwards); + void SetRawRCT1Data(uint32_t rawData); int32_t GetRCT1WallType(int32_t edge) const; colour_t GetRCT1WallColour() const; }; diff --git a/src/openrct2/world/Wall.cpp b/src/openrct2/world/Wall.cpp index 28f7e9bead..aa4e08628d 100644 --- a/src/openrct2/world/Wall.cpp +++ b/src/openrct2/world/Wall.cpp @@ -811,3 +811,10 @@ void WallElement::SetAnimationIsBackwards(bool isBackwards) if (isBackwards) animation |= WALL_ANIMATION_FLAG_DIRECTION_BACKWARD; } + +void WallElement::SetRawRCT1Data(uint32_t rawData) +{ + colour_3 = rawData & 0xFF; + colour_1 = (rawData >> 8) & 0xFF; + animation = (rawData >> 16) & 0xFF; +}