1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-26 16:24:35 +01:00

start moving RCT1 importer to C++

This commit is contained in:
Ted John
2016-04-17 03:28:07 +01:00
parent 72e625c5a3
commit cf7b81fd3a
7 changed files with 1080 additions and 1 deletions

224
src/rct1/S4Importer.cpp Normal file
View File

@@ -0,0 +1,224 @@
#include <Windows.h>
#include "../common.h"
#include "../core/List.hpp"
#include "../core/Util.hpp"
#include "import.h"
extern "C"
{
#include "../rct1.h"
#include "../util/sawyercoding.h"
}
/**
* Class to import RollerCoaster Tycoon 1 scenarios (*.SC4) and saved games (*.SV4).
*/
class S4Importer
{
public:
private:
rct1_s4 _s4;
uint8 _gameVersion;
// Lists of dynamic object entries
List<const char *> _rideEntries;
List<const char *> _smallSceneryEntries;
List<const char *> _largeSceneryEntries;
List<const char *> _wallEntries;
List<const char *> _sceneryGroupEntries;
// Lookup tables for converting from RCT1 hard coded types to the new dynamic object entries
uint8 _rideTypeToRideEntryMap[96];
uint8 _vehicleTypeToRideEntryMap[96];
uint8 _smallSceneryTypeToEntryMap[96];
uint8 _largeSceneryTypeToEntryMap[96];
uint8 _wallSceneryTypeToEntryMap[96];
uint8 _sceneryThemeTypeToEntryMap[24];
void Initialise();
/**
* Scans the map and research list for all the object types used and builds lists and
* lookup tables for converting from hard coded RCT1 object types to dynamic object entries.
*/
void CreateAvailableObjectMappings();
void AddAvailableEntriesFromResearchList();
void AddAvailableEntriesFromMap();
void AddAvailableEntriesFromRides();
void AddEntryForRideType(uint8 rideType);
void AddEntryForVehicleType(uint8 rideType, uint8 vehicleType);
void AddEntryForSmallScenery(uint8 smallSceneryType);
void AddEntriesForSceneryTheme(uint8 sceneryThemeType);
const rct1_research_item * GetResearchList(size_t * count);
};
void S4Importer::Initialise()
{
_gameVersion = sawyercoding_detect_rct1_version(_s4.game_version) & FILE_VERSION_MASK;
Memory::Set(_rideTypeToRideEntryMap, 255, sizeof(_rideTypeToRideEntryMap));
Memory::Set(_vehicleTypeToRideEntryMap, 255, sizeof(_vehicleTypeToRideEntryMap));
Memory::Set(_smallSceneryTypeToEntryMap, 255, sizeof(_smallSceneryTypeToEntryMap));
Memory::Set(_largeSceneryTypeToEntryMap, 255, sizeof(_largeSceneryTypeToEntryMap));
Memory::Set(_wallSceneryTypeToEntryMap, 255, sizeof(_wallSceneryTypeToEntryMap));
Memory::Set(_sceneryThemeTypeToEntryMap, 255, sizeof(_sceneryThemeTypeToEntryMap));
}
void S4Importer::CreateAvailableObjectMappings()
{
AddAvailableEntriesFromResearchList();
AddAvailableEntriesFromMap();
AddAvailableEntriesFromRides();
}
void S4Importer::AddAvailableEntriesFromResearchList()
{
size_t researchListCount;
const rct1_research_item * researchList = GetResearchList(&researchListCount);
for (size_t i = 0; i < researchListCount; i++)
{
const rct1_research_item * researchItem = &researchList[i];
if (researchItem->item == RCT1_RESEARCH_END_RESEARCHABLE ||
researchItem->item == RCT1_RESEARCH_END)
{
break;
}
if (researchItem->item == RCT1_RESEARCH_END_AVAILABLE)
{
continue;
}
switch (researchItem->category) {
case RCT1_RESEARCH_CATEGORY_THEME:
AddEntriesForSceneryTheme(researchItem->item);
break;
case RCT1_RESEARCH_CATEGORY_RIDE:
{
uint8 rideType = researchItem->item;
// Add all vehicles for this ride type
uint32 numVehicles = 0;
for (size_t j = 0; j < researchListCount; j++)
{
const rct1_research_item *researchItem2 = &researchList[j];
if (researchItem2->item == RCT1_RESEARCH_END_RESEARCHABLE ||
researchItem2->item == RCT1_RESEARCH_END_AVAILABLE)
{
break;
}
if (researchItem2->category == RCT1_RESEARCH_CATEGORY_VEHICLE &&
researchItem2->related_ride == rideType)
{
AddEntryForVehicleType(rideType, researchItem2->item);
numVehicles++;
}
}
// If no vehicles found so just add the default for this ride
if (numVehicles == 0)
{
AddEntryForRideType(rideType);
}
break;
}
}
}
}
void S4Importer::AddAvailableEntriesFromMap()
{
size_t maxTiles = 128 * 128;
size_t tileIndex = 0;
rct_map_element * mapElement = _s4.map_elements;
while (tileIndex < maxTiles)
{
switch (map_element_get_type(mapElement)) {
case MAP_ELEMENT_TYPE_SCENERY:
AddEntryForSmallScenery(mapElement->properties.scenery.type);
break;
}
if (map_element_is_last_for_tile(mapElement++))
{
tileIndex++;
}
}
}
void S4Importer::AddAvailableEntriesFromRides()
{
for (size_t i = 0; i < Util::CountOf(_s4.rides); i++)
{
rct1_ride * ride = &_s4.rides[i];
// TODO might need to check if ride type has a vehicle type
AddEntryForVehicleType(ride->type, ride->vehicle_type);
}
}
void S4Importer::AddEntryForRideType(uint8 rideType)
{
if (_rideTypeToRideEntryMap[rideType] == 255)
{
const char * entryName = RCT1::Tables::GetRideTypeObject(rideType);
_rideEntries.Add(entryName);
_rideTypeToRideEntryMap[rideType] = (uint8)_rideEntries.GetCount();
}
}
void S4Importer::AddEntryForVehicleType(uint8 rideType, uint8 vehicleType)
{
if (_vehicleTypeToRideEntryMap[rideType] == 255)
{
const char * entryName = RCT1::Tables::GetVehicleObject(vehicleType);
uint8 rideEntryIndex = (uint8)_rideEntries.GetCount();
_vehicleTypeToRideEntryMap[vehicleType] = rideEntryIndex;
_rideEntries.Add(entryName);
// Just overwrite this with the vehicle entry for now...
_rideTypeToRideEntryMap[rideType] = rideEntryIndex;
}
}
void S4Importer::AddEntryForSmallScenery(uint8 smallSceneryType)
{
if (_smallSceneryTypeToEntryMap[smallSceneryType] == 255)
{
const char * entryName = RCT1::Tables::GetSmallSceneryObject(smallSceneryType);
_smallSceneryEntries.Add(entryName);
_smallSceneryTypeToEntryMap[smallSceneryType] = (uint8)_rideEntries.GetCount();
}
}
void S4Importer::AddEntriesForSceneryTheme(uint8 sceneryThemeType)
{
const char * entryName = RCT1::Tables::GetSceneryGroupObject(sceneryThemeType);
_sceneryThemeTypeToEntryMap[sceneryThemeType] = (uint8)_sceneryGroupEntries.GetCount();
_sceneryGroupEntries.Add(entryName);
// TODO add entries for all scenery items belonging to scenery group
}
const rct1_research_item * S4Importer::GetResearchList(size_t * count)
{
// Loopy Landscapes stores research items in a different place
if (_gameVersion == FILE_VERSION_RCT1_LL)
{
*count = Util::CountOf(_s4.research_items_LL);
return _s4.research_items_LL;
}
else
{
*count = Util::CountOf(_s4.research_items);
return _s4.research_items;
}
}