Scripts that implement dialogs inserted into the main game window are put in this
directory.
+
-
+
These tools work by displaying dialogs or overlays in the game window, and
are mostly implemented by lua scripts.
@@ -2728,7 +2739,7 @@ display the word "DFHack" on the screen somewhere while active.
guideline because it arguably just fixes small usability bugs in the game UI.
-
+
Implemented by the manipulator plugin. To activate, open the unit screen and
press 'l'.
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.
directly to the main dwarf mode screen.
-
+
The search plugin adds search to the Stocks, Trading and Unit List screens.
Searching works the same way as the search option in "Move to Depot" does.
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.
-
+
To use, bind to a key and activate in the 'k' mode.
While active, use the suggested keys to switch the usual liquids parameters, and Enter
to select the target area and apply changes.
-
+
To use, bind to a key and activate in the 'q' mode.
Lists mechanisms connected to the building, and their links. Navigating the list centers
the view on the relevant linked buildings.
@@ -2798,7 +2809,7 @@ focus on the current one. Shift-Enter has an effect equivalent to pressing Enter
re-entering the mechanisms ui.
-
+
Backed by the rename plugin, this script allows entering the desired name
via a simple dialog in the game ui.
-
+
To use, bind to a key and activate in the 'q' mode, either immediately or after opening
the assign owner page.
The script lists other rooms owned by the same owner, or by the unit selected in the assign
list, and allows unassigning them.
-
+
Bind to a key, and activate in the Equip->View/Customize page of the military screen.
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
@@ -2831,13 +2842,13 @@ only that entry, and does it even if it is not 'individual choice'.
and may lead to inappropriate weapons being selected.
-
+
Bind to a key, and activate in the Hauling menu with the cursor over a Guide order.
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.
-
+
Bind to a key, and activate with a job selected in a workshop in the 'q' mode.
The script shows a list of the input reagents of the selected job, and allows changing
them like the job item-type and job item-material commands.
@@ -2865,7 +2876,7 @@ and then try to change the input item type, now it won't let you select
plan
you have to unset the material first.
-
+
Bind to a key, and activate with a job selected in a workshop in the 'q' mode.
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
@@ -2887,7 +2898,7 @@ as described in workflow documentation above.
can be used for troubleshooting jobs that don't match the right constraints.
-
+
Bind to a key, and activate when viewing a weapon rack in the 'q' mode.
This script is part of a group of related fixes to make the armory storage
work again. The existing issues are:
@@ -2907,7 +2918,7 @@ the intended user.
-
+
This plugin makes reactions with names starting with SPATTER_ADD_
produce contaminants on the items instead of improvements. The produced
contaminants are immune to being washed away by water or destroyed by
diff --git a/Readme.rst b/Readme.rst
index 7fbc42528..16665ab98 100644
--- a/Readme.rst
+++ b/Readme.rst
@@ -1761,6 +1761,17 @@ gui/*
Scripts that implement dialogs inserted into the main game window are put in this
directory.
+binpatch
+========
+
+Checks, applies or removes binary patches directly in memory at runtime::
+
+ binpatch check/apply/remove
+
+If the name of the patch has no extension or directory separators, the
+script uses ``hack/patches//.dif``, thus auto-selecting
+the version appropriate for the currently loaded executable.
+
quicksave
=========
diff --git a/dfhack.init-example b/dfhack.init-example
index 729747714..885849c33 100644
--- a/dfhack.init-example
+++ b/dfhack.init-example
@@ -132,3 +132,26 @@ tweak fast-trade
tweak military-stable-assign
# in same list, color units already assigned to squads in brown & green
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
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 6f33d5c8a..b141e9fa5 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -346,6 +346,10 @@ install(DIRECTORY ${dfhack_SOURCE_DIR}/scripts
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...
if(BUILD_DEVEL)
if(WIN32)
diff --git a/patches/v0.34.11 SDL/armorstand-capacity.dif b/patches/v0.34.11 SDL/armorstand-capacity.dif
new file mode 100644
index 000000000..e7d69a8c2
--- /dev/null
+++ b/patches/v0.34.11 SDL/armorstand-capacity.dif
@@ -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
diff --git a/patches/v0.34.11 SDL/custom-reagent-size.dif b/patches/v0.34.11 SDL/custom-reagent-size.dif
new file mode 100644
index 000000000..2227a48d0
--- /dev/null
+++ b/patches/v0.34.11 SDL/custom-reagent-size.dif
@@ -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
diff --git a/patches/v0.34.11 SDL/deconstruct-heapfall.dif b/patches/v0.34.11 SDL/deconstruct-heapfall.dif
new file mode 100644
index 000000000..05c0047d3
--- /dev/null
+++ b/patches/v0.34.11 SDL/deconstruct-heapfall.dif
@@ -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
diff --git a/patches/v0.34.11 SDL/deconstruct-teleport.dif b/patches/v0.34.11 SDL/deconstruct-teleport.dif
new file mode 100644
index 000000000..c6037e2c6
--- /dev/null
+++ b/patches/v0.34.11 SDL/deconstruct-teleport.dif
@@ -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
diff --git a/patches/v0.34.11 SDL/hospital-overstocking.dif b/patches/v0.34.11 SDL/hospital-overstocking.dif
new file mode 100644
index 000000000..2bc305e60
--- /dev/null
+++ b/patches/v0.34.11 SDL/hospital-overstocking.dif
@@ -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
diff --git a/patches/v0.34.11 SDL/training-ammo.dif b/patches/v0.34.11 SDL/training-ammo.dif
new file mode 100644
index 000000000..ea50d4221
--- /dev/null
+++ b/patches/v0.34.11 SDL/training-ammo.dif
@@ -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
+
diff --git a/patches/v0.34.11 SDL/weaponrack-unassign.dif b/patches/v0.34.11 SDL/weaponrack-unassign.dif
new file mode 100644
index 000000000..7760048ba
--- /dev/null
+++ b/patches/v0.34.11 SDL/weaponrack-unassign.dif
@@ -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
diff --git a/patches/v0.34.11 linux/armorstand-capacity.dif b/patches/v0.34.11 linux/armorstand-capacity.dif
new file mode 100644
index 000000000..36dbcf0a9
--- /dev/null
+++ b/patches/v0.34.11 linux/armorstand-capacity.dif
@@ -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
diff --git a/patches/v0.34.11 linux/custom-reagent-size.dif b/patches/v0.34.11 linux/custom-reagent-size.dif
new file mode 100644
index 000000000..d99269db1
--- /dev/null
+++ b/patches/v0.34.11 linux/custom-reagent-size.dif
@@ -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
diff --git a/patches/v0.34.11 linux/deconstruct-heapfall.dif b/patches/v0.34.11 linux/deconstruct-heapfall.dif
new file mode 100644
index 000000000..294118ac5
--- /dev/null
+++ b/patches/v0.34.11 linux/deconstruct-heapfall.dif
@@ -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
diff --git a/patches/v0.34.11 linux/deconstruct-teleport.dif b/patches/v0.34.11 linux/deconstruct-teleport.dif
new file mode 100644
index 000000000..3b3212109
--- /dev/null
+++ b/patches/v0.34.11 linux/deconstruct-teleport.dif
@@ -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
diff --git a/patches/v0.34.11 linux/hospital-overstocking.dif b/patches/v0.34.11 linux/hospital-overstocking.dif
new file mode 100644
index 000000000..73e5d2fac
--- /dev/null
+++ b/patches/v0.34.11 linux/hospital-overstocking.dif
@@ -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
diff --git a/patches/v0.34.11 linux/training-ammo.dif b/patches/v0.34.11 linux/training-ammo.dif
new file mode 100644
index 000000000..9fbcabe78
--- /dev/null
+++ b/patches/v0.34.11 linux/training-ammo.dif
@@ -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
diff --git a/patches/v0.34.11 linux/weaponrack-unassign.dif b/patches/v0.34.11 linux/weaponrack-unassign.dif
new file mode 100644
index 000000000..721f235e8
--- /dev/null
+++ b/patches/v0.34.11 linux/weaponrack-unassign.dif
@@ -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
+
diff --git a/scripts/binpatch.lua b/scripts/binpatch.lua
new file mode 100644
index 000000000..f0f14e929
--- /dev/null
+++ b/scripts/binpatch.lua
@@ -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 ')
+end
+run_command(cmd, name)