Hex Editing - Guide: Difference between revisions

From Heroes 3 wiki
Jump to navigation Jump to search
(Editing HotA creatures)
Line 23: Line 23:
QWORD and DWORD pointers are Little Endian representations of an address within the *.exe file, with 0x400000 added to them because of the way the game reads the code. Therefore if you want the DWORD pointer to find 0x27e484, you write it as 84 e4 67 00. DWORDs use IEE-754, while QWORDs use an 8-byte double-precision IEE-754 value.  
QWORD and DWORD pointers are Little Endian representations of an address within the *.exe file, with 0x400000 added to them because of the way the game reads the code. Therefore if you want the DWORD pointer to find 0x27e484, you write it as 84 e4 67 00. DWORDs use IEE-754, while QWORDs use an 8-byte double-precision IEE-754 value.  


Values followed by zeroes in the same block are 4-byte numbers - this essentially increases their available number range from (in decimal) 0-127 to 0-2147483647.


== Heroes ==
== Heroes ==
Line 31: Line 32:
Hero data is written as follows:
Hero data is written as follows:


GG 000000 RR 000000 HH 000000 SO 000000 OL 000000 ST 000000 TL 000000 SB 000000 SP 000000 U1 000000 U2 000000 U3 000000 PS 000000 PL 000000 R0 AS CO,
GG000000 RR000000 HH000000 SO000000 OL000000 ST000000 TL000000 SB000000 SP000000 U1000000 U2000000 U3000000 PS000000 PL000000 R0 AS CO 00,


where:
where:
Line 94: Line 95:
== Editing HotA Heroes ==
== Editing HotA Heroes ==


Hota heroes are coded in the HotA.dat, in the following order: (names written in plain text are also coded in plain text)
Hota heroes are coded in the HotA.dat, in the following order: (names written in quotes are coded in plain text)


07 000000 hero<ref_id> 12 000000 Heroes\hero_<ref_id>.str FACTION #large_portrait_file_name.pcx 0c000000 #small_portrait_file_name.pcx XX 000000 Specialty_Name YY 000000 Specialty Bonus: Object ZZ 000000 {Full Object} specialty_description PP 000000 HeroName QQ 000000 Biography 00000000 01 5c 0000 (number of zeroes may vary) GG 000000 RR 000000 HH 000000 SO 000000 OL 000000 ST 000000 TL 000000 SB 000000 SP 000000 U1 000000 U2 000000 U3 000000 PS 000000 PL 000000 R0 AS C0 00 00000000 00000000 1m 000000 1M 000000 2m 000000 2M 000000 3m 000000 3M 000000 08 000000 I8 TT 000000 ID 000000 AA 000000 DD 000000 DM 000000 U4 000000 U5 000000
07 000000 "hero<ref_id>" 12 000000 "Heroes\hero_<ref_id>.str" FACTION "#large_portrait_file_name.pcx" 0c000000 "#small_portrait_file_name.pcx" XX 000000 "Specialty_Name" YY 000000 "Specialty Bonus: Object" ZZ000000 "{Full Object}" 0d 0a 0d 0a (number of 0a 0d repetitions may differ) "specialty_description" PP000000 "HeroName" QQQQQQQQ "Biography" 00000000 01 5c 0000 (number of zeroes may vary) GG000000 RR000000 HH000000 SO000000 OL000000 ST000000 TL000000 SB000000 SP000000 U1000000 U2000000 U3000000 PS000000 PL000000 R0 AS C0 00 00000000 00000000 1m000000 1M000000 2m000000 2M000000 3m000000 3M000000 08000000 I8000000 TT000000 ID000000 AA000000 DD000000 DM000000 U4000000 U5000000, where:


* FACTION = 09 000000 00000000 0b 000000 for Cove heroes and 09 000000 00000000 00000000 07 000000 for Factory heroes,
* FACTION = 09 000000 00000000 0b 000000 for Cove heroes and 09 000000 00000000 00000000 07 000000 for Factory heroes,
Line 107: Line 108:
* {Full Object} is a text in curly parentheses {} stating again the specialty, f.e. "{Estates}", or "{Pirates, Corsairs and Sea Dogs}".  
* {Full Object} is a text in curly parentheses {} stating again the specialty, f.e. "{Estates}", or "{Pirates, Corsairs and Sea Dogs}".  
* specialty_description: Plain text description.  
* specialty_description: Plain text description.  
* PP = {{unk}} (but seems to be mostly 05 or 06)
* PP = Hero's name's length.
* QQ = {{unk}}, seems to be some sort of an ID as it seems to be unique for each hero; it is not, however, the reference ID.  
* QQQQQQQQ = {{unk}}, seems to be some sort of an ID as it seems to be unique for each hero; it is not, however, the reference ID. All QQ values are around 300 (dec).  
* 1m = minimum number of the first creature type in hero's starting army
* 1m = minimum number of the first creature type in hero's starting army
* 1M = maximum number of the first creature type in hero's starting army
* 1M = maximum number of the first creature type in hero's starting army
Line 118: Line 119:


Heroes in HotA.dat start at 0x23dd and end at 0x9886. Note, that for editing text itself it's best to use programs such as [https://github.com/sake12/HotA-editor/releases HotA Editor], instead of a direct hex-editing.  
Heroes in HotA.dat start at 0x23dd and end at 0x9886. Note, that for editing text itself it's best to use programs such as [https://github.com/sake12/HotA-editor/releases HotA Editor], instead of a direct hex-editing.  
== Editing HotA Creatures ==
While most statistics of base game creatures can be edited rather effortlessly (using MMArchive to unpack H3bitmap.lod or HotA_lng.lod), HotA creatures cannot be edited this way. Their data is stored at the beginning of HotA.dat, as follows:
08 000000 "most<ref_id>" 17 000000 "Monsters\monster<ref_id>.str" 09 000000 00000000 04 000000 "name_abbreviation" KK000000 "<animation_filename>.def" L1000000 "Monster_name (singular)" L2000000  "Monster name (plural)" 00000000 00000000 00000000 00000000 01 74 0000 TT 000000 UL 000000 0c556700  00556700 NNNNNNNN 80da9e03 60da9e03 30da9e03 WC000000 MC000000 OC000000 SC000000 CC000000 GeC000000 GC000000 FV000000 AV000000 GV000000 HG000000 HP000000 SP000000 AT000000 DF000000 DmgL000000 DmgH000000 SH000000 SN000000 OO000000 PP000000 QQ000000 RR000000 VV000000 WW000000 XX000000 YY000000 ZZ000000
* monst<ref_id> is monster's reference id in decimal, f.e. monst154
* name_abbreviation is a 4 letter abbreviation of the monster name. Never appears anywhere ever again. Note that not all abbreviations are just beginning or consonants, f.e. Haspids are written as "aspi" and nix as "nixx". This abbreviation doesn't seem to have to be unique, as Sea Serpent and Haspids have the same 4 letters here. 
* KK is the length of the animation_filename + 4 (and therefore the length of the entire "animation_filename.def"
* <animation_filename>.def  is the file name of the set of animations, saved as .def in HotA.lod or HotA.lod.
* L1 is the length of the monster name (singular)
* L2 is the length of the monster name (plural)
* 0x74 codes as "t" in ASCII
* TT is the reference id of the town the monster belongs to. 0x09 for Cove, 0x0a for Factory, FFFFFFFF for Neutrals and I bet if HotA ever releases a new town
* UL is the unit level -1 (sidenote: this is an example of numbers being used in a list with a zero-based numbering). FFFFFFFF for monsters with no level (f.e. Citadel / Castle Towers)
* 0c556700 (and 00556700) point to a similar table with creature sprite, text and other references in h3hota HD.exe and is probably used to insert the HotA.dat's creature table into this part of the exe.
* NNNNNNNN is equal to 0x10 for all Cove creatures (except the Sea Dog), Leprechauns and Satyrs, but can take different values: f.e. 65040200 for Cannon, 14100100 for Sea Dogs, 12040000 for Fangarms, 00040200 for Steel Golems... I don't know what these values represent, especially since they have such different magnitudes. (Perhaps they're a bitwise monster description being encoded into bytes.) {{unk}}
* 80da9e03, 60da9e03, 30da9e03 - {{unk}}
* WC is the cost of wood necessary to recruit the creature
* MC is the cost of mercury necessary to recruit the creature
* OC is the cost of ore necessary to recruit the creature
* SC is the cost of sulphur necessary to recruit the creature
* CC is the cost of crystals necessary to recruit the creature
* GeC is the cost of gems necessary to recruit the creature
* GC is the cost of gold necessary to recruit the creature. Note that all aforementioned cost values have 4 bytes to play with, so you the maximum unit cost is 2147483647 gold (or of any resource).
* FV is the Fight Value
* AV is the AI Value
* GV is the Growth
* HG is the Horde Growth
* HP is, surprisingly, hit points
* SP is speed
* AT is attack
* DF is defense
* DmgL is low end of the damage range
* DmgH is the high end of the damage range
* SH is the number of shots per battle
* SN is the number of spell casts per battle
* OO, PP, QQ, RR, VV, WW, XX, YY, ZZ - {{unk}}. Sometimes they take up 36 (!) bytes (such as for Ayssids), and sometimes only 8. I suspect they reference some sort of abilities the creatures have, or their descriptions.
When using custom functions or editing original code, note that all HotA (as well as some SoD monsters) have reference ID above 80, and therefore cannot be checked for using a simple check command, such as 83 FA ID. Instead, you have to use a longer command that accepts a 4-byte value (for EDX that would be 81 FA ID 000000).





Revision as of 18:52, 18 September 2024

This page is a work-in-progress. Details listed here may not be 100% accurate.

The following article describes some basics of hex edition. Offsets (and code itself in some locations) may vary based on game version.

Heroes of Might and Magic III is coded in Assembly x86. Each byte (a set of 2 hexadecimal characters) corresponds to either a function, or a value for an already determined function. The only exception is byte 0x90, which is non-coding and may be used to f.e. fill empty space.

Upper majority of creature stats, abilities, etc. is coded within the *.exe. While it may not be readable or understandable to a layman, in short time one can comprehend a lot of the code and find reason and rhyme in it (or at least, parts of it).

To open (and edit) the *.exe files, one needs a hex editor, f.e. frhed or another similar software.

Basics

Majority of HotA Horn of the Abyss additions are not directly in the h3hota.exe (or h3hota HD.exe), but instead in Hota.dat (and partly in HotA.dll).

Numbers

All (or almost all) numbers are written in Little Endian - the bytes are placed in reverse order. As an example, 0xA624C (0x before a number signifies it's hexadecimal) in Little Endian is written as 4C 62 0A 00. Note, that the system recognizes that a number is negative based on the fact that it's greater than half the number range: greater than 0x80 for a single byte, and greater than 0x80000000 for a 4-byte value.

Some numbers use a IEE-754 coding. It is recommended to use a calculator for such values, such as the one available on save-editor.com.

Keep in mind that most (but, surprisingly, not all) lists start at 0, not at 1, so the first element is element 0 and not element 1.

QWORD and DWORD pointers are Little Endian representations of an address within the *.exe file, with 0x400000 added to them because of the way the game reads the code. Therefore if you want the DWORD pointer to find 0x27e484, you write it as 84 e4 67 00. DWORDs use IEE-754, while QWORDs use an 8-byte double-precision IEE-754 value.

Values followed by zeroes in the same block are 4-byte numbers - this essentially increases their available number range from (in decimal) 0-127 to 0-2147483647.

Heroes

Heroes are very easy to edit. Hero data is stored in two sets, one containing general hero data and the other containing only hero specialties. Heroes are generally ordered by their faction (Castle, Rampart, Tower, etc.) and then their class (might or magic). Following standard heroes, are all campaign heroes.

Hero Data

Hero data is written as follows:

GG000000 RR000000 HH000000 SO000000 OL000000 ST000000 TL000000 SB000000 SP000000 U1000000 U2000000 U3000000 PS000000 PL000000 R0 AS CO 00,

where:

  • GG = Gender: 00 is male, 01 is female.
  • RR = Race. These are listed alphabetically, from Demon to Vampire. This has no in-game effect or visibility and the extensions preferred to default everyone to human, except Gelu who gets to be an elf.
  • HH = Class. Classes go in order of factions, and within a faction the might class is listed first. Therefore 00 = Knight, 01 = Cleric, 02 = Ranger, 03 = Druid, etc. Note, that HotA classes essentially "follow" this encoding.
  • SO = First skill (ref. ID).
  • OL = First skill's proficiency level (00 = Basic, * 01 = Advanced, 02 = Expert).
  • ST = Second skill (ref. ID). If there is no second skill, instead, FFFFFFFF is used, replacing ST and the zeroes following it.
  • TL = Second skill level. If there is no second skill, 00 is used (Basic).
  • SB = Spell Book. 00 = absent, 01 = present.
  • SP = Spell (ref. ID). If no spell is present, FFFFFFFF is used instead.
  • U1, U2, U3 = Starting army unit reference IDs.
  • PS = Small Portrait DWORD pointer, which leads to plain text name of the portrait in the H3bitmap.lod.
  • PL = Large Portrait, same as above. 00 = false, 01 = true.
  • R0 = allowed in RoE maps by default. 00 = false, 01 = true.
  • AS = Present by default in all non-RoE maps. 00 = false, 01 = true.
  • CO = Campaign-only. 00 = false, 01 = true.

Hero Specialties

Hero specialties are written one by one in the same order as heroes appear in, starting from 0x00278420.

The specialties look as follows:

TT 000000 ID 000000 AA 000000 DD 000000 DM 000000 U4 000000 U5 000000

TT - Specialty type. The following specialty types exist:

  • 00 = Skill specialty (+5% skill effect per level)
  • 01 = Basic Unit specialty (+1 speed, +1 Attack and Defense every <unit level> levels)
  • 02 = Resource (+1 gems per day, etc.)
  • 03 = Spell (+3% efficiency per level for most spells, sometimes special bonuses instead)
  • 04 = Static Unit specialty (static bonus to attack, defense, damage, speed, or any combination of them), f.e. Xeron, Kalt, Haart Lich, etc.
  • 05 = Speed (Sir Mullich only)
  • 06 = Unit Upgrade specialty (Gelu, Dracon, Bidley, etc.)
  • 07 = Dragon Specialty (Mutare, Mutare Drake)

ID = Reference ID of the specialized in Skill, Unit, Resource or Spell. (Not needed for Dragon and Speed specialties, where it is 00 and an unnecessary, unused 02, respectively).

AA = Attack bonus for Static Unit specialists (and Mutare).

DD = Defense bonus for Static Unit specialists (and Mutare).

DM = Damage bonus for Static Unit specialists (and probably Mutare).

U4 = Second unit (ref. ID) that can be upgraded (only used by Unit Upgrade specialists; otherwise left as 00. Note, that using the same unit twice for Unit Upgrade specialty essentially removes second unit from being upgradable; meanwhile using 00 sets the ID to Pikemen.)

U5 = Resulting unit ref. ID from the upgrade (only for Unit Upgrade specialists).


Note, that using a Unit Upgrade specialist, reference ID of unupgraded creatures ought to be used. F.e., Gelu references Archers and Wood Elves, but code naturally allows also for their upgrades to be improved with his specialty. This does not occur the other way around; specifying ID or U2 as an upgraded creature, will make the upgrade impossible for unupgraded creatures.

Sir Mullich's unit specialty amount (0x02) is located at 0x0E6669.

The amount of resources obtained from a gold specialty is saved at 0x0E4681 (as 350).

Only Xyron is specified to add speed thanks to his static unit specialty. This is (most likely) saved at the following address: 0x4b1b3 ???.

Note, that many "possible" specialties don't exist and simply won't do anything; examples include Tactics specialty, Teleport specialty, etc.


Editing HotA Heroes

Hota heroes are coded in the HotA.dat, in the following order: (names written in quotes are coded in plain text)

07 000000 "hero<ref_id>" 12 000000 "Heroes\hero_<ref_id>.str" FACTION "#large_portrait_file_name.pcx" 0c000000 "#small_portrait_file_name.pcx" XX 000000 "Specialty_Name" YY 000000 "Specialty Bonus: Object" ZZ000000 "{Full Object}" 0d 0a 0d 0a (number of 0a 0d repetitions may differ) "specialty_description" PP000000 "HeroName" QQQQQQQQ "Biography" 00000000 01 5c 0000 (number of zeroes may vary) GG000000 RR000000 HH000000 SO000000 OL000000 ST000000 TL000000 SB000000 SP000000 U1000000 U2000000 U3000000 PS000000 PL000000 R0 AS C0 00 00000000 00000000 1m000000 1M000000 2m000000 2M000000 3m000000 3M000000 08000000 I8000000 TT000000 ID000000 AA000000 DD000000 DM000000 U4000000 U5000000, where:

  • FACTION = 09 000000 00000000 0b 000000 for Cove heroes and 09 000000 00000000 00000000 07 000000 for Factory heroes,
  • #large_portrait_file_name.pcx, #small_portrait_file_name.pcx: # and the appropriate file name, f.e. #HPLP06.pcx
  • XX = ???
  • Specialty_Name is f.e. "Sea Dogs" or "Nix".
  • YY = ???
  • Specialty Bonus: Object refers to the following types of text: "Spell Bonus: Air Shield", "Creature Bonus: Sea Dogs", etc.
  • ZZ = ???
  • {Full Object} is a text in curly parentheses {} stating again the specialty, f.e. "{Estates}", or "{Pirates, Corsairs and Sea Dogs}".
  • specialty_description: Plain text description.
  • PP = Hero's name's length.
  • QQQQQQQQ = ???, seems to be some sort of an ID as it seems to be unique for each hero; it is not, however, the reference ID. All QQ values are around 300 (dec).
  • 1m = minimum number of the first creature type in hero's starting army
  • 1M = maximum number of the first creature type in hero's starting army
  • 2m = minimum number of the second creature type in hero's starting army
  • 2M = maximum number of the second creature type in hero's starting army
  • 3m = minimum number of the third creature type in hero's starting army
  • 3M = maximum number of the third creature type in hero's starting army
  • I8 = reference ID + 8 for heroes before ref ID 178 and reference ID + 7 for heroes after ref ID 178 (essentially, 0xb9 is skipped)

Heroes in HotA.dat start at 0x23dd and end at 0x9886. Note, that for editing text itself it's best to use programs such as HotA Editor, instead of a direct hex-editing.


Editing HotA Creatures

While most statistics of base game creatures can be edited rather effortlessly (using MMArchive to unpack H3bitmap.lod or HotA_lng.lod), HotA creatures cannot be edited this way. Their data is stored at the beginning of HotA.dat, as follows:

08 000000 "most<ref_id>" 17 000000 "Monsters\monster<ref_id>.str" 09 000000 00000000 04 000000 "name_abbreviation" KK000000 "<animation_filename>.def" L1000000 "Monster_name (singular)" L2000000 "Monster name (plural)" 00000000 00000000 00000000 00000000 01 74 0000 TT 000000 UL 000000 0c556700 00556700 NNNNNNNN 80da9e03 60da9e03 30da9e03 WC000000 MC000000 OC000000 SC000000 CC000000 GeC000000 GC000000 FV000000 AV000000 GV000000 HG000000 HP000000 SP000000 AT000000 DF000000 DmgL000000 DmgH000000 SH000000 SN000000 OO000000 PP000000 QQ000000 RR000000 VV000000 WW000000 XX000000 YY000000 ZZ000000

  • monst<ref_id> is monster's reference id in decimal, f.e. monst154
  • name_abbreviation is a 4 letter abbreviation of the monster name. Never appears anywhere ever again. Note that not all abbreviations are just beginning or consonants, f.e. Haspids are written as "aspi" and nix as "nixx". This abbreviation doesn't seem to have to be unique, as Sea Serpent and Haspids have the same 4 letters here.
  • KK is the length of the animation_filename + 4 (and therefore the length of the entire "animation_filename.def"
  • <animation_filename>.def is the file name of the set of animations, saved as .def in HotA.lod or HotA.lod.
  • L1 is the length of the monster name (singular)
  • L2 is the length of the monster name (plural)
  • 0x74 codes as "t" in ASCII
  • TT is the reference id of the town the monster belongs to. 0x09 for Cove, 0x0a for Factory, FFFFFFFF for Neutrals and I bet if HotA ever releases a new town
  • UL is the unit level -1 (sidenote: this is an example of numbers being used in a list with a zero-based numbering). FFFFFFFF for monsters with no level (f.e. Citadel / Castle Towers)
  • 0c556700 (and 00556700) point to a similar table with creature sprite, text and other references in h3hota HD.exe and is probably used to insert the HotA.dat's creature table into this part of the exe.
  • NNNNNNNN is equal to 0x10 for all Cove creatures (except the Sea Dog), Leprechauns and Satyrs, but can take different values: f.e. 65040200 for Cannon, 14100100 for Sea Dogs, 12040000 for Fangarms, 00040200 for Steel Golems... I don't know what these values represent, especially since they have such different magnitudes. (Perhaps they're a bitwise monster description being encoded into bytes.) ???
  • 80da9e03, 60da9e03, 30da9e03 - ???
  • WC is the cost of wood necessary to recruit the creature
  • MC is the cost of mercury necessary to recruit the creature
  • OC is the cost of ore necessary to recruit the creature
  • SC is the cost of sulphur necessary to recruit the creature
  • CC is the cost of crystals necessary to recruit the creature
  • GeC is the cost of gems necessary to recruit the creature
  • GC is the cost of gold necessary to recruit the creature. Note that all aforementioned cost values have 4 bytes to play with, so you the maximum unit cost is 2147483647 gold (or of any resource).
  • FV is the Fight Value
  • AV is the AI Value
  • GV is the Growth
  • HG is the Horde Growth
  • HP is, surprisingly, hit points
  • SP is speed
  • AT is attack
  • DF is defense
  • DmgL is low end of the damage range
  • DmgH is the high end of the damage range
  • SH is the number of shots per battle
  • SN is the number of spell casts per battle
  • OO, PP, QQ, RR, VV, WW, XX, YY, ZZ - ???. Sometimes they take up 36 (!) bytes (such as for Ayssids), and sometimes only 8. I suspect they reference some sort of abilities the creatures have, or their descriptions.


When using custom functions or editing original code, note that all HotA (as well as some SoD monsters) have reference ID above 80, and therefore cannot be checked for using a simple check command, such as 83 FA ID. Instead, you have to use a longer command that accepts a 4-byte value (for EDX that would be 81 FA ID 000000).


External links: