Add a script for manipulating binary patches at runtime, and some patches.

develop
Alexander Gavrilov 2012-11-11 17:24:13 +04:00
parent f657c20a1d
commit 012d22fa4f
20 changed files with 1440 additions and 70 deletions

@ -11,6 +11,7 @@ DFHack future
- added a small stand-alone utility for applying and removing binary patches. - added a small stand-alone utility for applying and removing binary patches.
- removebadthoughts: add --dry-run option - removebadthoughts: add --dry-run option
New scripts: New scripts:
- binpatch: the same as the stand-alone binpatch.exe, but works at runtime.
- region-pops: displays animal populations of the region and allows tweaking them. - region-pops: displays animal populations of the region and allows tweaking them.
New GUI scripts: New GUI scripts:
- gui/guide-path: displays the cached path for minecart Guide orders. - gui/guide-path: displays the cached path for minecart Guide orders.

@ -489,49 +489,50 @@ access DF memory and allow for easier development of new tools.</p>
<li><a class="reference internal" href="#scripts" id="id114">Scripts</a><ul> <li><a class="reference internal" href="#scripts" id="id114">Scripts</a><ul>
<li><a class="reference internal" href="#fix" id="id115">fix/*</a></li> <li><a class="reference internal" href="#fix" id="id115">fix/*</a></li>
<li><a class="reference internal" href="#gui" id="id116">gui/*</a></li> <li><a class="reference internal" href="#gui" id="id116">gui/*</a></li>
<li><a class="reference internal" href="#quicksave" id="id117">quicksave</a></li> <li><a class="reference internal" href="#binpatch" id="id117">binpatch</a></li>
<li><a class="reference internal" href="#setfps" id="id118">setfps</a></li> <li><a class="reference internal" href="#quicksave" id="id118">quicksave</a></li>
<li><a class="reference internal" href="#siren" id="id119">siren</a></li> <li><a class="reference internal" href="#setfps" id="id119">setfps</a></li>
<li><a class="reference internal" href="#growcrops" id="id120">growcrops</a></li> <li><a class="reference internal" href="#siren" id="id120">siren</a></li>
<li><a class="reference internal" href="#removebadthoughts" id="id121">removebadthoughts</a></li> <li><a class="reference internal" href="#growcrops" id="id121">growcrops</a></li>
<li><a class="reference internal" href="#slayrace" id="id122">slayrace</a></li> <li><a class="reference internal" href="#removebadthoughts" id="id122">removebadthoughts</a></li>
<li><a class="reference internal" href="#magmasource" id="id123">magmasource</a></li> <li><a class="reference internal" href="#slayrace" id="id123">slayrace</a></li>
<li><a class="reference internal" href="#digfort" id="id124">digfort</a></li> <li><a class="reference internal" href="#magmasource" id="id124">magmasource</a></li>
<li><a class="reference internal" href="#superdwarf" id="id125">superdwarf</a></li> <li><a class="reference internal" href="#digfort" id="id125">digfort</a></li>
<li><a class="reference internal" href="#drainaquifer" id="id126">drainaquifer</a></li> <li><a class="reference internal" href="#superdwarf" id="id126">superdwarf</a></li>
<li><a class="reference internal" href="#deathcause" id="id127">deathcause</a></li> <li><a class="reference internal" href="#drainaquifer" id="id127">drainaquifer</a></li>
<li><a class="reference internal" href="#deathcause" id="id128">deathcause</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#in-game-interface-tools" id="id128">In-game interface tools</a><ul> <li><a class="reference internal" href="#in-game-interface-tools" id="id129">In-game interface tools</a><ul>
<li><a class="reference internal" href="#dwarf-manipulator" id="id129">Dwarf Manipulator</a></li> <li><a class="reference internal" href="#dwarf-manipulator" id="id130">Dwarf Manipulator</a></li>
<li><a class="reference internal" href="#search" id="id130">Search</a></li> <li><a class="reference internal" href="#search" id="id131">Search</a></li>
<li><a class="reference internal" href="#gui-liquids" id="id131">gui/liquids</a></li> <li><a class="reference internal" href="#gui-liquids" id="id132">gui/liquids</a></li>
<li><a class="reference internal" href="#gui-mechanisms" id="id132">gui/mechanisms</a></li> <li><a class="reference internal" href="#gui-mechanisms" id="id133">gui/mechanisms</a></li>
<li><a class="reference internal" href="#gui-rename" id="id133">gui/rename</a></li> <li><a class="reference internal" href="#gui-rename" id="id134">gui/rename</a></li>
<li><a class="reference internal" href="#gui-room-list" id="id134">gui/room-list</a></li> <li><a class="reference internal" href="#gui-room-list" id="id135">gui/room-list</a></li>
<li><a class="reference internal" href="#gui-choose-weapons" id="id135">gui/choose-weapons</a></li> <li><a class="reference internal" href="#gui-choose-weapons" id="id136">gui/choose-weapons</a></li>
<li><a class="reference internal" href="#gui-guide-path" id="id136">gui/guide-path</a></li> <li><a class="reference internal" href="#gui-guide-path" id="id137">gui/guide-path</a></li>
<li><a class="reference internal" href="#gui-workshop-job" id="id137">gui/workshop-job</a></li> <li><a class="reference internal" href="#gui-workshop-job" id="id138">gui/workshop-job</a></li>
<li><a class="reference internal" href="#gui-workflow" id="id138">gui/workflow</a></li> <li><a class="reference internal" href="#gui-workflow" id="id139">gui/workflow</a></li>
<li><a class="reference internal" href="#gui-assign-rack" id="id139">gui/assign-rack</a></li> <li><a class="reference internal" href="#gui-assign-rack" id="id140">gui/assign-rack</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#behavior-mods" id="id140">Behavior Mods</a><ul> <li><a class="reference internal" href="#behavior-mods" id="id141">Behavior Mods</a><ul>
<li><a class="reference internal" href="#siege-engine" id="id141">Siege Engine</a><ul> <li><a class="reference internal" href="#siege-engine" id="id142">Siege Engine</a><ul>
<li><a class="reference internal" href="#rationale" id="id142">Rationale</a></li> <li><a class="reference internal" href="#rationale" id="id143">Rationale</a></li>
<li><a class="reference internal" href="#configuration-ui" id="id143">Configuration UI</a></li> <li><a class="reference internal" href="#configuration-ui" id="id144">Configuration UI</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#power-meter" id="id144">Power Meter</a></li> <li><a class="reference internal" href="#power-meter" id="id145">Power Meter</a></li>
<li><a class="reference internal" href="#steam-engine" id="id145">Steam Engine</a><ul> <li><a class="reference internal" href="#steam-engine" id="id146">Steam Engine</a><ul>
<li><a class="reference internal" href="#id1" id="id146">Rationale</a></li> <li><a class="reference internal" href="#id1" id="id147">Rationale</a></li>
<li><a class="reference internal" href="#construction" id="id147">Construction</a></li> <li><a class="reference internal" href="#construction" id="id148">Construction</a></li>
<li><a class="reference internal" href="#operation" id="id148">Operation</a></li> <li><a class="reference internal" href="#operation" id="id149">Operation</a></li>
<li><a class="reference internal" href="#explosions" id="id149">Explosions</a></li> <li><a class="reference internal" href="#explosions" id="id150">Explosions</a></li>
<li><a class="reference internal" href="#save-files" id="id150">Save files</a></li> <li><a class="reference internal" href="#save-files" id="id151">Save files</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#add-spatter" id="id151">Add Spatter</a></li> <li><a class="reference internal" href="#add-spatter" id="id152">Add Spatter</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
@ -2593,18 +2594,28 @@ caused by autodump bugs or other hacking mishaps.</p>
<p>Scripts that implement dialogs inserted into the main game window are put in this <p>Scripts that implement dialogs inserted into the main game window are put in this
directory.</p> directory.</p>
</div> </div>
<div class="section" id="binpatch">
<h2><a class="toc-backref" href="#id117">binpatch</a></h2>
<p>Checks, applies or removes binary patches directly in memory at runtime:</p>
<pre class="literal-block">
binpatch check/apply/remove &lt;patchname&gt;
</pre>
<p>If the name of the patch has no extension or directory separators, the
script uses <tt class="docutils literal"><span class="pre">hack/patches/&lt;df-version&gt;/&lt;name&gt;.dif</span></tt>, thus auto-selecting
the version appropriate for the currently loaded executable.</p>
</div>
<div class="section" id="quicksave"> <div class="section" id="quicksave">
<h2><a class="toc-backref" href="#id117">quicksave</a></h2> <h2><a class="toc-backref" href="#id118">quicksave</a></h2>
<p>If called in dwarf mode, makes DF immediately auto-save the game by setting a flag <p>If called in dwarf mode, makes DF immediately auto-save the game by setting a flag
normally used in seasonal auto-save.</p> normally used in seasonal auto-save.</p>
</div> </div>
<div class="section" id="setfps"> <div class="section" id="setfps">
<h2><a class="toc-backref" href="#id118">setfps</a></h2> <h2><a class="toc-backref" href="#id119">setfps</a></h2>
<p>Run <tt class="docutils literal">setfps &lt;number&gt;</tt> to set the FPS cap at runtime, in case you want to watch <p>Run <tt class="docutils literal">setfps &lt;number&gt;</tt> to set the FPS cap at runtime, in case you want to watch
combat in slow motion or something :)</p> combat in slow motion or something :)</p>
</div> </div>
<div class="section" id="siren"> <div class="section" id="siren">
<h2><a class="toc-backref" href="#id119">siren</a></h2> <h2><a class="toc-backref" href="#id120">siren</a></h2>
<p>Wakes up sleeping units, cancels breaks and stops parties either everywhere, <p>Wakes up sleeping units, cancels breaks and stops parties either everywhere,
or in the burrows given as arguments. In return, adds bad thoughts about or in the burrows given as arguments. In return, adds bad thoughts about
noise, tiredness and lack of protection. Also, the units with interrupted noise, tiredness and lack of protection. Also, the units with interrupted
@ -2612,7 +2623,7 @@ breaks will go on break again a lot sooner. The script is intended for
emergencies, e.g. when a siege appears, and all your military is partying.</p> emergencies, e.g. when a siege appears, and all your military is partying.</p>
</div> </div>
<div class="section" id="growcrops"> <div class="section" id="growcrops">
<h2><a class="toc-backref" href="#id120">growcrops</a></h2> <h2><a class="toc-backref" href="#id121">growcrops</a></h2>
<p>Instantly grow seeds inside farming plots.</p> <p>Instantly grow seeds inside farming plots.</p>
<p>With no argument, this command list the various seed types currently in <p>With no argument, this command list the various seed types currently in
use in your farming plots. use in your farming plots.
@ -2624,7 +2635,7 @@ growcrops plump 40
</pre> </pre>
</div> </div>
<div class="section" id="removebadthoughts"> <div class="section" id="removebadthoughts">
<h2><a class="toc-backref" href="#id121">removebadthoughts</a></h2> <h2><a class="toc-backref" href="#id122">removebadthoughts</a></h2>
<p>This script remove negative thoughts from your dwarves. Very useful against <p>This script remove negative thoughts from your dwarves. Very useful against
tantrum spirals.</p> tantrum spirals.</p>
<p>The script can target a single creature, when used with the <tt class="docutils literal">him</tt> argument, <p>The script can target a single creature, when used with the <tt class="docutils literal">him</tt> argument,
@ -2638,7 +2649,7 @@ but in the short term your dwarves will get much more joyful.</p>
quickly after you unpause.</p> quickly after you unpause.</p>
</div> </div>
<div class="section" id="slayrace"> <div class="section" id="slayrace">
<h2><a class="toc-backref" href="#id122">slayrace</a></h2> <h2><a class="toc-backref" href="#id123">slayrace</a></h2>
<p>Kills any unit of a given race.</p> <p>Kills any unit of a given race.</p>
<p>With no argument, lists the available races.</p> <p>With no argument, lists the available races.</p>
<p>With the special argument <tt class="docutils literal">him</tt>, targets only the selected creature.</p> <p>With the special argument <tt class="docutils literal">him</tt>, targets only the selected creature.</p>
@ -2664,7 +2675,7 @@ slayrace elve magma
</pre> </pre>
</div> </div>
<div class="section" id="magmasource"> <div class="section" id="magmasource">
<h2><a class="toc-backref" href="#id123">magmasource</a></h2> <h2><a class="toc-backref" href="#id124">magmasource</a></h2>
<p>Create an infinite magma source on a tile.</p> <p>Create an infinite magma source on a tile.</p>
<p>This script registers a map tile as a magma source, and every 12 game ticks <p>This script registers a map tile as a magma source, and every 12 game ticks
that tile receives 1 new unit of flowing magma.</p> that tile receives 1 new unit of flowing magma.</p>
@ -2679,7 +2690,7 @@ To remove all placed sources, call <tt class="docutils literal">magmasource stop
<p>With no argument, this command shows an help message and list existing sources.</p> <p>With no argument, this command shows an help message and list existing sources.</p>
</div> </div>
<div class="section" id="digfort"> <div class="section" id="digfort">
<h2><a class="toc-backref" href="#id124">digfort</a></h2> <h2><a class="toc-backref" href="#id125">digfort</a></h2>
<p>A script to designate an area for digging according to a plan in csv format.</p> <p>A script to designate an area for digging according to a plan in csv format.</p>
<p>This script, inspired from quickfort, can designate an area for digging. <p>This script, inspired from quickfort, can designate an area for digging.
Your plan should be stored in a .csv file like this:</p> Your plan should be stored in a .csv file like this:</p>
@ -2697,7 +2708,7 @@ To skip a row in your design, use a single <tt class="docutils literal">;</tt>.<
<p>The script takes the plan filename, starting from the root df folder.</p> <p>The script takes the plan filename, starting from the root df folder.</p>
</div> </div>
<div class="section" id="superdwarf"> <div class="section" id="superdwarf">
<h2><a class="toc-backref" href="#id125">superdwarf</a></h2> <h2><a class="toc-backref" href="#id126">superdwarf</a></h2>
<p>Similar to fastdwarf, per-creature.</p> <p>Similar to fastdwarf, per-creature.</p>
<p>To make any creature superfast, target it ingame using 'v' and:</p> <p>To make any creature superfast, target it ingame using 'v' and:</p>
<pre class="literal-block"> <pre class="literal-block">
@ -2707,17 +2718,17 @@ superdwarf add
<p>This plugin also shortens the 'sleeping' and 'on break' periods of targets.</p> <p>This plugin also shortens the 'sleeping' and 'on break' periods of targets.</p>
</div> </div>
<div class="section" id="drainaquifer"> <div class="section" id="drainaquifer">
<h2><a class="toc-backref" href="#id126">drainaquifer</a></h2> <h2><a class="toc-backref" href="#id127">drainaquifer</a></h2>
<p>Remove all 'aquifer' tag from the map blocks. Irreversible.</p> <p>Remove all 'aquifer' tag from the map blocks. Irreversible.</p>
</div> </div>
<div class="section" id="deathcause"> <div class="section" id="deathcause">
<h2><a class="toc-backref" href="#id127">deathcause</a></h2> <h2><a class="toc-backref" href="#id128">deathcause</a></h2>
<p>Focus a body part ingame, and this script will display the cause of death of <p>Focus a body part ingame, and this script will display the cause of death of
the creature.</p> the creature.</p>
</div> </div>
</div> </div>
<div class="section" id="in-game-interface-tools"> <div class="section" id="in-game-interface-tools">
<h1><a class="toc-backref" href="#id128">In-game interface tools</a></h1> <h1><a class="toc-backref" href="#id129">In-game interface tools</a></h1>
<p>These tools work by displaying dialogs or overlays in the game window, and <p>These tools work by displaying dialogs or overlays in the game window, and
are mostly implemented by lua scripts.</p> are mostly implemented by lua scripts.</p>
<div class="note"> <div class="note">
@ -2728,7 +2739,7 @@ display the word &quot;DFHack&quot; on the screen somewhere while active.</p>
guideline because it arguably just fixes small usability bugs in the game UI.</p> guideline because it arguably just fixes small usability bugs in the game UI.</p>
</div> </div>
<div class="section" id="dwarf-manipulator"> <div class="section" id="dwarf-manipulator">
<h2><a class="toc-backref" href="#id129">Dwarf Manipulator</a></h2> <h2><a class="toc-backref" href="#id130">Dwarf Manipulator</a></h2>
<p>Implemented by the manipulator plugin. To activate, open the unit screen and <p>Implemented by the manipulator plugin. To activate, open the unit screen and
press 'l'.</p> press 'l'.</p>
<p>This tool implements a Dwarf Therapist-like interface within the game UI. The <p>This tool implements a Dwarf Therapist-like interface within the game UI. The
@ -2764,7 +2775,7 @@ cursor onto that cell instead of toggling it.</li>
directly to the main dwarf mode screen.</p> directly to the main dwarf mode screen.</p>
</div> </div>
<div class="section" id="search"> <div class="section" id="search">
<h2><a class="toc-backref" href="#id130">Search</a></h2> <h2><a class="toc-backref" href="#id131">Search</a></h2>
<p>The search plugin adds search to the Stocks, Trading and Unit List screens.</p> <p>The search plugin adds search to the Stocks, Trading and Unit List screens.</p>
<p>Searching works the same way as the search option in &quot;Move to Depot&quot; does. <p>Searching works the same way as the search option in &quot;Move to Depot&quot; does.
You will see the Search option displayed on screen with a hotkey (usually 's'). You will see the Search option displayed on screen with a hotkey (usually 's').
@ -2783,13 +2794,13 @@ Value numbers displayed by the screen. Because of this, pressing the 't'
key while search is active clears the search instead of executing the trade.</p> key while search is active clears the search instead of executing the trade.</p>
</div> </div>
<div class="section" id="gui-liquids"> <div class="section" id="gui-liquids">
<h2><a class="toc-backref" href="#id131">gui/liquids</a></h2> <h2><a class="toc-backref" href="#id132">gui/liquids</a></h2>
<p>To use, bind to a key and activate in the 'k' mode.</p> <p>To use, bind to a key and activate in the 'k' mode.</p>
<p>While active, use the suggested keys to switch the usual liquids parameters, and Enter <p>While active, use the suggested keys to switch the usual liquids parameters, and Enter
to select the target area and apply changes.</p> to select the target area and apply changes.</p>
</div> </div>
<div class="section" id="gui-mechanisms"> <div class="section" id="gui-mechanisms">
<h2><a class="toc-backref" href="#id132">gui/mechanisms</a></h2> <h2><a class="toc-backref" href="#id133">gui/mechanisms</a></h2>
<p>To use, bind to a key and activate in the 'q' mode.</p> <p>To use, bind to a key and activate in the 'q' mode.</p>
<p>Lists mechanisms connected to the building, and their links. Navigating the list centers <p>Lists mechanisms connected to the building, and their links. Navigating the list centers
the view on the relevant linked buildings.</p> the view on the relevant linked buildings.</p>
@ -2798,7 +2809,7 @@ focus on the current one. Shift-Enter has an effect equivalent to pressing Enter
re-entering the mechanisms ui.</p> re-entering the mechanisms ui.</p>
</div> </div>
<div class="section" id="gui-rename"> <div class="section" id="gui-rename">
<h2><a class="toc-backref" href="#id133">gui/rename</a></h2> <h2><a class="toc-backref" href="#id134">gui/rename</a></h2>
<p>Backed by the rename plugin, this script allows entering the desired name <p>Backed by the rename plugin, this script allows entering the desired name
via a simple dialog in the game ui.</p> via a simple dialog in the game ui.</p>
<ul> <ul>
@ -2814,14 +2825,14 @@ It is also possible to rename zones from the 'i' menu.</p>
<p>The <tt class="docutils literal">building</tt> or <tt class="docutils literal">unit</tt> options are automatically assumed when in relevant ui state.</p> <p>The <tt class="docutils literal">building</tt> or <tt class="docutils literal">unit</tt> options are automatically assumed when in relevant ui state.</p>
</div> </div>
<div class="section" id="gui-room-list"> <div class="section" id="gui-room-list">
<h2><a class="toc-backref" href="#id134">gui/room-list</a></h2> <h2><a class="toc-backref" href="#id135">gui/room-list</a></h2>
<p>To use, bind to a key and activate in the 'q' mode, either immediately or after opening <p>To use, bind to a key and activate in the 'q' mode, either immediately or after opening
the assign owner page.</p> the assign owner page.</p>
<p>The script lists other rooms owned by the same owner, or by the unit selected in the assign <p>The script lists other rooms owned by the same owner, or by the unit selected in the assign
list, and allows unassigning them.</p> list, and allows unassigning them.</p>
</div> </div>
<div class="section" id="gui-choose-weapons"> <div class="section" id="gui-choose-weapons">
<h2><a class="toc-backref" href="#id135">gui/choose-weapons</a></h2> <h2><a class="toc-backref" href="#id136">gui/choose-weapons</a></h2>
<p>Bind to a key, and activate in the Equip-&gt;View/Customize page of the military screen.</p> <p>Bind to a key, and activate in the Equip-&gt;View/Customize page of the military screen.</p>
<p>Depending on the cursor location, it rewrites all 'individual choice weapon' entries <p>Depending on the cursor location, it rewrites all 'individual choice weapon' entries
in the selected squad or position to use a specific weapon type matching the assigned in the selected squad or position to use a specific weapon type matching the assigned
@ -2831,13 +2842,13 @@ only that entry, and does it even if it is not 'individual choice'.</p>
and may lead to inappropriate weapons being selected.</p> and may lead to inappropriate weapons being selected.</p>
</div> </div>
<div class="section" id="gui-guide-path"> <div class="section" id="gui-guide-path">
<h2><a class="toc-backref" href="#id136">gui/guide-path</a></h2> <h2><a class="toc-backref" href="#id137">gui/guide-path</a></h2>
<p>Bind to a key, and activate in the Hauling menu with the cursor over a Guide order.</p> <p>Bind to a key, and activate in the Hauling menu with the cursor over a Guide order.</p>
<p>The script displays the cached path that will be used by the order; the game <p>The script displays the cached path that will be used by the order; the game
computes it when the order is executed for the first time.</p> computes it when the order is executed for the first time.</p>
</div> </div>
<div class="section" id="gui-workshop-job"> <div class="section" id="gui-workshop-job">
<h2><a class="toc-backref" href="#id137">gui/workshop-job</a></h2> <h2><a class="toc-backref" href="#id138">gui/workshop-job</a></h2>
<p>Bind to a key, and activate with a job selected in a workshop in the 'q' mode.</p> <p>Bind to a key, and activate with a job selected in a workshop in the 'q' mode.</p>
<p>The script shows a list of the input reagents of the selected job, and allows changing <p>The script shows a list of the input reagents of the selected job, and allows changing
them like the <tt class="docutils literal">job <span class="pre">item-type</span></tt> and <tt class="docutils literal">job <span class="pre">item-material</span></tt> commands.</p> them like the <tt class="docutils literal">job <span class="pre">item-type</span></tt> and <tt class="docutils literal">job <span class="pre">item-material</span></tt> commands.</p>
@ -2865,7 +2876,7 @@ and then try to change the input item type, now it won't let you select <em>plan
you have to unset the material first.</p> you have to unset the material first.</p>
</div> </div>
<div class="section" id="gui-workflow"> <div class="section" id="gui-workflow">
<h2><a class="toc-backref" href="#id138">gui/workflow</a></h2> <h2><a class="toc-backref" href="#id139">gui/workflow</a></h2>
<p>Bind to a key, and activate with a job selected in a workshop in the 'q' mode.</p> <p>Bind to a key, and activate with a job selected in a workshop in the 'q' mode.</p>
<p>This script provides a simple interface to constraints managed by the workflow <p>This script provides a simple interface to constraints managed by the workflow
plugin. When active, it displays a list of all constraints applicable to the plugin. When active, it displays a list of all constraints applicable to the
@ -2887,7 +2898,7 @@ as described in <tt class="docutils literal">workflow</tt> documentation above.
can be used for troubleshooting jobs that don't match the right constraints.</p> can be used for troubleshooting jobs that don't match the right constraints.</p>
</div> </div>
<div class="section" id="gui-assign-rack"> <div class="section" id="gui-assign-rack">
<h2><a class="toc-backref" href="#id139">gui/assign-rack</a></h2> <h2><a class="toc-backref" href="#id140">gui/assign-rack</a></h2>
<p>Bind to a key, and activate when viewing a weapon rack in the 'q' mode.</p> <p>Bind to a key, and activate when viewing a weapon rack in the 'q' mode.</p>
<p>This script is part of a group of related fixes to make the armory storage <p>This script is part of a group of related fixes to make the armory storage
work again. The existing issues are:</p> work again. The existing issues are:</p>
@ -2907,7 +2918,7 @@ the intended user.</p>
</div> </div>
</div> </div>
<div class="section" id="behavior-mods"> <div class="section" id="behavior-mods">
<h1><a class="toc-backref" href="#id140">Behavior Mods</a></h1> <h1><a class="toc-backref" href="#id141">Behavior Mods</a></h1>
<p>These plugins, when activated via configuration UI or by detecting certain <p>These plugins, when activated via configuration UI or by detecting certain
structures in RAWs, modify the game engine behavior concerning the target structures in RAWs, modify the game engine behavior concerning the target
objects to add features not otherwise present.</p> objects to add features not otherwise present.</p>
@ -2918,20 +2929,20 @@ technical challenge, and do not represent any long-term plans to produce more
similar modifications of the game.</p> similar modifications of the game.</p>
</div> </div>
<div class="section" id="siege-engine"> <div class="section" id="siege-engine">
<h2><a class="toc-backref" href="#id141">Siege Engine</a></h2> <h2><a class="toc-backref" href="#id142">Siege Engine</a></h2>
<p>The siege-engine plugin enables siege engines to be linked to stockpiles, and <p>The siege-engine plugin enables siege engines to be linked to stockpiles, and
aimed at an arbitrary rectangular area across Z levels, instead of the original aimed at an arbitrary rectangular area across Z levels, instead of the original
four directions. Also, catapults can be ordered to load arbitrary objects, not four directions. Also, catapults can be ordered to load arbitrary objects, not
just stones.</p> just stones.</p>
<div class="section" id="rationale"> <div class="section" id="rationale">
<h3><a class="toc-backref" href="#id142">Rationale</a></h3> <h3><a class="toc-backref" href="#id143">Rationale</a></h3>
<p>Siege engines are a very interesting feature, but sadly almost useless in the current state <p>Siege engines are a very interesting feature, but sadly almost useless in the current state
because they haven't been updated since 2D and can only aim in four directions. This is an because they haven't been updated since 2D and can only aim in four directions. This is an
attempt to bring them more up to date until Toady has time to work on it. Actual improvements, attempt to bring them more up to date until Toady has time to work on it. Actual improvements,
e.g. like making siegers bring their own, are something only Toady can do.</p> e.g. like making siegers bring their own, are something only Toady can do.</p>
</div> </div>
<div class="section" id="configuration-ui"> <div class="section" id="configuration-ui">
<h3><a class="toc-backref" href="#id143">Configuration UI</a></h3> <h3><a class="toc-backref" href="#id144">Configuration UI</a></h3>
<p>The configuration front-end to the plugin is implemented by the gui/siege-engine <p>The configuration front-end to the plugin is implemented by the gui/siege-engine
script. Bind it to a key and activate after selecting a siege engine in 'q' mode.</p> script. Bind it to a key and activate after selecting a siege engine in 'q' mode.</p>
<p>The main mode displays the current target, selected ammo item type, linked stockpiles and <p>The main mode displays the current target, selected ammo item type, linked stockpiles and
@ -2952,7 +2963,7 @@ menu.</p>
</div> </div>
</div> </div>
<div class="section" id="power-meter"> <div class="section" id="power-meter">
<h2><a class="toc-backref" href="#id144">Power Meter</a></h2> <h2><a class="toc-backref" href="#id145">Power Meter</a></h2>
<p>The power-meter plugin implements a modified pressure plate that detects power being <p>The power-meter plugin implements a modified pressure plate that detects power being
supplied to gear boxes built in the four adjacent N/S/W/E tiles.</p> supplied to gear boxes built in the four adjacent N/S/W/E tiles.</p>
<p>The configuration front-end is implemented by the gui/power-meter script. Bind it to a <p>The configuration front-end is implemented by the gui/power-meter script. Bind it to a
@ -2961,11 +2972,11 @@ key and activate after selecting Pressure Plate in the build menu.</p>
configuration page, but configures parameters relevant to the modded power meter building.</p> configuration page, but configures parameters relevant to the modded power meter building.</p>
</div> </div>
<div class="section" id="steam-engine"> <div class="section" id="steam-engine">
<h2><a class="toc-backref" href="#id145">Steam Engine</a></h2> <h2><a class="toc-backref" href="#id146">Steam Engine</a></h2>
<p>The steam-engine plugin detects custom workshops with STEAM_ENGINE in <p>The steam-engine plugin detects custom workshops with STEAM_ENGINE in
their token, and turns them into real steam engines.</p> their token, and turns them into real steam engines.</p>
<div class="section" id="id1"> <div class="section" id="id1">
<h3><a class="toc-backref" href="#id146">Rationale</a></h3> <h3><a class="toc-backref" href="#id147">Rationale</a></h3>
<p>The vanilla game contains only water wheels and windmills as sources of <p>The vanilla game contains only water wheels and windmills as sources of
power, but windmills give relatively little power, and water wheels require power, but windmills give relatively little power, and water wheels require
flowing water, which must either be a real river and thus immovable and flowing water, which must either be a real river and thus immovable and
@ -2976,7 +2987,7 @@ it can be done just by combining existing features of the game engine
in a new way with some glue code and a bit of custom logic.</p> in a new way with some glue code and a bit of custom logic.</p>
</div> </div>
<div class="section" id="construction"> <div class="section" id="construction">
<h3><a class="toc-backref" href="#id147">Construction</a></h3> <h3><a class="toc-backref" href="#id148">Construction</a></h3>
<p>The workshop needs water as its input, which it takes via a <p>The workshop needs water as its input, which it takes via a
passable floor tile below it, like usual magma workshops do. passable floor tile below it, like usual magma workshops do.
The magma version also needs magma.</p> The magma version also needs magma.</p>
@ -3000,7 +3011,7 @@ short axles that can be built later than both of the engines.</p>
</div> </div>
</div> </div>
<div class="section" id="operation"> <div class="section" id="operation">
<h3><a class="toc-backref" href="#id148">Operation</a></h3> <h3><a class="toc-backref" href="#id149">Operation</a></h3>
<p>In order to operate the engine, queue the Stoke Boiler job (optionally <p>In order to operate the engine, queue the Stoke Boiler job (optionally
on repeat). A furnace operator will come, possibly bringing a bar of fuel, on repeat). A furnace operator will come, possibly bringing a bar of fuel,
and perform it. As a result, a &quot;boiling water&quot; item will appear and perform it. As a result, a &quot;boiling water&quot; item will appear
@ -3031,7 +3042,7 @@ decrease it by further 4%, and also decrease the whole steam
use rate by 10%.</p> use rate by 10%.</p>
</div> </div>
<div class="section" id="explosions"> <div class="section" id="explosions">
<h3><a class="toc-backref" href="#id149">Explosions</a></h3> <h3><a class="toc-backref" href="#id150">Explosions</a></h3>
<p>The engine must be constructed using barrel, pipe and piston <p>The engine must be constructed using barrel, pipe and piston
from fire-safe, or in the magma version magma-safe metals.</p> from fire-safe, or in the magma version magma-safe metals.</p>
<p>During operation weak parts get gradually worn out, and <p>During operation weak parts get gradually worn out, and
@ -3040,7 +3051,7 @@ toppled during operation by a building destroyer, or a
tantruming dwarf.</p> tantruming dwarf.</p>
</div> </div>
<div class="section" id="save-files"> <div class="section" id="save-files">
<h3><a class="toc-backref" href="#id150">Save files</a></h3> <h3><a class="toc-backref" href="#id151">Save files</a></h3>
<p>It should be safe to load and view engine-using fortresses <p>It should be safe to load and view engine-using fortresses
from a DF version without DFHack installed, except that in such from a DF version without DFHack installed, except that in such
case the engines won't work. However actually making modifications case the engines won't work. However actually making modifications
@ -3051,7 +3062,7 @@ being generated.</p>
</div> </div>
</div> </div>
<div class="section" id="add-spatter"> <div class="section" id="add-spatter">
<h2><a class="toc-backref" href="#id151">Add Spatter</a></h2> <h2><a class="toc-backref" href="#id152">Add Spatter</a></h2>
<p>This plugin makes reactions with names starting with <tt class="docutils literal">SPATTER_ADD_</tt> <p>This plugin makes reactions with names starting with <tt class="docutils literal">SPATTER_ADD_</tt>
produce contaminants on the items instead of improvements. The produced produce contaminants on the items instead of improvements. The produced
contaminants are immune to being washed away by water or destroyed by contaminants are immune to being washed away by water or destroyed by

@ -1761,6 +1761,17 @@ gui/*
Scripts that implement dialogs inserted into the main game window are put in this Scripts that implement dialogs inserted into the main game window are put in this
directory. directory.
binpatch
========
Checks, applies or removes binary patches directly in memory at runtime::
binpatch check/apply/remove <patchname>
If the name of the patch has no extension or directory separators, the
script uses ``hack/patches/<df-version>/<name>.dif``, thus auto-selecting
the version appropriate for the currently loaded executable.
quicksave quicksave
========= =========

@ -132,3 +132,26 @@ tweak fast-trade
tweak military-stable-assign tweak military-stable-assign
# in same list, color units already assigned to squads in brown & green # in same list, color units already assigned to squads in brown & green
tweak military-color-assigned tweak military-color-assigned
#######################################################
# Apply binary patches at runtime #
# #
# Commented out by default; enable the ones you want. #
#######################################################
# Bug 5994 - items teleported when removing a construction
#binpatch apply deconstruct-teleport
#binpatch apply deconstruct-heapfall
# Bug 4406 - hospital overstocking on all items
#binpatch apply hospital-overstocking
# Bug 808 - custom reactions completely using up all of their reagents
#binpatch apply custom-reagent-size
# Bug 4530 - marksdwarves not training when quiver full of combat-only ammo
#binpatch apply training-ammo
# Bug 1445 - weapon racks broken, armor stand capacity too low
#binpatch apply weaponrack-unassign
#binpatch apply armorstand-capacity

@ -346,6 +346,10 @@ install(DIRECTORY ${dfhack_SOURCE_DIR}/scripts
PATTERN "*.rb" PATTERN "*.rb"
) )
install(DIRECTORY ${dfhack_SOURCE_DIR}/patches
DESTINATION ${DFHACK_DATA_DESTINATION}
FILES_MATCHING PATTERN "*.dif")
# Unused for so long that it's not even relevant now... # Unused for so long that it's not even relevant now...
if(BUILD_DEVEL) if(BUILD_DEVEL)
if(WIN32) if(WIN32)

@ -0,0 +1,142 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
0x2ac6b
CC CC CC CC CC
66 39 E8 EB 53
.text:0042B86B loc_42B86B:
.text:0042B86B cmp ax, bp
.text:0042B86E jmp short loc_42B8C3
0x2ac7b
CC CC CC CC CC
E9 96 A2 00 00
.text:0042B87B loc_42B87B:
.text:0042B87B jmp loc_435B16
0x2acc3
CC CC CC CC CC CC CC CC CC CC CC CC CC
75 0A 66 FF 4C 24 16 79 03 58 EB AC C3
.text:0042B8C3 loc_42B8C3:
.text:0042B8C3 jnz short locret_42B8CF
.text:0042B8C5 dec word ptr [esp+16h] ; 4+8+8+2
.text:0042B8CA jns short locret_42B8CF
.text:0042B8CC pop eax
.text:0042B8CD jmp short loc_42B87B
.text:0042B8CF locret_42B8CF:
.text:0042B8CF retn
0x2b2a1
CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
66 C7 44 24 0E 01 00 8B 90 44 01 00 00 C3 CC
.text:0042BEA1 loc_42BEA1:
.text:0042BEA1 mov word ptr [esp+0Eh], 1 ; 4+8+2
.text:0042BEA8 mov edx, [eax+144h]
.text:0042BEAE retn
0x34d91
8B 90 44 01 00 00
E8 0B 65 FF FF 90
<<<<
.text:00435991 mov edx, [eax+144h]
====
.text:00435991 call loc_42BEA1
.text:00435996 nop
>>>>
0x34e53
0F 84 BD 00 00 00
E8 6B 5E FF FF 90
<<<<
.text:00435A53 jz loc_435B16
====
.text:00435A53 call loc_42B8C3
.text:00435A58 nop
>>>>
0x34ef3
66 3B C5 74 1E
E8 73 5D FF FF
<<<<
.text:00435AF3 cmp ax, bp
.text:00435AF6 jz short loc_435B16
====
.text:00435AF3 call loc_42B86B
>>>>
basically:
+ int allowed_count = 1; // to mean 2
...
- if (type(item) == new_type)
+ if (type(item) == new_type && --allowed_count < 0)
return false;
to allow up to two items of the same type at the same time
---8<---
This difference file is created by The Interactive Disassembler
Dwarf Fortress.exe
0002AC6B: CC 66
0002AC6C: CC 39
0002AC6D: CC E8
0002AC6E: CC EB
0002AC6F: CC 53
0002AC7B: CC E9
0002AC7C: CC 96
0002AC7D: CC A2
0002AC7E: CC 00
0002AC7F: CC 00
0002ACC3: CC 75
0002ACC4: CC 0A
0002ACC5: CC 66
0002ACC6: CC FF
0002ACC7: CC 4C
0002ACC8: CC 24
0002ACC9: CC 16
0002ACCA: CC 79
0002ACCB: CC 03
0002ACCC: CC 58
0002ACCD: CC EB
0002ACCE: CC AC
0002ACCF: CC C3
0002B2A1: CC 66
0002B2A2: CC C7
0002B2A3: CC 44
0002B2A4: CC 24
0002B2A5: CC 0E
0002B2A6: CC 01
0002B2A7: CC 00
0002B2A8: CC 8B
0002B2A9: CC 90
0002B2AA: CC 44
0002B2AB: CC 01
0002B2AC: CC 00
0002B2AD: CC 00
0002B2AE: CC C3
00034D91: 8B E8
00034D92: 90 0B
00034D93: 44 65
00034D94: 01 FF
00034D95: 00 FF
00034D96: 00 90
00034E53: 0F E8
00034E54: 84 6B
00034E55: BD 5E
00034E56: 00 FF
00034E57: 00 FF
00034E58: 00 90
00034EF3: 66 E8
00034EF4: 3B 73
00034EF5: C5 5D
00034EF6: 74 FF
00034EF7: 1E FF

@ -0,0 +1,91 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=808
Original code:
.text:00916BCE mov edi, ebp
.text:00916BD0 call eax
.text:00916BD2 test eax, eax
.text:00916BD4 jnz short loc_916C1C
.text:00916C0A mov edi, ebp
.text:00916C14 mov edi, ebp
Patch:
0x2ac34:
CC CC CC CC CC CC CC CC CC CC CC CC
8B 7C 24 78 8B 3C B7 FF D0 EB 25 CC
.text:0042B834 loc_42B834:
.text:0042B834 mov edi, [esp+78h]
.text:0042B838 mov edi, [edi+esi*4]
.text:0042B83B call eax
.text:0042B83D jmp short unk_42B864
0x2ac64
CC CC CC CC CC CC CC CC CC CC CC CC
85 C0 E9 69 B3 4E 00 CC CC CC CC CC
.text:0042B864 loc_42B864:
.text:0042B864 test eax, eax
.text:0042B866 jmp loc_916BD4
0x515fce
8B FD FF D0 85 C0
E9 61 4C B1 FF 90
.text:00916BCE jmp loc_42B834
.text:00916BD3 nop
.text:00916BD4 loc_916BD4:
0x51600a
8B FD
90 90
.text:00916C0A nop
.text:00916C0B nop
0x516014
8B FD
90 90
.text:00916C14 nop
.text:00916C15 nop
You can use this script to apply the generated patch below:
http://stalkr.net/files/ida/idadif.py
----8<----
This difference file is created by The Interactive Disassembler
Dwarf Fortress.exe
0002AC34: CC 8B
0002AC35: CC 7C
0002AC36: CC 24
0002AC37: CC 78
0002AC38: CC 8B
0002AC39: CC 3C
0002AC3A: CC B7
0002AC3B: CC FF
0002AC3C: CC D0
0002AC3D: CC EB
0002AC3E: CC 25
0002AC64: CC 85
0002AC65: CC C0
0002AC66: CC E9
0002AC67: CC 69
0002AC68: CC B3
0002AC69: CC 4E
0002AC6A: CC 00
00515FCE: 8B E9
00515FCF: FD 61
00515FD0: FF 4C
00515FD1: D0 B1
00515FD2: 85 FF
00515FD3: C0 90
0051600A: 8B 90
0051600B: FD 90
00516014: 8B 90
00516015: FD 90

@ -0,0 +1,61 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=5994
Original code:
.text:008629BD mov edi, [eax+38h]
.text:008629C0 mov eax, [eax+3Ch]
.text:008629C3 mov [esp+1Ch], eax
.text:008629C7 cmp edi, eax
.text:008629C9 jnb short loc_862A22
.text:008629CB jmp short loc_8629D0
.text:008629CD lea ecx, [ecx+0]
...
.text:00862A19 add edi, 4
.text:00862A1C cmp edi, [esp+1Ch]
.text:00862A20 jb short loc_8629D0
Patch:
0x461dbd
8B 78 38 8B 40 3C 89 44 24 1C 3B F8
8B 78 3C 8B 40 38 89 44 24 1C 39 F8
.text:008629BD mov edi, [eax+3Ch]
.text:008629C0 mov eax, [eax+38h]
.text:008629C3 mov [esp+1Ch], eax
.text:008629C7 cmp eax, edi
0x461dcb
EB 03 8D 49 00
83 EF 04 90 90
.text:008629CB sub edi, 4
.text:008629CE nop
.text:008629CF nop
0x461e19
83 C7 04 3B 7C 24 1C 72 AE
83 EF 04 3B 7C 24 1C 73 AE
.text:00862A19 sub edi, 4
.text:00862A1C cmp edi, [esp+1Ch]
.text:00862A20 jnb short loc_8629D0
You can use this script to apply the generated patch below:
http://stalkr.net/files/ida/idadif.py
----8<----
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
00461DBF: 38 3C
00461DC2: 3C 38
00461DC7: 3B 39
00461DCB: EB 83
00461DCC: 03 EF
00461DCD: 8D 04
00461DCE: 49 90
00461DCF: 00 90
00461E1A: C7 EF
00461E20: 72 73

@ -0,0 +1,104 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=5994
0x461de2
F6 46 0C 01 74 31
E9 0A 8E BC FF 90
.text:008629E2 jmp near ptr loc_42B7F1 ; << CAVE
.text:008629E7 nop
.text:008629E8 loc_8629E8:
0x2abf1
CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
8B 4C 24 2C F6 46 0C 01 75 08 E9 19 72 43 00
.text:0042B7F1 loc_42B7F1:
.text:0042B7F1 mov ecx, [esp+2Ch] ; job
.text:0042B7F5 test byte ptr [esi+0Ch], 1
.text:0042B7F9 jnz short near ptr loc_42B803
.text:0042B7FB coord_test_jfail:
.text:0042B7FB jmp loc_862A19
0x2ac03
CC CC CC CC CC CC CC CC CC CC CC CC CC
8B 41 10 3B 46 04 75 F0 EB 06 CC CC CC
.text:0042B803 loc_42B803:
.text:0042B803 mov eax, [ecx+10h] ; job->pos.(x,y)
.text:0042B806 cmp eax, [esi+4] ; item->pos.(x,y)
.text:0042B809 jnz short coord_test_jfail
.text:0042B80B jmp short near ptr loc_42B813
0x2ac13
CC CC CC CC CC CC CC CC CC CC CC CC CC
66 8B 41 14 66 3B 46 08 75 DE EB 06 CC
text:0042B813 loc_42B813:
.text:0042B813 mov ax, [ecx+14h] ; job->pos.z
.text:0042B817 cmp ax, [esi+8] ; item->pos.z
.text:0042B81B jnz short coord_test_jfail
.text:0042B81D jmp short near ptr loc_42B825
0x2ac25
CC CC CC CC CC CC CC CC CC CC CC
E9 BE 71 43 00 CC CC CC CC CC CC
.text:0042B825 loc_42B825:
.text:0042B825 jmp loc_8629E8
You can use this script to apply the generated patch below:
http://stalkr.net/files/ida/idadif.py
----8<----
This difference file is created by The Interactive Disassembler
Dwarf Fortress.exe
0002ABF1: CC 8B
0002ABF2: CC 4C
0002ABF3: CC 24
0002ABF4: CC 2C
0002ABF5: CC F6
0002ABF6: CC 46
0002ABF7: CC 0C
0002ABF8: CC 01
0002ABF9: CC 75
0002ABFA: CC 08
0002ABFB: CC E9
0002ABFC: CC 19
0002ABFD: CC 72
0002ABFE: CC 43
0002ABFF: CC 00
0002AC03: CC 8B
0002AC04: CC 41
0002AC05: CC 10
0002AC06: CC 3B
0002AC07: CC 46
0002AC08: CC 04
0002AC09: CC 75
0002AC0A: CC F0
0002AC0B: CC EB
0002AC0C: CC 06
0002AC13: CC 66
0002AC14: CC 8B
0002AC15: CC 41
0002AC16: CC 14
0002AC17: CC 66
0002AC18: CC 3B
0002AC19: CC 46
0002AC1A: CC 08
0002AC1B: CC 75
0002AC1C: CC DE
0002AC1D: CC EB
0002AC1E: CC 06
0002AC25: CC E9
0002AC26: CC BE
0002AC27: CC 71
0002AC28: CC 43
0002AC29: CC 00
00461DE2: F6 E9
00461DE3: 46 0A
00461DE4: 0C 8E
00461DE5: 01 BC
00461DE6: 74 FF
00461DE7: 31 90

@ -0,0 +1,62 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=4406
1. Include store in hospital jobs when recomputing counters
0x68a63
0F 85 58 01 00 00
90 90 90 90 90 90
<<<<
.text:00469663 jnz loc_4697C1
====
.text:00469663 nop
.text:00469664 nop
.text:00469665 nop
.text:00469666 nop
.text:00469667 nop
.text:00469668 nop
>>>>
- if (job->getBuildingRef(BUILDING_DESTINATION) != this) continue;
+ // NOP
This reference points to the containers, not the hospital civzone.
Since fixing this properly is too hard for a patch, just remove the
check. Most people have only one hospital anyway, and it is better
to err on the side of caution here.
2. Make the stockpiling code increment the right stock counters
0x3dcbf9
8B 0C 90 8B 81 80 00 00 00
8B 3C 90 8B 87 80 00 00 00
<<<<
.text:007DD7F9 mov ecx, [eax+edx*4]
.text:007DD7FC mov eax, [ecx+80h]
====
.text:007DD7F9 mov edi, [eax+edx*4]
.text:007DD7FC mov eax, [edi+80h]
>>>>
- id = civzones[i]->children[child_idx[i]]->id
+ cur_civzone = civzones[i] // existing var from previous loop
+ id = cur_civzone->children[child_idx[i]]->id
The reason being, later code uses that var (at this point containing
useless data) to increment counters and amounts in the hospital.
---8<---
This difference file is created by The Interactive Disassembler
Dwarf Fortress.exe
00068A63: 0F 90
00068A64: 85 90
00068A65: 58 90
00068A66: 01 90
00068A67: 00 90
00068A68: 00 90
003DCBFA: 0C 3C
003DCBFD: 81 87

@ -0,0 +1,83 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=4530
0x2ac85
CC CC CC CC CC CC CC CC CC CC CC
29 44 24 24 8B 9D 28 01 00 00 C3
.text:0042B885 loc_42B885:
.text:0042B885 sub [esp+24h], eax
.text:0042B889 mov ebx, [ebp+128h]
.text:0042B88F retn
0x2ac94
CC CC CC CC CC CC CC CC CC CC CC CC
89 C1 8B 00 FF 90 34 02 00 00 EB E5
.text:0042B894 loc_42B894:
.text:0042B894 mov ecx, eax
.text:0042B896 mov eax, [eax]
.text:0042B898 call dword ptr [eax+234h]
.text:0042B89E jmp short loc_42B885
0x6e28ff
29 44 24 20
90 90 90 90
<<<<
.text:00AE34FF sub [esp+20h], eax
====
.text:00AE34FF nop
.text:00AE3500 nop
.text:00AE3501 nop
.text:00AE3502 nop
>>>>
0x6e2999
8B 9D 28 01 00 00
E8 F6 82 94 FF 90
<<<<
.text:00AE3599 mov ebx, [ebp+128h]
====
.text:00AE3599 call loc_42B894
.text:00AE359E nop
>>>>
---8<---
This difference file is created by The Interactive Disassembler
Dwarf Fortress.exe
0002AC85: CC 29
0002AC86: CC 44
0002AC87: CC 24
0002AC88: CC 24
0002AC89: CC 8B
0002AC8A: CC 9D
0002AC8B: CC 28
0002AC8C: CC 01
0002AC8D: CC 00
0002AC8E: CC 00
0002AC8F: CC C3
0002AC94: CC 89
0002AC95: CC C1
0002AC96: CC 8B
0002AC97: CC 00
0002AC98: CC FF
0002AC99: CC 90
0002AC9A: CC 34
0002AC9B: CC 02
0002AC9C: CC 00
0002AC9D: CC 00
0002AC9E: CC EB
0002AC9F: CC E5
006E28FF: 29 90
006E2900: 44 90
006E2901: 24 90
006E2902: 20 90
006E2999: 8B E8
006E299A: 9D F6
006E299B: 28 82
006E299C: 01 94
006E299D: 00 FF
006E299E: 00 90

@ -0,0 +1,61 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
0x4c05c4
8B 8C 24 80 00 00 00
89 C1 90 90 90 90 90
<<<<
.text:008C11C4 mov ecx, [esp+98h+var_18]
====
.text:008C11C4 mov ecx, eax
.text:008C11C6 nop
.text:008C11C7 nop
.text:008C11C8 nop
.text:008C11C9 nop
.text:008C11CA nop
>>>>
0x4c06a1
8B 8C 24 80 00 00 00
89 C1 90 90 90 90 90
<<<<
.text:008C12A1 mov ecx, [esp+98h+var_18]
====
.text:008C12A1 mov ecx, eax
.text:008C12A3 nop
.text:008C12A4 nop
.text:008C12A5 nop
.text:008C12A6 nop
.text:008C12A7 nop
>>>>
basically:
b_squad_id = building->getSpecificSquad();
- if (b_squad_id != squad->id || !building->canUse(some_squad_id, 4))
+ if (b_squad_id != squad->id || !building->canUse(b_squad_id, 4))
unassign(building);
the reason being, some_other_squad_id contains irrelevant garbage at this point
---8<---
This difference file is created by The Interactive Disassembler
Dwarf Fortress.exe
004C05C4: 8B 89
004C05C5: 8C C1
004C05C6: 24 90
004C05C7: 80 90
004C05C8: 00 90
004C05C9: 00 90
004C05CA: 00 90
004C06A1: 8B 89
004C06A2: 8C C1
004C06A3: 24 90
004C06A4: 80 90
004C06A5: 00 90
004C06A6: 00 90
004C06A7: 00 90

@ -0,0 +1,147 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
0x9461
90 90 90 90 90 90 90 90 90 90 90 90 90 90
C7 44 24 18 01 00 00 00 FF A0 44 01 00 00
.text:08051461 sub_8051461 proc near
.text:08051461 mov dword ptr [esp+18h], 1
.text:08051469 jmp dword ptr [eax+144h]
.text:08051469 sub_8051461 endp
0x9548
90 90 90 90 90 90 90 90
FF 4C 24 14 78 08 EB 0B
.text:08051548 loc_8051548:
.text:08051548 dec dword ptr [esp+14h]
.text:0805154C js short loc_8051556
.text:0805154E jmp short loc_805155B
0x9556
90 90 90 90 90 90 90 90 90 90
E9 F6 8C 05 00 E9 D0 8D 05 00
.text:08051556 loc_8051556:
.text:08051556 jmp loc_80AA251
.text:0805155B loc_805155B:
.text:0805155B jmp loc_80AA330
0x9568
90 90 90 90 90 90 90 90
FF 4C 24 14 78 E8 EB 06
.text:08051568 loc_8051568:
.text:08051568 dec [esp+14h]
.text:0805156C js short loc_8051556
.text:0805156E jmp short loc_8051576
0x9576
90 90 90 90 90
E9 4D 8E 05 00
.text:08051576 loc_8051576:
.text:08051576 jmp loc_80AA3C8
0x62243
FF 90 44 01 00 00
E8 19 72 FA FF 90
<<<<
.text:080AA243 call dword ptr [eax+144h]
====
.text:080AA243 call sub_8051461
.text:080AA248 nop
>>>>
0x62369
E9 E3 FE FF FF
E9 DA 71 FA FF
<<<<
.text:080AA369 jmp loc_80AA251
====
.text:080AA369 jmp loc_8051548
>>>>
0x623f6
E9 56 FE FF FF
E9 6D 71 FA FF
<<<<
.text:080AA3F6 jmp loc_80AA251
====
.text:080AA3F6 jmp loc_8051568
>>>>
basically:
+ int allowed_count = 1; // to mean 2
...
- if (type(item) == new_type)
+ if (type(item) == new_type && --allowed_count < 0)
return false;
to allow up to two items of the same type at the same time
---8<---
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
00009461: 90 C7
00009462: 90 44
00009463: 90 24
00009464: 90 18
00009465: 90 01
00009466: 90 00
00009467: 90 00
00009468: 90 00
00009469: 90 FF
0000946A: 90 A0
0000946B: 90 44
0000946C: 90 01
0000946D: 90 00
0000946E: 90 00
00009548: 90 FF
00009549: 90 4C
0000954A: 90 24
0000954B: 90 14
0000954C: 90 78
0000954D: 90 08
0000954E: 90 EB
0000954F: 90 0B
00009556: 90 E9
00009557: 90 F6
00009558: 90 8C
00009559: 90 05
0000955A: 90 00
0000955B: 90 E9
0000955C: 90 D0
0000955D: 90 8D
0000955E: 90 05
0000955F: 90 00
00009568: 90 FF
00009569: 90 4C
0000956A: 90 24
0000956B: 90 14
0000956C: 90 78
0000956D: 90 E8
0000956E: 90 EB
0000956F: 90 06
00009576: 90 E9
00009577: 90 4D
00009578: 90 8E
00009579: 90 05
0000957A: 90 00
00062243: FF E8
00062244: 90 19
00062245: 44 72
00062246: 01 FA
00062247: 00 FF
00062248: 00 90
0006236A: E3 DA
0006236B: FE 71
0006236C: FF FA
000623F7: 56 6D
000623F8: FE 71
000623F9: FF FA

@ -0,0 +1,40 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=808
for (i = 0; i < num_items; i++)
{
ridx = reagent_idx[i];
sz = reagent_quantity[ridx]; // used quantity
if (sz <= 0) continue;
reag = reagent[ridx];
if (reag->flags.PRESERVE_REAGENT) continue;
rsz = items[i]->getTotalDimension();
<<<<<<<<
if (reag->flags3.ANY_RAW_MATERIAL)
rsz *= BASE_SIZE(items[i]->getType());
if (items[i]->subtractDimension(rsz))
========
/* Not in patch, but necessary for full correctness:
if (reag->flags3.ANY_RAW_MATERIAL)
rsz /= BASE_SIZE(items[i]->getType());
*/
if (reag->flags3.ANY_RAW_MATERIAL)
sz *= BASE_SIZE(items[i]->getType());
if (items[i]->subtractDimension(sz))
>>>>>>>>
destroy_item(items[i]);
reagent_quantity[ridx] -= rsz
if (reagent_quantity[ridx] < 0)
reagent_quantity[ridx] = 0;
}
You can use this script to apply the generated patch below:
http://stalkr.net/files/ida/idadif.py
----8<----
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
0087F7EF: F8 D8
0087F86F: F8 D8
0087F9AD: C7 C3
0087F9ED: C7 C3

@ -0,0 +1,83 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=5994
Original code:
.text:087AC378 cmp edx, eax
.text:087AC37A mov [esp+4Ch], eax
.text:087AC37E jnb loc_87A7034
.text:087AC384 mov [esp+48h], edx
.text:087AC388 mov [esp+54h], ebx
...
.text:087AC440 add dword ptr [esp+48h], 4
.text:087AC445 mov ebp, [esp+48h]
.text:087AC449 cmp [esp+4Ch], ebp
.text:087AC44D ja loc_87AC38C
Patch:
0x76437a
89 44 24 4C
89 54 24 4C
.text:087AC37A mov [esp+4Ch], edx
0x764384
89 54 24 48 89 5C 24 54
E8 8A 51 8A FF 90 90 90
.text:087AC384 call sub_8051513
.text:087AC389 nop
.text:087AC38A nop
.text:087AC38B nop
0x764440
83 44 24 48 04 8B 6C 24 48 39 6C 24 4C 0F 87 39 FF FF FF
83 6C 24 48 04 8B 6C 24 48 39 6C 24 4C 0F 86 39 FF FF FF
.text:087AC440 sub dword ptr [esp+48h], 4
.text:087AC445 mov ebp, [esp+48h]
.text:087AC449 cmp [esp+4Ch], ebp
.text:087AC44D jbe loc_87AC38C
0x9513
90 90 90 90 90 90 90 90 90 90 90 90 90
83 E8 04 89 44 24 4C 89 5C 24 58 C3 90
.text:08051513 sub_8051513 proc near
.text:08051513 sub eax, 4
.text:08051516 mov [esp+4Ch], eax ; 48h
.text:0805151A mov [esp+58h], ebx ; 54h
.text:0805151E retn
.text:0805151E sub_8051513 endp
You can use this script to apply the generated patch below:
http://stalkr.net/files/ida/idadif.py
----8<----
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
00009513: 90 83
00009514: 90 E8
00009515: 90 04
00009516: 90 89
00009517: 90 44
00009518: 90 24
00009519: 90 4C
0000951A: 90 89
0000951B: 90 5C
0000951C: 90 24
0000951D: 90 58
0000951E: 90 C3
0076437B: 44 54
00764384: 89 E8
00764385: 54 8A
00764386: 24 51
00764387: 48 8A
00764388: 89 FF
00764389: 5C 90
0076438A: 24 90
0076438B: 54 90
00764441: 44 6C
0076444E: 87 86

@ -0,0 +1,139 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=5994
0x7643f8
F6 46 0C 01 74 42
E9 B6 50 8A FF 90
.text:087AC3F8 jmp loc_80514B3 ; << CAVE
.text:087AC3FD nop
.text:087AC3FE loc_87AC3FE:
0x94b3
90 90 90 90 90 90 90 90 90 90 90 90 90
F6 46 0C 01 75 0A E9 82 AF 75 00 90 90
.text:080514B3 loc_80514B3:
.text:080514B3 test byte ptr [esi+0Ch], 1
.text:080514B7 jnz short loc_80514C3
.text:080514B9 coord_test_jfail:
.text:080514B9 jmp loc_87AC440
0x94c3
90 90 90 90 90 90 90 90 90 90 90 90 90
8D 9C 24 60 03 00 00 0F BF 03 EB 07 90
.text:080514C3 loc_80514C3:
.text:080514C3 lea ebx, [esp+360h]
.text:080514CA movsx eax, word ptr [ebx] ; job_z
.text:080514CD jmp short loc_80514D6
0x94d6
90 90 90 90 90 90 90 90 90 90
66 3B 46 08 75 DD EB 05 90 90
.text:080514D6 loc_80514D6:
.text:080514D6 cmp ax, [esi+8] ; item->pos.z
.text:080514DA jnz short coord_test_jfail
.text:080514DC jmp short loc_80514E3
0x94e3
90 90 90 90 90 90 90 90 90 90 90 90 90
0F BF 43 10 66 3B 46 04 75 CC EB 04 90
.text:080514E3 loc_80514E3:
.text:080514E3 movsx eax, word ptr [ebx+10h] ; job_x
.text:080514E7 cmp ax, [esi+4] ; item->pos.x
.text:080514EB jnz short coord_test_jfail
.text:080514ED jmp short loc_80514F3
0x94f3
90 90 90 90 90 90 90 90 90 90 90 90 90
0F BF 43 20 66 3B 46 06 75 BC EB 04 90
.text:080514F3 loc_80514F3:
.text:080514F3 movsx eax, word ptr [ebx+20h] ; job_y
.text:080514F7 cmp ax, [esi+6] ; item->pos.y
.text:080514FB jnz short coord_test_jfail
.text:080514FD jmp short loc_8051503
0x9503
90 90 90 90 90 90 90 90 90 90 90 90 90
E9 F6 AE 75 00 90 90 90 90 90 90 90 90
.text:08051503 loc_8051503:
.text:08051503 jmp loc_87AC3FE
You can use this script to apply the generated patch below:
http://stalkr.net/files/ida/idadif.py
----8<----
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
000094B3: 90 F6
000094B4: 90 46
000094B5: 90 0C
000094B6: 90 01
000094B7: 90 75
000094B8: 90 0A
000094B9: 90 E9
000094BA: 90 82
000094BB: 90 AF
000094BC: 90 75
000094BD: 90 00
000094C3: 90 8D
000094C4: 90 9C
000094C5: 90 24
000094C6: 90 60
000094C7: 90 03
000094C8: 90 00
000094C9: 90 00
000094CA: 90 0F
000094CB: 90 BF
000094CC: 90 03
000094CD: 90 EB
000094CE: 90 07
000094D6: 90 66
000094D7: 90 3B
000094D8: 90 46
000094D9: 90 08
000094DA: 90 75
000094DB: 90 DD
000094DC: 90 EB
000094DD: 90 05
000094E3: 90 0F
000094E4: 90 BF
000094E5: 90 43
000094E6: 90 10
000094E7: 90 66
000094E8: 90 3B
000094E9: 90 46
000094EA: 90 04
000094EB: 90 75
000094EC: 90 CC
000094ED: 90 EB
000094EE: 90 04
000094F3: 90 0F
000094F4: 90 BF
000094F5: 90 43
000094F6: 90 20
000094F7: 90 66
000094F8: 90 3B
000094F9: 90 46
000094FA: 90 06
000094FB: 90 75
000094FC: 90 BC
000094FD: 90 EB
000094FE: 90 04
00009503: 90 E9
00009504: 90 F6
00009505: 90 AE
00009506: 90 75
00009507: 90 00
007643F8: F6 E9
007643F9: 46 B6
007643FA: 0C 50
007643FB: 01 8A
007643FC: 74 FF
007643FD: 42 90

@ -0,0 +1,60 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=4406
1. Include store in hospital jobs when recomputing counters
0x746d7
75 D7
90 90
<<<<
.text:080BC6D7 jnz short loc_80BC6B0
====
.text:080BC6D7 nop
.text:080BC6D8 nop
>>>>
- if (job->getBuildingRef(BUILDING_DESTINATION) != this) continue;
+ // NOP
This reference points to the containers, not the hospital civzone.
Since fixing this properly is too hard for a patch, just remove the
check. Most people have only one hospital anyway, and it is better
to err on the side of caution here.
2. Make the stockpiling code increment the right stock counters
0x67cb0e
0B 04 90
8B 1C 90
0x67cb18
8B 40 74
8B 43 74
<<<<
.text:086C4B0E mov eax, [eax+edx*4]
.text:086C4B11 mov edx, [esp+ecx*4+39Ch+var_2B4]
.text:086C4B18 mov eax, [eax+74h]
====
.text:086C4B0E mov ebx, [eax+edx*4]
.text:086C4B11 mov edx, [esp+ecx*4+39Ch+var_2B4]
.text:086C4B18 mov eax, [ebx+74h]
>>>>
- id = civzones[i]->children[child_idx[i]]->id
+ cur_civzone = civzones[i] // existing var from previous loop
+ id = cur_civzone->children[child_idx[i]]->id
The reason being, later code uses that var (at this point containing
useless data) to increment counters and amounts in the hospital.
---8<---
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
000746D7: 75 90
000746D8: D7 90
0067CB0F: 04 1C
0067CB19: 40 43

@ -0,0 +1,85 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=4530
0x9508
90 90 90 90 90 90 90 90
E9 13 76 9C 00 90 90 90
.text:08051508 loc_8051508:
.text:08051508 jmp sub_8A18B20
0x9523
90 90 90 90 90 90 90 90 90 90 90 90 90
50 8B 03 53 FF 90 34 02 00 00 EB 09 90
.text:08051523 sub_8051523:
.text:08051523 push eax
.text:08051524 mov eax, [ebx]
.text:08051526 push ebx
.text:08051527 call dword ptr [eax+234h]
.text:0805152D jmp short loc_8051538
0x9538
90 90 90 90 90 90 90 90
29 44 24 64 5B 58 EB C8
.text:08051538 loc_8051538:
.text:08051538 sub [esp+64h], eax
.text:0805153C pop ebx
.text:0805153D pop eax
.text:0805153E jmp short loc_8051508
0xa5cdd0
29 44 24 58
90 90 90 90
.text:08AA4DD0 nop
.text:08AA4DD1 nop
.text:08AA4DD2 nop
.text:08AA4DD3 nop
0xa5e2c3
E8 58 28 F7 FF
E8 5B B2 5A FF
.text:08AA62C3 call sub_8051523
---8<---
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
00009508: 90 E9
00009509: 90 13
0000950A: 90 76
0000950B: 90 9C
0000950C: 90 00
00009523: 90 50
00009524: 90 8B
00009525: 90 03
00009526: 90 53
00009527: 90 FF
00009529: 90 34
0000952A: 90 02
0000952B: 90 00
0000952C: 90 00
0000952D: 90 EB
0000952E: 90 09
00009538: 90 29
00009539: 90 44
0000953A: 90 24
0000953B: 90 64
0000953C: 90 5B
0000953D: 90 58
0000953E: 90 EB
0000953F: 90 C8
00A5CDD0: 29 90
00A5CDD1: 44 90
00A5CDD2: 24 90
00A5CDD3: 58 90
00A5E2C4: 58 5B
00A5E2C5: 28 B2
00A5E2C6: F7 5A

@ -0,0 +1,45 @@
http://www.bay12games.com/dwarves/mantisbt/view.php?id=1445
Fix use of uninitialized variables to stop auto-unassigning racks:
0x7ee948
8B 7C 24 3C
89 C7 90 90
.text:08836948 mov edi, eax
.text:0883694A nop
.text:0883694B nop
0x7eea2f
8B 7C 24 3C
89 C7 90 90
.text:08836A2F mov edi, eax
.text:08836A31 nop
.text:08836A32 nop
basically:
b_squad_id = building->getSpecificSquad();
- if (b_squad_id != squad->id || !building->canUse(some_squad_id, 4))
+ if (b_squad_id != squad->id || !building->canUse(b_squad_id, 4))
unassign(building);
the reason being, some_other_squad_id contains irrelevant garbage at this point
---8<---
This difference file is created by The Interactive Disassembler
Dwarf_Fortress
007EE948: 8B 89
007EE949: 7C C7
007EE94A: 24 90
007EE94B: 3C 90
007EEA2F: 8B 89
007EEA30: 7C C7
007EEA31: 24 90
007EEA32: 3C 90

@ -0,0 +1,117 @@
-- Apply or remove binary patches at runtime.
local utils = require('utils')
function load_patch(name)
local filename = name
local auto = false
if not string.match(filename, '[./\\]') then
auto = true
filename = dfhack.getHackPath()..'/patches/'..dfhack.getDFVersion()..'/'..name..'.dif'
end
local file, err = io.open(filename, 'r')
if not file then
if auto and string.match(err, ': No such file or directory') then
return nil, 'no patch '..name..' for '..dfhack.getDFVersion()
else
return nil, err
end
end
local old_bytes = {}
local new_bytes = {}
for line in file:lines() do
if string.match(line, '^%x+:') then
local offset, oldv, newv = string.match(line, '^(%x+):%s*(%x+)%s+(%x+)%s*$')
if not offset then
file:close()
return nil, 'Could not parse: '..line
end
offset, oldv, newv = tonumber(offset,16), tonumber(oldv,16), tonumber(newv,16)
if oldv > 255 or newv > 255 then
file:close()
return nil, 'Invalid byte values: '..line
end
old_bytes[offset] = oldv
new_bytes[offset] = newv
end
end
return { name = name, old_bytes = old_bytes, new_bytes = new_bytes }
end
function rebase_table(input)
local output = {}
local base = dfhack.internal.getImageBase()
for k,v in pairs(input) do
local offset = dfhack.internal.adjustOffset(k)
if not offset then
return nil, string.format('invalid offset: %x', k)
end
output[base + offset] = v
end
return output
end
function rebase_patch(patch)
local nold, err = rebase_table(patch.old_bytes)
if not nold then return nil, err end
local nnew, err = rebase_table(patch.new_bytes)
if not nnew then return nil, err end
return { name = patch.name, old_bytes = nold, new_bytes = nnew }
end
function run_command(cmd,name)
local patch, err = load_patch(name)
if not patch then
dfhack.printerr('Could not load: '..err)
return
end
local rpatch, err = rebase_patch(patch)
if not rpatch then
dfhack.printerr(name..': '..err)
return
end
if cmd == 'check' then
local old_ok, err, addr = dfhack.internal.patchBytes({}, rpatch.old_bytes)
if old_ok then
print(name..': patch is not applied.')
elseif dfhack.internal.patchBytes({}, rpatch.new_bytes) then
print(name..': patch is applied.')
else
dfhack.printerr(string.format('%s: conflict at address %x', name, addr))
end
elseif cmd == 'apply' then
local ok, err, addr = dfhack.internal.patchBytes(rpatch.new_bytes, rpatch.old_bytes)
if ok then
print(name..': applied the patch.')
elseif dfhack.internal.patchBytes({}, rpatch.new_bytes) then
print(name..': patch is already applied.')
else
dfhack.printerr(string.format('%s: conflict at address %x', name, addr))
end
elseif cmd == 'remove' then
local ok, err, addr = dfhack.internal.patchBytes(rpatch.old_bytes, rpatch.new_bytes)
if ok then
print(name..': removed the patch.')
elseif dfhack.internal.patchBytes({}, rpatch.old_bytes) then
print(name..': patch is already removed.')
else
dfhack.printerr(string.format('%s: conflict at address %x', name, addr))
end
else
qerror('Invalid command: '..cmd)
end
end
local cmd,name = ...
if not cmd or not name then
qerror('Usage: binpatch check/apply/remove <patchname>')
end
run_command(cmd, name)