about Necromamcy targeted creature in Heroes2w.exe

The old Heroes games developed by New World Computing. Please specify which game you are referring to in your post.
scbw1234
Leprechaun
Leprechaun
Posts: 10
Joined: 21 Apr 2014
Location: China

about Necromamcy targeted creature in Heroes2w.exe

Unread postby scbw1234 » 21 Apr 2014, 17:01

Which hex address is it to change Necrmancy skill from creating skeletons to vampires in HOMM2?

User avatar
Darmani
Blood Fury
Blood Fury
Posts: 479
Joined: 06 Jan 2006
Location: Cambridge, MA

Unread postby Darmani » 23 Apr 2014, 06:17

The exact address will vary depending on your version, but I can tell you what I'm seeing:

Project Ironfist has uploaded a raw decompilation of the game to http://hg.gamecreation.org/project-iron ... HEROES2W.c. Looking there, we see in the definition of combatManager::UpdateArmyGroup the following (after some cleanup):

Code: Select all

  if ( giSkeletonsCreated && this->winningSide == side )
    armyGroup::Add(this->armies[side], CREATURE_SKELETON, giSkeletonsCreated, -1);
Bingo. We just need to change CREATURE_SKELETON (47) to CREATURE_VAMPIRE (52). The corresponding assembly, in http://hg.gamecreation.org/project-iron ... eroes2.asm:

Code: Select all

.text:00475D25 loc_475D25:                             ; CODE XREF: combatManager::UpdateArmyGroup(int)+74j
.text:00475D25                 cmp     ?giSkeletonsCreated@@3HA, 0 ; int giSkeletonsCreated
.text:00475D2C                 jz      loc_475D60
.text:00475D32                 mov     eax, [ebp+var_C]
.text:00475D35                 mov     ecx, [ebp+side]
.text:00475D38                 cmp     [eax+0F873h], ecx
.text:00475D3E                 jnz     loc_475D60
.text:00475D44 ; 29:     armyGroup::Add(this->armies[side], CREATURE_SKELETON, giSkeletonsCreated, -1);
.text:00475D44                 push    0FFFFFFFFh      ; stackIdx
.text:00475D46                 mov     eax, ?giSkeletonsCreated@@3HA ; int giSkeletonsCreated
.text:00475D4B                 push    eax             ; quantity
.text:00475D4C                 push    2Fh ; '/'       ; creatureType
.text:00475D4E                 mov     eax, [ebp+side]
.text:00475D51                 mov     ecx, [ebp+var_C]
.text:00475D54                 mov     ecx, [ecx+eax*4+3391h] ; this
.text:00475D5B                 call    ?Add@armyGroup@@QAEHHHH@Z ; armyGroup::Add(int,int,int)
And the corresponding hex. In my executable (HoMM II Gold, American release), this is from address 0x75125 to 0x7515F. You should be able to find a similar (but probably not identical, due to different addresses) sequence of hex in yours.

Code: Select all

 83 3D 64 4C 52 00 
00 0F 84 2E 00 00 00 8B  45 F4 8B 4D 08 39 88 73 
F8 00 00 0F 85 1C 00 00  00 6A FF A1 64 4C 52 00 
50 6A 2F 8B 45 08 8B 4D  F4 8B 8C 81 91 33 00 00 
E8 60 96 FF FF 
That "2F" is the skeleton creature code. Change it to 34 and you should have your vampires.

Hope that helps!

scbw1234
Leprechaun
Leprechaun
Posts: 10
Joined: 21 Apr 2014
Location: China

Unread postby scbw1234 » 24 Apr 2014, 13:04

Darmani wrote:The exact address will vary depending on your version, but I can tell you what I'm seeing:

Project Ironfist has uploaded a raw decompilation of the game to http://hg.gamecreation.org/project-iron ... HEROES2W.c. Looking there, we see in the definition of combatManager::UpdateArmyGroup the following (after some cleanup):

Code: Select all

  if ( giSkeletonsCreated && this->winningSide == side )
    armyGroup::Add(this->armies[side], CREATURE_SKELETON, giSkeletonsCreated, -1);
Bingo. We just need to change CREATURE_SKELETON (47) to CREATURE_VAMPIRE (52). The corresponding assembly, in http://hg.gamecreation.org/project-iron ... eroes2.asm:

Code: Select all

.text:00475D25 loc_475D25:                             ; CODE XREF: combatManager::UpdateArmyGroup(int)+74j
.text:00475D25                 cmp     ?giSkeletonsCreated@@3HA, 0 ; int giSkeletonsCreated
.text:00475D2C                 jz      loc_475D60
.text:00475D32                 mov     eax, [ebp+var_C]
.text:00475D35                 mov     ecx, [ebp+side]
.text:00475D38                 cmp     [eax+0F873h], ecx
.text:00475D3E                 jnz     loc_475D60
.text:00475D44 ; 29:     armyGroup::Add(this->armies[side], CREATURE_SKELETON, giSkeletonsCreated, -1);
.text:00475D44                 push    0FFFFFFFFh      ; stackIdx
.text:00475D46                 mov     eax, ?giSkeletonsCreated@@3HA ; int giSkeletonsCreated
.text:00475D4B                 push    eax             ; quantity
.text:00475D4C                 push    2Fh ; '/'       ; creatureType
.text:00475D4E                 mov     eax, [ebp+side]
.text:00475D51                 mov     ecx, [ebp+var_C]
.text:00475D54                 mov     ecx, [ecx+eax*4+3391h] ; this
.text:00475D5B                 call    ?Add@armyGroup@@QAEHHHH@Z ; armyGroup::Add(int,int,int)
And the corresponding hex. In my executable (HoMM II Gold, American release), this is from address 0x75125 to 0x7515F. You should be able to find a similar (but probably not identical, due to different addresses) sequence of hex in yours.

Code: Select all

 83 3D 64 4C 52 00 
00 0F 84 2E 00 00 00 8B  45 F4 8B 4D 08 39 88 73 
F8 00 00 0F 85 1C 00 00  00 6A FF A1 64 4C 52 00 
50 6A 2F 8B 45 08 8B 4D  F4 8B 8C 81 91 33 00 00 
E8 60 96 FF FF 
That "2F" is the skeleton creature code. Change it to 34 and you should have your vampires.

Hope that helps!
Hi!Darmani,thanks for your kind reply!

Can i ask how did you get this 0x75125 to 0x7515F address?As stated in Project Ironfist,the address was 00475D25-00475D5B,how did you translate it to 0x75125 to 0x7515F?The reason i ask is that my version might be different from yours,so that if i could learn how to translate it,i might be able to find it on my own.

Thank you!!

User avatar
Darmani
Blood Fury
Blood Fury
Posts: 479
Joined: 06 Jan 2006
Location: Cambridge, MA

Unread postby Darmani » 26 Apr 2014, 06:52

Sure! The 00475D25-00475D5B addresses are the runtime memory addresses of the game's code. That is, if an instruction in the game says "go to 00475D25," it will jump to this code.

There's no general way to translate between them. The game's executable is split into section; one section is marked as the main code, and the bytes in that section get laid out starting at 0x0040000.

I was able to translate this because I have a disassembly of the game in IDA, and it tells me both the address of the bytes, as well as the position in the executable.

If you want to try your own hand at creating patches, you can download a trial of IDA from the Hex-Rays website, and, if you PM me, I can share my IDB file.

If you just want to apply this patch and change skeletons to vampires, then the easiest thing to do would be to just search for a sequence of 6 bytes or so in your executable.

scbw1234
Leprechaun
Leprechaun
Posts: 10
Joined: 21 Apr 2014
Location: China

Unread postby scbw1234 » 26 Apr 2014, 18:03

Hi Darmani,thank you for your reply!

As for changing skeleton to vampire,what are the exact 6 bytes to search for?

User avatar
Darmani
Blood Fury
Blood Fury
Posts: 479
Joined: 06 Jan 2006
Location: Cambridge, MA

Unread postby Darmani » 27 Apr 2014, 01:09

I'd have to look at several versions to give you an exact sequence of 6 bytes that should work for you.

While it's helpful to search for 6 bytes, those 6 bytes are not what you're looking for. You're really looking for the bytes of code that control adding skeletons to an army after a battle. I've shared those 60 bytes of code from my version; you want to find a sequence of ~60 bytes in your version that looks very similar, if not identical. If you pick any 6 bytes from those 60 bytes and find it in your executable, and if it only occurs once, then chances are you've found the correct place.

scbw1234
Leprechaun
Leprechaun
Posts: 10
Joined: 21 Apr 2014
Location: China

Unread postby scbw1234 » 29 Apr 2014, 02:22

Darmani wrote:I'd have to look at several versions to give you an exact sequence of 6 bytes that should work for you.

While it's helpful to search for 6 bytes, those 6 bytes are not what you're looking for. You're really looking for the bytes of code that control adding skeletons to an army after a battle. I've shared those 60 bytes of code from my version; you want to find a sequence of ~60 bytes in your version that looks very similar, if not identical. If you pick any 6 bytes from those 60 bytes and find it in your executable, and if it only occurs once, then chances are you've found the correct place.
I I've tried the america version,and it worked!thank you.

However,the icon after the battle says what creature you revived is still skeleton but its actually vampire,thats pretty weird.

User avatar
Darmani
Blood Fury
Blood Fury
Posts: 479
Joined: 06 Jan 2006
Location: Cambridge, MA

Unread postby Darmani » 29 Apr 2014, 04:37

Yeah, I was just thinking about this the other day and I realized that would probably happen. I could probably dig that up too if it really bothers you.

scbw1234
Leprechaun
Leprechaun
Posts: 10
Joined: 21 Apr 2014
Location: China

Unread postby scbw1234 » 30 Apr 2014, 12:40

Darmani wrote:Yeah, I was just thinking about this the other day and I realized that would probably happen. I could probably dig that up too if it really bothers you.
really!?that would be awesome!if you can even change messsage from raising skeleton to vampire that would be perfect!

User avatar
Darmani
Blood Fury
Blood Fury
Posts: 479
Joined: 06 Jan 2006
Location: Cambridge, MA

Unread postby Darmani » 01 May 2014, 04:46

Sure! I'll make a note to take a stab at it after I finish preparing the talk I'm giving Monday.

scbw1234
Leprechaun
Leprechaun
Posts: 10
Joined: 21 Apr 2014
Location: China

Unread postby scbw1234 » 01 May 2014, 19:18

Darmani wrote:Sure! I'll make a note to take a stab at it after I finish preparing the talk I'm giving Monday.
Thank you! I'm really looking forward to your research

User avatar
Darmani
Blood Fury
Blood Fury
Posts: 479
Joined: 06 Jan 2006
Location: Cambridge, MA

Unread postby Darmani » 07 May 2014, 08:11

I don't have time to be as thorough in my writeup, but here's what I found:

Everything we're concerned with is in the combatManager::ShowSkeletons method.

The first thing of interest is the line:

Code: Select all

 iconWidget::iconWidget(v7, 173, 270, 32, 30, "mons32.icn", 47, 0, 900, 16, 1);
This creates the icon showing the skeleton. mons32.icn is a sprite archive that contains all the little 32x32 creature icons. We will again need to change the 47 to a 52.

The corresponding assembly:

Code: Select all

.text:0043E7D3                 push    1               ; a11
.text:0043E7D5                 push    10h             ; a10
.text:0043E7D7                 push    384h            ; fieldID
.text:0043E7DC                 push    0               ; mirror
.text:0043E7DE                 push    2Fh ; '/'       ; imgIdx
.text:0043E7E0                 push    offset aMons32_icn_0 ; "mons32.icn"
.text:0043E7E5                 push    1Eh             ; height
.text:0043E7E7                 push    20h ; ' '       ; width
.text:0043E7E9                 push    10Eh            ; y
.text:0043E7EE                 push    0ADh ; '¡'      ; x
.text:0043E7F3                 mov     ecx, [ebp+var_2C] ; this
.text:0043E7F6                 call    ??0iconWidget@@QAE@FFFFPADFCFFF@Z ; iconWidget::iconWidget(short,short,short,short,char *,short,signed char,short,short,short)
The corresponding bytes occur at 3DBD3-3DBFA in my executable. They are

Code: Select all

 6A 01 6A
 10 68 84 03 00 00 6A 00  6A 2F 68 DC E3 50 00 6A
 1E 6A 20 68 0E 01 00 00  68 AD 00 00 00 8B 4D D4
 E8 F5 
Again, we need to find the corresponding snippet and change the 2F to a 34.

The rest is just strings, so it will be easier. Doing a text search for a snippet shown when you raise skeletons, I found the following two strings in my executable:
Practicing the dark arts of necromancy, you are able to raise one of the enemy's dead to return under your service as a Skeleton.
and
"Practicing the dark arts of necromancy, you are able to raise %d of the enemy's dead to return under your service as Skeletons."
They start at 10C61C and 10C69C respectively. We will simply need to replace the "Skeleton." and "Skeletons." with "Vampire." and "Vampires.". Since "Vampire" is shorter than "Skeleton," after placing the period, we will need to terminate the string by placing a trailing null (the byte 00).

Hope that helps!

scbw1234
Leprechaun
Leprechaun
Posts: 10
Joined: 21 Apr 2014
Location: China

Hi i'm back!

Unread postby scbw1234 » 17 May 2014, 13:56

I'm sorry i was away from home last week.Just saw your reply awhile ago.Thanks alot for your hard work.it really helps alot!!

I'll check my version to see if this works!thank you!


Return to “Heroes I-IV”

Who is online

Users browsing this forum: Bing [Bot] and 25 guests