MrFlibble Posted June 11, 2011 Author Share Posted June 11, 2011 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+31jseg010:262E ; sub_1CA1C+3Bjseg010:262E C4 5E 06 les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xxseg010:2631 26 80 7F 08 02 cmp es:[bx+_buildingGame.houseID], 2 ; Compare Two Operandsseg010: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:xxseg010:263B 26 80 7F 02 04 cmp es:[bx+_buildingGame.TypeIndex], 4 ; Heavy Factoryseg010:2640seg010:2640 loc_1CA70: ; Jump if Not Zero (ZF=0)seg010:2640 75 19 jnz short loc_1CA8Bseg010:2642 C4 5E 06 les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xxseg010:2645 26 80 7F 4E 01 cmp es:[bx+_buildingGame.techLevel], 1 ; Compare Two Operandsseg010: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:xxseg010:264Fseg010:264F loc_1CA7F:seg010:264F 26 8B 47 5E mov ax, es:[bx+_buildingData.techUpgrade3]seg010:2653seg010:2653 loc_1CA83: ; Compare Two Operandsseg010:2653 3B 06 A6 38 cmp ax, missionNumberPreviousseg010:2657 7E 02 jle short loc_1CA8B ; Jump if Less or Equal (ZF=1 | SF!=OF)seg010:2659 EB CE jmp short Ret0The "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. Quote Link to comment Share on other sites More sharing options...
segra Posted September 2, 2011 Share Posted September 2, 2011 And for those curious few amongst us, i believe that piece of code matches this in OpenDunesrc/structure.cbool 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 :) 1 Quote Link to comment Share on other sites More sharing options...
segra Posted September 2, 2011 Share Posted September 2, 2011 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.cbool 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 = objectseg023:0F7B 74 05 jz short isFremen ; Jump if Zero (ZF=1)seg023:0F7D 83 FB 03 cmp bx, 3 ; BX = humanseg023:0F80seg023:0F80 loc_231B0: ; Jump if Not Zero (ZF=0)seg023:0F80 75 0E jnz short notFremenseg023:0F82seg023:0F82 isFremen: ; CODE XREF: isFriendly?+20jseg023:0F82 83 FA 01 cmp dx, 1 ; Compare Two Operandsseg023:0F85seg023:0F85 loc_231B5: ; Jump if Zero (ZF=1)seg023:0F85 74 05 jz short isAtreidesseg023:0F87seg023:0F87 loc_231B7: ; Compare Two Operandsseg023:0F87 83 FB 01 cmp bx, 1seg023:0F8Aseg023:0F8A loc_231BA: ; if object is Fremen, and Human is Atreides, Ret Trueseg023:0F8A 75 02 jnz short notAtreidesseg023:0F8Cseg023:0F8C isAtreides: ; CODE XREF: isFriendly?:loc_231B5jseg023:0F8C EB 10 jmp short retTrue ; Jump Quote Link to comment Share on other sites More sharing options...
segra Posted September 2, 2011 Share Posted September 2, 2011 I just read you already had that code, and its not what your after.. so i assume these pieces may have some effecttheres a few bits specific to atreides / fremensrc/unit.cif (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 1 Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted September 2, 2011 Author Share Posted September 2, 2011 Awesome! :DBTW, 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... Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted September 20, 2011 Author Share Posted September 20, 2011 It is mostly MrFlibble's job, but I want to beat him to it:http://forum.opendune.org/viewtopic.php?f=9&p=277Crossposting. 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, axpush axpush sixor ax, axxor dx, dxpush axpush 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+3Ejseg023:0ED5 33 C0 xor ax, ax ; Logical Exclusive ORseg023:0ED7 50 push ax ; unitIndexFindseg023:0ED8 56 push si ; houseIDseg023:0ED9 33 C0 xor ax, ax ; Logical Exclusive ORseg023:0EDBseg023:0EDB loc_2310B: ; Logical Exclusive ORseg023:0EDB 33 D2 xor dx, dxseg023:0EDD 50 push axseg023:0EDE 52 push dx ; houseGamePtrseg023:0EDFseg023:0EDF loc_2310F: ; Call Procedureseg023:0EDF 9A 43 02 ED 1D call houseUnitGameFindseg023:0EE4seg023:0EE4 loc_23114: ; Addseg023:0EE4 83 C4 08 add sp, 8seg023:0EE7seg023:0EE7 loc_23117: ; Jumpseg023:0EE7 EB 59 jmp short unitNextThe 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 ORseg031:2254 75 B0 jnz short buildingTest ; Jump if Not Zero (ZF=0)seg031:2256 33 C0 xor ax, ax ; Carryallseg031:2258 50 push ax ; unitIndexFindseg031:2259 56 push si ; houseIDseg031:225A 33 C0 xor ax, ax ; Logical Exclusive ORseg031:225C 33 D2 xor dx, dx ; Logical Exclusive ORseg031:225E 50 push axseg031:225F 52 push dx ; houseGamePtrseg031:2260 9A 43 02 ED 1D call houseUnitGameFind ; Call Procedureseg031:2265seg031:2265 loc_2A5C5: ; Addseg031:2265 83 C4 08 add sp, 8seg031:2268 EB 34 jmp short CarryAllCheck ; JumpApparently, this time it indeed concerns carryalls only, as it has something to do with ferrying Harvesters (if I got this part correctly, that is :)). Quote Link to comment Share on other sites More sharing options...
Jongware Posted October 14, 2011 Share Posted October 14, 2011 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+3Ejseg023:0ED5 33 C0 xor ax, ax ; Logical Exclusive ORseg023:0ED7 50 push ax ; unitIndexFindseg023:0ED8 56 push si ; houseIDseg023:0ED9 33 C0 xor ax, ax ; Logical Exclusive ORThe 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, 0xFFFFpush axpush siinc axas "inc ax" is only a single byte opcode. 1 Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted October 16, 2011 Author Share Posted October 16, 2011 Thanks! I'll try it out and see if it works :) Quote Link to comment Share on other sites More sharing options...
Nyerguds Posted October 18, 2011 Share Posted October 18, 2011 mov ax, 0xFFFF is 3 bytes though.[edit]Oh, whoops, for some reason I assumed xor ax, ax was only one byte. Yes, this could work:orig:33 C0 | 50 | 56 | 33 C0new:B8 FF FF | 50 | 56 | 40 1 Quote Link to comment Share on other sites More sharing options...
Jongware Posted October 19, 2011 Share Posted October 19, 2011 Of course the second xor ax,ax in the original code was not necessary at all :D Well, it probably came out as such out of the compiler. Wasn't Dune II written using Borland C? 1 Quote Link to comment Share on other sites More sharing options...
Nyerguds Posted October 23, 2011 Share Posted October 23, 2011 C or C++, not sure. Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted January 4, 2012 Author Share Posted January 4, 2012 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). Quote Link to comment Share on other sites More sharing options...
drnovice Posted June 25, 2012 Share Posted June 25, 2012 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 = objectseg023:0F7B 74 05 jz short isFremen ; Jump if Zero (ZF=1)seg023:0F7D 83 FB 03 cmp bx, 3 ; BX = humanseg023:0F80seg023:0F80 loc_231B0: ; Jump if Not Zero (ZF=0)seg023:0F80 75 0E jnz short notFremenseg023:0F82seg023:0F82 isFremen: ; CODE XREF: isFriendly?+20jseg023:0F82 83 FA 01 cmp dx, 1 ; Compare Two Operandsseg023:0F85seg023:0F85 loc_231B5: ; Jump if Zero (ZF=1)seg023:0F85 74 05 jz short isAtreidesseg023:0F87seg023:0F87 loc_231B7: ; Compare Two Operandsseg023:0F87 83 FB 01 cmp bx, 1seg023:0F8Aseg023:0F8A loc_231BA: ; if object is Fremen, and Human is Atreides, Ret Trueseg023:0F8A 75 02 jnz short notAtreidesseg023:0F8Cseg023:0F8C isAtreides: ; CODE XREF: isFriendly?:loc_231B5jseg023:0F8C EB 10 jmp short retTrue ; JumpMaybe 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... Quote Link to comment Share on other sites More sharing options...
Nyerguds Posted June 25, 2012 Share Posted June 25, 2012 Umm, that code DOES check both ways.After cleaning it up a bit, you get this:cmp dx, 3 // is object owner Fremen?jz .isFremencmp bx, 3 // Is Human player Fremen?jnz .notFremenisFremen:cmp dx, 1 // is object owner Atreides?jz .isAtreidescmp bx, 1 // Is Human player Atreides?jnz .notAtreidesisAtreides: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 simplyif ((ObjectHouse==Fremen || HumanHouse==Fremen) && (ObjectHouse==Atreides || HumanHouse==Atreides)) return true; // isFriendly returns true Quote Link to comment Share on other sites More sharing options...
drnovice Posted June 26, 2012 Share Posted June 26, 2012 Ok it seems that this piece only 'tell in game' that Atreides &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 ifelse if object is Atreides and human=Fremen then AI object -> nothing else AI object -> hunt for human end ifend ifand 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 AIelse AI object -> hunt for humanend if Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted June 26, 2012 Author Share Posted June 26, 2012 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. Quote Link to comment Share on other sites More sharing options...
drnovice Posted June 27, 2012 Share Posted June 27, 2012 seg023:0F78 loc_231A8: ; CODE XREF: isFriendly?:loc_231A4jseg023:0F78 83 FA 03 cmp dx, 3 ; DX = objectseg023:0F7B 74 05 jz short isFremen ; Jump if Zero (ZF=1)seg023:0F7D 83 FB 03 cmp bx, 3 ; BX = humanseg023:0F80seg023:0F80 loc_231B0: ; Jump if Not Zero (ZF=0)seg023:0F80 75 0E jnz short notFremenseg023:0F82seg023:0F82 isFremen: ; CODE XREF: isFriendly?+20jseg023:0F82 83 FA 01 cmp dx, 1 ; Compare Two Operandsseg023:0F85seg023:0F85 loc_231B5: ; Jump if Zero (ZF=1)seg023:0F85 74 05 jz short isAtreidesseg023:0F87seg023:0F87 loc_231B7: ; Compare Two Operandsseg023:0F87 83 FB 01 cmp bx, 1seg023:0F8Aseg023:0F8A loc_231BA: ; if object is Fremen, and Human is Atreides, Ret Trueseg023:0F8A 75 02 jnz short notAtreidesseg023:0F8Cseg023:0F8C isAtreides: ; CODE XREF: isFriendly?:loc_231B5jseg023:0F8C EB 10 jmp short retTrue ; Jumpseg023:0F8E ; ---------------------------------------------------------------------------seg023:0F8Eseg023:0F8E notAtreides: ; CODE XREF: isFriendly?:loc_231BAjseg023:0F8E EB DE jmp short retFalse ; Jumpseg023:0F90 ; ---------------------------------------------------------------------------seg023:0F90seg023:0F90 notFremen: ; CODE XREF: isFriendly?:loc_231B0jseg023:0F90 3B 16 2C 3A cmp dx, houseHumanID ; Compare Two Operandsseg023:0F94seg023:0F94 loc_231C4: ; Jump if Zero (ZF=1)seg023:0F94 74 06 jz short objectIsHumanseg023:0F96seg023:0F96 loc_231C6: ; Compare Two Operandsseg023:0F96 3B 1E 2C 3A cmp bx, houseHumanIDseg023:0F9Aseg023:0F9A loc_231CA: ; if object is not human, and house is not human, ret trueseg023:0F9A 75 02 jnz short retTrueseg023:0F9Cseg023:0F9C objectIsHuman: ; CODE XREF: isFriendly?:loc_231C4jseg023:0F9C EB D0 jmp short retFalse ; JumpI 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], axseg023:0915 B8 01 00 mov ax, 1seg023:0918 8A 4E 0A mov cl, byte ptr [bp+houseIndex]seg023:091B D3 E0 shl ax, cl ; Shift Logical Leftseg023:091D 89 46 F6 mov [bp+houseRevealed], axseg023:0920 83 7E 0A 01 cmp [bp+houseIndex], 1 ; Compare Two Operandsseg023: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:xxseg023:0929 26 80 7F 02 19 cmp es:[bx+_unitGame.typeIndex], 19h ; sandwormseg023:092E 74 04 jz short notAtreOrWorm ; Jump if Zero (ZF=1)seg023:0930seg023:0930 loc_22B60: ; Logical Inclusive ORseg023:0930 83 4E F6 08 or [bp+houseRevealed], 8seg023:0934seg023:0934 notAtreOrWorm: ; CODE XREF: sub_22B24+30jseg023:0934 ; sub_22B24+3Ajseg023:0934 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg023:0937 26 8A 47 09 mov al, es:[bx+_unitGame.houseRevealed]seg023:093B B4 00 mov ah, 0seg023:093D 85 46 F6 test [bp+houseRevealed], ax ; Logical Compareseg023:0940seg023:0940 loc_22B70: ; Jump if Zero (ZF=1)seg023:0940 74 18 jz short loc_22B8Aseg023:0942 C4 5E F8 les bx, [bp+houseGamePtr] ; Load Full Pointer to ES:xxseg023:0945 26 F7 47 04 08 00 test es:[bx+_houseGame.IndexLastFound], 8 ; Logical Compareseg023: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:xxseg023:0950seg023: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 ORseg023:0957 E9 94 02 jmp Done ; Jumpwithout have expected results. 1 Quote Link to comment Share on other sites More sharing options...
drnovice Posted June 27, 2012 Share Posted June 27, 2012 I saw another step:seg023:0B9F loc_22DCF: ; unit not friendlyseg023:0B9F C4 5E 06 les bx, [bp+unitGamePtr]seg023:0BA2 26 80 7F 4F 08 cmp es:[bx+_unitGame.actionCurrent], 8 ; Compare Two Operandsseg023:0BA7 75 12 jnz short checkHouseID ; Jump if Not Zero (ZF=0)seg023:0BA9 B8 0B 00 mov ax, 0Bh ; Huntseg023:0BAC 50 push ax ; actionseg023:0BAD FF 76 08 push word ptr [bp+unitGamePtr+2]seg023:0BB0 FF 76 06 push word ptr [bp+unitGamePtr] ; unitGamePtrseg023:0BB3 9A 05 00 6F 25 call unitActionstart ; Call Procedureseg023:0BB8 83 C4 06 add sp, 6 ; Addseg023:0BBBseg023:0BBB checkHouseID: ; CODE XREF: sub_22B24+2A9jseg023:0BBB ; sub_22B24+2B3jseg023:0BBB C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg023: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 Operandsseg023:0BC7 74 11 jz short AtreFre ; Jump if Zero (ZF=1)seg023:0BC9seg023:0BC9 loc_22DF9: ; Load Full Pointer to ES:xxseg023:0BC9 C4 5E 06 les bx, [bp+unitGamePtr]seg023:0BCC 26 80 7F 08 03 cmp es:[bx+_unitGame.houseID], 3 ; Fremenseg023:0BD1 75 11 jnz short loc_22E14 ; Jump if Not Zero (ZF=0)seg023:0BD3 83 3E 2C 3A 01 cmp houseHumanID, 1 ; Atreseg023:0BD8 75 0A jnz short loc_22E14 ; Jump if Not Zero (ZF=0)seg023:0BDAseg023:0BDA AtreFre: ; CODE XREF: sub_22B24+2D3jseg023:0BDA C4 5E 06 les bx, [bp+unitGamePtr] ; unit = fremen and human = atreseg023:0BDD 26 C6 47 09 FF mov es:[bx+_unitGame.houseRevealed], 0FFhseg023:0BE2 EB 0A jmp short Done ; Jumpseg023:0BE4 ; ---------------------------------------------------------------------------seg023:0BE4seg023:0BE4 loc_22E14: ; CODE XREF: sub_22B24+2DDjseg023:0BE4 ; sub_22B24+2E4jseg023:0BE4 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg023:0BE7 8A 46 F6 mov al, byte ptr [bp+houseRevealed]seg023:0BEA 26 08 47 09 or es:[bx+_unitGame.houseRevealed], al ; Logical Inclusive ORseg023:0BEEseg023:0BEE Done: ; CODE XREF: sub_22B24+Fjseg023:0BEE ; sub_22B24+63j ...seg023:0BEE 5E pop siseg023:0BEF 8B E5 mov sp, bpseg023:0BF1 5D pop bpseg023:0BF2 CB retf ; Return Far from Procedureseg023:0BF2 sub_22B24 endpThis piece:seg023:0BC3 3B 06 2C 3Ain Dunex.exe files I found so:3B 06 38 3Aand also:seg023:0BD3 83 3E 2C 3A 01in Dunex.exe file:83 3E 38 3A 01I 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. 1 Quote Link to comment Share on other sites More sharing options...
Nyerguds Posted June 27, 2012 Share Posted June 27, 2012 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. Quote Link to comment Share on other sites More sharing options...
drnovice Posted June 27, 2012 Share Posted June 27, 2012 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], 3then 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... Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted June 27, 2012 Author Share Posted June 27, 2012 .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], 3Since 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). Quote Link to comment Share on other sites More sharing options...
drnovice Posted June 27, 2012 Share Posted June 27, 2012 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. Quote Link to comment Share on other sites More sharing options...
Nyerguds Posted July 2, 2012 Share Posted July 2, 2012 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 likecmp 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. Quote Link to comment Share on other sites More sharing options...
drnovice Posted July 5, 2012 Share Posted July 5, 2012 I'll search for OPCODES, because I don't know it. 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! :PSo: don't try this at home! P.S. "Die" command also works (Sandworm disappears) but it doesn't after selected "Destruct". Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted July 6, 2012 Author Share Posted July 6, 2012 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! :PSo: don't try this at home! 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). Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.