Jump to content

EXE editing & programming issues


MrFlibble

Recommended Posts

Remember I mentioned I've found the code that can change the Ordos' availability level for Siege Tanks? Well, turns out I got that wrong. Here's the code as parsed in Segra's database:

seg010:262E                   loc_1CA5E:                                                  ; CODE XREF: sub_1CA1C+31j
seg010:262E ; sub_1CA1C+3Bj
seg010:262E C4 5E 06 les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xx
seg010:2631 26 80 7F 08 02 cmp es:[bx+_buildingGame.houseID], 2 ; Compare Two Operands
seg010:2636 75 23 jnz short loc_1CA8B ; Jump if Not Zero (ZF=0)
seg010:2638 C4 5E 06 les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xx
seg010:263B 26 80 7F 02 04 cmp es:[bx+_buildingGame.TypeIndex], 4 ; Heavy Factory
seg010:2640
seg010:2640 loc_1CA70: ; Jump if Not Zero (ZF=0)
seg010:2640 75 19 jnz short loc_1CA8B
seg010:2642 C4 5E 06 les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xx
seg010:2645 26 80 7F 4E 01 cmp es:[bx+_buildingGame.techLevel], 1 ; Compare Two Operands
seg010:264A 75 0F jnz short loc_1CA8B ; Jump if Not Zero (ZF=0)
seg010:264C C4 5E FC les bx, [bp+buildingDataPtr] ; Load Full Pointer to ES:xx
seg010:264F
seg010:264F loc_1CA7F:
seg010:264F 26 8B 47 5E mov ax, es:[bx+_buildingData.techUpgrade3]
seg010:2653
seg010:2653 loc_1CA83: ; Compare Two Operands
seg010:2653 3B 06 A6 38 cmp ax, missionNumberPrevious
seg010:2657 7E 02 jle short loc_1CA8B ; Jump if Less or Equal (ZF=1 | SF!=OF)
seg010:2659 EB CE jmp short Ret0

The "06" byte I thought was the previous mission number was actually part of the code that compares the previous mission number (for the current mission) to a variable that is calculated elsewhere. Changing the "jump if less or equal" condition to "jump if less", as well as changing the type of compared variable from "previous mission number" to "current mission number" produced weird results, so I decided to leave this alone. And if you're wondering why changing "06" to "05" made the Ordos get Siege Tanks in mission 6, the reason is that this change effectively disabled the routine, giving the Ordos the second Heavy Factory upgrade from mission 5 onwards (like with the other Houses), and since they skip level 2 upgrade and get level 3 right after level one, this change gave the Ordos Siege Tanks in mission 5.

Link to comment
Share on other sites

  • 2 months later...

And for those curious few amongst us, i believe that piece of code matches this in OpenDune

src/structure.c

bool Structure_IsUpgradable(Structure *s)

<snip>

if (s->o.houseID == HOUSE_ORDOS && s->o.type == STRUCTURE_HEAVY_VEHICLE && s->upgradeLevel == 1 && si->upgradeCampaign[2] > g_campaignID) return false;

hey All :)

  • Upvote 1
Link to comment
Share on other sites

Theoretically, if the code exception is found that makes the Fremen AI hostile towards other AI players if the human player is Atreides, it can be "inverted" to work for the Fremen human player in tandem with an Atreides AI. It might have something to do with the isFriendly? variable, but I'm not sure if I checked all instances of it. The trick here is that we do not know how exactly the alliance between the AI players is handled. I suppose it would be logical to assume that by default, all AI players are friendly towards each other. If that is the case, then the code exception would be something like if {human player = Atreides} & {AI player = Fremen} then {attack other AI players} or maybe if {AI player = Fremen} & {owner of units in Fremen units' range = other AI} then {attack AI unit}. I've been looking for it a while ago, without much success so far, so I'm not sure if I checked all possibilities I could think of.

house.c

bool House_AreAllied(uint8 houseID1, uint8 houseID2)

<snip>

if (houseID1 == HOUSE_FREMEN || houseID2 == HOUSE_FREMEN) {

return (houseID1 == HOUSE_ATREIDES || houseID2 == HOUSE_ATREIDES);

}

seg023:0F5B ; int __cdecl __far isFriendly?(int objectHouseID, int HumanHouseID)

seg023:0F5B isFriendly? proc far ; CODE XREF: sub_15008+12CP

<snip>

seg023:0F78 83 FA 03 cmp dx, 3 ; DX = object

seg023:0F7B 74 05 jz short isFremen ; Jump if Zero (ZF=1)

seg023:0F7D 83 FB 03 cmp bx, 3 ; BX = human

seg023:0F80

seg023:0F80 loc_231B0: ; Jump if Not Zero (ZF=0)

seg023:0F80 75 0E jnz short notFremen

seg023:0F82

seg023:0F82 isFremen: ; CODE XREF: isFriendly?+20j

seg023:0F82 83 FA 01 cmp dx, 1 ; Compare Two Operands

seg023:0F85

seg023:0F85 loc_231B5: ; Jump if Zero (ZF=1)

seg023:0F85 74 05 jz short isAtreides

seg023:0F87

seg023:0F87 loc_231B7: ; Compare Two Operands

seg023:0F87 83 FB 01 cmp bx, 1

seg023:0F8A

seg023:0F8A loc_231BA: ; if object is Fremen, and Human is Atreides, Ret True

seg023:0F8A 75 02 jnz short notAtreides

seg023:0F8C

seg023:0F8C isAtreides: ; CODE XREF: isFriendly?:loc_231B5j

seg023:0F8C EB 10 jmp short retTrue ; Jump

Link to comment
Share on other sites

I just read you already had that code, and its not what your after.. so i assume these pieces may have some effect

theres a few bits specific to atreides / fremen

src/unit.c

if (houseID == HOUSE_ATREIDES && unit->o.type != UNIT_SANDWORM) {

houseIDBit |= (1 << HOUSE_FREMEN);

}

if (unit->o.houseID == g_playerHouseID || (unit->o.houseID == HOUSE_FREMEN && g_playerHouseID == HOUSE_ATREIDES)) {

unit->o.seenByHouses = 0xFF;

} else {

unit->o.seenByHouses |= houseIDBit;

}

not sure of the disassembly location atm, but it shouldnt be too hard to find

  • Upvote 1
Link to comment
Share on other sites

Awesome! :D

BTW, TrueBrain has been asking about the partially functional "editor mode" within Dune 2 code, and I remember that you posted something about a mode in which terrain tiles can be selected, and no action generally takes place on the map, but I couldn't find the exact post (forum search seems to be of little help ATM for some reason). I remember playing around with debug option bytes, but I was never able to activate that mode in any version I have access to...

Link to comment
Share on other sites

  • 3 weeks later...

It is mostly MrFlibble's job, but I want to beat him to it:

http://forum.opendune.org/viewtopic.php?f=9&p=277

Crossposting. Mostly because I wonder what you guys think. Basically, when you now attack a structure of the enemy in OpenDUNE, they massively hunt you down. By all means it seems the intended behaviour.

Patching Dune2 should be easy enough, if there is room for it (byte-wise). In 1423:0EAE (no clue where this maps in the executable), it reads:

xor ax, ax
push ax
push si
xor ax, ax
xor dx, dx
push ax
push dx
<call function in 0x0FE4> (Unit_FindFirst)

The first line (xor ax, ax) should be: mov ax, 0xFFFF.

For those who don't like to read the link above: Dune2 scans all units of the house of the structure that got attacked (if non-human of course), and puts them in HUNTING mode when they were in AREA_GUARD mode. But due to the above glitch, it only searches for Carry-alls, instead of all units (0 vs 0xFFFF). This seems an innocent glitch, with huge change in gameplay.

I've finally found some time to track this down in Segra's database. Here's the code:

seg023:0ED5                   loc_23105:                                                  ; CODE XREF: sub_230A6+3Ej
seg023:0ED5 33 C0 xor ax, ax ; Logical Exclusive OR
seg023:0ED7 50 push ax ; unitIndexFind
seg023:0ED8 56 push si ; houseID
seg023:0ED9 33 C0 xor ax, ax ; Logical Exclusive OR
seg023:0EDB
seg023:0EDB loc_2310B: ; Logical Exclusive OR
seg023:0EDB 33 D2 xor dx, dx
seg023:0EDD 50 push ax
seg023:0EDE 52 push dx ; houseGamePtr
seg023:0EDF
seg023:0EDF loc_2310F: ; Call Procedure
seg023:0EDF 9A 43 02 ED 1D call houseUnitGameFind
seg023:0EE4
seg023:0EE4 loc_23114: ; Add
seg023:0EE4 83 C4 08 add sp, 8
seg023:0EE7
seg023:0EE7 loc_23117: ; Jump
seg023:0EE7 EB 59 jmp short unitNext

The problem is, to change xor ax, ax (33 C0) to mov ax, 0xFFFF (B8 FF FF) there has to be room for an extra byte, and I don't think the code around this area can be effectively messed up with to free up the room for an extra byte... Any ideas?

Also, it might be interesting to note that a similar piece of code exists elsewhere:

seg031:224E 8B 46 F4                          mov     ax, word ptr [bp+buildingGamePtr]
seg031:2251 0B 46 F6 or ax, word ptr [bp+buildingGamePtr+2] ; Logical Inclusive OR
seg031:2254 75 B0 jnz short buildingTest ; Jump if Not Zero (ZF=0)
seg031:2256 33 C0 xor ax, ax ; Carryall
seg031:2258 50 push ax ; unitIndexFind
seg031:2259 56 push si ; houseID
seg031:225A 33 C0 xor ax, ax ; Logical Exclusive OR
seg031:225C 33 D2 xor dx, dx ; Logical Exclusive OR
seg031:225E 50 push ax
seg031:225F 52 push dx ; houseGamePtr
seg031:2260 9A 43 02 ED 1D call houseUnitGameFind ; Call Procedure
seg031:2265
seg031:2265 loc_2A5C5: ; Add
seg031:2265 83 C4 08 add sp, 8
seg031:2268 EB 34 jmp short CarryAllCheck ; Jump

Apparently, this time it indeed concerns carryalls only, as it has something to do with ferrying Harvesters (if I got this part correctly, that is :)).

Link to comment
Share on other sites

  • 4 weeks later...

I've finally found some time to track this down in Segra's database. Here's the code:

seg023:0ED5                   loc_23105:                                                  ; CODE XREF: sub_230A6+3Ej
seg023:0ED5 33 C0 xor ax, ax ; Logical Exclusive OR
seg023:0ED7 50 push ax ; unitIndexFind
seg023:0ED8 56 push si ; houseID
seg023:0ED9 33 C0 xor ax, ax ; Logical Exclusive OR

The problem is, to change xor ax, ax (33 C0) to mov ax, 0xFFFF (B8 FF FF) there has to be room for an extra byte, and I don't think the code around this area can be effectively messed up with to free up the room for an extra byte... Any ideas?

How about this:

mov ax, 0xFFFF
push ax
push si
inc ax

as "inc ax" is only a single byte opcode.

  • Upvote 1
Link to comment
Share on other sites

  • 2 months later...

I finally got myself to check if the solution Jongware proposed works, and indeed it does :) In the few tests, the AI would first destroy the intruding unit that attacked its structures, then head for the player's base. I haven't tested it more thoroughly though, but hopefully it doesn't interfere with other AI functions like attack teams.

I wonder though what the second chunk that picks units in a similar way really does (I think I mentioned it somewhere above).

Link to comment
Share on other sites

  • 5 months later...
seg023:0F5B ; int __cdecl __far isFriendly?(int objectHouseID, int HumanHouseID)

seg023:0F5B isFriendly? proc far ; CODE XREF: sub_15008+12CP

<snip>

seg023:0F78 83 FA 03 cmp dx, 3 ; DX = object

seg023:0F7B 74 05 jz short isFremen ; Jump if Zero (ZF=1)

seg023:0F7D 83 FB 03 cmp bx, 3 ; BX = human

seg023:0F80

seg023:0F80 loc_231B0: ; Jump if Not Zero (ZF=0)

seg023:0F80 75 0E jnz short notFremen

seg023:0F82

seg023:0F82 isFremen: ; CODE XREF: isFriendly?+20j

seg023:0F82 83 FA 01 cmp dx, 1 ; Compare Two Operands

seg023:0F85

seg023:0F85 loc_231B5: ; Jump if Zero (ZF=1)

seg023:0F85 74 05 jz short isAtreides

seg023:0F87

seg023:0F87 loc_231B7: ; Compare Two Operands

seg023:0F87 83 FB 01 cmp bx, 1

seg023:0F8A

seg023:0F8A loc_231BA: ; if object is Fremen, and Human is Atreides, Ret True

seg023:0F8A 75 02 jnz short notAtreides

seg023:0F8C

seg023:0F8C isAtreides: ; CODE XREF: isFriendly?:loc_231B5j

seg023:0F8C EB 10 jmp short retTrue ; Jump

Maybe if replace 03 with 01 and vice versa you can obtain Fremen with Atreides allies IA working, but I think that if you return to play Atreides, Fremen IA don't work anyway.

We should find an algorithm that works bilaterally...

Link to comment
Share on other sites

Umm, that code DOES check both ways.

After cleaning it up a bit, you get this:

cmp dx, 3 // is object owner Fremen?
jz .isFremen
cmp bx, 3 // Is Human player Fremen?
jnz .notFremen

isFremen:
cmp dx, 1 // is object owner Atreides?
jz .isAtreides
cmp bx, 1 // Is Human player Atreides?
jnz .notAtreides

isAtreides:
jmp .retTrue

// (no real info about where this is)
notAtreides:
notFremen:

The first block of 4 lines checks if either the object owner or the human player are Fremen. If not, it jumps out, otherwise it continues. The second block of 4 lines checks if either the object owner or the human player are Atreides. Once both checks clear, it returns true. That DOES work both ways.

Rewritten in standard (pseudo)code, this whole block is simply


if ((ObjectHouse==Fremen || HumanHouse==Fremen) && (ObjectHouse==Atreides || HumanHouse==Atreides))
return true; // isFriendly returns true

Link to comment
Share on other sites

Ok it seems that this piece only 'tell in game' that Atreides &amp;amp; Fremen aren't hostile.

In fact Atreides AI does't attack Fremen human and vice versa, the problem is that Fremen AI interacts with Atreides human, but Atreides AI not (apart Sandworm).

So we should find a piece that tells:

if human=Atreides and AI=Fremen then

if object is Fremen then AI object -> hunt for others AI end if

else

if object is Atreides and human=Fremen then

AI object -> nothing

else

AI object -> hunt for human

end if

end if

and modify something else:

if (human=Atreides or human=Fremen) and (AI=Fremen or AI=Atreides) and (object is Fremen or object is Atreides) then

AI object -> hunt for others AI

else

AI object -> hunt for human

end if

Link to comment
Share on other sites

Ok it seems that this piece only 'tell in game' that Atreides & Fremen aren't hostile.

In fact Atreides AI does't attack Fremen human and vice versa, the problem is that Fremen AI interacts with Atreides human, but Atreides AI not (apart Sandworm).

Exactly. I remember trying to locate the code that makes Fremen AI hostile to other AI plyers if the human player is Atreides, but no chunks that have the Atreides and/or Fremen House indexes seem to have anything to do with that. But then again, I could have missed something due to lack of experience.
Link to comment
Share on other sites


seg023:0F78 loc_231A8: ; CODE XREF: isFriendly?:loc_231A4j
seg023:0F78 83 FA 03 cmp dx, 3 ; DX = object
seg023:0F7B 74 05 jz short isFremen ; Jump if Zero (ZF=1)
seg023:0F7D 83 FB 03 cmp bx, 3 ; BX = human
seg023:0F80
seg023:0F80 loc_231B0: ; Jump if Not Zero (ZF=0)
seg023:0F80 75 0E jnz short notFremen
seg023:0F82
seg023:0F82 isFremen: ; CODE XREF: isFriendly?+20j
seg023:0F82 83 FA 01 cmp dx, 1 ; Compare Two Operands
seg023:0F85
seg023:0F85 loc_231B5: ; Jump if Zero (ZF=1)
seg023:0F85 74 05 jz short isAtreides
seg023:0F87
seg023:0F87 loc_231B7: ; Compare Two Operands
seg023:0F87 83 FB 01 cmp bx, 1
seg023:0F8A
seg023:0F8A loc_231BA: ; if object is Fremen, and Human is Atreides, Ret True
seg023:0F8A 75 02 jnz short notAtreides
seg023:0F8C
seg023:0F8C isAtreides: ; CODE XREF: isFriendly?:loc_231B5j
seg023:0F8C EB 10 jmp short retTrue ; Jump
seg023:0F8E ; ---------------------------------------------------------------------------
seg023:0F8E
seg023:0F8E notAtreides: ; CODE XREF: isFriendly?:loc_231BAj
seg023:0F8E EB DE jmp short retFalse ; Jump
seg023:0F90 ; ---------------------------------------------------------------------------
seg023:0F90
seg023:0F90 notFremen: ; CODE XREF: isFriendly?:loc_231B0j
seg023:0F90 3B 16 2C 3A cmp dx, houseHumanID ; Compare Two Operands
seg023:0F94
seg023:0F94 loc_231C4: ; Jump if Zero (ZF=1)
seg023:0F94 74 06 jz short objectIsHuman
seg023:0F96
seg023:0F96 loc_231C6: ; Compare Two Operands
seg023:0F96 3B 1E 2C 3A cmp bx, houseHumanID
seg023:0F9A
seg023:0F9A loc_231CA: ; if object is not human, and house is not human, ret true
seg023:0F9A 75 02 jnz short retTrue
seg023:0F9C
seg023:0F9C objectIsHuman: ; CODE XREF: isFriendly?:loc_231C4j
seg023:0F9C EB D0 jmp short retFalse ; Jump

I tried to change Fremen ID with Ordos ID, and it worked: Atreides human has Ordos AI interaction ally.

But if you change Atreides ID to another, two factions aren't hostile but first ID house (object) ignore interacts with second ID house.

It seems that only Atreides (and ONLY in second position!) have the right behavior to have another House AI interaction ally.

i.e.

a) If you put first House ID 01 (Atreides) and second House ID 03 (Fremen), they aren't hostile but neither (Human Atreides or Human Fremen) has AI interaction ally.

b) If you put first House ID 02 (Ordos) and second House ID 01 (Atreides), they aren't hostile and Atreides Human has Ordos AI interaction ally, but Ordos Human doesn't!

c) If you put first House ID 02 (Ordos) and second House ID 03 (Fremen) they aren't hostile but neither (Human Ordos or Human Fremen) has AI interaction ally.

I tried also to change in combo House ID in this piece:


seg023:0912 loc_22B42:
seg023:0912 89 46 F8 mov word ptr [bp+houseGamePtr], ax
seg023:0915 B8 01 00 mov ax, 1
seg023:0918 8A 4E 0A mov cl, byte ptr [bp+houseIndex]
seg023:091B D3 E0 shl ax, cl ; Shift Logical Left
seg023:091D 89 46 F6 mov [bp+houseRevealed], ax
seg023:0920 83 7E 0A 01 cmp [bp+houseIndex], 1 ; Compare Two Operands
seg023:0924 75 0E jnz short notAtreOrWorm ; Jump if Not Zero (ZF=0)
seg023:0926 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg023:0929 26 80 7F 02 19 cmp es:[bx+_unitGame.typeIndex], 19h ; sandworm
seg023:092E 74 04 jz short notAtreOrWorm ; Jump if Zero (ZF=1)
seg023:0930
seg023:0930 loc_22B60: ; Logical Inclusive OR
seg023:0930 83 4E F6 08 or [bp+houseRevealed], 8
seg023:0934
seg023:0934 notAtreOrWorm: ; CODE XREF: sub_22B24+30j
seg023:0934 ; sub_22B24+3Aj
seg023:0934 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg023:0937 26 8A 47 09 mov al, es:[bx+_unitGame.houseRevealed]
seg023:093B B4 00 mov ah, 0
seg023:093D 85 46 F6 test [bp+houseRevealed], ax ; Logical Compare
seg023:0940
seg023:0940 loc_22B70: ; Jump if Zero (ZF=1)
seg023:0940 74 18 jz short loc_22B8A
seg023:0942 C4 5E F8 les bx, [bp+houseGamePtr] ; Load Full Pointer to ES:xx
seg023:0945 26 F7 47 04 08 00 test es:[bx+_houseGame.IndexLastFound], 8 ; Logical Compare
seg023:094B 74 0D jz short loc_22B8A ; Jump if Zero (ZF=1)
seg023:094D C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg023:0950
seg023:0950 loc_22B80:
seg023:0950 8A 46 F6 mov al, byte ptr [bp+houseRevealed]
seg023:0953 26 08 47 09 or es:[bx+_unitGame.houseRevealed], al ; Logical Inclusive OR
seg023:0957 E9 94 02 jmp Done ; Jump

without have expected results.

  • Upvote 1
Link to comment
Share on other sites

I saw another step:


seg023:0B9F loc_22DCF: ; unit not friendly
seg023:0B9F C4 5E 06 les bx, [bp+unitGamePtr]
seg023:0BA2 26 80 7F 4F 08 cmp es:[bx+_unitGame.actionCurrent], 8 ; Compare Two Operands
seg023:0BA7 75 12 jnz short checkHouseID ; Jump if Not Zero (ZF=0)
seg023:0BA9 B8 0B 00 mov ax, 0Bh ; Hunt
seg023:0BAC 50 push ax ; action
seg023:0BAD FF 76 08 push word ptr [bp+unitGamePtr+2]
seg023:0BB0 FF 76 06 push word ptr [bp+unitGamePtr] ; unitGamePtr
seg023:0BB3 9A 05 00 6F 25 call unitActionstart ; Call Procedure
seg023:0BB8 83 C4 06 add sp, 6 ; Add
seg023:0BBB
seg023:0BBB checkHouseID: ; CODE XREF: sub_22B24+2A9j
seg023:0BBB ; sub_22B24+2B3j
seg023:0BBB C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg023:0BBE 26 8A 47 08 mov al, es:[bx+_unitGame.houseID]
seg023:0BC2 98 cbw ; AL -> AX (with sign)
seg023:0BC3 3B 06 2C 3A cmp ax, houseHumanID ; Compare Two Operands
seg023:0BC7 74 11 jz short AtreFre ; Jump if Zero (ZF=1)
seg023:0BC9
seg023:0BC9 loc_22DF9: ; Load Full Pointer to ES:xx
seg023:0BC9 C4 5E 06 les bx, [bp+unitGamePtr]
seg023:0BCC 26 80 7F 08 03 cmp es:[bx+_unitGame.houseID], 3 ; Fremen
seg023:0BD1 75 11 jnz short loc_22E14 ; Jump if Not Zero (ZF=0)
seg023:0BD3 83 3E 2C 3A 01 cmp houseHumanID, 1 ; Atre
seg023:0BD8 75 0A jnz short loc_22E14 ; Jump if Not Zero (ZF=0)
seg023:0BDA
seg023:0BDA AtreFre: ; CODE XREF: sub_22B24+2D3j
seg023:0BDA C4 5E 06 les bx, [bp+unitGamePtr] ; unit = fremen and human = atre
seg023:0BDD 26 C6 47 09 FF mov es:[bx+_unitGame.houseRevealed], 0FFh
seg023:0BE2 EB 0A jmp short Done ; Jump
seg023:0BE4 ; ---------------------------------------------------------------------------
seg023:0BE4
seg023:0BE4 loc_22E14: ; CODE XREF: sub_22B24+2DDj
seg023:0BE4 ; sub_22B24+2E4j
seg023:0BE4 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg023:0BE7 8A 46 F6 mov al, byte ptr [bp+houseRevealed]
seg023:0BEA 26 08 47 09 or es:[bx+_unitGame.houseRevealed], al ; Logical Inclusive OR
seg023:0BEE
seg023:0BEE Done: ; CODE XREF: sub_22B24+Fj
seg023:0BEE ; sub_22B24+63j ...
seg023:0BEE 5E pop si
seg023:0BEF 8B E5 mov sp, bp
seg023:0BF1 5D pop bp
seg023:0BF2 CB retf ; Return Far from Procedure
seg023:0BF2 sub_22B24 endp

This piece:

seg023:0BC3 3B 06 2C 3A

in Dunex.exe files I found so:

3B 06 38 3A

and also:

seg023:0BD3 83 3E 2C 3A 01

in Dunex.exe file:

83 3E 38 3A 01

I don't know what it means, but I can say that 'shared vision' works for ALL Houses when you set allies in isFriend? functions (as showed precedent post) and maybe 38 bit it's responsable for this.

  • Upvote 1
Link to comment
Share on other sites

Might be handier to analyse if you quote the asm instructions instead of meaningless bytes.

What is "houseHumanID" in that code? An address? A renamed register? Because to me, that just seems like a version difference where the other version just happens to use a different register for houseHumanID, or where the version differences cause a hardcoded address for houseHumanID to be slightly different.

Link to comment
Share on other sites

You're right, it was a renamed register. Sorry but I don't know this language. I only try for logical or exclusion.

So apart exact values as hex numbers that are compared I don't know really what is 38 byte rather 2F and so on.

Now I opened dunex.exe with IDA Pro and it's very differente about definitions (obviously without segra comments and renamed-more clear functions and variables).

.ida file is created by original v1.07 dune2.exe, right?

Can you help me in a code piece, when the hex indicate a pointer, what a register and what an istruction (cmp, jz, jnz, ...)??

For example how I undestand in a sample:


seg023:0BCC 26 80 7F 08 03 cmp es:[bx+_unitGame.houseID], 3

then in 26 80 7F 08 03 string, apart 03 value (hex of 3 than is clear that indicates House ID) what is hex that indicates about cmp instruction and what hex that indicates is about bx register and so on...

Link to comment
Share on other sites

.ida file is created by original v1.07 dune2.exe, right?

There are at least three different versions of DUNE2.EXE v1.07 available, and in fact Segra did his analysis using a fourth version I personally have never encountered before. So to actually use the data from his database, I had to identify relevant pieces of the EXE I was going to edit because the bytes and their locations are different (the instructions are the same though).

seg023:0BCC 26 80 7F 08 03                                      cmp      es:[bx+_unitGame.houseID], 3

Since I have minimal coding experience, I've never bothered to delve deep into suchlike codes. It's enough for me to understand that it checks in the instant above if the currently handled unit belongs to the Fremen, and that Fremen can be changed to another House by editing the index. As I never intended to make large changes to the code, I didn't bother trying to get farther into understanding what stuff does what.Anyhoo, you results seem indicate that there must be a separate piece of code that tells the game to change an AI's behaviour to hostile towards other AIs if that particular AI player is allied with the Atreides. Finding that code would enable to change the Atreides for the Fremen and make Fremen have functional Atreides allies, but this also means that it might be problematic to make this code work both ways at the same time (as is your intention if I understand you correctly).

Link to comment
Share on other sites

Yes, one of our goals could be find the code that it's responsible to change AI behavior once 'the game understand' that is allied (by isFriendly? function) and try to modify it to work bilaterally or so that it can also work with other factions apart Atreides.

Alternatively if we can't but find the code, we could create differente .exe version to work with harkonnen->sardaukar ally or fremen->atreides ally and so on, changing privileged ID (Atreides) with another faction ID.

Link to comment
Share on other sites

People, really, you can't analyze those bytes like that. You simply don't give enough information.

If you right click on the instruction in IDA, it will give suggestions of other ways to display it, including, in raw values, something like this:

cmp es:[bx+value], 3

(value being an actual number)

That 'value' is already identified as _unitGame.houseID, but without knowing that, you can't exactly match it to the bytes. Heck, if the "3" could somehow be replaced by what it actually IS (HouseEnum.Fremen), the code would look like

cmp es:[bx+_unitGame.houseID], HouseEnum.Fremen

...thus removing ALL identifiable links with the bytecode.

Long story short: bytes don't matter. They're generated FROM the code. If you want to delve into that, translate the instruction to bare values first, without any identified names, and use OPCODES.HLP to see what the specific opcodes for "cmp register, value at address" are.

Link to comment
Share on other sites

I'll search for OPCODES, because I don't know it. :unsure:

About IA Atreides->Fremen alliance, "Area Guard" I remember it doesn't work (AI does nothing) so as "Ambush" or "Hunt", but yesterday trying "Guard" command set, it partly works: with Fremen human, Atreides AI attack WHEN they are attacked by other enemies AI (really also when a bullet goes in their box) so they counterattack. But if bullet doesn't touch them, they do nothing again (while we know that "Guard" attacks even if its just within range of the box).

And about Sandworm: any command type different to "Area Guard" does attack any most important and nearest unit (also friendly); if you turn to "Area Guard" instead it tries to eat those targets, but it doesn't do it.

All this with the exception of "Destruct" command: it turns Sandworm into an immortal and infinite eater (if last command before this was different to "Area Guard", otherwise it becomes shy) of units! Once selected you can't ever take away and it doesn't disappear aftet 3-4 "meals"!

Because of this command should destroy itself but maybe it works only for Devastator: to the game as if it was "destroyed" but it wasn't! Also trying to hit him, Sandworm is damaged by shots but:

a) it doesn't disappear when less 50% of hit points (so you can see for the first time a Sandworm with yellow/red bar!)

b) it doesn't die when no more hit points! In this case is no longer selectable with the cursor, but it will continue to move and eat units! :P

So: don't try this at home! :laugh:

P.S. "Die" command also works (Sandworm disappears) but it doesn't after selected "Destruct".

Link to comment
Share on other sites

All this with the exception of "Destruct" command: it turns Sandworm into an immortal and infinite eater (if last command before this was different to "Area Guard", otherwise it becomes shy) of units! Once selected you can't ever take away and it doesn't disappear aftet 3-4 "meals"!

Because of this command should destroy itself but maybe it works only for Devastator: to the game as if it was "destroyed" but it wasn't! Also trying to hit him, Sandworm is damaged by shots but:

a) it doesn't disappear when less 50% of hit points (so you can see for the first time a Sandworm with yellow/red bar!)

b) it doesn't die when no more hit points! In this case is no longer selectable with the cursor, but it will continue to move and eat units! :P

So: don't try this at home! :laugh:

P.S. "Die" command also works (Sandworm disappears) but it doesn't after selected "Destruct".

Wow, this is truly a very interesting find! Kind of a game breaker though.

BTW, you can see a regular Sandworm with a red or yellow bar in the game, if you pre-place it on a map with less that 50% hit points. In that case, it disappears once it's hit by anything. (I've played around with that to test a rumour that if a Sandworm is hit by a Harkonnen cluster missile, it explodes much like a spice bloom, leaving a fresh spice filed behind; naturally, it's not the case).

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...