diff --git a/src/saveload/tracerestrict_sl.cpp b/src/saveload/tracerestrict_sl.cpp index 93d43cf3ea..8e983a78b3 100644 --- a/src/saveload/tracerestrict_sl.cpp +++ b/src/saveload/tracerestrict_sl.cpp @@ -11,9 +11,10 @@ #include "../stdafx.h" #include "../tracerestrict.h" +#include "../strings_func.h" +#include "../string_func.h" #include "saveload.h" #include -#include "saveload.h" static const SaveLoad _trace_restrict_mapping_desc[] = { SLE_VAR(TraceRestrictMappingItem, program_id, SLE_UINT32), @@ -66,7 +67,20 @@ static void Load_TRRP() SlObject(&stub, _trace_restrict_program_stub_desc); prog->items.resize(stub.length); SlArray(&(prog->items[0]), stub.length, SLE_UINT32); - assert(prog->Validate().Succeeded()); + 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())); + for (unsigned int i = 0; i < prog->items.size(); i++) { + if (i % 3) { + strend += seprintf(strend, lastof(str), " %08X", prog->items[i]); + } else { + strend += seprintf(strend, lastof(str), "\n%4u: %08X", i, prog->items[i]); + } + } + SlErrorCorrupt(str); + } } } diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 85c0fd0631..c69da07ce8 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -414,7 +414,7 @@ void TraceRestrictProgram::DecrementRefCount() { * Validate a instruction list * Returns successful result if program seems OK * This only validates that conditional nesting is correct, - * and that all non-conditionals have a known type, at present + * and that all instructions have a known type, at present */ CommandCost TraceRestrictProgram::Validate(const std::vector &items, TraceRestrictProgramActionsUsedFlags &actions_used_flags) { // static to avoid needing to re-alloc/resize on each execution @@ -464,6 +464,23 @@ CommandCost TraceRestrictProgram::Validate(const std::vector } HandleCondition(condstack, condflags, true); } + + switch (GetTraceRestrictType(item)) { + case TRIT_COND_ENDIF: + case TRIT_COND_UNDEFINED: + case TRIT_COND_TRAIN_LENGTH: + case TRIT_COND_MAX_SPEED: + case TRIT_COND_CURRENT_ORDER: + case TRIT_COND_NEXT_ORDER: + case TRIT_COND_LAST_STATION: + case TRIT_COND_CARGO: + case TRIT_COND_ENTRY_DIRECTION: + case TRIT_COND_PBS_ENTRY_SIGNAL: + break; + + default: + return_cmd_error(STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION); + } } else { switch (GetTraceRestrictType(item)) { case TRIT_PF_DENY: