2015-07-21 23:28:53 +00:00
|
|
|
/*
|
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** @file tracerestrict_sl.cpp Code handling saving and loading of trace restrict programs */
|
|
|
|
|
|
|
|
#include "../stdafx.h"
|
|
|
|
#include "../tracerestrict.h"
|
2015-09-02 19:51:30 +00:00
|
|
|
#include "../strings_func.h"
|
|
|
|
#include "../string_func.h"
|
2015-07-21 23:28:53 +00:00
|
|
|
#include "saveload.h"
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
static const SaveLoad _trace_restrict_mapping_desc[] = {
|
|
|
|
SLE_VAR(TraceRestrictMappingItem, program_id, SLE_UINT32),
|
|
|
|
};
|
|
|
|
|
2015-07-27 17:55:57 +00:00
|
|
|
/**
|
|
|
|
* Load mappings
|
|
|
|
*/
|
2015-07-21 23:28:53 +00:00
|
|
|
static void Load_TRRM()
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
while ((index = SlIterateArray()) != -1) {
|
|
|
|
TraceRestrictMappingItem &item = _tracerestrictprogram_mapping[index];
|
|
|
|
SlObject(&item, _trace_restrict_mapping_desc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-27 17:55:57 +00:00
|
|
|
/**
|
|
|
|
* Save mappings
|
|
|
|
*/
|
2015-07-21 23:28:53 +00:00
|
|
|
static void Save_TRRM()
|
|
|
|
{
|
|
|
|
for (TraceRestrictMapping::iterator iter = _tracerestrictprogram_mapping.begin();
|
|
|
|
iter != _tracerestrictprogram_mapping.end(); ++iter) {
|
|
|
|
SlSetArrayIndex(iter->first);
|
|
|
|
SlObject(&(iter->second), _trace_restrict_mapping_desc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-27 17:55:57 +00:00
|
|
|
/** program length save header struct */
|
2015-07-21 23:28:53 +00:00
|
|
|
struct TraceRestrictProgramStub {
|
2024-01-07 16:41:53 +00:00
|
|
|
uint32_t length;
|
2015-07-21 23:28:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const SaveLoad _trace_restrict_program_stub_desc[] = {
|
|
|
|
SLE_VAR(TraceRestrictProgramStub, length, SLE_UINT32),
|
|
|
|
};
|
|
|
|
|
2015-07-27 17:55:57 +00:00
|
|
|
/**
|
|
|
|
* Load program pool
|
|
|
|
*/
|
2015-07-21 23:28:53 +00:00
|
|
|
static void Load_TRRP()
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
TraceRestrictProgramStub stub;
|
|
|
|
while ((index = SlIterateArray()) != -1) {
|
|
|
|
TraceRestrictProgram *prog = new (index) TraceRestrictProgram();
|
|
|
|
SlObject(&stub, _trace_restrict_program_stub_desc);
|
|
|
|
prog->items.resize(stub.length);
|
2021-10-02 15:45:02 +00:00
|
|
|
if (stub.length > 0) SlArray(prog->items.data(), stub.length, SLE_UINT32);
|
2019-12-28 13:06:22 +00:00
|
|
|
if (SlXvIsFeaturePresent(XSLFI_JOKERPP)) {
|
|
|
|
for (size_t i = 0; i < prog->items.size(); i++) {
|
|
|
|
TraceRestrictItem &item = prog->items[i]; // note this is a reference,
|
|
|
|
if (GetTraceRestrictType(item) == 19 || GetTraceRestrictType(item) == 20) {
|
|
|
|
SetTraceRestrictType(item, (TraceRestrictItemType)(GetTraceRestrictType(item) + 2));
|
|
|
|
}
|
|
|
|
if (IsTraceRestrictDoubleItem(item)) i++;
|
|
|
|
}
|
|
|
|
}
|
2024-01-19 21:35:46 +00:00
|
|
|
if (SlXvIsFeatureMissing(XSLFI_TRACE_RESTRICT, 17)) {
|
|
|
|
/* TRIT_SLOT subtype moved from cond op to combined aux and cond op field in version 17.
|
|
|
|
* Do this for all previous versions to avoid cases where it is unexpectedly present despite the version,
|
|
|
|
* e.g. in JokerPP and non-SLXI tracerestrict saves.
|
|
|
|
*/
|
|
|
|
for (size_t i = 0; i < prog->items.size(); i++) {
|
|
|
|
TraceRestrictItem &item = prog->items[i]; // note this is a reference
|
|
|
|
if (GetTraceRestrictType(item) == TRIT_SLOT) {
|
|
|
|
TraceRestrictSlotSubtypeField subtype = static_cast<TraceRestrictSlotSubtypeField>(GetTraceRestrictCondOp(item));
|
2024-01-20 22:49:55 +00:00
|
|
|
if (subtype == 7) {
|
|
|
|
/* Was TRSCOF_ACQUIRE_TRY_ON_RESERVE */
|
|
|
|
subtype = TRSCOF_ACQUIRE_TRY;
|
|
|
|
}
|
2024-01-19 21:35:46 +00:00
|
|
|
SetTraceRestrictCombinedAuxCondOpField(item, subtype);
|
|
|
|
}
|
|
|
|
if (IsTraceRestrictDoubleItem(item)) i++;
|
|
|
|
}
|
|
|
|
}
|
2015-09-02 19:51:30 +00:00
|
|
|
CommandCost validation_result = prog->Validate();
|
|
|
|
if (validation_result.Failed()) {
|
|
|
|
char str[4096];
|
|
|
|
char *strend = str + seprintf(str, lastof(str), "Trace restrict program %d: %s\nProgram dump:",
|
|
|
|
index, GetStringPtr(validation_result.GetErrorMessage()));
|
2023-05-30 22:29:53 +00:00
|
|
|
uint fail_offset = validation_result.HasResultData() ? validation_result.GetResultData() : UINT32_MAX;
|
2023-03-09 03:01:20 +00:00
|
|
|
for (uint i = 0; i < (uint)prog->items.size(); i++) {
|
|
|
|
if ((i % 3) == 0) {
|
|
|
|
strend += seprintf(strend, lastof(str), "\n%4u:", i);
|
2015-09-02 19:51:30 +00:00
|
|
|
}
|
2023-03-09 03:01:20 +00:00
|
|
|
strend += seprintf(strend, lastof(str), (i == fail_offset) ? " [%08X]" : " %08X", prog->items[i]);
|
2015-09-02 19:51:30 +00:00
|
|
|
}
|
|
|
|
SlErrorCorrupt(str);
|
|
|
|
}
|
2015-07-21 23:28:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-27 17:55:57 +00:00
|
|
|
/**
|
|
|
|
* Save a program, used by SlAutolength
|
|
|
|
*/
|
2015-07-21 23:28:53 +00:00
|
|
|
static void RealSave_TRRP(TraceRestrictProgram *prog)
|
|
|
|
{
|
|
|
|
TraceRestrictProgramStub stub;
|
2024-01-07 16:41:53 +00:00
|
|
|
stub.length = (uint32_t)prog->items.size();
|
2015-07-21 23:28:53 +00:00
|
|
|
SlObject(&stub, _trace_restrict_program_stub_desc);
|
2021-10-02 15:45:02 +00:00
|
|
|
SlArray(prog->items.data(), stub.length, SLE_UINT32);
|
2015-07-21 23:28:53 +00:00
|
|
|
}
|
|
|
|
|
2015-07-27 17:55:57 +00:00
|
|
|
/**
|
|
|
|
* Save program pool
|
|
|
|
*/
|
2015-07-21 23:28:53 +00:00
|
|
|
static void Save_TRRP()
|
|
|
|
{
|
2020-01-06 18:45:51 +00:00
|
|
|
for (TraceRestrictProgram *prog : TraceRestrictProgram::Iterate()) {
|
2015-07-21 23:28:53 +00:00
|
|
|
SlSetArrayIndex(prog->index);
|
|
|
|
SlAutolength((AutolengthProc*) RealSave_TRRP, prog);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-30 20:14:14 +00:00
|
|
|
/** program length save header struct */
|
|
|
|
struct TraceRestrictSlotStub {
|
2024-01-07 16:41:53 +00:00
|
|
|
uint32_t length;
|
2017-03-30 20:14:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const SaveLoad _trace_restrict_slot_stub_desc[] = {
|
|
|
|
SLE_VAR(TraceRestrictSlotStub, length, SLE_UINT32),
|
|
|
|
};
|
|
|
|
|
|
|
|
static const SaveLoad _trace_restrict_slot_desc[] = {
|
|
|
|
SLE_VAR(TraceRestrictSlot, max_occupancy, SLE_UINT32),
|
2020-05-21 19:19:57 +00:00
|
|
|
SLE_SSTR(TraceRestrictSlot, name, SLF_ALLOW_CONTROL),
|
2017-03-30 20:14:14 +00:00
|
|
|
SLE_VAR(TraceRestrictSlot, owner, SLE_UINT8),
|
2022-01-18 18:51:24 +00:00
|
|
|
SLE_CONDVAR_X(TraceRestrictSlot, vehicle_type, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TRACE_RESTRICT, 13)),
|
2017-03-30 20:14:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load slot pool
|
|
|
|
*/
|
|
|
|
static void Load_TRRS()
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
TraceRestrictSlotStub stub;
|
|
|
|
while ((index = SlIterateArray()) != -1) {
|
|
|
|
TraceRestrictSlot *slot = new (index) TraceRestrictSlot();
|
|
|
|
SlObject(slot, _trace_restrict_slot_desc);
|
|
|
|
SlObject(&stub, _trace_restrict_slot_stub_desc);
|
|
|
|
slot->occupants.resize(stub.length);
|
2021-10-02 15:45:02 +00:00
|
|
|
if (stub.length) SlArray(slot->occupants.data(), stub.length, SLE_UINT32);
|
2017-03-30 20:14:14 +00:00
|
|
|
}
|
|
|
|
TraceRestrictSlot::RebuildVehicleIndex();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Save a slot, used by SlAutolength
|
|
|
|
*/
|
|
|
|
static void RealSave_TRRS(TraceRestrictSlot *slot)
|
|
|
|
{
|
|
|
|
SlObject(slot, _trace_restrict_slot_desc);
|
|
|
|
TraceRestrictSlotStub stub;
|
2024-01-07 16:41:53 +00:00
|
|
|
stub.length = (uint32_t)slot->occupants.size();
|
2017-03-30 20:14:14 +00:00
|
|
|
SlObject(&stub, _trace_restrict_slot_stub_desc);
|
2021-10-02 15:45:02 +00:00
|
|
|
if (stub.length) SlArray(slot->occupants.data(), stub.length, SLE_UINT32);
|
2017-03-30 20:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Save slot pool
|
|
|
|
*/
|
|
|
|
static void Save_TRRS()
|
|
|
|
{
|
2020-01-06 18:45:51 +00:00
|
|
|
for (TraceRestrictSlot *slot : TraceRestrictSlot::Iterate()) {
|
2017-03-30 20:14:14 +00:00
|
|
|
SlSetArrayIndex(slot->index);
|
|
|
|
SlAutolength((AutolengthProc*) RealSave_TRRS, slot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-31 18:08:35 +00:00
|
|
|
static const SaveLoad _trace_restrict_counter_desc[] = {
|
|
|
|
SLE_VAR(TraceRestrictCounter, value, SLE_INT32),
|
|
|
|
SLE_SSTR(TraceRestrictCounter, name, SLF_ALLOW_CONTROL),
|
|
|
|
SLE_VAR(TraceRestrictCounter, owner, SLE_UINT8),
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load counter pool
|
|
|
|
*/
|
|
|
|
static void Load_TRRC()
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
while ((index = SlIterateArray()) != -1) {
|
|
|
|
TraceRestrictCounter *ctr = new (index) TraceRestrictCounter();
|
|
|
|
SlObject(ctr, _trace_restrict_counter_desc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Save a counter, used by SlAutolength
|
|
|
|
*/
|
|
|
|
static void RealSave_TRRC(TraceRestrictCounter *ctr)
|
|
|
|
{
|
|
|
|
SlObject(ctr, _trace_restrict_counter_desc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Save counter pool
|
|
|
|
*/
|
|
|
|
static void Save_TRRC()
|
|
|
|
{
|
|
|
|
for (TraceRestrictCounter *ctr : TraceRestrictCounter::Iterate()) {
|
|
|
|
SlSetArrayIndex(ctr->index);
|
|
|
|
SlAutolength((AutolengthProc*) RealSave_TRRC, ctr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-27 17:55:57 +00:00
|
|
|
/**
|
|
|
|
* Update program reference counts from just-loaded mapping
|
|
|
|
*/
|
2015-07-21 23:28:53 +00:00
|
|
|
void AfterLoadTraceRestrict()
|
|
|
|
{
|
|
|
|
for (TraceRestrictMapping::iterator iter = _tracerestrictprogram_mapping.begin();
|
|
|
|
iter != _tracerestrictprogram_mapping.end(); ++iter) {
|
2022-06-11 21:15:19 +00:00
|
|
|
_tracerestrictprogram_pool.Get(iter->second.program_id)->IncrementRefCount(iter->first);
|
2015-07-21 23:28:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-25 17:10:15 +00:00
|
|
|
extern const ChunkHandler trace_restrict_chunk_handlers[] = {
|
|
|
|
{ 'TRRM', Save_TRRM, Load_TRRM, nullptr, nullptr, CH_SPARSE_ARRAY }, // Trace Restrict Mapping chunk
|
|
|
|
{ 'TRRP', Save_TRRP, Load_TRRP, nullptr, nullptr, CH_ARRAY }, // Trace Restrict Mapping Program Pool chunk
|
|
|
|
{ 'TRRS', Save_TRRS, Load_TRRS, nullptr, nullptr, CH_ARRAY }, // Trace Restrict Slot Pool chunk
|
|
|
|
{ 'TRRC', Save_TRRC, Load_TRRC, nullptr, nullptr, CH_ARRAY }, // Trace Restrict Counter Pool chunk
|
2015-07-21 23:28:53 +00:00
|
|
|
};
|
2021-10-25 17:10:15 +00:00
|
|
|
|
|
|
|
extern const ChunkHandlerTable _trace_restrict_chunk_handlers(trace_restrict_chunk_handlers);
|