Compare commits

...

4 Commits

53 changed files with 305 additions and 149 deletions
+2
View File
@@ -13,6 +13,8 @@ add_files(
geometry_func.hpp
geometry_type.hpp
kdtree.hpp
label.cpp
label_type.hpp
math_func.cpp
math_func.hpp
multimap.hpp
+29
View File
@@ -0,0 +1,29 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
*/
/** @file label.cpp Implementation of label functions. */
#include "../stdafx.h"
#include "label_type.hpp"
#include "../string_func.h"
#include "../safeguards.h"
/**
* Get the label as a \c std::string.
* If the label is all \c std::isgraph characters, it will return these characters as string,
* otherwise it will format it as a 8-digit hexadecimal.
* @return The label as string.
*/
std::string BaseLabel::AsString() const
{
if (std::ranges::all_of(*this, [](uint8_t c) { return std::isgraph(c); })) {
return std::string{reinterpret_cast<const char *>(this->data()), this->size()};
}
return FormatArrayAsHex(*this);
}
+72
View File
@@ -0,0 +1,72 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
*/
/** @file label_type.hpp A type for 4 character labels/tags/ids in files that should be read/shown as is. */
#ifndef LABEL_TYPE_HPP
#define LABEL_TYPE_HPP
/** Base for a four character label/tag/id. */
struct BaseLabel : std::array<uint8_t, 4> {
/**
* Check whether the label is empty.
* @return \c true iff the label is empty, i.e. all zeros.
*/
constexpr inline bool Empty() const
{
return std::ranges::all_of(*this, [](uint8_t b) { return b == 0; });
};
/**
* Get the label as a \c std::string.
* If the label is all \c std::isgraph characters, it will return these characters as string,
* otherwise it will format it as a 8-digit hexadecimal.
* @return The label as string.
*/
std::string AsString() const;
};
/**
* A four character label/tag/id.
* @tparam Tag Type to distinguish labels/tags/ids of different types.
*/
template <typename Tag>
struct Label : BaseLabel {
/** Create an empty label, i.e. all zeros. */
constexpr Label()
{
std::ranges::fill(*this, 0);
}
/**
* Create a label with the given 4 letter character string.
* @param label The label value.
* @note This defines 5 characters, but the 5th character is assumed to null-terminator.
*/
constexpr Label(const char (&label)[5])
{
std::copy(label, label + this->size(), this->begin());
}
/**
* Create a label with the given 4 bytes.
* @param label The label value.
*/
constexpr Label(const uint8_t (&label)[4])
{
std::copy(label, label + this->size(), this->begin());
}
/**
* Default spaceship operator.
* @param other The label to compare to.
* @return The comparison ordering.
*/
constexpr std::strong_ordering operator<=>(const Label<Tag> &other) const = default;
};
#endif /* LABEL_TYPE_HPP */
+3 -7
View File
@@ -96,7 +96,7 @@ static ChangeInfoResult ObjectChangeInfo(uint first, uint last, int prop, ByteRe
}
switch (prop) {
case 0x08: { // Class ID
case 0x08: // Class ID
/* Allocate space for this object. */
if (spec == nullptr) {
spec = std::make_unique<ObjectSpec>();
@@ -104,16 +104,12 @@ static ChangeInfoResult ObjectChangeInfo(uint first, uint last, int prop, ByteRe
spec->size = OBJECT_SIZE_1X1; // Default for NewGRFs that manage to not set it (1x1)
}
/* Swap classid because we read it in BE. */
uint32_t classid = buf.ReadDWord();
spec->class_index = ObjectClass::Allocate(std::byteswap(classid));
spec->class_index = ObjectClass::Allocate(buf.ReadLabel<ObjectClass::GlobalID>());
break;
}
case 0x09: { // Class name
case 0x09: // Class name
AddStringForMapping(GRFStringID{buf.ReadWord()}, [spec = spec.get()](StringID str) { ObjectClass::Get(spec->class_index)->name = str; });
break;
}
case 0x0A: // Object name
AddStringForMapping(GRFStringID{buf.ReadWord()}, &spec->name);
+2 -4
View File
@@ -88,15 +88,13 @@ static ChangeInfoResult RoadStopChangeInfo(uint first, uint last, int prop, Byte
}
switch (prop) {
case 0x08: { // Road Stop Class ID
case 0x08: // Road Stop Class ID
if (rs == nullptr) {
rs = std::make_unique<RoadStopSpec>();
}
uint32_t classid = buf.ReadDWord();
rs->class_index = RoadStopClass::Allocate(std::byteswap(classid));
rs->class_index = RoadStopClass::Allocate(buf.ReadLabel<RoadStopClass::GlobalID>());
break;
}
case 0x09: // Road stop type
rs->stop_type = (RoadStopAvailabilityType)buf.ReadByte();
+2 -5
View File
@@ -49,17 +49,14 @@ static ChangeInfoResult StationChangeInfo(uint first, uint last, int prop, ByteR
}
switch (prop) {
case 0x08: { // Class ID
case 0x08: // Class ID
/* Property 0x08 is special; it is where the station is allocated */
if (statspec == nullptr) {
statspec = std::make_unique<StationSpec>();
}
/* Swap classid because we read it in BE meaning WAYP or DFLT */
uint32_t classid = buf.ReadDWord();
statspec->class_index = StationClass::Allocate(std::byteswap(classid));
statspec->class_index = StationClass::Allocate(buf.ReadLabel<StationClass::GlobalID>());
break;
}
case 0x09: { // Define sprite layout
uint16_t tiles = buf.ReadExtendedByte();
+13
View File
@@ -10,6 +10,7 @@
#ifndef NEWGRF_BYTEREADER_H
#define NEWGRF_BYTEREADER_H
#include "../core/label_type.hpp"
#include "../core/string_consumer.hpp"
class OTTDByteReaderSignal { };
@@ -94,6 +95,18 @@ public:
return this->consumer.ReadUntilChar('\0', StringConsumer::SKIP_ONE_SEPARATOR);
}
/**
* Read a label.
* @return The read label.
*/
template <typename T> requires std::is_base_of_v<BaseLabel, T>
T ReadLabel()
{
T label{};
std::ranges::copy(this->consumer.Read(label.size()), label.data());
return label;
}
size_t Remaining() const
{
return this->consumer.GetBytesLeft();
+4 -4
View File
@@ -30,10 +30,10 @@
template <>
/* static */ void AirportClass::InsertDefaults()
{
AirportClass::Get(AirportClass::Allocate('SMAL'))->name = STR_AIRPORT_CLASS_SMALL;
AirportClass::Get(AirportClass::Allocate('LARG'))->name = STR_AIRPORT_CLASS_LARGE;
AirportClass::Get(AirportClass::Allocate('HUB_'))->name = STR_AIRPORT_CLASS_HUB;
AirportClass::Get(AirportClass::Allocate('HELI'))->name = STR_AIRPORT_CLASS_HELIPORTS;
AirportClass::Get(AirportClass::Allocate("SMAL"))->name = STR_AIRPORT_CLASS_SMALL;
AirportClass::Get(AirportClass::Allocate("LARG"))->name = STR_AIRPORT_CLASS_LARGE;
AirportClass::Get(AirportClass::Allocate("HUB_"))->name = STR_AIRPORT_CLASS_HUB;
AirportClass::Get(AirportClass::Allocate("HELI"))->name = STR_AIRPORT_CLASS_HELIPORTS;
}
template <>
+11 -5
View File
@@ -10,6 +10,7 @@
#ifndef NEWGRF_CLASS_H
#define NEWGRF_CLASS_H
#include "core/label_type.hpp"
#include "newgrf_type.h"
#include "strings_type.h"
@@ -45,12 +46,17 @@ private:
public:
using spec_type = Tspec;
using index_type = Tindex;
using GlobalID = Label<NewGRFClass<Tspec, Tindex>>; ///< Type for the global identifier of the class.
uint32_t global_id; ///< Global ID for class, e.g. 'DFLT', 'WAYP', etc.
StringID name; ///< Name of this class.
GlobalID global_id; ///< Global ID for class, e.g. 'DFLT', 'WAYP', etc.
StringID name; ///< Name of this class.
/* Public constructor as emplace_back needs access. */
NewGRFClass(uint32_t global_id, StringID name) : global_id(global_id), name(name) { }
/**
* Create the class.
* @param global_id The globally unique identifier of the class.
* @param name The name of the class.
*/
NewGRFClass(GlobalID global_id, StringID name) : global_id(global_id), name(name) { }
/**
* Get read-only span of specs of this class.
@@ -90,7 +96,7 @@ public:
bool IsUIAvailable(uint index) const;
static void Reset();
static Tindex Allocate(uint32_t global_id);
static Tindex Allocate(GlobalID global_id);
static void Assign(Tspec *spec);
static uint GetClassCount();
static uint GetUIClassCount();
+1 -1
View File
@@ -29,7 +29,7 @@ void NewGRFClass<Tspec, Tindex>::Reset()
* second time, this first allocation will be given.
*/
template <typename Tspec, typename Tindex>
Tindex NewGRFClass<Tspec, Tindex>::Allocate(uint32_t global_id)
Tindex NewGRFClass<Tspec, Tindex>::Allocate(GlobalID global_id)
{
auto found = std::ranges::find(NewGRFClass::classes, global_id, &NewGRFClass::global_id);
+4 -4
View File
@@ -136,8 +136,8 @@ void ResetObjects()
}
/* Set class for originals. */
_object_specs[OBJECT_LIGHTHOUSE].class_index = ObjectClass::Allocate('LTHS');
_object_specs[OBJECT_TRANSMITTER].class_index = ObjectClass::Allocate('TRNS');
_object_specs[OBJECT_LIGHTHOUSE].class_index = ObjectClass::Allocate("LTHS");
_object_specs[OBJECT_TRANSMITTER].class_index = ObjectClass::Allocate("TRNS");
/* Reset any overrides that have been set. */
_object_mngr.ResetOverride();
@@ -146,8 +146,8 @@ void ResetObjects()
template <>
/* static */ void ObjectClass::InsertDefaults()
{
ObjectClass::Get(ObjectClass::Allocate('LTHS'))->name = STR_OBJECT_CLASS_LTHS;
ObjectClass::Get(ObjectClass::Allocate('TRNS'))->name = STR_OBJECT_CLASS_TRNS;
ObjectClass::Get(ObjectClass::Allocate("LTHS"))->name = STR_OBJECT_CLASS_LTHS;
ObjectClass::Get(ObjectClass::Allocate("TRNS"))->name = STR_OBJECT_CLASS_TRNS;
}
template <>
+4 -4
View File
@@ -25,9 +25,6 @@ struct TileInfo;
/** The maximum amount of roadstops a single GRF is allowed to add */
static const int NUM_ROADSTOPS_PER_GRF = UINT16_MAX - 1;
static const uint32_t ROADSTOP_CLASS_LABEL_DEFAULT = 'DFLT';
static const uint32_t ROADSTOP_CLASS_LABEL_WAYPOINT = 'WAYP';
/** Class IDs for stations. */
using RoadStopClassID = PoolID<uint16_t, struct RoadStopClassIDTag, UINT16_MAX, UINT16_MAX>;
@@ -164,6 +161,9 @@ struct RoadStopSpec : NewGRFSpecBase<RoadStopClassID> {
using RoadStopClass = NewGRFClass<RoadStopSpec, RoadStopClassID>;
static const RoadStopClass::GlobalID ROADSTOP_CLASS_LABEL_DEFAULT{"DFLT"}; ///< Class label for default road stops.
static const RoadStopClass::GlobalID ROADSTOP_CLASS_LABEL_WAYPOINT{"WAYP"}; ///< Class label for default road waypoints.
std::optional<SpriteLayoutProcessor> GetRoadStopLayout(TileInfo *ti, const RoadStopSpec *spec, BaseStation *st, StationType type, int view, std::span<int32_t> regs100 = {});
void DrawRoadStopTile(int x, int y, RoadType roadtype, const RoadStopSpec *spec, StationType type, int view);
@@ -191,7 +191,7 @@ void RoadStopUpdateCachedTriggers(BaseStation *st);
*/
inline bool IsWaypointClass(const RoadStopClass &cls)
{
return cls.global_id == ROADSTOP_CLASS_LABEL_WAYPOINT || GB(cls.global_id, 24, 8) == UINT8_MAX;
return cls.global_id == ROADSTOP_CLASS_LABEL_WAYPOINT || cls.global_id[0] == UINT8_MAX;
}
#endif /* NEWGRF_ROADSTATION_H */
+4 -4
View File
@@ -98,9 +98,6 @@ struct StationResolverObject : public SpecializedResolverObject<StationRandomTri
uint32_t GetDebugID() const override;
};
static const uint32_t STATION_CLASS_LABEL_DEFAULT = 'DFLT';
static const uint32_t STATION_CLASS_LABEL_WAYPOINT = 'WAYP';
/** Class IDs for stations. */
using StationClassID = PoolID<uint16_t, struct StationClassIDTag, UINT16_MAX, UINT16_MAX>;
@@ -188,6 +185,9 @@ struct StationSpec : NewGRFSpecBase<StationClassID> {
/** Class containing information relating to station classes. */
using StationClass = NewGRFClass<StationSpec, StationClassID>;
static const StationClass::GlobalID STATION_CLASS_LABEL_DEFAULT{"DFLT"}; ///< Class label for default rail station.
static const StationClass::GlobalID STATION_CLASS_LABEL_WAYPOINT{"WAYP"}; ///< Class label for default rail waypoints.
const StationSpec *GetStationSpec(TileIndex t);
/**
@@ -208,7 +208,7 @@ inline uint16_t GetStationLayoutKey(uint8_t platforms, uint8_t length)
*/
inline bool IsWaypointClass(const StationClass &cls)
{
return cls.global_id == STATION_CLASS_LABEL_WAYPOINT || GB(cls.global_id, 24, 8) == UINT8_MAX;
return cls.global_id == STATION_CLASS_LABEL_WAYPOINT || cls.global_id[0] == UINT8_MAX;
}
/* Evaluate a tile's position within a station, and return the result a bitstuffed format. */
+1 -1
View File
@@ -73,7 +73,7 @@ static void SaveReal_AIPL(int arg)
}
struct AIPLChunkHandler : ChunkHandler {
AIPLChunkHandler() : ChunkHandler('AIPL', ChunkType::Table) {}
AIPLChunkHandler() : ChunkHandler("AIPL", ChunkType::Table) {}
void Load() const override
{
+2 -2
View File
@@ -15,11 +15,11 @@
#include "../safeguards.h"
struct APIDChunkHandler : NewGRFMappingChunkHandler {
APIDChunkHandler() : NewGRFMappingChunkHandler('APID', _airport_mngr) {}
APIDChunkHandler() : NewGRFMappingChunkHandler("APID", _airport_mngr) {}
};
struct ATIDChunkHandler : NewGRFMappingChunkHandler {
ATIDChunkHandler() : NewGRFMappingChunkHandler('ATID', _airporttile_mngr) {}
ATIDChunkHandler() : NewGRFMappingChunkHandler("ATID", _airporttile_mngr) {}
};
static const ATIDChunkHandler ATID;
+1 -1
View File
@@ -23,7 +23,7 @@ static const SaveLoad _animated_tile_desc[] = {
};
struct ANITChunkHandler : ChunkHandler {
ANITChunkHandler() : ChunkHandler('ANIT', ChunkType::Table) {}
ANITChunkHandler() : ChunkHandler("ANIT", ChunkType::Table) {}
void Save() const override
{
+1 -1
View File
@@ -26,7 +26,7 @@ static const SaveLoad _engine_renew_desc[] = {
};
struct ERNWChunkHandler : ChunkHandler {
ERNWChunkHandler() : ChunkHandler('ERNW', ChunkType::Table) {}
ERNWChunkHandler() : ChunkHandler("ERNW", ChunkType::Table) {}
void Save() const override
{
+2 -2
View File
@@ -45,7 +45,7 @@ static CargoMonitorID FixupCargoMonitor(CargoMonitorID number)
/** #_cargo_deliveries monitoring map. */
struct CMDLChunkHandler : ChunkHandler {
CMDLChunkHandler() : ChunkHandler('CMDL', ChunkType::Table) {}
CMDLChunkHandler() : ChunkHandler("CMDL", ChunkType::Table) {}
void Save() const override
{
@@ -88,7 +88,7 @@ struct CMDLChunkHandler : ChunkHandler {
/** #_cargo_pickups monitoring map. */
struct CMPUChunkHandler : ChunkHandler {
CMPUChunkHandler() : ChunkHandler('CMPU', ChunkType::Table) {}
CMPUChunkHandler() : ChunkHandler("CMPU", ChunkType::Table) {}
void Save() const override
{
+1 -1
View File
@@ -143,7 +143,7 @@ SaveLoadTable GetCargoPacketDesc()
}
struct CAPAChunkHandler : ChunkHandler {
CAPAChunkHandler() : ChunkHandler('CAPA', ChunkType::Table) {}
CAPAChunkHandler() : ChunkHandler("CAPA", ChunkType::Table) {}
void Save() const override
{
+1 -1
View File
@@ -39,7 +39,7 @@ static const SaveLoad _cheats_desc[] = {
struct CHTSChunkHandler : ChunkHandler {
CHTSChunkHandler() : ChunkHandler('CHTS', ChunkType::Table) {}
CHTSChunkHandler() : ChunkHandler("CHTS", ChunkType::Table) {}
void Save() const override
{
+1 -1
View File
@@ -551,7 +551,7 @@ static const SaveLoad _company_desc[] = {
};
struct PLYRChunkHandler : ChunkHandler {
PLYRChunkHandler() : ChunkHandler('PLYR', ChunkType::Table) {}
PLYRChunkHandler() : ChunkHandler("PLYR", ChunkType::Table) {}
void Save() const override
{
+1 -1
View File
@@ -30,7 +30,7 @@ static const SaveLoad _depot_desc[] = {
};
struct DEPTChunkHandler : ChunkHandler {
DEPTChunkHandler() : ChunkHandler('DEPT', ChunkType::Table) {}
DEPTChunkHandler() : ChunkHandler("DEPT", ChunkType::Table) {}
void Save() const override
{
+4 -4
View File
@@ -19,7 +19,7 @@
/** Prices in pre 126 savegames */
struct PRICChunkHandler : ChunkHandler {
PRICChunkHandler() : ChunkHandler('PRIC', ChunkType::ReadOnly) {}
PRICChunkHandler() : ChunkHandler("PRIC", ChunkType::ReadOnly) {}
void Load() const override
{
@@ -32,7 +32,7 @@ struct PRICChunkHandler : ChunkHandler {
/** Cargo payment rates in pre 126 savegames */
struct CAPRChunkHandler : ChunkHandler {
CAPRChunkHandler() : ChunkHandler('CAPR', ChunkType::ReadOnly) {}
CAPRChunkHandler() : ChunkHandler("CAPR", ChunkType::ReadOnly) {}
void Load() const override
{
@@ -58,7 +58,7 @@ static const SaveLoad _economy_desc[] = {
/** Economy variables */
struct ECMYChunkHandler : ChunkHandler {
ECMYChunkHandler() : ChunkHandler('ECMY', ChunkType::Table) {}
ECMYChunkHandler() : ChunkHandler("ECMY", ChunkType::Table) {}
void Save() const override
{
@@ -89,7 +89,7 @@ static const SaveLoad _cargopayment_desc[] = {
};
struct CAPYChunkHandler : ChunkHandler {
CAPYChunkHandler() : ChunkHandler('CAPY', ChunkType::Table) {}
CAPYChunkHandler() : ChunkHandler("CAPY", ChunkType::Table) {}
void Save() const override
{
+3 -3
View File
@@ -62,7 +62,7 @@ Engine *GetTempDataEngine(EngineID index, VehicleType type, uint16_t local_id)
}
struct ENGNChunkHandler : ChunkHandler {
ENGNChunkHandler() : ChunkHandler('ENGN', ChunkType::Table) {}
ENGNChunkHandler() : ChunkHandler("ENGN", ChunkType::Table) {}
void Save() const override
{
@@ -135,7 +135,7 @@ void ResetTempEngineData()
}
struct ENGSChunkHandler : ChunkHandler {
ENGSChunkHandler() : ChunkHandler('ENGS', ChunkType::ReadOnly) {}
ENGSChunkHandler() : ChunkHandler("ENGS", ChunkType::ReadOnly) {}
void Load() const override
{
@@ -162,7 +162,7 @@ static const SaveLoad _engine_id_mapping_desc[] = {
};
struct EIDSChunkHandler : ChunkHandler {
EIDSChunkHandler() : ChunkHandler('EIDS', ChunkType::Table) {}
EIDSChunkHandler() : ChunkHandler("EIDS", ChunkType::Table) {}
void Save() const override
{
+2 -2
View File
@@ -52,7 +52,7 @@ static void SaveReal_GSDT(int)
}
struct GSDTChunkHandler : ChunkHandler {
GSDTChunkHandler() : ChunkHandler('GSDT', ChunkType::Table) {}
GSDTChunkHandler() : ChunkHandler("GSDT", ChunkType::Table) {}
void Load() const override
{
@@ -153,7 +153,7 @@ static const SaveLoad _game_language_desc[] = {
};
struct GSTRChunkHandler : ChunkHandler {
GSTRChunkHandler() : ChunkHandler('GSTR', ChunkType::Table) {}
GSTRChunkHandler() : ChunkHandler("GSTR", ChunkType::Table) {}
void Load() const override
{
+1 -1
View File
@@ -375,7 +375,7 @@ static const SaveLoad _gamelog_desc[] = {
};
struct GLOGChunkHandler : ChunkHandler {
GLOGChunkHandler() : ChunkHandler('GLOG', ChunkType::Table) {}
GLOGChunkHandler() : ChunkHandler("GLOG", ChunkType::Table) {}
void LoadCommon(Gamelog &gamelog) const
{
+1 -1
View File
@@ -26,7 +26,7 @@ static const SaveLoad _goals_desc[] = {
};
struct GOALChunkHandler : ChunkHandler {
GOALChunkHandler() : ChunkHandler('GOAL', ChunkType::Table) {}
GOALChunkHandler() : ChunkHandler("GOAL", ChunkType::Table) {}
void Save() const override
{
+1 -1
View File
@@ -30,7 +30,7 @@ static const SaveLoad _group_desc[] = {
};
struct GRPSChunkHandler : ChunkHandler {
GRPSChunkHandler() : ChunkHandler('GRPS', ChunkType::Table) {}
GRPSChunkHandler() : ChunkHandler("GRPS", ChunkType::Table) {}
void Save() const override
{
+5 -5
View File
@@ -211,7 +211,7 @@ static const SaveLoad _industry_desc[] = {
};
struct INDYChunkHandler : ChunkHandler {
INDYChunkHandler() : ChunkHandler('INDY', ChunkType::Table) {}
INDYChunkHandler() : ChunkHandler("INDY", ChunkType::Table) {}
void Save() const override
{
@@ -303,11 +303,11 @@ struct INDYChunkHandler : ChunkHandler {
};
struct IIDSChunkHandler : NewGRFMappingChunkHandler {
IIDSChunkHandler() : NewGRFMappingChunkHandler('IIDS', _industry_mngr) {}
IIDSChunkHandler() : NewGRFMappingChunkHandler("IIDS", _industry_mngr) {}
};
struct TIDSChunkHandler : NewGRFMappingChunkHandler {
TIDSChunkHandler() : NewGRFMappingChunkHandler('TIDS', _industile_mngr) {}
TIDSChunkHandler() : NewGRFMappingChunkHandler("TIDS", _industile_mngr) {}
};
/** Description of the data to save and load in #IndustryBuildData. */
@@ -317,7 +317,7 @@ static const SaveLoad _industry_builder_desc[] = {
/** Industry builder. */
struct IBLDChunkHandler : ChunkHandler {
IBLDChunkHandler() : ChunkHandler('IBLD', ChunkType::Table) {}
IBLDChunkHandler() : ChunkHandler("IBLD", ChunkType::Table) {}
void Save() const override
{
@@ -348,7 +348,7 @@ static const SaveLoad _industrytype_builder_desc[] = {
/** Industry-type build data. */
struct ITBLChunkHandler : ChunkHandler {
ITBLChunkHandler() : ChunkHandler('ITBL', ChunkType::Table) {}
ITBLChunkHandler() : ChunkHandler("ITBL", ChunkType::Table) {}
void Save() const override
{
+2 -2
View File
@@ -34,7 +34,7 @@ void AfterLoadLabelMaps()
}
struct RAILChunkHandler : ChunkHandler {
RAILChunkHandler() : ChunkHandler('RAIL', ChunkType::Table) {}
RAILChunkHandler() : ChunkHandler("RAIL", ChunkType::Table) {}
static inline const SaveLoad description[] = {
SLE_VAR(LabelObject<RailTypeLabel>, label, VarTypes::U32),
@@ -69,7 +69,7 @@ struct RAILChunkHandler : ChunkHandler {
};
struct ROTTChunkHandler : ChunkHandler {
ROTTChunkHandler() : ChunkHandler('ROTT', ChunkType::Table) {}
ROTTChunkHandler() : ChunkHandler("ROTT", ChunkType::Table) {}
static inline const SaveLoad description[] = {
SLE_VAR(LabelObject<RoadTypeLabel>, label, VarTypes::U32),
+2 -2
View File
@@ -27,7 +27,7 @@ static const SaveLoad _league_table_elements_desc[] = {
};
struct LEAEChunkHandler : ChunkHandler {
LEAEChunkHandler() : ChunkHandler('LEAE', ChunkType::Table) {}
LEAEChunkHandler() : ChunkHandler("LEAE", ChunkType::Table) {}
void Save() const override
{
@@ -58,7 +58,7 @@ static const SaveLoad _league_tables_desc[] = {
};
struct LEATChunkHandler : ChunkHandler {
LEATChunkHandler() : ChunkHandler('LEAT', ChunkType::Table) {}
LEATChunkHandler() : ChunkHandler("LEAT", ChunkType::Table) {}
void Save() const override
{
+3 -3
View File
@@ -259,7 +259,7 @@ void AfterLoadLinkGraphs()
* All link graphs.
*/
struct LGRPChunkHandler : ChunkHandler {
LGRPChunkHandler() : ChunkHandler('LGRP', ChunkType::Table) {}
LGRPChunkHandler() : ChunkHandler("LGRP", ChunkType::Table) {}
void Save() const override
{
@@ -287,7 +287,7 @@ struct LGRPChunkHandler : ChunkHandler {
* All link graph jobs.
*/
struct LGRJChunkHandler : ChunkHandler {
LGRJChunkHandler() : ChunkHandler('LGRJ', ChunkType::Table) {}
LGRJChunkHandler() : ChunkHandler("LGRJ", ChunkType::Table) {}
void Save() const override
{
@@ -315,7 +315,7 @@ struct LGRJChunkHandler : ChunkHandler {
* Link graph schedule.
*/
struct LGRSChunkHandler : ChunkHandler {
LGRSChunkHandler() : ChunkHandler('LGRS', ChunkType::Table) {}
LGRSChunkHandler() : ChunkHandler("LGRS", ChunkType::Table) {}
void Save() const override
{
+11 -11
View File
@@ -27,7 +27,7 @@ static const SaveLoad _map_desc[] = {
};
struct MAPSChunkHandler : ChunkHandler {
MAPSChunkHandler() : ChunkHandler('MAPS', ChunkType::Table) {}
MAPSChunkHandler() : ChunkHandler("MAPS", ChunkType::Table) {}
void Save() const override
{
@@ -67,7 +67,7 @@ struct MAPSChunkHandler : ChunkHandler {
static const uint MAP_SL_BUF_SIZE = 4096;
struct MAPTChunkHandler : ChunkHandler {
MAPTChunkHandler() : ChunkHandler('MAPT', ChunkType::Riff) {}
MAPTChunkHandler() : ChunkHandler("MAPT", ChunkType::Riff) {}
void Load() const override
{
@@ -94,7 +94,7 @@ struct MAPTChunkHandler : ChunkHandler {
};
struct MAPHChunkHandler : ChunkHandler {
MAPHChunkHandler() : ChunkHandler('MAPH', ChunkType::Riff) {}
MAPHChunkHandler() : ChunkHandler("MAPH", ChunkType::Riff) {}
void Load() const override
{
@@ -121,7 +121,7 @@ struct MAPHChunkHandler : ChunkHandler {
};
struct MAPOChunkHandler : ChunkHandler {
MAPOChunkHandler() : ChunkHandler('MAPO', ChunkType::Riff) {}
MAPOChunkHandler() : ChunkHandler("MAPO", ChunkType::Riff) {}
void Load() const override
{
@@ -148,7 +148,7 @@ struct MAPOChunkHandler : ChunkHandler {
};
struct MAP2ChunkHandler : ChunkHandler {
MAP2ChunkHandler() : ChunkHandler('MAP2', ChunkType::Riff) {}
MAP2ChunkHandler() : ChunkHandler("MAP2", ChunkType::Riff) {}
void Load() const override
{
@@ -178,7 +178,7 @@ struct MAP2ChunkHandler : ChunkHandler {
};
struct M3LOChunkHandler : ChunkHandler {
M3LOChunkHandler() : ChunkHandler('M3LO', ChunkType::Riff) {}
M3LOChunkHandler() : ChunkHandler("M3LO", ChunkType::Riff) {}
void Load() const override
{
@@ -205,7 +205,7 @@ struct M3LOChunkHandler : ChunkHandler {
};
struct M3HIChunkHandler : ChunkHandler {
M3HIChunkHandler() : ChunkHandler('M3HI', ChunkType::Riff) {}
M3HIChunkHandler() : ChunkHandler("M3HI", ChunkType::Riff) {}
void Load() const override
{
@@ -232,7 +232,7 @@ struct M3HIChunkHandler : ChunkHandler {
};
struct MAP5ChunkHandler : ChunkHandler {
MAP5ChunkHandler() : ChunkHandler('MAP5', ChunkType::Riff) {}
MAP5ChunkHandler() : ChunkHandler("MAP5", ChunkType::Riff) {}
void Load() const override
{
@@ -259,7 +259,7 @@ struct MAP5ChunkHandler : ChunkHandler {
};
struct MAPEChunkHandler : ChunkHandler {
MAPEChunkHandler() : ChunkHandler('MAPE', ChunkType::Riff) {}
MAPEChunkHandler() : ChunkHandler("MAPE", ChunkType::Riff) {}
void Load() const override
{
@@ -299,7 +299,7 @@ struct MAPEChunkHandler : ChunkHandler {
};
struct MAP7ChunkHandler : ChunkHandler {
MAP7ChunkHandler() : ChunkHandler('MAP7', ChunkType::Riff) {}
MAP7ChunkHandler() : ChunkHandler("MAP7", ChunkType::Riff) {}
void Load() const override
{
@@ -326,7 +326,7 @@ struct MAP7ChunkHandler : ChunkHandler {
};
struct MAP8ChunkHandler : ChunkHandler {
MAP8ChunkHandler() : ChunkHandler('MAP8', ChunkType::Riff) {}
MAP8ChunkHandler() : ChunkHandler("MAP8", ChunkType::Riff) {}
void Load() const override
{
+2 -2
View File
@@ -121,7 +121,7 @@ static const SaveLoad _date_check_desc[] = {
* @note currently some unrelated stuff is just put here.
*/
struct DATEChunkHandler : ChunkHandler {
DATEChunkHandler() : ChunkHandler('DATE', ChunkType::Table) {}
DATEChunkHandler() : ChunkHandler("DATE", ChunkType::Table) {}
void Save() const override
{
@@ -165,7 +165,7 @@ static const SaveLoad _view_desc[] = {
};
struct VIEWChunkHandler : ChunkHandler {
VIEWChunkHandler() : ChunkHandler('VIEW', ChunkType::Table) {}
VIEWChunkHandler() : ChunkHandler("VIEW", ChunkType::Table) {}
void Save() const override
{
+1 -1
View File
@@ -62,7 +62,7 @@ void NewGRFMappingChunkHandler::Load() const
}
struct NGRFChunkHandler : ChunkHandler {
NGRFChunkHandler() : ChunkHandler('NGRF', ChunkType::Table) {}
NGRFChunkHandler() : ChunkHandler("NGRF", ChunkType::Table) {}
static inline std::array<uint32_t, GRFConfig::MAX_NUM_PARAMS> param;
static inline uint8_t num_params;
+8 -2
View File
@@ -13,10 +13,16 @@
#include "../newgrf_commons.h"
#include "saveload.h"
/** Chunk handler for data of the OverrideManagerBase. */
struct NewGRFMappingChunkHandler : ChunkHandler {
OverrideManagerBase &mapping;
OverrideManagerBase &mapping; ///< The override manager to save/load.
NewGRFMappingChunkHandler(uint32_t id, OverrideManagerBase &mapping) : ChunkHandler(id, ChunkType::Table), mapping(mapping) {}
/**
* Create the handler.
* @param id The identifier of the chunk
* @param mapping The override manager to save/load.
*/
NewGRFMappingChunkHandler(ChunkId id, OverrideManagerBase &mapping) : ChunkHandler(id, ChunkType::Table), mapping(mapping) {}
void Save() const override;
void Load() const override;
};
+2 -2
View File
@@ -30,7 +30,7 @@ static const SaveLoad _object_desc[] = {
};
struct OBJSChunkHandler : ChunkHandler {
OBJSChunkHandler() : ChunkHandler('OBJS', ChunkType::Table) {}
OBJSChunkHandler() : ChunkHandler("OBJS", ChunkType::Table) {}
void Save() const override
{
@@ -67,7 +67,7 @@ struct OBJSChunkHandler : ChunkHandler {
};
struct OBIDChunkHandler : NewGRFMappingChunkHandler {
OBIDChunkHandler() : NewGRFMappingChunkHandler('OBID', _object_mngr) {}
OBIDChunkHandler() : NewGRFMappingChunkHandler("OBID", _object_mngr) {}
};
static const OBIDChunkHandler OBID;
+3 -3
View File
@@ -159,7 +159,7 @@ SaveLoadTable GetOrderDescription()
}
struct ORDRChunkHandler : ChunkHandler {
ORDRChunkHandler() : ChunkHandler('ORDR', ChunkType::ReadOnly) {}
ORDRChunkHandler() : ChunkHandler("ORDR", ChunkType::ReadOnly) {}
void Load() const override
{
@@ -249,7 +249,7 @@ SaveLoadTable GetOrderListDescription()
}
struct ORDLChunkHandler : ChunkHandler {
ORDLChunkHandler() : ChunkHandler('ORDL', ChunkType::Table) {}
ORDLChunkHandler() : ChunkHandler("ORDL", ChunkType::Table) {}
void Save() const override
{
@@ -320,7 +320,7 @@ SaveLoadTable GetOrderBackupDescription()
}
struct BKORChunkHandler : ChunkHandler {
BKORChunkHandler() : ChunkHandler('BKOR', ChunkType::Table) {}
BKORChunkHandler() : ChunkHandler("BKOR", ChunkType::Table) {}
void Save() const override
{
+1 -1
View File
@@ -19,7 +19,7 @@ static const SaveLoad _randomizer_desc[] = {
};
struct SRNDChunkHandler : ChunkHandler {
SRNDChunkHandler() : ChunkHandler('SRND', ChunkType::Table)
SRNDChunkHandler() : ChunkHandler("SRND", ChunkType::Table)
{}
void Save() const override
+38 -25
View File
@@ -458,6 +458,17 @@ static inline void SlWriteUint64(uint64_t x)
SlWriteUint32(static_cast<uint32_t>(x));
}
/**
* Read the \c ChunkId.
* @return The read \c ChunkId.
*/
static inline ChunkId SlReadChunkId()
{
ChunkId label{};
for (uint8_t &b : label) b = SlReadByte();
return label;
}
/**
* Read in the header descriptor of an object or an array.
* If the highest bit is set (7), then the index is bigger than 127
@@ -2275,7 +2286,7 @@ static void SlSaveChunk(const ChunkHandler &ch)
{
if (ch.type == ChunkType::ReadOnly) return;
SlWriteUint32(ch.id);
for (uint8_t b : ch.id) SlWriteByte(b);
Debug(sl, 2, "Saving chunk {}", ch.GetName());
_sl.chunk_type = ch.type;
@@ -2323,7 +2334,7 @@ static void SlSaveChunks()
* @param id the chunk in question
* @return returns the appropriate chunkhandler
*/
static const ChunkHandler *SlFindChunkHandler(uint32_t id)
static const ChunkHandler *SlFindChunkHandler(ChunkId id)
{
for (const ChunkHandler &ch : ChunkHandlers()) if (ch.id == id) return &ch;
return nullptr;
@@ -2332,13 +2343,10 @@ static const ChunkHandler *SlFindChunkHandler(uint32_t id)
/** Load all chunks */
static void SlLoadChunks()
{
uint32_t id;
const ChunkHandler *ch;
for (ChunkId id = SlReadChunkId(); !id.Empty(); id = SlReadChunkId()) {
Debug(sl, 2, "Loading chunk {}", id.AsString());
for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
Debug(sl, 2, "Loading chunk {:c}{:c}{:c}{:c}", id >> 24, id >> 16, id >> 8, id);
ch = SlFindChunkHandler(id);
const ChunkHandler *ch = SlFindChunkHandler(id);
if (ch == nullptr) SlErrorCorrupt("Unknown chunk type");
SlLoadChunk(*ch);
}
@@ -2347,13 +2355,10 @@ static void SlLoadChunks()
/** Load all chunks for savegame checking */
static void SlLoadCheckChunks()
{
uint32_t id;
const ChunkHandler *ch;
for (ChunkId id = SlReadChunkId(); id.Empty(); id = SlReadChunkId()) {
Debug(sl, 2, "Loading chunk {}", id.AsString());
for (id = SlReadUint32(); id != 0; id = SlReadUint32()) {
Debug(sl, 2, "Loading chunk {:c}{:c}{:c}{:c}", id >> 24, id >> 16, id >> 8, id);
ch = SlFindChunkHandler(id);
const ChunkHandler *ch = SlFindChunkHandler(id);
if (ch == nullptr) SlErrorCorrupt("Unknown chunk type");
SlLoadCheckChunk(*ch);
}
@@ -2814,23 +2819,26 @@ struct LZMASaveFilter : SaveFilter {
************* END OF CODE *****************
*******************************************/
/** Unique 4-letter tag for the different saveload formats. */
using SaveLoadFormatTag = Label<struct SaveLoadFormatLabelTag>;
/** The format for a reader/writer type of a savegame */
struct SaveLoadFormat {
std::shared_ptr<LoadFilter> (*init_load)(std::shared_ptr<LoadFilter> chain); ///< Constructor for the load filter.
std::shared_ptr<SaveFilter> (*init_write)(std::shared_ptr<SaveFilter> chain, uint8_t compression); ///< Constructor for the save filter.
std::string_view name; ///< name of the compressor/decompressor (debug-only)
uint32_t tag; ///< the 4-letter tag by which it is identified in the savegame
SaveLoadFormatTag tag; ///< the 4-letter tag by which it is identified in the savegame
uint8_t min_compression; ///< the minimum compression level of this format
uint8_t default_compression; ///< the default compression level of this format
uint8_t max_compression; ///< the maximum compression level of this format
};
static const uint32_t SAVEGAME_TAG_LZO = TO_BE32('OTTD');
static const uint32_t SAVEGAME_TAG_NONE = TO_BE32('OTTN');
static const uint32_t SAVEGAME_TAG_ZLIB = TO_BE32('OTTZ');
static const uint32_t SAVEGAME_TAG_LZMA = TO_BE32('OTTX');
static const SaveLoadFormatTag SAVEGAME_TAG_LZO{"OTTD"}; ///< Tag for a game compressed with LZO
static const SaveLoadFormatTag SAVEGAME_TAG_NONE{"OTTN"}; ///< Tag for a game without compression.
static const SaveLoadFormatTag SAVEGAME_TAG_ZLIB{"OTTZ"}; ///< Tag for a game with zlib compression.
static const SaveLoadFormatTag SAVEGAME_TAG_LZMA{"OTTX"}; ///< Tag for a game with lzma compression.
/** The different saveload formats known/understood by OpenTTD. */
static const SaveLoadFormat _saveload_formats[] = {
@@ -3025,8 +3033,10 @@ static SaveLoadResult SaveFileToDisk(bool threaded)
auto [fmt, compression] = GetSavegameFormat(_savegame_format);
/* We have written our stuff to memory, now write it to file! */
uint32_t hdr[2] = { fmt.tag, TO_BE32(to_underlying(SAVEGAME_VERSION) << 16) };
_sl.sf->Write((uint8_t*)hdr, sizeof(hdr));
_sl.sf->Write(fmt.tag.data(), fmt.tag.size());
uint32_t version = TO_BE32(to_underlying(SAVEGAME_VERSION) << 16);
_sl.sf->Write(reinterpret_cast<uint8_t *>(&version), sizeof(version));
_sl.sf = fmt.init_write(_sl.sf, compression);
_sl.dumper->Flush(_sl.sf);
@@ -3126,7 +3136,7 @@ SaveLoadResult SaveWithFilter(std::shared_ptr<SaveFilter> writer, bool threaded)
* @param raw_version The raw version from the savegame header.
* @return The SaveLoadFormat to use for attempting to open the savegame.
*/
static const SaveLoadFormat *DetermineSaveLoadFormat(uint32_t tag, uint32_t raw_version)
static const SaveLoadFormat *DetermineSaveLoadFormat(SaveLoadFormatTag tag, uint32_t raw_version)
{
auto fmt = std::ranges::find(_saveload_formats, tag, &SaveLoadFormat::tag);
if (fmt != std::end(_saveload_formats)) {
@@ -3178,11 +3188,14 @@ static SaveLoadResult DoLoad(std::shared_ptr<LoadFilter> reader, bool load_check
_load_check_data.checkable = true;
}
uint32_t hdr[2];
if (_sl.lf->Read((uint8_t*)hdr, sizeof(hdr)) != sizeof(hdr)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
SaveLoadFormatTag tag{};
if (_sl.lf->Read(tag.data(), tag.size()) != tag.size()) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
uint32_t version;
if (_sl.lf->Read(reinterpret_cast<uint8_t*>(&version), sizeof(version)) != sizeof(version)) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);
/* see if we have any loader for this type. */
const SaveLoadFormat *fmt = DetermineSaveLoadFormat(hdr[0], hdr[1]);
const SaveLoadFormat *fmt = DetermineSaveLoadFormat(tag, version);
/* loader for this savegame type is not implemented? */
if (fmt->init_load == nullptr) {
+17 -8
View File
@@ -11,6 +11,7 @@
#define SAVELOAD_H
#include "saveload_error.hpp"
#include "../core/label_type.hpp"
#include "../fileio_type.h"
#include "../fios.h"
@@ -479,12 +480,20 @@ enum class ChunkType : uint8_t {
ReadOnly, ///< Chunk is never saved.
};
/** Label/unique identifier for each of the chunks in the savegame. */
using ChunkId = Label<struct ChunkIdTag>;;
/** Handlers and description of chunk. */
struct ChunkHandler {
uint32_t id; ///< Unique ID (4 letters).
ChunkType type; ///< Type of the chunk. @see ChunkType
ChunkId id; ///< Unique ID (4 letters).
ChunkType type; ///< Type of the chunk. @see ChunkType
ChunkHandler(uint32_t id, ChunkType type) : id(id), type(type) {}
/**
* Create this ChunkHandler.
* @param id The unique identifier/name of this chunk.
* @param type The type of chunk
*/
ChunkHandler(ChunkId id, ChunkType type) : id(id), type(type) {}
/** Ensure the destructor of the sub classes are called as well. */
virtual ~ChunkHandler() = default;
@@ -516,13 +525,13 @@ struct ChunkHandler {
*/
virtual void LoadCheck(size_t len = 0) const;
/**
* Get the name of this chunk.
* @return The chunks 4 letter name/unique identifier.
*/
std::string GetName() const
{
return std::string()
+ static_cast<char>(this->id >> 24)
+ static_cast<char>(this->id >> 16)
+ static_cast<char>(this->id >> 8)
+ static_cast<char>(this->id);
return this->id.AsString();
}
};
+2 -2
View File
@@ -142,7 +142,7 @@ static void SaveSettings(const SettingTable &settings, void *object)
}
struct OPTSChunkHandler : ChunkHandler {
OPTSChunkHandler() : ChunkHandler('OPTS', ChunkType::ReadOnly) {}
OPTSChunkHandler() : ChunkHandler("OPTS", ChunkType::ReadOnly) {}
void Load() const override
{
@@ -156,7 +156,7 @@ struct OPTSChunkHandler : ChunkHandler {
};
struct PATSChunkHandler : ChunkHandler {
PATSChunkHandler() : ChunkHandler('PATS', ChunkType::Table) {}
PATSChunkHandler() : ChunkHandler("PATS", ChunkType::Table) {}
void Load() const override
{
+1 -1
View File
@@ -32,7 +32,7 @@ static const SaveLoad _sign_desc[] = {
};
struct SIGNChunkHandler : ChunkHandler {
SIGNChunkHandler() : ChunkHandler('SIGN', ChunkType::Table) {}
SIGNChunkHandler() : ChunkHandler("SIGN", ChunkType::Table) {}
void Save() const override
{
+3 -3
View File
@@ -531,7 +531,7 @@ static const SaveLoad _old_station_desc[] = {
};
struct STNSChunkHandler : ChunkHandler {
STNSChunkHandler() : ChunkHandler('STNS', ChunkType::ReadOnly) {}
STNSChunkHandler() : ChunkHandler("STNS", ChunkType::ReadOnly) {}
void Load() const override
{
@@ -722,7 +722,7 @@ static const SaveLoad _station_desc[] = {
};
struct STNNChunkHandler : ChunkHandler {
STNNChunkHandler() : ChunkHandler('STNN', ChunkType::Table) {}
STNNChunkHandler() : ChunkHandler("STNN", ChunkType::Table) {}
void Save() const override
{
@@ -765,7 +765,7 @@ struct STNNChunkHandler : ChunkHandler {
};
struct ROADChunkHandler : ChunkHandler {
ROADChunkHandler() : ChunkHandler('ROAD', ChunkType::Table) {}
ROADChunkHandler() : ChunkHandler("ROAD", ChunkType::Table) {}
void Save() const override
{
+1 -1
View File
@@ -25,7 +25,7 @@ static const SaveLoad _storage_desc[] = {
/** Persistent storage data. */
struct PSACChunkHandler : ChunkHandler {
PSACChunkHandler() : ChunkHandler('PSAC', ChunkType::Table) {}
PSACChunkHandler() : ChunkHandler("PSAC", ChunkType::Table) {}
void Load() const override
{
+2 -2
View File
@@ -39,7 +39,7 @@ static const SaveLoad _story_page_elements_desc[] = {
};
struct STPEChunkHandler : ChunkHandler {
STPEChunkHandler() : ChunkHandler('STPE', ChunkType::Table) {}
STPEChunkHandler() : ChunkHandler("STPE", ChunkType::Table) {}
void Save() const override
{
@@ -81,7 +81,7 @@ static const SaveLoad _story_pages_desc[] = {
};
struct STPAChunkHandler : ChunkHandler {
STPAChunkHandler() : ChunkHandler('STPA', ChunkType::Table) {}
STPAChunkHandler() : ChunkHandler("STPA", ChunkType::Table) {}
void Save() const override
{
+1 -1
View File
@@ -111,7 +111,7 @@ void InitializeOldNames()
}
struct NAMEChunkHandler : ChunkHandler {
NAMEChunkHandler() : ChunkHandler('NAME', ChunkType::ReadOnly) {}
NAMEChunkHandler() : ChunkHandler("NAME", ChunkType::ReadOnly) {}
void Load() const override
{
+1 -1
View File
@@ -30,7 +30,7 @@ static const SaveLoad _subsidies_desc[] = {
};
struct SUBSChunkHandler : ChunkHandler {
SUBSChunkHandler() : ChunkHandler('SUBS', ChunkType::Table) {}
SUBSChunkHandler() : ChunkHandler("SUBS", ChunkType::Table) {}
void Save() const override
{
+2 -2
View File
@@ -370,11 +370,11 @@ static const SaveLoad _town_desc[] = {
};
struct HIDSChunkHandler : NewGRFMappingChunkHandler {
HIDSChunkHandler() : NewGRFMappingChunkHandler('HIDS', _house_mngr) {}
HIDSChunkHandler() : NewGRFMappingChunkHandler("HIDS", _house_mngr) {}
};
struct CITYChunkHandler : ChunkHandler {
CITYChunkHandler() : ChunkHandler('CITY', ChunkType::Table) {}
CITYChunkHandler() : ChunkHandler("CITY", ChunkType::Table) {}
void Save() const override
{
+1 -1
View File
@@ -1114,7 +1114,7 @@ static const SaveLoad _vehicle_desc[] = {
};
struct VEHSChunkHandler : ChunkHandler {
VEHSChunkHandler() : ChunkHandler('VEHS', ChunkType::SparseTable) {}
VEHSChunkHandler() : ChunkHandler("VEHS", ChunkType::SparseTable) {}
void Save() const override
{
+1 -1
View File
@@ -17,7 +17,7 @@ extern void SlSkipArray();
/** Water Region savegame data is no longer used, but still needed for old savegames to load without errors. */
struct WaterRegionChunkHandler : ChunkHandler {
WaterRegionChunkHandler() : ChunkHandler('WRGN', ChunkType::ReadOnly)
WaterRegionChunkHandler() : ChunkHandler("WRGN", ChunkType::ReadOnly)
{}
void Load() const override
+1 -1
View File
@@ -186,7 +186,7 @@ static const SaveLoad _old_waypoint_desc[] = {
};
struct CHKPChunkHandler : ChunkHandler {
CHKPChunkHandler() : ChunkHandler('CHKP', ChunkType::ReadOnly) {}
CHKPChunkHandler() : ChunkHandler("CHKP", ChunkType::ReadOnly) {}
void Load() const override
{
+20 -5
View File
@@ -8,6 +8,7 @@
/** @file soundloader_wav.cpp Loading of wav sounds. */
#include "stdafx.h"
#include "core/label_type.hpp"
#include "core/math_func.hpp"
#include "debug.h"
#include "random_access_file_type.h"
@@ -16,6 +17,20 @@
#include "safeguards.h"
using WavTag = Label<struct WavTagTag>; ///< Label for different tags in the file
/**
* Read a \c WavTag from the file.
* @param file The file to read from.
* @return The read \c WavTag.
*/
WavTag ReadWavTag(RandomAccessFile &file)
{
WavTag tag;
file.ReadBlock(tag.data(), tag.size());
return tag;
}
/** Wav file (RIFF/WAVE) sound loader. */
class SoundLoader_Wav : public SoundLoader {
public:
@@ -28,16 +43,16 @@ public:
RandomAccessFile &file = *sound.file;
/* Check RIFF/WAVE header. */
if (file.ReadDword() != std::byteswap<uint32_t>('RIFF')) return false;
if (ReadWavTag(file) != WavTag{"RIFF"}) return false;
file.ReadDword(); // Skip data size
if (file.ReadDword() != std::byteswap<uint32_t>('WAVE')) return false;
if (ReadWavTag(file) != WavTag{"WAVE"}) return false;
/* Read riff tags */
for (;;) {
uint32_t tag = file.ReadDword();
WavTag tag = ReadWavTag(file);
uint32_t size = file.ReadDword();
if (tag == std::byteswap<uint32_t>('fmt ')) {
if (tag == WavTag{"fmt "}) {
uint16_t format = file.ReadWord();
if (format != 1) {
Debug(grf, 0, "SoundLoader_Wav: Unsupported format {}, expected 1 (uncompressed PCM).", format);
@@ -64,7 +79,7 @@ public:
/* We've read 16 bytes of this chunk, we can skip anything extra. */
size -= 16;
} else if (tag == std::byteswap<uint32_t>('data')) {
} else if (tag == WavTag{"data"}) {
uint align = sound.channels * sound.bits_per_sample / 8;
if (Align(size, align) != size) {
/* Ensure length is aligned correctly for channels and BPS. */