diff --git a/src/lang/extra/english.txt b/src/lang/extra/english.txt index 5e05844bf8..47094daca3 100644 --- a/src/lang/extra/english.txt +++ b/src/lang/extra/english.txt @@ -1297,6 +1297,7 @@ STR_NEWGRF_INSPECT_SPRITE_DUMP_PANEL_TOOLTIP_MARK :{BLACK}Click to STR_NEWGRF_INSPECT_SPRITE_DUMP_PANEL_TOOLTIP_COLLAPSE :{BLACK}Shift+Click to collapse sprite group STR_NEWGRF_INSPECT_SPRITE_DUMP_PANEL_TOOLTIP_HIGHLIGHT_TEMP :{BLACK}Ctrl+Click to highlight temporary storage register STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_SIGNALS :Signals +STR_NEWGRF_INSPECT_CAPTION_TRACERESTRICT :Routing restriction program at {HEX}/{HEX} STR_NEWGRF_ERROR_UNIMPLEMETED_MAPPED_FEATURE_ID :Unimplemented remapped feature ID: name: {2:RAW_STRING}, mapped to: {5:HEX} (sprite {3:NUM}) STR_NEWGRF_ERROR_UNIMPLEMETED_MAPPED_PROPERTY :Unimplemented remapped Action 0 property feature: {4:HEX}, name: {2:RAW_STRING}, mapped to: {5:HEX} (sprite {3:NUM}) STR_NEWGRF_ERROR_UNIMPLEMETED_MAPPED_ACTION5_TYPE :Unimplemented remapped Action 5 type: name: {2:RAW_STRING}, mapped to: {4:HEX} (sprite {3:NUM}) diff --git a/src/newgrf.h b/src/newgrf.h index a7b8471c28..868830f359 100644 --- a/src/newgrf.h +++ b/src/newgrf.h @@ -97,6 +97,7 @@ enum GrfSpecFeature : uint8 { GSF_REAL_FEATURE_END = GSF_NEWLANDSCAPE, GSF_FAKE_STATION_STRUCT = GSF_END, ///< Fake station struct GrfSpecFeature for NewGRF debugging + GSF_FAKE_TRACERESTRICT, ///< Fake routing restriction GrfSpecFeature for debugging GSF_FAKE_END, ///< End of the fake features GSF_ERROR_ON_USE = 0xFE, ///< An invalid value which generates an immediate error on mapping diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index 807958052b..4e3922073b 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -26,6 +26,7 @@ #include "../clear_map.h" #include "../tunnelbridge.h" #include "../train_speed_adaptation.h" +#include "../tracerestrict.h" /* Helper for filling property tables */ #define NIP(prop, base, variable, type, name) { name, (ptrdiff_t)cpp_offsetof(base, variable), cpp_sizeof(base, variable), prop, type } @@ -2127,6 +2128,108 @@ static const NIFeature _nif_station_struct = { new NIHStationStruct(), }; +class NIHTraceRestrict : public NIHelper { + bool IsInspectable(uint index) const override { return true; } + bool ShowExtraInfoOnly(uint index) const override { return true; } + uint GetParent(uint index) const override { return UINT32_MAX; } + const void *GetInstance(uint index)const override { return nullptr; } + const void *GetSpec(uint index) const override { return nullptr; } + + void SetStringParameters(uint index) const override + { + SetDParam(0, STR_NEWGRF_INSPECT_CAPTION_TRACERESTRICT); + SetDParam(1, GetTraceRestrictRefIdTileIndex(static_cast(index))); + SetDParam(2, GetTraceRestrictRefIdTrack(static_cast(index))); + } + + uint32 GetGRFID(uint index) const override { return 0; } + + uint Resolve(uint index, uint var, uint param, GetVariableExtra *extra) const override + { + return 0; + } + + void ExtraInfo(uint index, NIExtraInfoOutput &output) const override + { + TraceRestrictRefId ref = static_cast(index); + const TraceRestrictProgram *prog = GetTraceRestrictProgram(ref, false); + + if (prog == nullptr) { + output.print("No program"); + return; + } + + char buffer[1024]; + seprintf(buffer, lastof(buffer), "Index: %u", prog->index); + output.print(buffer); + output.print(""); + + seprintf(buffer, lastof(buffer), "Actions used: 0x%X", prog->actions_used_flags); + output.print(buffer); + auto check_action = [&](TraceRestrictProgramActionsUsedFlags flag, const char *label) { + if (prog->actions_used_flags & flag) { + seprintf(buffer, lastof(buffer), " %s", label); + output.print(buffer); + } + }; +#define CA(f) check_action(TRPAUF_##f, #f); + CA(PF) + CA(RESERVE_THROUGH) + CA(LONG_RESERVE) + CA(WAIT_AT_PBS) + CA(SLOT_ACQUIRE) + CA(SLOT_RELEASE_BACK) + CA(SLOT_RELEASE_FRONT) + CA(PBS_RES_END_WAIT) + CA(PBS_RES_END_SLOT) + CA(REVERSE) + CA(SPEED_RESTRICTION) + CA(TRAIN_NOT_STUCK) + CA(CHANGE_COUNTER) + CA(NO_PBS_BACK_PENALTY) + CA(SLOT_ACQUIRE_ON_RES) + CA(SPEED_ADAPTATION) + CA(PBS_RES_END_SIMULATE) + CA(RESERVE_THROUGH_ALWAYS) + CA(CMB_SIGNAL_MODE_CTRL) + CA(ORDER_CONDITIONALS) +#undef CA + output.print(""); + + seprintf(buffer, lastof(buffer), "Ref count: %u", prog->refcount); + output.print(buffer); + const TraceRestrictRefId *refs = prog->GetRefIdsPtr(); + for (uint32 i = 0; i < prog->refcount; i++) { + TileIndex tile = GetTraceRestrictRefIdTileIndex(refs[i]); + seprintf(buffer, lastof(buffer), " %X x %X, track: %X", TileX(tile), TileY(tile), GetTraceRestrictRefIdTrack(refs[i])); + output.print(buffer); + } + output.print(""); + + seprintf(buffer, lastof(buffer), "Program: items: %u, instructions: %u", (uint)prog->items.size(), (uint)prog->GetInstructionCount()); + output.print(buffer); + auto iter = prog->items.begin(); + auto end = prog->items.end(); + while (iter != end) { + if (IsTraceRestrictDoubleItem(*iter)) { + seprintf(buffer, lastof(buffer), " %08X %08X", *iter, *(iter + 1)); + iter += 2; + } else { + seprintf(buffer, lastof(buffer), " %08X", *iter); + ++iter; + } + output.print(buffer); + } + } +}; + +static const NIFeature _nif_tracerestrict = { + nullptr, + nullptr, + nullptr, + new NIHTraceRestrict(), +}; + /*** NewGRF road types ***/ static const NIVariable _niv_roadtypes[] = { @@ -2418,5 +2521,6 @@ static const NIFeature * const _nifeatures[] = { &_nif_newlandscape, // GSF_NEWLANDSCAPE &_nif_town, // GSF_FAKE_TOWNS &_nif_station_struct, // GSF_FAKE_STATION_STRUCT + &_nif_tracerestrict, // GSF_FAKE_TRACERESTRICT }; static_assert(lengthof(_nifeatures) == GSF_FAKE_END); diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 257adf3e41..6a166b6d51 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -47,6 +47,7 @@ #include "infrastructure_func.h" #include "zoom_func.h" #include "group_gui_list.h" +#include "newgrf_debug.h" #include "core/span_type.hpp" #include "3rdparty/cpp-btree/btree_map.h" @@ -2756,6 +2757,16 @@ public: return ES_NOT_HANDLED; } + bool IsNewGRFInspectable() const override + { + return true; + } + + void ShowNewGRFInspectWindow() const override + { + ::ShowNewGRFInspectWindow(GSF_FAKE_TRACERESTRICT, MakeTraceRestrictRefId(this->tile, this->track)); + } + private: /** * Helper function to make start and end instructions (these are not stored in the actual program) @@ -3519,6 +3530,7 @@ static const NWidgetPart _nested_program_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, TR_WIDGET_CAPTION), SetDataTip(STR_TRACE_RESTRICT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), + NWidget(WWT_DEBUGBOX, COLOUR_GREY), NWidget(WWT_IMGBTN, COLOUR_GREY, TR_WIDGET_HIGHLIGHT), SetMinimalSize(12, 12), SetDataTip(SPR_SHARED_ORDERS_ICON, STR_TRACE_RESTRICT_HIGHLIGHT_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_GREY), NWidget(WWT_STICKYBOX, COLOUR_GREY),