<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://openloco.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://openloco.io/" rel="alternate" type="text/html" /><updated>2026-07-27T21:09:04+00:00</updated><id>https://openloco.io/feed.xml</id><title type="html">OpenLoco</title><subtitle>An open source re-implementation of Chris Sawyer&apos;s Locomotion</subtitle><entry><title type="html">OpenLoco version 26.07.1</title><link href="https://openloco.io/news/2026/07/openloco-v26.07.1.html" rel="alternate" type="text/html" title="OpenLoco version 26.07.1" /><published>2026-07-27T18:30:00+00:00</published><updated>2026-07-27T18:30:00+00:00</updated><id>https://openloco.io/news/2026/07/openloco-v26.07.1</id><content type="html" xml:base="https://openloco.io/news/2026/07/openloco-v26.07.1.html"><![CDATA[<p>OpenLoco v26.07.1 is out! Only one day after v26.07, unfortunately. We’re patching a few bugs in this one!</p>

<p>Please find the <a href="https://openloco.io/download/">download</a> on our website, or read the
<a href="https://github.com/OpenLoco/OpenLoco/blob/v26.07.1/CHANGELOG.md">changelog</a> on GitHub.</p>

<h2 id="fixed-initial-game-setup">Fixed initial game setup</h2>

<p>You may have read in <a href="https://openloco.io/news/2026/07/openloco-v26.07.html">yesterday’s announcement</a>
that we reworked the game initialisation functions. This was all fine and good, <em>unless</em> you had
no game config yet, e.g. when you had never played the game before on your machine. In that case,
we normally show a popup asking you where <em>Locomotion</em> has been installed, leading you into a file browser
where you can select the right folder. It was that last part that broke. Oops! It’s fixed now,
thanks to @ZehMatt! <a href="https://github.com/OpenLoco/OpenLoco/pull/3844">(#3844)</a></p>

<h2 id="raise-the-limit-of-audio-sources-fix-the-lag-when-the-limit-is-reached">Raise the limit of audio sources, fix the lag when the limit is reached</h2>

<p>@LeftOfZen noticed extreme lag on large maps with many vehicles. It turned out that in this edge case
the game quickly reaches the limit for the engine, OpenAL. By default, it can handle 256 sources at once,
after which you’re not supposed to add more. Well, we continued adding more anyway, triggering (invisible)
errors and therefore lag.</p>

<p>Fixing the matter, @ZehMatt increased the limit to 1024 sources, and made sure we now actually <em>stop</em>
adding more audio sources once the limit has been reached. <a href="https://github.com/OpenLoco/OpenLoco/pull/3841">(#3841)</a></p>

<h2 id="jittery-object-grid-scrollviews-part-2">Jittery ‘object grid’ scrollviews, part 2</h2>

<p>Yesterday, we declared victory on the jitter issue with scrollviews for object selection
(industries, town buildings, trees, walls). Unfortunately, we spoke too soon. One line was accidentally
dropped from the patch, leading to the issue not being resolved, after all.</p>

<p>Well, in the pursuit of what that line had been, we ended up fixing another edge case where the
scrollbar ‘thumb’ was not being resized when it needed to be. In the end, these scrollviews are now
even better than they were. A silver lining, right? <a href="https://github.com/OpenLoco/OpenLoco/pull/3840">(#3840)</a></p>

<h2 id="can-click-beyond-end-of-list-in-company-liststation-listmusic-selection-windows">Can click beyond end of list in company list/station list/music selection windows</h2>

<p>An off-by-one in the company list, station list, and music selection windows meant that you could select an
empty ‘item’ beyond the end of the actual list, leading to an invalid action being performed
(e.g. opening a window to a non-existing company or station). Not good! Thankfully, this one was an easy fix.
<a href="https://github.com/OpenLoco/OpenLoco/pull/3847">(#3847)</a></p>]]></content><author><name>Aaron van Geffen</name></author><category term="news" /><summary type="html"><![CDATA[OpenLoco v26.07.1 is out! Only one day after v26.07, unfortunately. We’re patching a few bugs in this one!]]></summary></entry><entry><title type="html">OpenLoco version 26.07</title><link href="https://openloco.io/news/2026/07/openloco-v26.07.html" rel="alternate" type="text/html" title="OpenLoco version 26.07" /><published>2026-07-26T07:00:00+00:00</published><updated>2026-07-26T07:00:00+00:00</updated><id>https://openloco.io/news/2026/07/openloco-v26.07</id><content type="html" xml:base="https://openloco.io/news/2026/07/openloco-v26.07.html"><![CDATA[<p>OpenLoco v26.07 is out! This month’s release incorporates changes made both this month and last as 
we didn’t have enough to put into a dedicated 26.06 release. As such, we’ve got some quality-of-life 
additions to UI, bug fixes for window and chart rendering, plenty of under-the-hood engine work, 
improvements to the codebase itself in terms of cleanliness and maintainability, updated translations, 
and plenty of shiny new OpenGraphics objects!</p>

<h2 id="extra-zoom-levels">Extra zoom levels</h2>

<p>Sneaking in at the very last minute, @ZehMatt dropped us all an epic feature - extra zoom levels! Now 
there are 2 additional zoom levels allowing you to zoom in 2x and 4x further respectively. This is 
a huge improvement that we are sure everyone will love!</p>

<figure class="third ">
  
    
      <a href="/assets/img/26.07/old_zoom.png" title="Old maximum zoom level">
          <img src="/assets/img/26.07/old_zoom.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/2x_zoom.png" title="New 2x zoom in">
          <img src="/assets/img/26.07/2x_zoom.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/4x_zoom.png" title="New 4x zoom in">
          <img src="/assets/img/26.07/4x_zoom.png" alt="" />
      </a>
    
  
  
</figure>

<h2 id="cargo-statistics">Cargo statistics</h2>

<p>@spacek531 added some useful cargo statistics display to the towns and industries windows, giving the 
player more info about what is happening in the game.</p>

<figure class="third ">
  
    
      <a href="/assets/img/26.07/cargo_industry_stats.png" title="Industry cargo stats">
          <img src="/assets/img/26.07/cargo_industry_stats.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/cargo_town_stats_1.png" title="Towns now display if they have any transport companies nearby">
          <img src="/assets/img/26.07/cargo_town_stats_1.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/cargo_town_stats_2.png" title="Towns now also display the cargo statistics for the last month">
          <img src="/assets/img/26.07/cargo_town_stats_2.png" alt="" />
      </a>
    
  
  
</figure>

<h2 id="jukebox-and-music">Jukebox and music</h2>

<p>@LeeSpork made some improvements to the UI for music options, adding extra options to the Audio 
settings and allowing it to open the jukebox without having to start/load a game. They also fixed 
a bug with the jukebox window not invalidating after unchecking “Play music” from the main toolbar.</p>

<p><img src="/assets/img/26.07/audio_settings.png" alt="New audio options screen" /></p>

<h2 id="home-button-in-file-browser">Home button in file browser</h2>

<p>@LeeSpork added a welcome UI improvement; a button in the file browser dialogue to allow the user to 
return to the ‘home’ folder for your locomotion files, ensuring you can always get back to the default 
save folder, no matter where you’ve ended up.</p>

<p><img src="/assets/img/26.07/home_button.png" alt="New file browser home button" /></p>

<h2 id="string-formatting-fixes-and-spelling-updates">String formatting fixes and spelling updates</h2>

<p>Grammar and spelling aficionados, rejoice! @LeftofZen and @AaronVanGeffen added some improvements and 
fixes to string formatting and English translations. Amongst other things, no longer to en-GB users have 
to see ‘z’ in half their words, and no longer do en-US users need to see <code class="language-plaintext highlighter-rouge">annexe</code>.</p>

<p>One of the longest-standing spelling mistakes, and indeed a vanilla spelling mistake, is the in-game 
track <code class="language-plaintext highlighter-rouge">A Traveller's Serenade</code>, which was spelt incorrectly as <code class="language-plaintext highlighter-rouge">seranade</code>. No longer!</p>

<h2 id="bug-fixes--stability">Bug Fixes &amp; Stability</h2>

<p>A large number of visual and gameplay bugs have been resolved. @AaronVanGeffen solved the long-standing 
issue of jittering in scrollviews in the terraform, town list and industry list windows. He also fixed 
an issue with the population chart overflowing and thus rendering as a visual glitch, and to top it off 
he also fixed a bug preventing windows from showing their resize handles.</p>

<p>Additionally, @duncanspumpkin fixed an issue with the data path when starting the game from command line.</p>

<h2 id="keybindingshortcut-improvements">Keybinding/Shortcut improvements</h2>

<p>@ZehMatt added multiple improvements to shortcuts/keybinds, including a very neat keybinding previewer:</p>

<p><img src="/assets/img/26.07/shortcut_improvements.gif" alt="Keybinding visualiser" /></p>

<h2 id="performance-and-engine-optimisation">Performance and Engine Optimisation</h2>

<p>Under the hood we have some noticeable performance gains, particularly in loop-heavy operations. 
@ZehMatt optimised the code for yearly update cycles, improved tile element iterators, refactored 
how the tile elements are stored, refactored the startup process of the game to separate out 
CLI logic from the rest of the game logic, and improved the widget system allowing easier future 
improvements, expansion and safety.</p>

<p>@LeeSpork refactored some window events and @AaronVanGeffen improved how custom mouse cursors are 
stored, as well as a bug being fixed by @LeftofZen around those custom cursors not being rendered 
properly.</p>

<h2 id="codebase-cleanup--refactoring">Codebase Cleanup &amp; Refactoring</h2>

<p>The codebase itself received a lot of attention and refactoring to improve development ease and compile 
times. @spacek531 and @LeftofZen continued the long project of providing human-readable names for 
previously-unknown variables in the code base, stemming from the reverse-engineering efforts. 
@AaronVanGeffen and @duncanspumpkin improved null pointer checking, which should hopefully result 
in less crashes. Transitive header dependencies in the codebase were improved by @AaronVanGeffen and 
@LeftofZen, and @ZehMatt improved the Visual Studio CI/CD setup to handle VS 2026. @duncanspumpkin 
improved the code surrounding how tree removal is handled, and last but not least, new contributor 
@killerdevildog added some useful helper functions around iterating over in-game objects, something 
which is done frequently.</p>

<h2 id="opengraphics">OpenGraphics</h2>

<p>Over the last 2 months we have had an enormous number of contributions from @shusaura85 and 
@phosphorus551. We also fixed some issues with some very old PRs, so we were able to merge some 
vehicles from @glenjimen as well. We are now up to a total of 150 OG objects, bringing us over 25% 
mark of vanilla’s 545 objects! Additionally, a number of vehicles were updated with new stats in 
anticipation of a rebalanced US vehicle set.</p>

<h3 id="vehicles">Vehicles</h3>

<h4 id="trains">Trains</h4>

<p>@phosphorus551 added no less than <em>19</em> trains since the last OG update, and @glenjimen contributed 
3 himself:</p>

<figure class="third ">
  
    
      <a href="/assets/img/26.07/OG_656.png" title="OG_656">
          <img src="/assets/img/26.07/OG_656.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_BALDWIN1.png" title="OG_BALDWIN1">
          <img src="/assets/img/26.07/OG_BALDWIN1.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_C33.png" title="OG_C33">
          <img src="/assets/img/26.07/OG_C33.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_CL67.png" title="OG_CL67">
          <img src="/assets/img/26.07/OG_CL67.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_DEH46.png" title="OG_DEH46">
          <img src="/assets/img/26.07/OG_DEH46.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_EB35.png" title="OG_EB35">
          <img src="/assets/img/26.07/OG_EB35.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_GE66.png" title="OG_GE66">
          <img src="/assets/img/26.07/OG_GE66.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_GE442.png" title="OG_GE442">
          <img src="/assets/img/26.07/OG_GE442.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_GE443.png" title="OG_GE443">
          <img src="/assets/img/26.07/OG_GE443.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_HG23.png" title="OG_HG23">
          <img src="/assets/img/26.07/OG_HG23.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_HGE44.png" title="OG_HGE44">
          <img src="/assets/img/26.07/OG_HGE44.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_HGE442.png" title="OG_HGE442">
          <img src="/assets/img/26.07/OG_HGE442.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_SPECIAL.png" title="OG_SPECIAL">
          <img src="/assets/img/26.07/OG_SPECIAL.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_USPACIF.png" title="OG_USPACIF">
          <img src="/assets/img/26.07/OG_USPACIF.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_GOODSN1.png" title="OG_GOODSN1">
          <img src="/assets/img/26.07/OG_GOODSN1.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_HOPPER.png" title="OG_GOODSN1">
          <img src="/assets/img/26.07/OG_HOPPER.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_HOPPER2.png" title="OG_GOODSN1">
          <img src="/assets/img/26.07/OG_HOPPER2.png" alt="" />
      </a>
    
  
  
</figure>

<h4 id="trams">Trams</h4>

<p>@phosphorus551 added all of the tram replacements; pictured in order: <code class="language-plaintext highlighter-rouge">OG_TRAM1</code>, <code class="language-plaintext highlighter-rouge">OG_TRAM2</code>, <code class="language-plaintext highlighter-rouge">OG_TRAM3</code>, 
<code class="language-plaintext highlighter-rouge">OG_TRAM4</code>, and <code class="language-plaintext highlighter-rouge">OG_TRAMCOMB</code>:</p>

<figure class="third ">
  
    
      <a href="/assets/img/26.07/OG_TRAM1.png" title="OG_TRAM1">
          <img src="/assets/img/26.07/OG_TRAM1.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_TRAM2.png" title="OG_TRAM2">
          <img src="/assets/img/26.07/OG_TRAM2.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_TRAM3.png" title="OG_TRAM3">
          <img src="/assets/img/26.07/OG_TRAM3.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_TRAM4.png" title="OG_TRAM4">
          <img src="/assets/img/26.07/OG_TRAM4.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_TRAMCOMB.png" title="OG_TRAMCOMB">
          <img src="/assets/img/26.07/OG_TRAMCOMB.png" alt="" />
      </a>
    
  
  
</figure>

<h3 id="town-names">Town Names</h3>

<p>@shusaura85 implemented all of the town names replacements.</p>

<table>
  <thead>
    <tr>
      <th>Object name</th>
      <th>Name style</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">OG_ATOWNNAM</code></td>
      <td>American names</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">OG_ETOWNNAM</code></td>
      <td>English names</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">OG_FTOWNNAM</code></td>
      <td>French names</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">OG_LTOWNNAM</code></td>
      <td>Latin-American/Spanish names</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">OG_STOWNNAM</code></td>
      <td>Silly names</td>
    </tr>
  </tbody>
</table>

<p>Here is a selection of names that you could see in-game if you use “silly” town names from <code class="language-plaintext highlighter-rouge">OG_STOWNNAM</code>:
<img src="/assets/img/26.07/OG_STOWNNAM.png" alt="OG_STOWNNAM" /></p>

<h3 id="roads-tracks-bridges">Roads, Tracks, Bridges</h3>

<p>@shusaura85 added <code class="language-plaintext highlighter-rouge">OG_BRDGSUSP</code>, aka the suspension bridge, as well as both US roads (<code class="language-plaintext highlighter-rouge">OG_ROADUS1</code>, 
and <code class="language-plaintext highlighter-rouge">OG_ROADUS1</code>). Finally, @phosphorus551 recreated the standard-gauge track object, <code class="language-plaintext highlighter-rouge">OG_TRACKST</code>.</p>

<figure class="third ">
  
    
      <a href="/assets/img/26.07/OG_BRDGSUSP.png" title="Suspension bridge (OG_BRDGESUSP)">
          <img src="/assets/img/26.07/OG_BRDGSUSP.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_ROADUS1.png" title="US Road 1 (OG_ROADUS1)">
          <img src="/assets/img/26.07/OG_ROADUS1.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_ROADUS2.png" title="US Road 2 (OG_ROADUS2)">
          <img src="/assets/img/26.07/OG_ROADUS2.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/26.07/OG_TRACKST.png" title="Standard gauge track (OG_TRACKST)">
          <img src="/assets/img/26.07/OG_TRACKST.png" alt="" />
      </a>
    
  
  
</figure>]]></content><author><name>Benjamin Sutas</name></author><category term="news" /><summary type="html"><![CDATA[OpenLoco v26.07 is out! This month’s release incorporates changes made both this month and last as we didn’t have enough to put into a dedicated 26.06 release. As such, we’ve got some quality-of-life additions to UI, bug fixes for window and chart rendering, plenty of under-the-hood engine work, improvements to the codebase itself in terms of cleanliness and maintainability, updated translations, and plenty of shiny new OpenGraphics objects!]]></summary></entry><entry><title type="html">OpenLoco version 26.05</title><link href="https://openloco.io/news/2026/05/openloco-v26.05.html" rel="alternate" type="text/html" title="OpenLoco version 26.05" /><published>2026-05-30T08:00:00+00:00</published><updated>2026-05-30T08:00:00+00:00</updated><id>https://openloco.io/news/2026/05/openloco-v26.05</id><content type="html" xml:base="https://openloco.io/news/2026/05/openloco-v26.05.html"><![CDATA[<p>OpenLoco v26.05 is out! This month’s release focuses primarily on some quality-of-life UI changes,
while also addressing some annoying bugs and paving the way for a better codebase.</p>

<h2 id="making-cargo-more-intuitive">Making cargo more intuitive</h2>

<p>To indicate what cargo is produced by industries and what cargo passes through stations, Locomotion
uses small icons in various places. This makes sense when you consider the game originally had to
run on displays with resolutions of 640×480 or 800×600. While experienced players have likely memorised
the meaning of all these icons, they do make it quite hard for new players to pick things up.
Well, nowadays we can afford to use up a bit more space, right?</p>

<p>This month, we’ve reworked the station construction tab to list cargo produced and accepted by
a new station in full, with a label next to the icons
(<a href="https://github.com/OpenLoco/OpenLoco/pull/3734">#3734</a>).</p>

<p>Before:</p>

<p><img src="/assets/img/26.05/construct_cargo_before.png" alt="Station construction, before" /></p>

<p>After:</p>

<p><img src="/assets/img/26.05/construct_cargo_after.png" alt="Station construction, after" /></p>

<p>We’ve also added tooltips to the cargo icons in the station window, so you can still quickly look up
what an icon means without having to check the construction window again
(<a href="https://github.com/OpenLoco/OpenLoco/pull/3735">#3735</a>).</p>

<p><img src="/assets/img/26.05/station_window_cargo.png" alt="Station construction, after" /></p>

<h2 id="increase-dimensions-of-build-vehicle-window">Increase dimensions of Build Vehicle window</h2>

<p>Last month, we introduced <a href="/news/2026/04/openloco-v26.04.html#add-more-sorting-options-when-building-vehicles">new sorting options</a>
for the Build Vehicle window. Thinking the sort options weren’t that easy to discover, and the window
felt a little cramped anyway, @AaronVanGeffen set out to improve the window further. The sort options
have been moved into a dropdown of their own, and the window has been made a little larger by default
<a href="https://github.com/OpenLoco/OpenLoco/pull/3710">(#3710)</a>.</p>

<p>Before:</p>

<p><img src="/assets/img/26.05/build_vehicle_before.png" alt="Build Vehicle window, before" /></p>

<p>After:</p>

<p><img src="/assets/img/26.05/build_vehicle_after.png" alt="Build Vehicle window, after" /></p>

<h2 id="fix-item-removal-in-various-list-windows">Fix item removal in various list windows</h2>

<p>We also changed the way <a href="/news/2026/04/openloco-v26.04.html#refactor-list-windows-to-use-faster-sorting-algorithm">list windows work</a>
last month. While our tests looked very promising, there was one thing we did not properly test:
item removal. Suppose you deleted a vehicle while the vehicle list was open? Yeah, the game would crash.
Oops. The same thing happened with the other list windows: stations, towns, industries, and companies.
We’ve reworked the way items are removed (<a href="https://github.com/OpenLoco/OpenLoco/pull/3727">#3727</a>),
so this shouldn’t bug us again.</p>

<p>Our rework presented another edge case when regenerating the landscape in the scenario editor.
If you happened to have the town or industry list windows open, their lists would not fully refresh.
Suppose you regenerated with more or fewer towns or indeed industries, the list would refresh,
but not repopulate. This meant entries would potentially be missing — or lead to invalid entries.
We’ve added a hard refresh to both windows for this particular situation
(<a href="https://github.com/OpenLoco/OpenLoco/pull/3733">#3733</a>).</p>

<h2 id="fix-save-state-not-being-deterministic-without-auto-save">Fix save state not being deterministic without auto save</h2>

<p>Something that puzzled us in the past, but ultimately forgot about, was that save games would
not give the exact same result <em>on disk</em> unless autosaves had been enabled. Our replay checks always
used autosaves, though, so surely there couldn’t be a big problem?</p>

<p>Aiming for a perfectly deterministic simulation, @ZehMatt investigated the matter once more.
He found the whole reason it was not deterministic to be that there was lingering game state for stations.
When autosaves were enabled, it would zero some fields out every time an autosave was performed.
In particular, this also impacted how cargo stats were calculated, since it used the <em>old</em> data,
which also influenced the pseudo-random number generator (prng).</p>

<p>We have changed the station manager to now explicitly zero-initialise the remaining fields
when allocating a new station (<a href="https://github.com/OpenLoco/OpenLoco/pull/3737">#3737</a>).
With that, the game now always outputs binary identical files, and the determinism bug is gone.</p>

<h2 id="separate-openloco-into-a-library-and-app">Separate OpenLoco into a library and app</h2>

<p>When we revamped our CMake config <a href="/news/2022/11/openloco-v22.11.html#project-layout-change-cmake-1686">a few years ago</a>,
we set out to modularise our codebase to make it easier to create smaller, testable targets.
This was successful to a degree, but mostly for particular data structures and utility functions.
The majority of the actual game code was still not explicitly covered by tests, save for replay tests
covering parts of the simulation. Splitting it up further would be a monumental task, surely…</p>

<p>Cue @ZehMatt. Eager to expand test coverage to include tile element management at least,
he split up the source tree to distinguish an OpenLoco <em>library</em> from the actual game. This, then,
would allow targeting particular functions without actually running the full game.</p>

<p>As of <a href="https://github.com/OpenLoco/OpenLoco/pull/3742">#3742</a>, this became a reality!
Many files were moved around to realise this! We now build the source tree as a library,
with the main game executable using (linking) this library.</p>

<h2 id="allow-setting-preferred-company-name">Allow setting preferred company name</h2>

<p>OpenLoco has allowed players to set up preferred company ‘owner’ names and faces for a while,
but for in-game companies, we’ve been stuck with ‘Name Transport’ still… until now!
In <a href="https://github.com/OpenLoco/OpenLoco/pull/3720">#3720</a>, new contributor @Llammissar
added an exta option to let players set custom <em>company names</em> as well! Neat.</p>

<p><img src="/assets/img/26.05/custom_company_name.jpg" alt="Custom company names" /></p>]]></content><author><name>Aaron van Geffen</name></author><category term="news" /><summary type="html"><![CDATA[OpenLoco v26.05 is out! This month’s release focuses primarily on some quality-of-life UI changes, while also addressing some annoying bugs and paving the way for a better codebase.]]></summary></entry><entry><title type="html">OpenLoco version 26.04</title><link href="https://openloco.io/news/2026/04/openloco-v26.04.html" rel="alternate" type="text/html" title="OpenLoco version 26.04" /><published>2026-04-29T21:30:00+00:00</published><updated>2026-04-29T21:30:00+00:00</updated><id>https://openloco.io/news/2026/04/openloco-v26.04</id><content type="html" xml:base="https://openloco.io/news/2026/04/openloco-v26.04.html"><![CDATA[<p>OpenLoco v26.04 is out! This month’s release introduces the first version of a new feature that has
been in the works for a few months: blueprints! Moreover, we have a bunch of bugfixes and improvements
lined up. Please read on for the details.</p>

<h2 id="start-copypaste-implementation-for-blueprints">Start copy/paste implementation for blueprints</h2>

<p>One of the long-term plans we set out with when starting OpenLoco, is the idea of blueprints.
These would allow you to save and rebuild parts of your map in another. For example, that massive
station with an interchange you made? Yeah, you would be able to save that, and rebuild it in
the same or other map.</p>

<p>Obviously, this is not a trivial feature to add. As such, we never really got around to
implementing it… until @duncanspumpkin suddenly had a nice proof-of-concept for basic copy/paste
functionality <a href="https://github.com/OpenLoco/OpenLoco/pull/3649">(#3649)</a>.
You simply select part of the map to copy it, then paste it elsewhere on the map. This then
provides basic proof-of-concept functionality behind these blueprints.
Over the past month, some of the rough edges were smoothed out, and we decided to merge it
as part of the construction window — for now.</p>

<p>At present it will only work for railroad track, signal and station map elements.
We will look to improve the support for other map elements such as roads, buildings, and terrain.</p>

<p>In the near future, we aim to extend this feature into the full-blown blueprints feature
we talked about. We’re not quite sure where they’ll go yet. Maybe in a tab in the construction
window, or maybe in a seperate window entirely? Exciting times, for sure.</p>

<p>For a simple example, check out the following clip:</p>
<video style="width: 90%; margin: auto" controls="">
	<source src="/assets/mp4/26.04/blueprints_copy_paste.mp4" type="video/mp4" />
	<source src="/assets/webm/26.04/blueprints_copy_paste.webm" type="video/webm" />
</video>

<h2 id="fix-auto-layout-for-cars-that-are-centered">Fix auto layout for cars that are centered</h2>

<p>A few community members have reported the fact that when a vehicle object has the
<code class="language-plaintext highlighter-rouge">centrePosition</code> flag, it does not correctly centre on the train. This bug was introduced when
@duncanspumpkin reimplemented the train auto layout code. The vanilla game’s auto layout code
was very long and complex, and had to be implemented all in one go. This often leads to mistakes.
For this particular issue, at the time, Duncan had it working almost correctly,
except when there was an even amount of cars. Whilst fixing, that though, this bug slipped in
Just typical that, whilst fixing an edge case, you completely break the general case!</p>

<p>@Hammster created a fix for the issue <a href="https://github.com/OpenLoco/OpenLoco/pull/3572">(#3572)</a>
and Duncan tidied up the fix to make it align with the codebase.</p>

<h2 id="fix-loan-potentially-going-negative-3688">Fix loan potentially going negative (#3688)</h2>

<p>A few releases ago, @duncanspumpkin decided to try align all of our UI code that handled
increasing/decreasing amounts. This was meant to reduce the chance of subtle bugs in the
various places where we do this. Unfortunately, for the loan payback, he forgot that
money types can go negative, so the wrong lower limit was set.</p>

<p>It was easy to fix, Duncan wanted to go through all the other changes he made for
increasing/decreasing to ensure he hadn’t made similar mistakes.
Fortunately, we concluded he hadn’t.</p>

<h2 id="new-cheat-keep-cargo-on-vehicle-pickupmodify">New cheat: keep cargo on vehicle pickup/modify</h2>

<p>Tired of losing cargo when picking up or modifying a vehicle? We’re guessing that’s how @ethan-xd
felt when he implemented a cheat to prevent just that
<a href="https://github.com/OpenLoco/OpenLoco/pull/3591">(#3591)</a>.
It’s just a checkbox away.</p>

<p><img src="/assets/img/26.04/cheat_vehicle_cargo_pickup.png" alt="Cargo cheat screenshot" /></p>

<h2 id="jukebox-improvements">Jukebox improvements</h2>

<p>This month, we’ve merged a few of @LeeSpork’s patches on what seems to be their favourite part
of the code base: the jukebox. Notably, they fixed music automatically resuming after saving
when the game paused <a href="https://github.com/OpenLoco/OpenLoco/pull/3185">(#3185)</a>, even when the
game itself would still be paused.</p>

<p>The original Locomotion title theme can now be added to the ‘custom’ jukebox playlist as well
<a href="https://github.com/OpenLoco/OpenLoco/pull/3639">(#3639)</a>. It is still not included by default.</p>

<p>After last month’s addition of separate volume sliders for the various game audio channels,
the jukebox suddenly felt out of place. Instead of just moving it back to its own tab
in the options window, we’ve opted to move the jukebox into its own window instead
<a href="https://github.com/OpenLoco/OpenLoco/pull/3703">(#3707)</a>. It can be quickly opened via the
audio (ear) menu, or via a custom keyboard shortcut.</p>

<h2 id="refactor-list-windows-to-use-faster-sorting-algorithm">Refactor list windows to use faster sorting algorithm</h2>

<p>Keen-eyed players may have noticed that the game’s list windows have always updated three rows at a time.
This was most notable when the window was just opened: every game tick, three more rows would be added.
Similarly, values for existing rows would be updated in an almost ‘scrolling’ fashion.
While there was something satisfying about this, it also meant that it would take a few seconds before
e.g. the higher-digit vehicles would appear in the lists.</p>

<p>This month, @AaronVanGeffen has reworked these lists to now use a two-step approach instead.
When opening the window, all relevant ids are stored in</p>

<p>This applies to the company list <a href="https://github.com/OpenLoco/OpenLoco/pull/3705">(#3705)</a>,
station list <a href="https://github.com/OpenLoco/OpenLoco/pull/3704">(#3704)</a>,
industry list <a href="https://github.com/OpenLoco/OpenLoco/pull/3703">(#3703)</a>,
town list <a href="https://github.com/OpenLoco/OpenLoco/pull/3702">(#3702)</a>, and
vehicle lists <a href="https://github.com/OpenLoco/OpenLoco/pull/3701">(#3701)</a> windows.</p>

<p>This fixes a problem with vehicle lists <a href="https://github.com/OpenLoco/OpenLoco/pull/3701">(#3701)</a>
where having both the general vehicle list as well as station-specific ones open at the same time
could lead to flickering vehicle rows.</p>

<p>Finally, we unified the use of two window struct properties that were both used for keeping
track of the amount of rows displayed. As of this release, the previously unnamed variable <code class="language-plaintext highlighter-rouge">var_83C</code>
is no longer used for this purpose, replacing it with <code class="language-plaintext highlighter-rouge">rowCount</code>
<a href="https://github.com/OpenLoco/OpenLoco/pull/3709">(#3709)</a>.</p>

<h2 id="add-more-sorting-options-when-building-vehicles">Add more sorting options when building vehicles</h2>

<p>As of OpenLoco v23.10, the Build Vehicle window has had
<a href="/news/2023/10/openloco-v23.10.html#add-filters-to-build-vehicle-window-2148">options to search/filter</a>
the listed components, e.g. by powered/unpowered. Similarly, the list could be sorted by name or
year of invention. @ethan-xd saw an opportunity to add more sorting options, and introduced the ability
to sort descending as well (#3594).</p>

<h2 id="address-sanitisation-passes">Address sanitisation passes</h2>

<p>Investigating a mysterious crash, @ZehMatt set out on an
<a href="https://en.wikipedia.org/wiki/Code_sanitizer#AddressSanitizer">AddressSanitizer</a> quest.
Two bugs surfaced in the process.</p>

<p>First, he discovered copying news messages into the news window was going one byte beyond its
buffer limit <a href="https://github.com/OpenLoco/OpenLoco/pull/3719">(#3719)</a>. Fortunately,
this was a buffer on the top of the active stack frame, so unlikely to lead to anything truly bad.</p>

<p>Second, he discovered an issue with the routing iterator. The way it was set up would return
a pointer to routing data, rather than the actual value
<a href="https://github.com/OpenLoco/OpenLoco/pull/3718">(#3718)</a>.
This meant that, in case the routing table changed, the iterator might suddenly return a
different value than expected. As a preventative measure, this was changed to return a immediate
value instead.</p>

<p>We’re not sure if either of these actually solved bugs that people actually encountered,
but they’re a good examples of the kind of issue we have to look out for.</p>

<h2 id="name-a-few-more-previously-unnamed-things">Name a few more previously unnamed things</h2>

<p>@duncanspumpkin named the <code class="language-plaintext highlighter-rouge">awaitingCargoTransfer</code> flag, placed on vehicle components
<a href="https://github.com/OpenLoco/OpenLoco/pull/3621">(#3621)</a>.
As the name suggets, this indicates a vehicle component is waiting for a cargo transfer.
When placed on vehicle head structs it indicates that the vehicle <em>cannot</em> wait at the station for
further loading. In the future, we would like to split this off to a different flag to make
cargo loading more flexible.</p>

<p>When it comes to buildings, we recently discovered buildings are categorised into what we now call
<em>amenity categories</em>. Towns use these to decide what buildings to keep or replace, and indeed to build.
So far, we’ve named religious buildings (e.g. churches), hotels, parks, courthouses,
parks, and landmarks. There is room for three more categories, but no vanilla objects seem to use them.
In fact, most vanilla buildings do not have an amenity category, as they are general residential.
Either way, it’s interesting to still discover more of these subtle, underlying mechanisms.</p>

<p>Objects that claim to belong to any of these newly discovered amenity categories now have their
category validated. If an invalid value is found, the object now can no longer be loaded to prevent crashes
<a href="https://github.com/OpenLoco/OpenLoco/pull/3623">(#3623)</a>.
Such invalid values were especially dangerous as they could end up writing data to many different parts of the save file,
corrupting saves in unexpected ways. Luckily, most of the time doing so would immediately cause a crash, though,
instead of subtly corrupting your save!</p>

<p>On the topic of unexpected values, a similar check is now applied to the building generator function id
associated with miscellaneous building objects.</p>

<p>There are still quite a few unnamed flags and variables left. If you feel like joining in on the naming effort,
please reach out to us on Discord!</p>

<h2 id="localisation-improvements">Localisation improvements</h2>

<p>@erdikayaTR has improved the Turkish localisation, adding translations for newer strings and clarifying older ones
<a href="https://github.com/OpenLoco/OpenLoco/pull/3712">(#3712)</a>.</p>

<p>Like Locomotion, OpenLoco support custom keyboard shortcuts. @LeeSpork noticed one of the lesser used modifier keys,
the <code class="language-plaintext highlighter-rouge">Menu</code> key, was not being localised. This has now been fixed <a href="https://github.com/OpenLoco/OpenLoco/pull/3467">(#3467)</a>.</p>

<h2 id="fix-crash-when-starting-bus-behind-bus">Fix crash when starting bus behind bus</h2>

<p>This was quite a curious bug, in that you only hit the issue when starting a bus <em>immediately</em>
behind another bus when it is stationary. Technically, the vanilla game suffered from this mistake as well,
but instead of crashing it would just read invalid memory and miscalculate the road occupancy.
Instead of reading a non-existing object, the null value involved is now correctly ignored
<a href="https://github.com/OpenLoco/OpenLoco/pull/3698">(#3698)</a>.</p>

<h2 id="fix-new-signals-not-correctly-updating-network">Fix new signals not correctly updating network</h2>

<p>Due to a mistake made during implementing the ‘Place Signal’ code, depending on where you clicked on the track
when placing a signal, the game might not actually update the signal network! This would cause unexpected
crashes/stoppages of trains.</p>

<p>@duncanspumpkin investigated and fixed the issue <a href="https://github.com/OpenLoco/OpenLoco/pull/3697">(#3697)</a>.
He realised that the issue was missed during testing, as back then we were using straight track pieces,
which in retrospect wouldn’t be affected by the issue.
There might yet be further issues with this code, so please let us know if you still encounter
odd issues when adding a signal to track.</p>]]></content><author><name>Aaron van Geffen</name></author><category term="news" /><summary type="html"><![CDATA[OpenLoco v26.04 is out! This month’s release introduces the first version of a new feature that has been in the works for a few months: blueprints! Moreover, we have a bunch of bugfixes and improvements lined up. Please read on for the details.]]></summary></entry><entry><title type="html">OpenLoco version 26.03.1</title><link href="https://openloco.io/news/2026/04/openloco-v26.03.1.html" rel="alternate" type="text/html" title="OpenLoco version 26.03.1" /><published>2026-04-01T09:00:00+00:00</published><updated>2026-04-01T09:00:00+00:00</updated><id>https://openloco.io/news/2026/04/openloco-v26.03.1</id><content type="html" xml:base="https://openloco.io/news/2026/04/openloco-v26.03.1.html"><![CDATA[<p>OpenLoco v26.03.1 is out! Yeah, only one day after v26.03. Remember how we announced we had
<a href="https://openloco.io/news/2026/03/openloco-v26.03.html#improved-entity-invalidation">improved entity invalidation</a>?
Turns out there was a gaping bug that would occur when the viewport is rotated. Oops.
@ZehMatt quickly patched the issue, but obviously we wish we had caught this before the release.</p>

<p>Please find the <a href="https://openloco.io/download/">download</a> on our website, or read the
<a href="https://github.com/OpenLoco/OpenLoco/blob/v26.03.1/CHANGELOG.md">changelog</a> on GitHub.</p>]]></content><author><name>Aaron van Geffen</name></author><category term="news" /><summary type="html"><![CDATA[OpenLoco v26.03.1 is out! Yeah, only one day after v26.03. Remember how we announced we had improved entity invalidation? Turns out there was a gaping bug that would occur when the viewport is rotated. Oops. @ZehMatt quickly patched the issue, but obviously we wish we had caught this before the release.]]></summary></entry><entry><title type="html">OpenLoco version 26.03</title><link href="https://openloco.io/news/2026/03/openloco-v26.03.html" rel="alternate" type="text/html" title="OpenLoco version 26.03" /><published>2026-03-31T14:30:00+00:00</published><updated>2026-03-31T14:30:00+00:00</updated><id>https://openloco.io/news/2026/03/openloco-v26.03</id><content type="html" xml:base="https://openloco.io/news/2026/03/openloco-v26.03.html"><![CDATA[<p>OpenLoco v26.03 is out! This month’s release focuses on moving to our (graphics) backend to SDL3,
as well as a rework of the audio engine. Some more cool new features have been in the works since last month,
but they haven’t landed yet this month. Please be patient for a while longer :-)</p>

<p>What follows is a quick summary of the new features and bug fixes for this month.</p>

<h2 id="migrate-codebase-to-sdl3">Migrate codebase to SDL3</h2>

<p>When implementing a game, programmers can choose to either target a particular operating system directly,
or use an intermediary layer that makes it possible to target multiple platforms in one go.
To this end, OpenLoco has made use of <a href="https://www.libsdl.org/">SDL</a> since the beginning.
Recently, a major new version of the SDL API was released, meaning old APIs were replaced and new ones added.
To make it possible to leverage the new functionality, we had to rewrite part of our codebase.</p>

<p>The majority set of rewrites was merged early in the month (<a href="https://github.com/OpenLoco/OpenLoco/pull/2882">#2882</a>),
followed by a series of improvements on display handling by new contributor @kevinz26
(<a href="https://github.com/OpenLoco/OpenLoco/pull/3671">#3671</a>). Nice!</p>

<h2 id="audio-volume-can-now-be-set-separately-by-channel">Audio volume can now be set separately by channel</h2>

<p>There are many different kinds of audio in Locomotion. It even includes a jukebox! Like Locomotion,
OpenLoco only had a single volume slider, grouped with the music options. Until this month, that is,
as now you can set a specific volume for each specific kind of audio
(<a href="https://github.com/OpenLoco/OpenLoco/pull/3678">#3678</a>)!</p>

<p><img src="/assets/img/26.03/volume-sliders.png" alt="Volume sliders" /></p>

<h2 id="vehicle-sounds-now-use-reverb-when-entering-or-leaving-a-tunnel">Vehicle sounds now use reverb when entering or leaving a tunnel</h2>

<p>Armed with a newly-refactored audio subsystem (<a href="https://github.com/OpenLoco/OpenLoco/pull/3678">#3678</a>),
@ZehMatt set out to add a new effect to the game: reverb! This is now used for vehicle running sounds
when they are in a tunnel <a href="https://github.com/OpenLoco/OpenLoco/pull/3678">#3678</a>. We think it’s a nice touch!</p>

<p>Here’s what it sounded like in v26.02:</p>
<video style="width: 90%; margin: auto" controls="">
	<source src="/assets/mp4/26.03/output-v26.02-clip.mp4" type="video/mp4" />
	<source src="/assets/webm/26.03/output-v26.02-clip.webm" type="video/webm" />
</video>

<p>And here’s what it sounds like in v26.03:</p>
<video style="width: 90%; margin: auto" controls="">
	<source src="/assets/mp4/26.03/output-v26.03-clip.mp4" type="video/mp4" />
	<source src="/assets/webm/26.03/output-v26.03-clip.webm" type="video/webm" />
</video>

<h2 id="improved-entity-invalidation">Improved entity invalidation</h2>

<p>Normally, tiles are ‘invalidated’ whenever elements or entities on them have changed, requiring them to be redrawn.
However, under some circumstances, e.g. when dragging a vehicle ‘ghost’ around, it was possible for a (ghostly) remnant
of the vehicle to stay behind. It seems we missed a spot, somewhere!</p>

<p>This was reworked by making the invalidation <em>implicit</em> in the entity’s <code class="language-plaintext highlighter-rouge">moveTo</code> call, rather than <em>explicit</em>.
@ZehMatt realised there was an optimisation here: sometimes, a tile was invalidated even if the vehicle hadn’t
actually moved (<a href="https://github.com/OpenLoco/OpenLoco/pull/3312">#3312</a>)!
This probably won’t lead to much of a rendering speedup, but it’s a nice bonus!</p>

<h2 id="news-settings-default-to-newspaper-style-again">News settings default to newspaper style again</h2>

<p>Last November, we reworked the <a href="/news/2025/11/openloco-v25.11.html#rework-remaining-legacy-config-into-modern-config">remaining Locomotion config settings</a>,
folding them into our own, modern OpenLoco config file. We missed an edge case, however.
For <em>new</em> config files, news settings were not initialised correctly.
Indeed, all news settings defaulted to <em>off</em>, rather than the newspaper style players have come to expect. Oops.</p>

<p>New config files will now get the right ‘newspaper’ defaults
(<a href="https://github.com/OpenLoco/OpenLoco/pull/3657">#3657</a>). Unfortunately, we can’t reset the settings
without affecting players with custom news settings, however. So if you’re not seeing news unexpectedly,
please check the news options in the messages window.</p>

<h2 id="new-widget-identification">New widget identification</h2>

<p>When a player interacts with an element in an in-game window, a so-called widget, you often want something to happen.
To do this, the input subsystem relays to the relevant window that a particular widget has been interacted with
in a certain way, so that the window can do what is expected.</p>

<p>Like Locomotion before it, OpenLoco handles this by using a numeric index. Using <code class="language-plaintext highlighter-rouge">enum</code>s,
the first widget in a window is assigned index <code class="language-plaintext highlighter-rouge">0</code>, the next index <code class="language-plaintext highlighter-rouge">1</code>, etc.
This is great if your widgets are sequential, but we would like to move to a
more declarative way of denoting the window layout. Suddenly, widgets are not so sequential any more,
meaning we need a new way to identify them. Enter <code class="language-plaintext highlighter-rouge">WidgetId</code>
<a href="https://github.com/OpenLoco/OpenLoco/pull/3560">#3560</a>.</p>

<p>Instead of simple <code class="language-plaintext highlighter-rouge">enum</code> sequences, <code class="language-plaintext highlighter-rouge">WidgetId</code>s are instantiated using a string, which is hashed to a number at compile time.
This means we still get something that’s easy for machines to compare with, while also making it possible
for interface design to be moved externally to the C++ internals. Something nice to look forward to.</p>

<h2 id="improved-assertions">Improved assertions</h2>

<p>Traditionally, in C and C++, programmers can use <code class="language-plaintext highlighter-rouge">assert</code> to denote what would otherwise be implicit
expectations in source code. For example, you might want to make sure that a particular thing never happens,
e.g. the sky shouldn’t be painted in a green colour, somehow. Such extra checks take time, though, so typically
<code class="language-plaintext highlighter-rouge">assert</code>s are skipped entirely in non-debug builds.</p>

<p>There are times when we <strong>do</strong> want things to fail, though, and when they do, preferably with a bit of
extra information. Enter our own assertion diagnostics
<a href="https://github.com/OpenLoco/OpenLoco/pull/3656">#3656</a>, courtesy of @ZehMatt.
These have the added advantage of saving the source location, so error traces don’t show the error handler
as the source of the error, but the actual location where the assertion was triggered.
Hopefully, these will help narrow down any pesky mistakes in the future!</p>

<h2 id="drawing-circles">Drawing circles</h2>

<p>Locomotion sported a necessary feature for new players: in-game tutorials.
While not really going into the nitty-gritty of the game, they helpfully covered the basics.
Unfortunately, though, they are simply a sequence of mouse pointer locations,
recorded separately for common screen resolutions at the time the game was released:
640×480, 800×600, and 1024×768. If these resolutions seem alien to you, well,
this is what most of us had to contend with back in the day!</p>

<p>In recent discussion, we talked about how best to replace the old ‘mouse’ tutorials.
One idea is to use the new widget identifiers to mark the elements that instead should be clicked
<em>by the player</em> to advance the tutorial.</p>

<p>One way to mark them would be to use circles, someone suggested.
A problem presented itself: oddly enough, we had no primitive yet to draw circles!
@ZehMatt stepped up and implemented one in <a href="https://github.com/OpenLoco/OpenLoco/pull/3559">#3559</a>.</p>

<p>Tutorials haven’t changed yet, and probably won’t for a while. But at least we can now draw circles!</p>

<p><img src="/assets/img/26.03/circles.gif" alt="Basic circles" /></p>

<h2 id="opengraphics">OpenGraphics</h2>

<p>This month saw 3 contributions from @shusaura85:</p>

<p>An updated dry grass object:
<img src="/assets/img/26.03/og_grassbr.png" alt="OG_GRASSBR" /></p>

<p>Two new roads:
<img src="/assets/img/26.03/og_roadone.png" alt="OG_ROADONE" /></p>

<p><img src="/assets/img/26.03/og_roadtmc.png" alt="OG_ROADTMC" /></p>]]></content><author><name>Aaron van Geffen</name></author><category term="news" /><summary type="html"><![CDATA[OpenLoco v26.03 is out! This month’s release focuses on moving to our (graphics) backend to SDL3, as well as a rework of the audio engine. Some more cool new features have been in the works since last month, but they haven’t landed yet this month. Please be patient for a while longer :-)]]></summary></entry><entry><title type="html">OpenLoco version 26.02</title><link href="https://openloco.io/news/2026/02/openloco-v26.02.html" rel="alternate" type="text/html" title="OpenLoco version 26.02" /><published>2026-02-28T07:30:00+00:00</published><updated>2026-02-28T07:30:00+00:00</updated><id>https://openloco.io/news/2026/02/openloco-v26.02</id><content type="html" xml:base="https://openloco.io/news/2026/02/openloco-v26.02.html"><![CDATA[<p>OpenLoco v26.02 is out! This month’s release mostly focuses on bugfixes. People with an eye on our Discord will know
some cool new features are in the works, but they haven’t landed yet this month. The dev team ended up rather busy with Life,
but that just means there is more to look forward to in the upcoming month!</p>

<p>What follows is a quick summary of the bugs and their fixes.</p>

<h2 id="crash-when-hovering-over-stations-with-the-order-tab-open-2205">Crash when hovering over stations with the order tab open (#2205)</h2>

<p>We kept getting weird crash reports that we couldn’t quite place, somehow involving the vehicle order manager.
It had us puzzled for a while, until @Sashna on Discord came up with a reliable way to reproduce the issue.
As it turns out, there was a situation where a pointer to the end of the order table could be reused, leading to
it being incremented past the end of the table! Once this was diagnosed, Duncan was able to come up with
a fix relatively quickly.</p>

<h2 id="the-vsync-setting-is-not-saved-correctly-3626">The vsync setting is not saved correctly (#3626)</h2>

<p>In <a href="https://github.com/OpenLoco/OpenLoco/releases/v26.01/">the previous release</a>,
we introduced an optional vsync cap for the game’s frame rate.
Ironically, the setting was not saving correctly, leading to an uncapped frame rate after restarting the game.
This was a minor issue to resolve, so at least now it actually persists!</p>

<h2 id="constant-alternating-colors-on-vehicles-and-other-things-3627">Constant alternating colors on vehicles and other things (#3627)</h2>

<p>We also introduced <a href="/news/2026/01/openloco-v26.01.html#parallel-drawing">parallel, multi-threaded rendering</a>
in the previous release. However, the remap colours in the game were still <em>sharing</em> a palette buffer.
This led to a race condition for e.g. recoloured vehicles, meaning they would alternate between colours
in certain situations. Ironically, this was flagged as a potential issue ahead of time, but the relevant
‘thread local’ keyword had not been applied. After we identified that this was indeed the cause,
it was another one-line fix.</p>

<h2 id="macos-builds-are-missing-opengraphics-objects-3629">macOS builds are missing OpenGraphics objects (#3629)</h2>

<p>As of December 2025, we have native builds for macOS again. However, as it turns out, the application bundles
were missing our OpenGraphics objects entirely! CMake wizard Duncan dug into this and found the cause to be a bug
to do with CMake presets! A workaround was promptly applied, and our macOS builds now ship with OpenGraphics objects!</p>

<h2 id="can-click-beyond-last-item-in-town-and-industry-list-windows-opening-invalid-windows-3652">Can click beyond last item in town and industry list windows, opening invalid windows (#3652)</h2>

<p>@LeeSpork identified an issue where the town and industry list windows would let the player select ‘items’
where there were none, just after the end of the list. This led to opening invalid windows, often triggering a crash.
Turns out the relevant checks were using <code class="language-plaintext highlighter-rouge">&gt;</code> instead of <code class="language-plaintext highlighter-rouge">&gt;=</code> to check bounds. Foiled again, off-by-one errors!</p>]]></content><author><name>Aaron van Geffen</name></author><category term="news" /><summary type="html"><![CDATA[OpenLoco v26.02 is out! This month’s release mostly focuses on bugfixes. People with an eye on our Discord will know some cool new features are in the works, but they haven’t landed yet this month. The dev team ended up rather busy with Life, but that just means there is more to look forward to in the upcoming month!]]></summary></entry><entry><title type="html">OpenLoco version 26.01</title><link href="https://openloco.io/news/2026/01/openloco-v26.01.html" rel="alternate" type="text/html" title="OpenLoco version 26.01" /><published>2026-01-30T16:00:00+00:00</published><updated>2026-01-30T16:00:00+00:00</updated><id>https://openloco.io/news/2026/01/openloco-v26.01</id><content type="html" xml:base="https://openloco.io/news/2026/01/openloco-v26.01.html"><![CDATA[<p>OpenLoco v26.01 is out! Last month we finally finished making the game binary standalone; this
means we now enter a bit of a refactoring and general code cleanup phase.</p>

<p>Over the next few months, the refactoring will be aimed towards getting ready for a new save format
(NSF). For the NSF, we will be aiming to increase the map size limits, and generally most other
limits. It is not a simple task of just changing some constants though, so don’t expect this to be
completed for a while. Related to the NSF, we will also be looking at introducing a new object
format (NOF). The NOF will allow removing limitations of the DAT format and will hopefully be more
human readable. Much like the NSF, this will take quite some time to fully decide how it will work.</p>

<p>Even when we move to a NSF and NOF, we will still maintain support for the old formats in various
ways, so don’t worry about losing your favourite custom objects.</p>

<p>Other areas for improvement are path finding. I suspect that we won’t be able to improve the land
path finding just yet, without an NSF, but the water path finding should be achievable. If you have
knowledge on pathfinding algorithms, it would be great to hear from you.</p>

<h2 id="openloco">OpenLoco</h2>

<h3 id="parallel-drawing">Parallel drawing</h3>

<p>@ZehMatt added parallel drawing support to OpenLoco
(<a href="https://github.com/OpenLoco/OpenLoco/pull/2825">#2825</a>). For the first time, having a multi-core CPU
will actually improve performance in OpenLoco! The way drawing works in OpenLoco is that the
window is split up into columns of 32 pixels wide (the width of a tile). Each column is drawn
independently of the others. This is trivially parallelisable and @ZehMatt really showed this as
the number of lines of code required to add parallel drawing was just 28!</p>

<p>However, keep in mind that drawing is not always the bottleneck of OpenLoco. Just running the
simulation can be very CPU intensive, and that is not something we can easily parallelise at this time.</p>

<p>Related to this change, @lapingvino on Discord mentioned this change caused dependency issues on
his system. I might have been a little dismissive of the issue at first as we were only using the
C++ standard library parallelism features, but after looking into it properly it did turn out that
GCC’s <code class="language-plaintext highlighter-rouge">libstdc++</code> depends on Intel TBB for parallelism. So if you are using <code class="language-plaintext highlighter-rouge">libstdc++</code> you now need to
remember to have TBB if you want parallel drawing to work
(<a href="https://github.com/OpenLoco/OpenLoco/pull/#3608">#3608</a>).
Unfortunately, GCC will silently remove the parallelism if TBB is not found so we didn’t catch this
on any of our CI systems as they only have the minimum of required dependencies installed.</p>

<h3 id="name-unknown-flags-and-variables">Name unknown flags and variables</h3>

<p>@Cgettys, myself, @shusaura85 all worked on identifying various flags, variables and other unknowns
in the codebase (<a href="https://github.com/OpenLoco/OpenLoco/pull/3512">#3512</a>,
<a href="https://github.com/OpenLoco/OpenLoco/pull/3615">#3615</a>,
<a href="https://github.com/OpenLoco/OpenLoco/pull/3571">#3571</a>,
<a href="https://github.com/OpenLoco/OpenLoco/pull/3600">#3600</a>,
<a href="https://github.com/OpenLoco/OpenLoco/pull/3550">#3550</a>).
Ideally, we would like to have all save file and object file related data
identified before embarking on the NSF and NOF work. It’s not terribly exciting work, but I
personally quite enjoy finally assigning a name to something and understanding how it affects the
simulation.</p>

<h3 id="various-refactoring-and-bugs">Various refactoring and bugs</h3>

<p>@AaronVanGeffen, myself, @ethan-xd, @ZehMatt, @LeeSpork, @LeftOfZen, all worked on various minor
refactoring and minor bugs. Checkout the changelog for details on the bugs.</p>

<h2 id="opengraphics">OpenGraphics</h2>

<p>We made a mistake last month and accidentally didn’t include all of the OpenGraphics objects that had
been created. We have corrected the issue and you should now see all of the objects released last month.</p>

<p>Onto the fun stuff; this months was the most productive month yet! Contributions have been organised by creator below.</p>

<h3 id="phosporus551">@phosporus551</h3>

<p>@phosporus551 had an insane 37 contributions this month:</p>

<p>28 OpenGraphics recreations:</p>

<figure class="third ">
  
    
      <a href="/assets/img/26.01/og_ae47.png" title="OG_AE47">
          <img src="/assets/img/26.01/og_ae47.png" alt="OG_AE47" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_alcocent.png" title="OG_ALCOCENT">
          <img src="/assets/img/26.01/og_alcocent.png" alt="OG_ALCOCENT" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_apt.png" title="OG_APT">
          <img src="/assets/img/26.01/og_apt.png" alt="OG_APT" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_ce68.png" title="OG_CE68">
          <img src="/assets/img/26.01/og_ce68.png" alt="OG_CE68" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_dash7.png" title="OG_DASH7">
          <img src="/assets/img/26.01/og_dash7.png" alt="OG_DASH7" />
      </a>
    
  
    
      <a href="/assets/img/26.01/e8.png" title="E8">
          <img src="/assets/img/26.01/og_e8.png" alt="E8" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_estar.png" title="OG_ESTAR">
          <img src="/assets/img/26.01/og_estar.png" alt="OG_ESTAR" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_flatbeds.png" title="All the new flatbegs">
          <img src="/assets/img/26.01/og_flatbeds.png" alt="OG_FLATBEDS" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_mailus1.png" title="OG_MAILUS1">
          <img src="/assets/img/26.01/og_mailus1.png" alt="OG_MAILUS1" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_mk1.png" title="OG_MK1">
          <img src="/assets/img/26.01/og_mk1.png" alt="OG_MK1" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_mk2.png" title="OG_MK2">
          <img src="/assets/img/26.01/og_mk2.png" alt="OG_MK2" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_pcar1.png" title="OG_PCAR1">
          <img src="/assets/img/26.01/og_pcar1.png" alt="OG_PCAR1" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_pcar2.png" title="OG_PCAR2">
          <img src="/assets/img/26.01/og_pcar2.png" alt="OG_PCAR2" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_pcarus1.png" title="OG_PCARUS1">
          <img src="/assets/img/26.01/og_pcarus1.png" alt="OG_PCARUS1" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_pcarus2.png" title="OG_PCARUS2">
          <img src="/assets/img/26.01/og_pcar2.png" alt="OG_PCARUS2" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_rbe24.png" title="OG_RBE24">
          <img src="/assets/img/26.01/og_rbe24.png" alt="OG_RBE24" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_sd70mac.png" title="OG_SD70MAC">
          <img src="/assets/img/26.01/og_sd70mac.png" alt="OG_SD70MAC" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_swiss1.png" title="OG_SWISS1">
          <img src="/assets/img/26.01/og_swiss1.png" alt="OG_SWISS1" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_swiss2.png" title="OG_SWISS2">
          <img src="/assets/img/26.01/og_swiss2.png" alt="OG_SWISS2" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_swiss3.png" title="OG_SWISS3">
          <img src="/assets/img/26.01/og_swiss3.png" alt="OG_SWISS3" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_swiss5.png" title="OG_SWISS5">
          <img src="/assets/img/26.01/og_swiss5.png" alt="OG_SWISS5" />
      </a>
    
  
    
      <a href="/assets/img/26.01/og_tgv.png" title="OG_TGV">
          <img src="/assets/img/26.01/og_tgv.png" alt="OG_TGV" />
      </a>
    
  
  
</figure>

<p>7 <em>branch new</em> narrow-gauge trains (that don’t replace a vanilla object). These fill a gameplay gap
in the mid tier for narrow-gauge trains. Whilst wider game balance for vehicles still has to be
discussed in more detail, these certainly go a long way to bridging the underpowered nature of
the vanilla narrow-gague vehicle selection.</p>

<p><img src="/assets/img/26.01/og_ng2.png" alt="OG_NG2" /></p>

<p>2 revisions on existing OpenGraphics objects:</p>

<p><img src="/assets/img/26.01/og_hst_mk3_update.png" alt="OG_HST_MK3" /></p>

<h3 id="shusaura85">@shusaura85</h3>

<p>@shusaura85 fixed a vanilla compatiblity issue with level crossings not being able to be placed on the existing <code class="language-plaintext highlighter-rouge">OG_ROADRGH</code>, as well as added <code class="language-plaintext highlighter-rouge">OG_BRDGGIRD</code>:</p>

<p><img src="/assets/img/26.01/og_brdggird.png" alt="OG_BRDGGIRD" /></p>

<h3 id="glenjimen">@glenjimen</h3>

<p>@glenjimen contributed <code class="language-plaintext highlighter-rouge">OG_COAL1</code>:</p>

<p><img src="/assets/img/26.01/og_coal1.png" alt="OG_COAL1" /></p>]]></content><author><name>Duncan Frost</name></author><category term="news" /><summary type="html"><![CDATA[OpenLoco v26.01 is out! Last month we finally finished making the game binary standalone; this means we now enter a bit of a refactoring and general code cleanup phase.]]></summary></entry><entry><title type="html">OpenLoco version 25.12</title><link href="https://openloco.io/news/2025/12/openloco-v25.12.html" rel="alternate" type="text/html" title="OpenLoco version 25.12" /><published>2025-12-20T09:00:00+00:00</published><updated>2025-12-20T09:00:00+00:00</updated><id>https://openloco.io/news/2025/12/openloco-v25.12</id><content type="html" xml:base="https://openloco.io/news/2025/12/openloco-v25.12.html"><![CDATA[<p>OpenLoco v25.12 is out! This release marks a major milestone for the project.
We completed the C++ reimplemention in <a href="/news/2025/09/openloco-v25.09.html">v25.09</a> a few months ago,
but were still dependent on vanilla memory space. This month, we celebrate the complete
reworking of the memory space as well.</p>

<p>In short, this means the game can now be compiled <em>natively</em> for all platforms.
This makes this month’s release available in <strong>64-bits</strong> architecture for Windows, Linux, and macOS.
You can expect builds to be faster, and much easier to port to new operating systems.
Of course, we are extremely happy with this result, and what this means for future possibilities.</p>

<p>In this blog post, we’ll look back on how the memory space was reworked,
as well as some quality-of-life changes that were merged this month,
and the progress the OpenGraphics project has seen. Let’s get going.</p>

<h2 id="big-loco_global-integration-extravaganza">Big loco_global integration extravaganza</h2>

<p>Until this month, we still mirrored the vanilla game’s approached to <em>memory space</em> in most places.
As often talked about in previous blogs, this was done with <code class="language-plaintext highlighter-rouge">loco_global</code> instances.
Last month, we reported on the progress of reworking this, going from
342 <code class="language-plaintext highlighter-rouge">loco_globals</code> in the v25.10 release to just 157 in v25.11…
Remarkably, this month takes us down to <strong>0</strong> <code class="language-plaintext highlighter-rouge">loco_globals</code> — yes, zero!
It was a massive team effort, but it’s paid off massively, making 64-bit builds finally possible.</p>

<p>We usually list PR numbers in our dev log sections, however there were 46 PRs just for
<code class="language-plaintext highlighter-rouge">loco_global</code> removal this month! If you’re curious to see what such PRs look like,
you can find them on GitHub. Follow
<a href="https://github.com/OpenLoco/OpenLoco/pulls?q=is%3Apr+milestone%3Av25.12+interop+OR+global+OR+loco_globals">this link</a>
for a list of the relevant PRs.</p>

<p>To illustrate the growth and removal of <code class="language-plaintext highlighter-rouge">loco_global</code> instances from the project’s inception to now,
please take a look at the graph below. As more of the game became reimplemented, more memory had to be
shared between vanilla functions and our C++ functions, thus increasing the number of <code class="language-plaintext highlighter-rouge">loco_global</code>s.
Only once all vanilla systems had been reimplemented could the relevant memory be fully integrated.
Clearly, the last few months saw the final stretches of this effort.</p>

<p><img src="/assets/img/25.12/loco_globals.png" alt="loco globals over time" /></p>

<h2 id="larger-windows-and-new-window-styles">Larger windows and new window styles</h2>

<p>Compared to other Chris Sawyer games, Locomotion stands out due to its relatively sober window decorations.
In fact, the ‘gradient’ look that characterises them is drawn using just one big sprite! For this reason,
window sizes were limited to a width of 800 pixels — that’s all the sprite afforded!</p>

<p>Of course, nowadays, we have screens that are quite a bit bigger, so we frequently got requests
for windows to be made larger. Well, here we are! Certain windows, e.g. the vehicle list and map window,
can now be resized up to 2000x2000 pixels — much wider than was possible in the original game.</p>

<p>While we were working on this, Aaron had fun playing with introducing some new variants of the default
window frame style. The gradient can now be disabled, resulting in a solid background colour. Moreover,
the frame background can now be made translucent, resulting in a neat effect that we just had to include.
Have a look at the gallery below for some examples.</p>

<figure class="third ">
  
    
      <a href="/assets/img/25.12/window_style_gradient.png" title="Gradient window style">
          <img src="/assets/img/25.12/window_style_gradient.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/25.12/window_style_solid.png" title="Solid window style">
          <img src="/assets/img/25.12/window_style_solid.png" alt="" />
      </a>
    
  
    
      <a href="/assets/img/25.12/window_style_translucent.png" title="Translucent window style">
          <img src="/assets/img/25.12/window_style_translucent.png" alt="" />
      </a>
    
  
  
</figure>

<h2 id="more-resizeable-windows">More resizeable windows</h2>

<p>Some players have amassed thousands of objects. Even with the filters OpenLoco introduced,
from time to time we received requests to expand the object selection window. With larger windows
now being possible, we’ve opted to make the object selection window resizeable.
The default dimensions haven’t changed, but you can now
<a href="https://github.com/OpenLoco/OpenLoco/pull/3405">resize it (#3405)</a> to be a whopping 2000x2000 pixels,
for all your extreme object listing needs.</p>

<p>It was brought to our attention that the vehicle list was quite glitchy when made <em>smaller</em> than its
default size. We seized the opportunity to rework its resize routines, capitalising on the increased
window limits as well. You can now <a href="https://github.com/OpenLoco/OpenLoco/pull/3531">resize it (#3531)</a>
to be quite a bit taller indeed!</p>

<p>Finally, the music selection window has been reworked by @LeeSpork.
The window now lists the years music applies to, and allows you to order the list by name or year.
This is made even more useful by allowing you to resize the window!
We hope this increases your playlist customisation prowess
<a href="https://github.com/OpenLoco/OpenLoco/pull/3384">quite a bit (#3384)</a>.</p>

<h2 id="doubling-down-on-cmake">Doubling down on CMake</h2>

<p>Over the past few years, we’ve continued to rely on CMake to tie our toolchain together. While initially
we were dabbling with Visual Studio solution files for Windows, and several CMake files for Linux and even macOS,
@Duncanspumpkin unified these to work on all platforms, and we’re now reaping even more the fruits of this labour.
Since we had to rework our CMake toolchain again to make 64-bit builds possible,
we took the opportunity to drop a bunch of now-unnecessary things in the process.
Let’s take them one at a time.</p>

<h3 id="interop-removal">Interop removal</h3>

<p>First off, no longer needing to interop with the vanilla game has allowed us to
<a href="https://github.com/OpenLoco/OpenLoco/pull/3491">remove a fair bit of code (#3491)</a>.
This moment has been highly anticipated, and @Duncanspumpkin was all to eager to get it done.</p>

<h3 id="cmake-presets">CMake presets</h3>

<p>While CMake has been <em>the</em> go-to tool to build OpenLoco for a while, it could be a little confusing
to get it to build so-called <em>cross-platform</em> builds, in this case building 32-bit software on a 64-bit system.
Now that this is no longer necessary, CMake presets could be
<a href="https://github.com/OpenLoco/OpenLoco/pull/3523">simplified quite a bit (#3523)</a>.
The project readme was adjusted accordingly. Whether you’re on Windows, Linux, macOS, or even BSD,
it should be super easy to set up the compiler toolchain now.</p>

<h3 id="linux-builds">Linux builds</h3>

<p>For our <em>continous integration</em> (CI) build platform, we generally rely on <a href="https://github.com/microsoft/vcpkg">vcpkg</a>
to build libraries we depend on, e.g. the SDL2 hardware abstraction layer.
While Linux distributions tend to have their own package manager, you <em>can</em> opt-in to using vcpkg
if the system packages are not up-to-date enough.
All this to say, our ‘vcpkg’ Linux preset has now been
<a href="https://github.com/OpenLoco/OpenLoco/pull/3494">updated to use x64 (#3494)</a> as well.</p>

<h3 id="macos-builds">macOS builds</h3>

<p>The return of macOS builds is something that part of the team has been eagerly anticipating.
Even when the codebase wasn’t <em>entirely</em> ready, Aaron started to hack away at getting
<a href="https://github.com/OpenLoco/OpenLoco/pull/3288">native 64-bit builds (#3288)</a>
for this platform. Much of the work tied in with the <code class="language-plaintext highlighter-rouge">loco_global</code> rework, and was ultimately split off
into their own PRs to ease the review process.
Duncan created a <a href="https://github.com/OpenLoco/OpenLoco/pull/3499">CI job for macOS (#3499)</a>
as well, so we now have regular macOS builds on GitHub again!</p>

<h3 id="header-checks">Header checks</h3>

<p>Finally, @ZehMatt did quite a bit of <a href="https://github.com/OpenLoco/OpenLoco/pull/3532">house cleaning (#3532)</a>,
modernising parts of the <code class="language-plaintext highlighter-rouge">CMakeLists</code> files that were a bit neglected, and reworking the header checks.
These checks are quite important, as they ensure we don’t have any implicit dependencies
between headers. This allows us to keep headers small while not getting surprised when using them.</p>

<h2 id="opengraphics">OpenGraphics</h2>

<p>This month we had 11 vehicle contributions from @glenjimen and a bridge contribution from @shusaura85!</p>

<h3 id="vehicles">Vehicles</h3>

<figure class="third ">
  
    
      <a href="/assets/img/25.12/og_cattlen1.png" title="OG_CATTLEN1">
          <img src="/assets/img/25.12/og_cattlen1.png" alt="OG_CATTLEN1" />
      </a>
    
  
    
      <a href="/assets/img/25.12/og_pcarsw1.png" title="OG_PCARSW1">
          <img src="/assets/img/25.12/og_pcarsw1.png" alt="OG_PCARSW1" />
      </a>
    
  
    
      <a href="/assets/img/25.12/og_pvan1.png" title="OG_PVAN1">
          <img src="/assets/img/25.12/og_pvan1.png" alt="OG_PVAN1" />
      </a>
    
  
    
      <a href="/assets/img/25.12/og_mailsw1.png" title="OG_MAILSW1">
          <img src="/assets/img/25.12/og_mailsw1.png" alt="OG_MAILSW1" />
      </a>
    
  
    
      <a href="/assets/img/25.12/og_mailsw4.png" title="OG_MAILSW4">
          <img src="/assets/img/25.12/og_mailsw4.png" alt="OG_MAILSW4" />
      </a>
    
  
    
      <a href="/assets/img/25.12/og_mailus2.png" title="OG_MAILUS2">
          <img src="/assets/img/25.12/og_mailus2.png" alt="OG_MAILUS2" />
      </a>
    
  
    
      <a href="/assets/img/25.12/og_swiss4.png" title="OG_SWISS4">
          <img src="/assets/img/25.12/og_swiss4.png" alt="OG_SWISS4" />
      </a>
    
  
    
      <a href="/assets/img/25.12/og_oiln1.png" title="OG_OILN1">
          <img src="/assets/img/25.12/og_oiln1.png" alt="OG_OILN1" />
      </a>
    
  
    
      <a href="/assets/img/25.12/og_oil1.png" title="OG_OIL1">
          <img src="/assets/img/25.12/og_oil1.png" alt="OG_OIL1" />
      </a>
    
  
    
      <a href="/assets/img/25.12/og_oil2.png" title="OG_OIL2">
          <img src="/assets/img/25.12/og_oil2.png" alt="OG_OIL2" />
      </a>
    
  
    
      <a href="/assets/img/25.12/og_openn1.png" title="OG_OPENN1">
          <img src="/assets/img/25.12/og_openn1.png" alt="OG_OPENN1" />
      </a>
    
  
  
</figure>

<h3 id="bridges">Bridges</h3>

<p><img src="/assets/img/25.12/og_brdgstar.png" alt="OG_BRDGSTAR" /></p>

<h2 id="happy-holidays">Happy Holidays!</h2>

<p>Thank you for supporting OpenLoco over the years!
We’re very happy with the milestones we’ve reached this year, both on a code and at a community level.
With the end of 2025 in sight, we wish you all happy holidays!</p>

<p><img src="/assets/img/25.12/locoXmasTree.gif" alt="locoXmasTree" /></p>

<p><em>Thanks to @Glenjimen for this little diorama!</em></p>]]></content><author><name>Aaron van Geffen</name></author><category term="news" /><summary type="html"><![CDATA[OpenLoco v25.12 is out! This release marks a major milestone for the project. We completed the C++ reimplemention in v25.09 a few months ago, but were still dependent on vanilla memory space. This month, we celebrate the complete reworking of the memory space as well.]]></summary></entry><entry><title type="html">OpenLoco version 25.11</title><link href="https://openloco.io/news/2025/11/openloco-v25.11.html" rel="alternate" type="text/html" title="OpenLoco version 25.11" /><published>2025-11-05T09:45:00+00:00</published><updated>2025-11-05T09:45:00+00:00</updated><id>https://openloco.io/news/2025/11/openloco-v25.11</id><content type="html" xml:base="https://openloco.io/news/2025/11/openloco-v25.11.html"><![CDATA[<p>OpenLoco v25.11 is out! This release introduces some neat quality-of-life features to the game,
as well as several bug fixes. More importantly, we continue our efforts of reworking the game’s
memory space, and the OpenGraphics project is also seeing big progress. Let’s dig in!</p>

<h2 id="prevent-accidental-cargo-removal">Prevent accidental cargo removal</h2>

<p>New contributor @luciditee got back into the game recently, and fell into the age-old trap where
changing vehicles would remove all of their cargo. Never again, they declared. And so,
<a href="https://github.com/OpenLoco/OpenLoco/pull/3323">#3323</a> was filed, which adds a confirmation dialog
to the vehicle component tab. This means changing vehicle/wagon order now prompts for confirmation
<em>if</em> the vehicle is currently transporting cargo. A similar prompt is displayed when refitting a vehicle
to transport different cargo, as can be seen in the screenshot below.</p>

<p><img src="/assets/img/25.11/refit-prompt.jpg" alt="refit prompt" /></p>

<h2 id="rework-remaining-legacy-config-into-modern-config">Rework remaining legacy config into modern config</h2>

<p>Since we started work on OpenLoco, the game has always had two config files: one for the
‘new’ options OpenLoco introduces, and one for the vanilla game’s settings.
Over time, some variables were moved over (e.g. shortcuts), but it was generally
a matter of two worlds.</p>

<p>The main reason for this was that we were still dealing with vanilla game functions that we hadn’t yet
reimplemented in C++. These functions were still expecting to be able to read from the old
config location! As of <a href="/news/2025/09/openloco-v25.09.html">v25.09</a>, all functions have been
reimplemented, though. To be fully implemented, we have to move on config-wise as well.</p>

<p>As of <a href="https://github.com/OpenLoco/OpenLoco/pull/3323">#3323</a>, all config variables are now
stored in the <code class="language-plaintext highlighter-rouge">openloco.yml</code> file. You can find this in the OpenLoco folder in your user profile
(in Windows, this is <code class="language-plaintext highlighter-rouge">AppData\Roaming</code>). Go take a peek!</p>

<h2 id="show-ai-allocations-as-regular-ghost-elements">Show AI allocations as regular ghost elements</h2>

<p>Despite their flaws, some people like playing the game with AI companies enabled. However, sometimes,
there is considerable delay between the AI planning a route and actually building it. In the mean time,
the planned route is reserved using invisible elements. This may be frustrating, as players aren’t
allowed to build over them.</p>

<p>In <a href="https://github.com/OpenLoco/OpenLoco/pull/3270">#3270</a>, a new option
was introduced to make these planned routes visible as ‘ghost’ elements, much like how players’
construction tiles show up. Note that this option is off by default, as we consider it a bit of a cheat.
Below are a few screenshots of what it looks like.</p>

<p><img src="/assets/img/25.11/ai-ghosts-1.png" alt="ai ghosts" /></p>

<p><img src="/assets/img/25.11/ai-ghosts-2.png" alt="ai ghosts" /></p>

<h2 id="merge-sound-and-music-tabs-in-options-window">Merge sound and music tabs in options window</h2>

<p>This month, @LeeSpork continues their quest of making the OpenLoco jukebox experience as smooth as possible.
A longstanding request was to make the music options, and therefore the music volume settings, accessible
from the title screen. In <a href="https://github.com/OpenLoco/OpenLoco/pull/3326">#3326</a>, the tab was revealed
on the title screen. It was quickly followed by <a href="https://github.com/OpenLoco/OpenLoco/pull/3352">#3352</a>, though,
which merges the relatively short ‘sound’ tab into the ‘music’ tab, which is now called ‘audio’.
There are already plans for separate volume controls, e.g. for music and sound effects, so watch this space!</p>

<p><img src="/assets/img/25.11/audio-tab.png" alt="audio tab" /></p>

<h2 id="disallow-interfering-with-competitors-roads-and-road-stations">Disallow interfering with competitor’s roads and road stations</h2>

<p>@LeeSpork discovered that it was possible for players to interfere with competitors’ roads.
They quickly filed patches to prevent competitor road removal (<a href="https://github.com/OpenLoco/OpenLoco/pull/3335">#3335</a>),
as well as competitor road station replacement (<a href="https://github.com/OpenLoco/OpenLoco/pull/3336">#3336</a>).
Nice catch!</p>

<h2 id="add-platform-and-arch-to-title-screen">Add platform and arch to title screen</h2>

<p>As we previously mentioned, as of <a href="/news/2025/09/openloco-v25.09.html">v25.09</a>, all game functions have been
reimplemented in C++. We’re not <em>quite</em> at the point where we can make fully working 64-bit builds
(<a href="https://github.com/OpenLoco/OpenLoco/pull/3288">#3288</a>),
however, we realised this would be a good time to add platform and processor/arch information to the title screen.
With <a href="https://github.com/OpenLoco/OpenLoco/pull/3328">#3328</a> merged,
you can now find this info in the lower-left corner, just below the usual version information.</p>

<h2 id="catch-filestream-exceptions-when-loading-from-cli">Catch FileStream exceptions when loading from CLI</h2>

<p>This may be a bit obscure, but have you ever tried to load OpenLoco with command-line arguments?
As long as you’re passing arguments the game understands, with files that exist, the game
is happy to process everything. If it doesn’t understand an argument, the game assumes you’re
trying to load a file, though. If this ‘file’ doesn’t exist, the game would throw a <code class="language-plaintext highlighter-rouge">FileStream</code>
exception, but not catch it, crashing the game. This is now mitigated by
<a href="https://github.com/OpenLoco/OpenLoco/pull/3363">#3363</a>, letting the game instead
just log a warning to the console.</p>

<h2 id="rename-a-bunch-of-things">Rename a bunch of things</h2>

<p>Over the course of the literal <em>years</em> we’ve worked on OpenLoco, some parts of the codebase
have basically not been touched since they were initially implemented. With the benefit of
understanding the codebase better, some things could be named better, in retrospect.
This month, some community members expressed interest in understanding the path/signal/routing
functions, for example. To make them easier to understand, @duncanspumpkin has renamed
a bunch of variables (<a href="https://github.com/OpenLoco/OpenLoco/pull/3350">#3350</a>).</p>

<p>Following this example, @AaronVanGeffen set out to rename several <code class="language-plaintext highlighter-rouge">sub_</code> functions, that had
not received a new name in the reverse engineering process
(<a href="https://github.com/OpenLoco/OpenLoco/pull/3359">#3359</a>).
Similarly, one of the first game commands we implemented was the <code class="language-plaintext highlighter-rouge">LoadSaveQuitGame</code>
game command. We now understand this better, leading us to rename its arguments
(<a href="https://github.com/OpenLoco/OpenLoco/pull/3367">#3367</a>).</p>

<h2 id="big-loco_global-integration-extravaganza">Big loco_global integration extravaganza</h2>

<p>As we previously mentioned, as of <a href="/news/2025/09/openloco-v25.09.html">v25.09</a>,
all game functions have been reimplemented in C++. However, we still mirror the vanilla game’s
<em>memory space</em> in several places. As often talked about in previous blogs, this is done with
<code class="language-plaintext highlighter-rouge">loco_global</code> instances. When the project started off, these were introduced as a high-level wrapper
around a particular memory address. We’re now at the point where the remaining wrappers
can be reworked. As you might imagine, this is quite a bit of work, still.
Fortunately, this month, we’ve seen a lot of <em>team effort</em> to get there. To illustrate,
while our v25.10 release still had 342 <code class="language-plaintext highlighter-rouge">loco_globals</code>, this month, we’re down to just <strong>157</strong> of them.
This is great progress! Unfortunately, many of the remaining ones are less trivial to tackle…but we’ll get there!</p>

<p>We usually list PR numbers in our dev log sections, however there were 20 PRs just for
<code class="language-plaintext highlighter-rouge">loco_global</code> removal this month! If you’re curious to see what such PRs look like,
you can find them on GitHub. Follow
<a href="https://github.com/OpenLoco/OpenLoco/pulls?q=is%3Apr+milestone%3Av25.11+interop+OR+global+OR+buffer+OR+loco_globals">this link</a>
for a list of the relevant PRs.</p>

<h2 id="opengraphics">OpenGraphics</h2>

<p>Over the last 2 months we’ve have 11 new objects added to the OpenGraphics repo, and 2 updates to existing ones!</p>

<h3 id="roads">Roads</h3>

<ul>
  <li>@shusaura85 replaced <code class="language-plaintext highlighter-rouge">ROADRGH</code> with <code class="language-plaintext highlighter-rouge">OG_ROADRGH</code>:</li>
</ul>

<p><img src="/assets/img/25.11/og_roadrgh.png" alt="OG_ROADRGH" /></p>

<h3 id="bridges">Bridges</h3>

<ul>
  <li>@shusaura85 replaced <code class="language-plaintext highlighter-rouge">BRDGBRCK</code> with <code class="language-plaintext highlighter-rouge">OG_BRDGBRCK</code>:</li>
</ul>

<p><img src="/assets/img/25.11/og_brdgbrck.png" alt="OG_BRDGBRCK" /></p>

<ul>
  <li>@shusaura85 replaced <code class="language-plaintext highlighter-rouge">BRDGWOOD</code> with <code class="language-plaintext highlighter-rouge">OG_BRDGWOOD</code>:</li>
</ul>

<p><img src="/assets/img/25.11/og_brdgwood.png" alt="OG_BRDGWOOD" /></p>

<h3 id="landcliffedge">Land/CliffEdge</h3>

<p>@hibiii added a <em>new</em> land type called <code class="language-plaintext highlighter-rouge">OG_VOID</code>, as well as the corresponding CliffEdge for it, <code class="language-plaintext highlighter-rouge">OG_LSVOID</code>:</p>

<p><img src="/assets/img/25.11/og_void.png" alt="OG_VOID" /></p>

<h3 id="vehicles">Vehicles</h3>

<p>@glenjimen replaced <code class="language-plaintext highlighter-rouge">CATTLE1</code> with <code class="language-plaintext highlighter-rouge">OG_CATTLE1</code>:</p>

<p><img src="/assets/img/25.11/og_cattle1.png" alt="OG_CATTLE1" /></p>

<p>@glenjimen replaced <code class="language-plaintext highlighter-rouge">GOODS3</code> with <code class="language-plaintext highlighter-rouge">OG_GOODS3</code>:</p>

<p><img src="/assets/img/25.11/og_goods3.png" alt="OG_GOODS3" /></p>

<p>@phosporus551 replaced <code class="language-plaintext highlighter-rouge">CL71</code> with <code class="language-plaintext highlighter-rouge">OG_CL71</code>:</p>

<p><img src="/assets/img/25.11/og_cl71.png" alt="OG_CL71" /></p>

<p>@phosporus551 updated <code class="language-plaintext highlighter-rouge">OG_RE441</code> with new sprites from a new rendering pipeline:</p>

<p><img src="/assets/img/25.11/og_re441.png" alt="OG_RE441" /></p>

<p>@phosporus551 replaced <code class="language-plaintext highlighter-rouge">RE442</code> with <code class="language-plaintext highlighter-rouge">OG_RE442</code>:</p>

<p><img src="/assets/img/25.11/og_re442.png" alt="OG_RE444" /></p>

<p>@phosporus551 updated <code class="language-plaintext highlighter-rouge">OG_656</code> with new sprites from a new rendering pipeline:</p>

<p><img src="/assets/img/25.11/og_656.png" alt="OG_656" /></p>

<p>@phosporus551 replaced <code class="language-plaintext highlighter-rouge">460</code> with <code class="language-plaintext highlighter-rouge">OG_460</code>:</p>

<p><img src="/assets/img/25.11/og_460.png" alt="OG_460" /></p>

<p>@phosporus551 replaced <code class="language-plaintext highlighter-rouge">EWIV</code> with <code class="language-plaintext highlighter-rouge">OG_EWIV</code>, as well as the corresponding <code class="language-plaintext highlighter-rouge">EWIVDT</code> with <code class="language-plaintext highlighter-rouge">OG_EWIVDT</code>:</p>

<p><img src="/assets/img/25.11/og_ewiv.png" alt="OG_EWIV" /></p>]]></content><author><name>Aaron van Geffen</name></author><category term="news" /><summary type="html"><![CDATA[OpenLoco v25.11 is out! This release introduces some neat quality-of-life features to the game, as well as several bug fixes. More importantly, we continue our efforts of reworking the game’s memory space, and the OpenGraphics project is also seeing big progress. Let’s dig in!]]></summary></entry></feed>