drnovice Posted May 3, 2013 Share Posted May 3, 2013 Recently I'm working to fix 3 bugs:capturing structures with deviated units did not unlock techwindtrap power information incorrect after capturing a windtrapradar scan double-counted some units and missed othersOpenDune team have shown how fixed them:https://github.com/OpenDUNE/OpenDUNE/pull/193https://github.com/OpenDUNE/OpenDUNE/pull/178 I tried to fix original EXE by hex editing.Testing the changes I haven't encountered problems or side effects.So I think that changes could be near stable. 1 Quote Link to comment Share on other sites More sharing options...
drnovice Posted May 3, 2013 Share Posted May 3, 2013 To fix: capturing structures with deviated units did not unlock tech. seg031:2E88 loc_2B1E8: ; CODE XREF: sub_2AFFC+1E7 jseg031:2E88 C4 5E 0A les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xxseg031:2E8B 26 8A 47 08 mov al, es:[bx+_buildingGame.houseID]seg031:2E8F 98 cbw ; AL -> AX (with sign)seg031:2E90 8B F0 mov si, axseg031:2E92seg031:2E92 loc_2B1F2:seg031:2E92 FF 76 08 push word ptr [bp+unitGamePtr+2]seg031:2E95 FF 76 06 push word ptr [bp+unitGamePtr] ; unitGamePtrseg031:2E98 90 nop ; No Operationseg031:2E99 0E push csseg031:2E9A E8 8D 07 call near ptr unitGameHouseIDGet ; Call Procedureseg031:2E9D 59 pop cxseg031:2E9E 59 pop cxseg031:2E9F C4 5E 0A les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xxseg031:2EA2 26 88 47 08 mov es:[bx+_buildingGame.houseID], alseg031:2EA6 56 push si ; houseIDseg031:2EA7 9A BD 13 43 0A call buildingPrereqSetup ; Call Procedureseg031:2EAC 59 pop cxseg031:2EAD 50 push axseg031:2EAE 52 push dxseg031:2EAF 56 push si ; houseIndexseg031:2EB0 9A AB 01 C7 0E call houseGamePtrGet ; Call Procedureseg031:2EB5 59 pop cxseg031:2EB6 8B D8 mov bx, axseg031:2EB8 8E C2 mov es, dxseg031:2EBA 58 pop axseg031:2EBBseg031:2EBB loc_2B21B:seg031:2EBB 26 89 47 10 mov es:[bx+_houseGame.preReqs2], axseg031:2EBF 58 pop axseg031:2EC0seg031:2EC0 loc_2B220:seg031:2EC0 26 89 47 0E mov es:[bx+_houseGame.preReqs1], axseg031:2EC4seg031:2EC4 loc_2B224: ; Load Full Pointer to ES:xxseg031:2EC4 C4 5E 06 les bx, [bp+unitGamePtr]seg031:2EC4 C4 5E 0A les bx, [bp+buildingGamePtr]seg031:2EC7seg031:2EC7 loc_2B227:seg031:2EC7 26 8A 47 08 mov al, es:[bx+_unitGame.houseID]seg031:2EC7 26 8A 47 08 mov al, es:[bx+_buildingGame.houseID]seg031:2ECB 98 cbw ; AL -> AX (with sign)seg031:2ECC 50 push ax ; houseIDseg031:2ECD 9A BD 13 43 0A call buildingPrereqSetup ; Call Procedureseg031:2ED2 59 pop cxseg031:2ED3 50 push axseg031:2ED4 52 push dxseg031:2ED5 C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg031:2EC4 C4 5E 0A les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xxseg031:2ED8 26 8A 47 08 mov al, es:[bx+_unitGame.houseID]seg031:2ED8 26 8A 47 08 mov al, es:[bx+_buildingGame.houseID]seg031:2EDC 98 cbw ; AL -> AX (with sign)seg031:2EDD 50 push ax ; houseIndexseg031:2EDEseg031:2EDE loc_2B23E: ; Call Procedureseg031:2EDE 9A AB 01 C7 0E call houseGamePtrGetseg031:2EE3 59 pop cxseg031:2EE4 8B D8 mov bx, axseg031:2EE6 8E C2 mov es, dxseg031:2EE8 58 pop axseg031:2EE9 26 89 47 10 mov es:[bx+_houseGame.preReqs2], axseg031:2EED 58 pop axseg031:2EEE 26 89 47 0E mov es:[bx+_houseGame.preReqs1], ax Just loads buildingGamePtr (that is already changed the HouseID by capturing) instead of uinitGamePtr. Quote Link to comment Share on other sites More sharing options...
drnovice Posted May 3, 2013 Share Posted May 3, 2013 To fix: windtrap power information incorrect after capturing a windtrap.Since there was no room bytes on Structure_GetStructuresBuilt() function (buildingPrereqSetup on opcode) I decided to insert Windtrap re-count into houseTotalSpicePower (House_CalculatePowerAndCredit() on c++ code) function, within houseGamePtr that we need to make changes. seg010:1F87 loc_1C3B7:seg010:1F87 8B 46 F2 mov ax, word ptr [bp+houseGamePtr]seg010:1F8A 0B 46 F4 or ax, word ptr [bp+houseGamePtr+2] ; Logical Inclusive ORseg010:1F8D 75 03 jnz short loc_1C3C2 ; Jump if Not Zero (ZF=0)seg010:1F8F E9 43 01 jmp loc_1C505 ; Jumpseg010:1F92 ; ---------------------------------------------------------------------------seg010:1F92seg010:1F92 loc_1C3C2: ; CODE XREF: houseTotalSpicePower+1D jseg010:1F92 33 FF xor di, di ; Logical Exclusive ORseg010:1F94seg010:1F94 loc_1C3C4:seg010:1F94 C7 46 FE 00 00 mov [bp+var_2], 0seg010:1F99 C4 5E F2 les bx, [bp+houseGamePtr] ; Load Full Pointer to ES:xxseg010:1F87 loc_1C3B7:seg010:1F87 33 FF xor di, di ; Logical Exclusive ORseg010:1F89 C7 46 FE 00 00 mov [bp+var_2], 0seg010:1F8E C4 5E F2 les bx, [bp+houseGamePtr] ; Load Full Pointer to ES:xxseg010:1F91 26 C7 47 1A 00 00 mov es:[bx+_houseGame.windtrapCount], 0seg010:1F97seg010:1F97 loc_1C3C4:seg010:1F97 90 90 90 90 90 nop ; No Operationsseg010:1F9Cseg010:1F9C loc_1C3CC:seg010:1F9C 26 C7 47 14 00 00 mov es:[bx+_houseGame.creditsSiloMax], 0seg010:1FA2 B8 FF FF mov ax, 0FFFFhseg010:1FA5seg010:1FA5 loc_1C3D5: ; typeIndexFindseg010:1FA5 50 push axseg010:1FA6seg010:1FA6 loc_1C3D6: ; houseIDseg010:1FA6 FF 76 06 push [bp+houseID]seg010:1FA9 33 C0 xor ax, ax ; Logical Exclusive ORseg010:1FAB 33 D2 xor dx, dx ; Logical Exclusive ORseg010:1FADseg010:1FAD loc_1C3DD:seg010:1FAD 50 push axseg010:1FAE 52 push dx ; houseGamePtrseg010:1FAFseg010:1FAF loc_1C3DF: ; Call Procedureseg010:1FAF 9A FD 00 8B 0E call buildingGameFindseg010:1FB4 83 C4 08 add sp, 8 ; Addseg010:1FB7 E9 AD 00 jmp loc_1C497 ; Jumpseg010:1FBA ; ---------------------------------------------------------------------------seg010:1FBAseg010:1FBA loc_1C3EA: ; CODE XREF: houseTotalSpicePower:loc_1C4A5 jseg010:1FBA C4 5E FA les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xxseg010:1FBD 26 8A 47 02 mov al, es:[bx+2]seg010:1FC1seg010:1FC1 loc_1C3F1: ; AL -> AX (with sign)seg010:1FC1 98 cbwseg010:1FC2seg010:1FC2 loc_1C3F2:seg010:1FC2 BA 60 00 mov dx, 60h ; '`'seg010:1FC5 F7 EA imul dx ; Signed Multiplyseg010:1FC7 05 0A 00 add ax, 0Ah ; Addseg010:1FCA C7 46 F8 9D 2A mov word ptr [bp+buildingDataPtr+2], seg seg129seg010:1FCFseg010:1FCF loc_1C3FF:seg010:1FCF 89 46 F6 mov word ptr [bp+buildingDataPtr], axseg010:1FD2 C4 5E F6 les bx, [bp+buildingDataPtr] ; Load Full Pointer to ES:xxseg010:1FD5 26 8B 47 36 mov ax, es:[bx+_buildingData.SpiceStorage]seg010:1FD9 C4 5E F2 les bx, [bp+houseGamePtr] ; Load Full Pointer to ES:xxseg010:1FDC 26 01 47 14 add es:[bx+_houseGame.creditsSiloMax], ax ; Addseg010:1FE0 C4 5E F6 les bx, [bp+buildingDataPtr] ; Load Full Pointer to ES:xxseg010:1FE3 26 83 7F 38 00 cmp es:[bx+_buildingData.PowerUsage], 0 ; Compare Two Operandsseg010:1FE8 7D 66 jge short loc_1C480 ; Jump if Greater or Equal (SF=OF)seg010:1FEA C4 5E FA les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xxseg010:1FED 26 8B 47 0E mov ax, es:[bx+_buildingGame.HitPoints]seg010:1FF1 C4 5E F6 les bx, [bp+buildingDataPtr] ; Load Full Pointer to ES:xxseg010:1FF4 26 3B 47 10 cmp ax, es:[bx+_buildingData.HitPoints] ; Compare Two Operandsseg010:1FF8seg010:1FF8 loc_1C428: ; Jump if Greater or Equal (SF=OF)seg010:1FF8 7D 49 jge short loc_1C473seg010:1FF1 90 90 90 nop ; No Operationsseg010:1FF4 90 90 90 90 nop ; No Operationsseg010:1FF8seg010:1FF8 loc_1C428seg010:1FF8 90 90 nop ; No Operationsseg010:1FFAseg010:1FFA loc_1C42A: ; Load Full Pointer to ES:xxseg010:1FFA C4 5E FA les bx, [bp+buildingGamePtr]seg010:1FFDseg010:1FFD loc_1C42D:seg010:1FFD 26 FF 77 0E push es:[bx+_buildingGame.HitPoints]seg010:2001seg010:2001 loc_1C431: ; Load Full Pointer to ES:xxseg010:2001 C4 5E F6 les bx, [bp+buildingDataPtr]seg010:2004seg010:2004 loc_1C434:seg010:2004 26 FF 77 10 push es:[bx+_buildingData.HitPoints]seg010:2008 9A 2A 00 CA 32 call j_unknownCalc ; Call Procedureseg010:200D 59 pop cxseg010:200E 59 pop cxseg010:200F 8B F0 mov si, axseg010:2011seg010:2011 loc_1C441: ; Compare Two Operandsseg010:2011 81 FE 80 00 cmp si, 80h ; 'Ç'seg010:2015 76 04 jbe short loc_1C44B ; Jump if Below or Equal (CF=1 | ZF=1)seg010:2017seg010:2017 loc_1C447:seg010:2017 8B C6 mov ax, siseg010:2019seg010:2019 loc_1C449: ; Jumpseg010:2019 EB 03 jmp short loc_1C44Eseg010:201B ; ---------------------------------------------------------------------------seg010:201Bseg010:201B loc_1C44B: ; CODE XREF: houseTotalSpicePower+A5 jseg010:201B B8 80 00 mov ax, 80h ; 'Ç'seg010:201Eseg010:201E loc_1C44E: ; CODE XREF: houseTotalSpicePower:loc_1C449 jseg010:201E 8B F0 mov si, axseg010:2020seg010:2020 loc_1C450: ; Compare Two Operandsseg010:2020 81 FE FF 00 cmp si, 0FFhseg010:2024 73 04 jnb short loc_1C45A ; Jump if Not Below (CF=0)seg010:2026 8B C6 mov ax, siseg010:2028seg010:2028 loc_1C458: ; Jumpseg010:2028 EB 03 jmp short loc_1C45Dseg010:202A ; ---------------------------------------------------------------------------seg010:202Aseg010:202A loc_1C45A: ; CODE XREF: houseTotalSpicePower+B4 jseg010:202A B8 FF 00 mov ax, 0FFhseg010:202Dseg010:202D loc_1C45D: ; CODE XREF: houseTotalSpicePower:loc_1C458 jseg010:202D 8B F0 mov si, axseg010:2011 loc_1C441:seg010:2011 90 nop ; No Operationseg010:2012 C4 5E F2 les bx, [bp+houseGamePtr] ; Load Full Pointer to ES:xxseg010:2015 26 FF 47 1A inc es:[bx+_houseGame.windtrapCount]seg010:2019seg010:2019 loc_1C449:seg010:2019 90 90 nop ; No Operationsseg010:201B ; ---------------------------------------------------------------------------seg010:201Bseg010:201B loc_1C44B:seg010:201B 90 90 90 nop ; No Operationsseg010:201Eseg010:201E loc_1C44E:seg010:201E 90 90 nop ; No Operationsseg010:2020seg010:2020 loc_1C450:seg010:2020 90 90 90 90 nop ; No Operationsseg010:2024 90 90 nop ; No Operationsseg010:2026 90 90 nop ; No Operationsseg010:2028seg010:2028 loc_1C458seg010:2028 90 90 nop ; No Operationsseg010:202A ; ---------------------------------------------------------------------------seg010:202Aseg010:202A loc_1C45Aseg010:202A 90 90 90 nop ; No Operationsseg010:202Dseg010:202D loc_1C45D:seg010:202D 90 90 nop ; No Operationsseg010:202F 56 push siseg010:2030seg010:2030 loc_1C460: ; Load Full Pointer to ES:xxseg010:2030 C4 5E F6 les bx, [bp+buildingDataPtr]seg010:2033 26 8B 47 38 mov ax, es:[bx+_buildingData.PowerUsage]seg010:2037 F7 D8 neg ax ; Two's Complement Negationseg010:2039 50 push axseg010:203Aseg010:203A loc_1C46A: ; Call Procedureseg010:203A 9A 20 00 CA 32 call j_unknownCalc2seg010:203Fseg010:203F loc_1C46F:seg010:203F 59 pop cxseg010:2040 59 pop cxseg010:2041 EB 09 jmp short loc_1C47C ; Jumpseg010:2043 ; ---------------------------------------------------------------------------seg010:2043seg010:2043 loc_1C473: ; CODE XREF: houseTotalSpicePower:loc_1C428 jseg010:2043 C4 5E F6 les bx, [bp+buildingDataPtr] ; Load Full Pointer to ES:xxseg010:2046 26 8B 47 38 mov ax, es:[bx+_buildingData.PowerUsage]seg010:204A F7 D8 neg ax ; Two's Complement Negationseg010:204Cseg010:204C loc_1C47C: ; CODE XREF: houseTotalSpicePower+D1 jseg010:204C 03 F8 add di, ax ; Addseg010:204E EB 0A jmp short loc_1C48A ; Jumpseg010:2050 ; ---------------------------------------------------------------------------seg010:2050seg010:2050 loc_1C480: ; CODE XREF: houseTotalSpicePower+78 jseg010:2050 C4 5E F6 les bx, [bp+buildingDataPtr] ; Load Full Pointer to ES:xxseg010:2053 26 8B 47 38 mov ax, es:[bx+_buildingData.PowerUsage]seg010:2057 01 46 FE add [bp+var_2], ax ; Addseg010:205Aseg010:205A loc_1C48A: ; CODE XREF: houseTotalSpicePower+DE jseg010:205A 33 C0 xor ax, ax ; Logical Exclusive ORseg010:205C 33 D2 xor dx, dx ; Logical Exclusive ORseg010:205E 50 push axseg010:205Fseg010:205F loc_1C48F: ; houseGamePtrseg010:205F 52 push dxseg010:2060 9A 3D 01 8B 0E call buildingGameGetNextPtr ; Call Procedureseg010:2065 59 pop cxseg010:2066 59 pop cxseg010:2067seg010:2067 loc_1C497: ; CODE XREF: houseTotalSpicePower+47 jseg010:2067 89 56 FC mov word ptr [bp+buildingGamePtr+2], dxseg010:206Aseg010:206A loc_1C49A:seg010:206A 89 46 FA mov word ptr [bp+buildingGamePtr], axseg010:206D 8B 46 FA mov ax, word ptr [bp+buildingGamePtr]seg010:2070seg010:2070 loc_1C4A0: ; Logical Inclusive ORseg010:2070 0B 46 FC or ax, word ptr [bp+buildingGamePtr+2]seg010:2073 74 03 jz short loc_1C4A8 ; Jump if Zero (ZF=1)seg010:2075seg010:2075 loc_1C4A5: ; Jumpseg010:2075 E9 42 FF jmp loc_1C3EAseg010:2078 ; ---------------------------------------------------------------------------seg010:2078seg010:2078 loc_1C4A8: ; CODE XREF: houseTotalSpicePower+103 jseg010:2078 C4 5E F2 les bx, [bp+houseGamePtr] ; Load Full Pointer to ES:xxseg010:207Bseg010:207B loc_1C4AB:seg010:207B 26 89 7F 16 mov es:[bx+_houseGame.PowerOutput], di I set to 0 WindtrapCount variable at starting, then on structure research cycle if building has negative PowerUsage WindtrapCount is increased.I removed (nopED) even 50% HP check, because originally if a Wintrap had less than 50% HP, also provided almost 50% of PowerOutput, instead should count exactly relative % of HP (e.g. if 10% of HP, PowerOutput should be 10% of the Total for that Wintrap). Quote Link to comment Share on other sites More sharing options...
drnovice Posted May 3, 2013 Share Posted May 3, 2013 To fix: radar scan double-counted some units and missed others.Originally cycle is done on g_unitFindCount-1 (unitsGameCount), for this reason Radar count is wrong because last unit on map isn't counted. [snip] I had to remove completely the array sorting (that I don't undestand why is it made) because there was no enough room to make another cycle on g_unitFindCount value. Array sorting to cycle needs to g_unitFindCount-1 because it always checks between i-th element of array and i-th+1, therefore if was cycling on exactly g_unitFindCount, last unit checks the last i-th element with the i-th+1 on overflow... the result is units that start oddly to disappear on map... Then I removed dec AX register so unitLoop cycles on exactly g_unitFindCount. EDITED: I had to bend the stuff space-time to make this change... 8) It's a bit complicated but should work without having to remove array sorting.I used DI register as flag: at start the loop cycles only for UnitCount, then same loop is re-cycled only for array sorting.Thanks to Dynasty's indication. EDITED2: Discard, entire post is wrong Quote Link to comment Share on other sites More sharing options...
dynasty Posted May 3, 2013 Share Posted May 3, 2013 The sorting is necessary for drawing, otherwise units with smaller y might overlap those with bigger y. The main problem with the code was that when two units were swapped, the first was counted twice and the second completely missed. This makes the radar scan hard to read when there is a battle going on, because bullets move about. The missing final unit is relatively minor, and probably not fixable in the given space. To fix the swapping problem, you want to delay the unit count until after the sort. e.g. for (i = 0; i < g_unitFindCount - 1; i++) { Unit *u1; Unit *u2; uint16 y1; uint16 y2; u1 = g_unitFindArray[i]; u2 = g_unitFindArray[i + 1]; ... if ((int16)y1 > (int16)y2) { g_unitFindArray[i] = u2; g_unitFindArray[i + 1] = u1; } u1 = g_unitFindArray[i]; if ((u1->o.seenByHouses & (1 << g_playerHouseID)) != 0 && !u1->o.flags.s.isNotOnMap) { if (House_AreAllied(u1->o.houseID, g_playerHouseID)) { h->unitCountAllied++; } else { h->unitCountEnemy++; } } } 1 Quote Link to comment Share on other sites More sharing options...
drnovice Posted May 4, 2013 Share Posted May 4, 2013 Thanks for reply.What does it mean overlap units? Can you show me an example?It could do when you save/load a game?I tried to play 9th mission with more than 50 friend units and more that 10 enemy units every time...game was slowed but I noticed nothing about overlap...I even tried to move opcode bytes of sort array FIRST of units count, but some functions must be in certain position otherwise game crashes. Quote Link to comment Share on other sites More sharing options...
drnovice Posted May 4, 2013 Share Posted May 4, 2013 To fix the swapping problem, you want to delay the unit count until after the sort. e.g.On opcode bytes it isn't so simple: you can't move isFriendly? function (House_AreAllied() on c++) since on original code is called first, otherwise game crashes (don't know why, but divide error is returned); so I have to find another solution about it. Quote Link to comment Share on other sites More sharing options...
drnovice Posted May 4, 2013 Share Posted May 4, 2013 Dynasty, now should work it.The conditional is a must because I haven't tested a full game, but it no longer crashes and the count is always correct.Again I haven't noticed this overlap that you talking about, however I trust you when you tell that array sorting is necessary. ;) With lots of beer I have expanded my foreknowledge, better than the spice... :) Quote Link to comment Share on other sites More sharing options...
Nyerguds Posted May 5, 2013 Share Posted May 5, 2013 drnovice: Those are in kind of an annoying format to copy into an exe... could you just add the actual byte ranges of the original and changed blocks underneath the full explanation, in each post? Quote Link to comment Share on other sites More sharing options...
drnovice Posted May 6, 2013 Share Posted May 6, 2013 Sure Nyerguds, I'll modified the posts when have more time.Meanwhile, you could see the blocks of original and changes bytes in the Collection that I attached. ;) 2 Quote Link to comment Share on other sites More sharing options...
Nyerguds Posted May 7, 2013 Share Posted May 7, 2013 Ohh right. You update that. Heh Quote Link to comment Share on other sites More sharing options...
drnovice Posted May 7, 2013 Share Posted May 7, 2013 No problem. :)The collection is a .zip file that contains .pdf files cataloged for sections.If you have time and want to try the changes, let's give me a feedback about any problem, because I didn't test very much it. Quote Link to comment Share on other sites More sharing options...
drnovice Posted May 27, 2013 Share Posted May 27, 2013 The previous code is wrong. Units Array Sort didn't work so Units weren't redrawed when a tank went over an infantry Unit for example. Right tested code is: EDITED: Hmm, it seems to freeze into a Scenario on stressing with several units. Maybe there a case that the loop is no loger able to break. I'm working to fix it. Sorry for the rush. 1 Quote Link to comment Share on other sites More sharing options...
drnovice Posted May 28, 2013 Share Posted May 28, 2013 It needs further testing (if someone else can test it would give me more feedback): seg015:000A loc_1DEDA: ; Load Full Pointer to ES:xxseg015:000A C4 1E 3A 3A les bx, houseHumanGamePtrseg015:000Eseg015:000E loc_1DEDE:seg015:000E 26 C7 47 0A 00 00 mov es:[bx+_houseGame.field_A], 0seg015:0014seg015:0014 loc_1DEE4: ; Load Full Pointer to ES:xxseg015:0014 C4 1E 3A 3A les bx, houseHumanGamePtrseg015:0018seg015:0018 loc_1DEE8:seg015:0018 26 C7 47 0C 00 00 mov es:[bx+_houseGame.objectTypeIndex], 0seg015:001E BF FF FA mov di, FFFAhseg015:0021 EB 02 jmp short loc_1DEEE ; Jumpseg015:0023seg015:0023 secondInit:seg015:0023 33 FF xor di, diseg015:001Eseg015:001E loc_1DEEE: ; Logical Exclusive ORseg015:001E 33 F6 xor si, siseg015:0020seg015:0020 loc_1DEF0: ; Jumpseg015:0020 E9 0B 01 jmp loc_1DFFEseg015:0023 ; ---------------------------------------------------------------------------seg015:0023seg015:0023 glb_1DEF3: ; CODE XREF: unitsSort:loc_1E006 jseg015:0023 unitLoop: ; si = indexseg015:0023 8B DE mov bx, siseg015:0025seg015:0025 loc_1DEF5:seg015:0025 B1 02 mov cl, 2seg015:0027seg015:0027 loc_1DEF7: ; Shift Logical Leftseg015:0027 D3 E3 shl bx, clseg015:0029seg015:0029 loc_1DEF9:seg015:0029 8B 87 40 84 mov ax, word ptr (unitsGamePtrs+2)[bx]seg015:002Dseg015:002D loc_1DEFD:seg015:002D 8B 97 3E 84 mov dx, word ptr unitsGamePtrs[bx]seg015:0031seg015:0031 loc_1DF01:seg015:0031 89 46 FE mov word ptr [bp+unitGamePtr+2], axseg015:0034seg015:0034 loc_1DF04:seg015:0034 89 56 FC mov word ptr [bp+unitGamePtr], dxseg015:0037seg015:0037 loc_1DF07:seg015:0037 8B DE mov bx, siseg015:0039seg015:0039 loc_1DF09:seg015:0039 B1 02 mov cl, 2seg015:003Bseg015:003B loc_1DF0B: ; Shift Logical Leftseg015:003B D3 E3 shl bx, clseg015:003Dseg015:003D loc_1DF0D:seg015:003D 8B 87 44 84 mov ax, word ptr (unitsGamePtrs+6)[bx]seg015:0041seg015:0041 loc_1DF11:seg015:0041 8B 97 42 84 mov dx, word ptr (unitsGamePtrs+4)[bx]seg015:0045seg015:0045 loc_1DF15:seg015:0045 89 46 FA mov word ptr [bp+unitGamePtr2+2], axseg015:0048seg015:0048 loc_1DF18:seg015:0048 89 56 F8 mov word ptr [bp+unitGamePtr2], dxseg015:004Bseg015:004B seg015:0045 loopCheck1:seg015:0045 81 FF FF FA cmp di, FFFAhseg015:0049 75 4B jnz short loc_1DF66 ; Jump if Not Zero (ZF=0)seg015:004Bseg015:004B loopCheck2:seg015:004B 3B 36 EC 35 cmp si, unitsGameCountseg015:004F 74 CE jz short secondInitloc_1DF1B: ; Load Full Pointer to ES:xxseg015:004B C4 5E FC les bx, [bp+unitGamePtr]seg015:004Eseg015:004E loc_1DF1E:seg015:004E 26 8A 47 09 mov al, es:[bx+_unitGame.houseRevealed]seg015:0052seg015:0052 loc_1DF22:seg015:0052 B4 00 mov ah, 0seg015:0054seg015:0054 loc_1DF24:seg015:0054 BA 01 00 mov dx, 1seg015:0057seg015:0057 loc_1DF27:seg015:0057 8A 0E 38 3A mov cl, byte ptr houseHumanIDseg015:005Bseg015:005B loc_1DF2B: ; Shift Logical Leftseg015:005B D3 E2 shl dx, clseg015:005Dseg015:005D loc_1DF2D: ; Logical Compareseg015:005D 85 C2 test ax, dxseg015:005Fseg015:005F loc_1DF2F: ; Jump if Zero (ZF=1)seg015:005F 74 2B jz short loc_1DF66seg015:0061seg015:0061 loc_1DF31: ; Load Full Pointer to ES:xxseg015:0061 C4 5E FC les bx, [bp+unitGamePtr]seg015:0064seg015:0064 loc_1DF34: ; Logical Compareseg015:0064 26 F7 47 04 04 00 test es:[bx+_unitGame.unitState], 4seg015:006Aseg015:006A loc_1DF3A: ; Jump if Not Zero (ZF=0)seg015:006A 75 23 jnz short loc_1DF66seg015:006Cseg015:006C loc_1DF3C: ; HumanHouseIDseg015:006C FF 36 38 3A push houseHumanIDseg015:0070seg015:0070 loc_1DF40: ; Load Full Pointer to ES:xxseg015:0070 C4 5E FC les bx, [bp+unitGamePtr]seg015:0073seg015:0073 loc_1DF43:seg015:0073 26 8A 47 08 mov al, es:[bx+_unitGame.houseID]seg015:0077 98 cbw ; AL -> AX (with sign)seg015:0078seg015:0078 loc_1DF48: ; objectHouseIDseg015:0078 50 push axseg015:0079seg015:0079 loc_1DF49: ; Call Procedureseg015:0079 9A 34 0F 2C 12 call isFriendly?seg015:007Eseg015:007E loc_1DF4E:seg015:007E 59 pop cxseg015:007Fseg015:007F loc_1DF4F:seg015:007F 59 pop cxseg015:0080 C4 1E 3A 3A les bx, houseHumanGamePtrseg015:0080seg015:0080 loc_1DF50: ; Logical Inclusive ORseg015:0080 0B C0 or ax, axseg015:0082 74 06 jz short loc_1DF5E ; Jump if Zero (ZF=1)seg015:0084seg015:0084 loc_1DF54: ; Load Full Pointer to ES:xxseg015:0084 C4 1E 3A 3A les bx, houseHumanGamePtrseg015:0088seg015:0088 loc_1DF58: ; Increment by 1seg015:0088 26 FF 47 0C inc es:[bx+_houseGame.objectTypeIndex]seg015:008C EB 04 jmp short loc_1DF66 ; Jumpseg015:008E ; ---------------------------------------------------------------------------seg015:008Eseg015:008E loc_1DF5E: ; CODE XREF: unitsSort+80 jseg015:008E C4 1E 3A 3A les bx, houseHumanGamePtr ; Load Full Pointer to ES:xxseg015:0092seg015:0092 loc_1DF62: ; Increment by 1seg015:0092 26 FF 47 0A inc es:[bx+_houseGame.field_A]seg015:0092seg015:0092 90 nop ; No Operationseg015:0193 46 inc si ; Increment by 1seg015:0094 EB 8D jmp unitLoopseg015:0096seg015:0096 loc_1DF66: ; CODE XREF: unitsSort:loc_1DF2F jseg015:0096 ; unitsSort:loc_1DF3A j ...seg015:0096 C4 5E FC les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg015:0099 26 FF 77 0C push es:[bx+_unitGame.mapTileY] ; retValueseg015:009Dseg015:009D loc_1DF6D: ; intseg015:009D 26 FF 77 0A push es:[bx+_unitGame.mapTileX]seg015:00A1seg015:00A1 loc_1DF71: ; Call Procedureseg015:00A1 9A 7E 00 48 0D call returnArg2AsAXseg015:00A6seg015:00A6 loc_1DF76:seg015:00A6 59 pop cxseg015:00A7 59 pop cxseg015:00A8seg015:00A8 loc_1DF78:seg015:00A8 8B F8 mov di, axseg015:00AA C4 5E F8 les bx, [bp+unitGamePtr2] ; Load Full Pointer to ES:xxseg015:00AD 26 FF 77 0C push word ptr es:[bx+0Ch] ; retValueseg015:00B1seg015:00B1 loc_1DF81: ; intseg015:00B1 26 FF 77 0A push word ptr es:[bx+0Ah]seg015:00B5seg015:00B5 loc_1DF85: ; Call Procedureseg015:00B5 9A 7E 00 48 0D call returnArg2AsAXseg015:00BA 59 pop cxseg015:00BB 59 pop cxseg015:00BCseg015:00BC loc_1DF8C:seg015:00BC 89 46 F6 mov [bp+var_A], axseg015:00BFseg015:00BF loc_1DF8F: ; Load Full Pointer to ES:xxseg015:00BF C4 5E FC les bx, [bp+unitGamePtr]seg015:00C2seg015:00C2 loc_1DF92:seg015:00C2 26 8A 47 02 mov al, es:[bx+2]seg015:00C6 98 cbw ; AL -> AX (with sign)seg015:00C7seg015:00C7 loc_1DF97:seg015:00C7 BA 5A 00 mov dx, 5Ah ; 'Z'seg015:00CA F7 EA imul dx ; Signed Multiplyseg015:00CC BA 10 2B mov dx, seg seg130seg015:00CF 8B D8 mov bx, axseg015:00D1seg015:00D1 loc_1DFA1:seg015:00D1 8E C2 mov es, dxseg015:00D3 assume es:seg130seg015:00D3 26 83 BF 3C 00 00 cmp es:[bx+_unitData.MovementType], 0 ; Compare Two Operandsseg015:00D9 75 04 jnz short loc_1DFAF ; Jump if Not Zero (ZF=0)seg015:00DB 81 EF 00 01 sub di, 100h ; Integer Subtractionseg015:00DFseg015:00DF loc_1DFAF: ; CODE XREF: unitsSort+D7 jseg015:00DF C4 5E F8 les bx, [bp+unitGamePtr2] ; Load Full Pointer to ES:xxseg015:00E2 assume es:nothingseg015:00E2 26 8A 47 02 mov al, es:[bx+_unitGame.typeIndex]seg015:00E6seg015:00E6 loc_1DFB6: ; AL -> AX (with sign)seg015:00E6 98 cbwseg015:00E7 BA 5A 00 mov dx, 5Ah ; 'Z'seg015:00EA F7 EA imul dx ; Signed Multiplyseg015:00EC BA 10 2B mov dx, seg seg130seg015:00EFseg015:00EF loc_1DFBF:seg015:00EF 8B D8 mov bx, axseg015:00F1 8E C2 mov es, dxseg015:00F3 assume es:seg130seg015:00F3seg015:00F3 loc_1DFC3: ; Compare Two Operandsseg015:00F3 26 83 BF 3C 00 00 cmp es:[bx+_unitData.MovementType], 0seg015:00F9 75 05 jnz short loc_1DFD0 ; Jump if Not Zero (ZF=0)seg015:00FBseg015:00FB loc_1DFCB: ; Integer Subtractionseg015:00FB 81 6E F6 00 01 sub [bp+var_A], 100hseg015:0100seg015:0100 loc_1DFD0: ; CODE XREF: unitsSort+F7 jseg015:0100 3B 7E F6 cmp di, [bp+var_A] ; Compare Two Operandsseg015:0103seg015:0103 loc_1DFD3: ; Jump if Less or Equal (ZF=1 | SF!=OF)seg015:0103 7E 24 jle short loc_1DFFDseg015:0105 8B DE mov bx, siseg015:0107seg015:0107 loc_1DFD7:seg015:0107 B1 02 mov cl, 2seg015:0109seg015:0109 loc_1DFD9: ; Shift Logical Leftseg015:0109 D3 E3 shl bx, clseg015:010B 8B 46 FA mov ax, word ptr [bp+unitGamePtr2+2]seg015:010Eseg015:010E loc_1DFDE:seg015:010E 8B 56 F8 mov dx, word ptr [bp+unitGamePtr2]seg015:0111seg015:0111 loc_1DFE1:seg015:0111 89 87 40 84 mov word ptr (unitsGamePtrs+2)[bx], axseg015:0115 89 97 3E 84 mov word ptr unitsGamePtrs[bx], dxseg015:0119 8B DE mov bx, siseg015:011B B1 02 mov cl, 2seg015:011D D3 E3 shl bx, cl ; Shift Logical Leftseg015:0119 90 90 nop ; No Operationsseg015:011F 8B 46 FE mov ax, word ptr [bp+unitGamePtr+2]seg015:0122 8B 56 FC mov dx, word ptr [bp+unitGamePtr]seg015:0125 89 87 44 84 mov word ptr (unitsGamePtrs+6)[bx], axseg015:0129seg015:0129 loc_1DFF9:seg015:0129 89 97 42 84 mov word ptr (unitsGamePtrs+4)[bx], dxseg015:012Dseg015:012D loc_1DFFD: ; CODE XREF: unitsSort:loc_1DFD3 jseg015:012D 46 inc si ; Increment by 1seg015:012Eseg015:012E loc_1DFFE: ; CODE XREF: unitsSort:loc_1DEF0 jseg015:012E A1 EC 35 mov ax, unitsGameCountseg015:012D 90 90 90 90 nop ; No Operationsseg015:0131 48 dec ax ; Decrement by 1seg015:0132 3B C6 cmp ax, si ; Compare Two Operandsseg015:0134 7E 03 jle short loc_1E009 ; Jump if Less or Equal (ZF=1 | SF!=OF)seg015:0136seg015:0136 loc_1E006: ; Jumpseg015:0136 E9 EA FE jmp unitLoop I tried to set di register to FFFAh value so I hope that this value never is used for Array Sorting, second part of loop. Search for: c4 1e 3a 3a 26 c7 47 0c 00 00 33 f6e9 0b 01 8b de b1 02 d3 e3 8b 87 40 84 8b 97 3e84 89 46 fe 89 56 fc 8b de b1 02 d3 e3 8b 87 4484 8b 97 42 84 89 46 fa 89 56 f8 c4 5e fc 26 8a47 09 b4 00 ba 01 00 8a 0e 38 3a d3 e2 85 c2 7435 c4 5e fc 26 f7 47 04 04 00 75 2a ff 36 38 3ac4 5e fc 26 8a 47 08 98 50 9a 34 0f 2c 12 59 590b c0 74 0a c4 1e 3a 3a 26 ff 47 0c eb 08 c4 1e3a 3a 26 ff 47 0a c4 5e fc 26 ff 77 0c 26 ff 770a 9a 7e 00 48 0d 59 59 8b f8 c4 5e f8 26 ff 770c 26 ff 77 0a 9a 7e 00 48 0d 59 59 89 46 f6 c45e fc 26 8a 47 02 98 ba 5a 00 f7 ea ba 10 2b 8bd8 8e c2 26 83 bf 3c 00 00 75 04 81 ef 00 01 c45e f8 26 8a 47 02 98 ba 5a 00 f7 ea ba 10 2b 8bd8 8e c2 26 83 bf 3c 00 00 75 05 81 6e f6 00 013b 7e f6 7e 28 8b de b1 02 d3 e3 8b 46 fa 8b 56f8 89 87 40 84 89 97 3e 84 8b de b1 02 d3 e3 8b46 fe 8b 56 fc 89 87 44 84 89 97 42 84 46 a1 ec35 48 3b c6 7e 03 e9 ea fe Replace with: 26 c7 47 0c 00 00 bf ff fa eb 02 33ff 33 f6 8b de b1 02 d3 e3 8b 87 40 84 8b 97 3e84 89 46 fe 89 56 fc 8b 87 44 84 8b 97 42 84 8946 fa 89 56 f8 81 ff ff fa 75 4b 3b 36 ec 35 74ce c4 5e fc 26 8a 47 09 b4 00 ba 01 00 8a 0e 383a d3 e2 85 c2 74 2b 26 f7 47 04 04 00 75 23 ff36 38 3a 26 8a 47 08 98 50 9a 34 0f 2c 12 59 59c4 1e 3a 3a 0b c0 74 06 26 ff 47 0c eb 04 26 ff47 0a 90 46 eb 8d c4 5e fc 26 ff 77 0c 26 ff 770a 9a 7e 00 48 0d 59 59 8b f8 c4 5e f8 26 ff 770c 26 ff 77 0a 9a 7e 00 48 0d 59 59 89 46 f6 c45e fc 26 8a 47 02 98 ba 5a 00 f7 ea ba 10 2b 8bd8 8e c2 26 83 bf 3c 00 00 75 04 81 ef 00 01 c45e f8 26 8a 47 02 98 ba 5a 00 f7 ea ba 10 2b 8bd8 8e c2 26 83 bf 3c 00 00 75 05 81 6e f6 00 013b 7e f6 7e 24 8b de b1 02 d3 e3 8b 46 fa 8b 56f8 89 87 40 84 89 97 3e 84 90 90 8b 46 fe 8b 56fc 89 87 44 84 89 97 42 84 46 a1 ec 35 90 90 9090 48 3b c6 7e 03 e9 ea fe Quote Link to comment Share on other sites More sharing options...
drnovice Posted May 30, 2013 Share Posted May 30, 2013 Finally I managed Sandworm behaviour!Did you remember the spawning Fremen Warriors from Atreides/Fremen Palace as Special Weapon?Spawned units are set on Hunt command by default (expected by code) so a spawned Sandworm on Hunt command together Warriors, it starts to swallow them before they start to go against enemies!So I "say" to code that Warrior/Warriors typeIndex (04 & 02) aren't valid targets (0 is returned): seg031:14F0 loc_29850: ; Integer Subtractionseg031:14F0 83 EC 04 sub sp, 4seg031:14F3 56 push siseg031:14F4 57 push diseg031:14F5 33 F6 xor si, si ; Logical Exclusive ORseg031:14F7 8B 46 06 mov ax, word ptr [bp+pUnitGamePtr]seg031:14FA 0B 46 08 or ax, word ptr [bp+pUnitGamePtr+2] ; Logical Inclusive ORseg031:14FD 74 08 jz short ret0 ; Jump if Zero (ZF=1)seg031:14FF 8B 46 0A mov ax, word ptr [bp+unitGamePtr]seg031:1502 0B 46 0C or ax, word ptr [bp+unitGamePtr+2] ; Logical Inclusive ORseg031:1505 75 05 jnz short unitCheck ; Jump if Not Zero (ZF=0)seg031:1507seg031:1507 ret0: ; CODE XREF: calcTime?Distance?+10 jseg031:1507 33 C0 xor ax, ax ; Logical Exclusive ORseg031:1509seg031:1509 loc_29869: ; CODE XREF: calcTime?Distance?+FD jseg031:1509 E9 E1 00 jmp Done ; Jumpseg031:150C ; ---------------------------------------------------------------------------seg031:150Cseg031:150C unitCheck: ; CODE XREF: calcTime?Distance?+18 jseg031:150C C4 5E 0A les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg031:150F 26 FF 77 0C push es:[bx+_unitGame.mapTileY] ; posYseg031:1513 26 FF 77 0A push es:[bx+_unitGame.mapTileX] ; posXseg031:1517seg031:1517 loc_29877: ; Call Procedureseg031:1517 9A 86 00 48 0D call mapIndexFromMapTileXYseg031:151C 59 pop cxseg031:151D 59 pop cxseg031:151E 50 push ax ; mapPosseg031:151F 9A 4D 00 D0 42 call j_mapTileCheckIfFogWar ; Call Procedureseg031:1524 59 pop cxseg031:1525 0B C0 or ax, ax ; Logical Inclusive ORseg031:1527 75 03 jnz short loc_2988C ; Jump if Not Zero (ZF=0)seg031:1529 E9 BC 00 jmp retSI ; Jumpseg031:152C ; ---------------------------------------------------------------------------seg031:152Cseg031:152C loc_2988C: ; CODE XREF: calcTime?Distance?+3A jseg031:152C C4 5E 0A les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg031:152F 26 8A 47 02 mov al, es:[bx+_unitGame.typeIndex]seg031:1533 98 cbw ; AL -> AX (with sign)seg031:1537 8B F8 mov di, axseg031:1537 90 nop ; No Operationseg031:1534 BA 5A 00 mov dx, size _unitDataseg031:1537 F7 EA imul dx ; Signed Multiplyseg031:1539 05 00 00 add ax, 0 ; Addseg031:153C C7 46 FE 10 2B mov word ptr [bp+unitDataPtr+2], seg seg130seg031:1541 89 46 FC mov word ptr [bp+unitDataPtr], axseg031:1544 33 F6 xor si, si ; Logical Exclusive ORseg031:1546 C4 5E 0A les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg031:1549 26 FF 77 0C push es:[bx+_unitGame.mapTileY] ; posYseg031:154D 26 FF 77 0A push es:[bx+_unitGame.mapTileX] ; posXseg031:1551 9A 86 00 48 1D call mapIndexFromMapTileXY ; Call Procedureseg031:1556 59 pop cxseg031:1557 59 pop cxseg031:1558 50 push ax ; mapPositionseg031:1559 9A 61 00 D0 42 call j_mapTileTypeGet ; Call Procedureseg031:155E 59 pop cxseg031:155Fseg031:155F loc_298BF:seg031:155F BA 1C 00 mov dx, 1Chseg031:1562seg031:1562 loc_298C2: ; Signed Multiplyseg031:1562 F7 EA imul dxseg031:1564 8B D8 mov bx, axseg031:1566 83 BF 40 3A 00 cmp word_46E60[bx], 0 ; Compare Two Operandsseg031:156B 74 7B jz short retSI ; Jump if Zero (ZF=1)seg031:156D C4 5E FC les bx, [bp+unitDataPtr] ; Load Full Pointer to ES:xxseg031:1570seg031:1570 loc_298D0:seg031:1570 26 8B 5F 3C mov bx, es:[bx+_unitData.MovementType]seg031:1574 83 FB 03 cmp bx, 3 ; switch 4 casesseg031:1577 77 14 ja short loc_298EF ; defaultseg031:1579 D1 E3 shl bx, 1 ; Shift Logical Leftseg031:157Bseg031:157B loc_298DB: ; switch jumpseg031:157B 2E FF A7 F3 15 jmp cs:off_29953[bx]seg031:1580seg031:1580 Tracked: ; DATA XREF: seg031:off_29953 oseg031:1580 BE E8 03 mov si, 3E8h ; case 0x1seg031:1583 EB 08 jmp short loc_298EF ; Jumpseg031:1585 ; ---------------------------------------------------------------------------seg031:1585seg031:1585 Foot: ; CODE XREF: calcTime?Distance?:loc_298DB jseg031:1585 ; DATA XREF: seg031:off_29953 oseg031:1585 BE 64 00 mov si, 64h ; 'd' ; case 0x0seg031:1588 EB 03 jmp short loc_298EF ; Jumpseg031:158A ; ---------------------------------------------------------------------------seg031:158Aseg031:158A Wheeled: ; CODE XREF: calcTime?Distance?:loc_298DB jseg031:158A ; DATA XREF: seg031:off_29953 oseg031:158A BE 88 13 mov si, 1388h ; case 0x3seg031:158D EB 04 jmp short loc_298F3 ; Jumpseg031:158F ; ---------------------------------------------------------------------------seg031:158Fseg031:158F loc_298EF: ; CODE XREF: calcTime?Distance?+8A jseg031:1593 83 FF 02 cmp di, 2 ; Compare Two Operandsseg031:156B 74 05 jz short caseFremen ; Jump if Zero (ZF=1)seg031:1593 83 FF 04 cmp di, 4 ; Compare Two Operandsseg031:156B 75 02 jnz short loc_298F3 ; Jump if Not Zero (ZF=0)seg031:1593 caseFremen:seg031:158F 33 F6 xor si, si ; defaultseg031:1591 EB 00 jmp short $+2 ; Jumpseg031:1593seg031:1593 loc_298F3: ; CODE XREF: calcTime?Distance?+96 jseg031:1593 ; calcTime?Distance?+9B j ...seg031:1593 C4 5E 0A les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg031:1596 26 80 7F 6A 00 cmp es:[bx+_unitGame.speed3], 0 ; Compare Two Operandsseg031:159B 75 07 jnz short loc_29907 ; Jump if Not Zero (ZF=0)seg031:159D C4 5E 0A les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg031:15A0 26 80 7F 51 00 cmp es:[bx+_unitGame.weaponCooldownTimer], 0 ; Compare Two Operandsseg031:15A5 74 04 jz short loc_2990B ; Jump if Zero (ZF=1)seg031:15A7seg031:15A7 loc_29907: ; CODE XREF: calcTime?Distance?+AE jseg031:15A7 B1 02 mov cl, 2seg031:15A9 D3 E6 shl si, cl ; Shift Logical Leftseg031:15ABseg031:15AB loc_2990B: ; CODE XREF: calcTime?Distance?+B8 jseg031:15AB C4 5E 0A les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xxseg031:15AEseg031:15AE loc_2990E: ; buildingPosYseg031:15AE 26 FF 77 0C push es:[bx+_unitGame.mapTileY]seg031:15B2seg031:15B2 loc_29912: ; buildingPosXseg031:15B2 26 FF 77 0A push es:[bx+_unitGame.mapTileX]seg031:15B6 C4 5E 06 les bx, [bp+pUnitGamePtr] ; Load Full Pointer to ES:xxseg031:15B9 26 FF 77 0C push es:[bx+_unitGame.mapTileY] ; unitPosYseg031:15BDseg031:15BD loc_2991D: ; unitPosXseg031:15BD 26 FF 77 0A push es:[bx+_unitGame.mapTileX]seg031:15C1seg031:15C1 loc_29921: ; Call Procedureseg031:15C1 9A 04 01 48 1D call getDistance?seg031:15C6 83 C4 08 add sp, 8 ; Addseg031:15C9 8B F8 mov di, axseg031:15CB 0B FF or di, di ; Logical Inclusive ORseg031:15CD 74 0B jz short loc_2993A ; Jump if Zero (ZF=1)seg031:15CF 0B F6 or si, si ; Logical Inclusive ORseg031:15D1seg031:15D1 loc_29931: ; Jump if Zero (ZF=1)seg031:15D1 74 07 jz short loc_2993Aseg031:15D3 8B C6 mov ax, siseg031:15D5 99 cwd ; AX -> DX:AX (with sign)seg031:15D6seg031:15D6 loc_29936: ; Signed Divideseg031:15D6 F7 FF idiv diseg031:15D8 8B F0 mov si, axseg031:15DAseg031:15DA loc_2993A: ; CODE XREF: calcTime?Distance?+E0 jseg031:15DA ; calcTime?Distance?:loc_29931 jseg031:15DA 83 FF 02 cmp di, 2 ; Compare Two Operandsseg031:15DD 7D 09 jge short retSI ; Jump if Greater or Equal (SF=OF)seg031:15DF BA 02 00 mov dx, 2seg031:15E2 8B C6 mov ax, siseg031:15E4 F7 EA imul dx ; Signed Multiplyseg031:15E6 8B F0 mov si, axseg031:15E8seg031:15E8 retSI: ; CODE XREF: calcTime?Distance?+3C jseg031:15E8 ; calcTime?Distance?+7E j ...seg031:15E8 8B C6 mov ax, siseg031:15EA E9 1C FF jmp loc_29869 ; Jump Only for expert players! ;) 1 Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted June 1, 2013 Author Share Posted June 1, 2013 Hey, this is an extremely clever solution! I'd never come up with anything like that :) Congratulations! This means that the Fremen in DuneX can now have some really badass superweapon after all ^_^ Quote Link to comment Share on other sites More sharing options...
drnovice Posted June 2, 2013 Share Posted June 2, 2013 Yes, you know it's long time that I wanted to study a way to make coexist Fremen (Warriors) & Sandworm, just as background Dune storyline.Then, only Troopers (or Warriors) super weapon it wasn't properly convenient like Saboteur or Death Hand.Now we can work to create both DuneX spinoff and the other mod that I have got work in progress... ;) Quote Link to comment Share on other sites More sharing options...
Nyerguds Posted June 4, 2013 Share Posted June 4, 2013 Uhh... small note... is there any guarantee at all that the sandworm will actually spawn on sand? Quote Link to comment Share on other sites More sharing options...
drnovice Posted June 4, 2013 Share Posted June 4, 2013 Just as Fremen Troopers in original game never appear over structures or Scenario offlimits, I think the same is made for Sandworm into an invalid location, simply it doesn't appear.By my tests, never I saw a spawned Sandworm into rock tile. However if you want to see the case of Map_FindLocationTile(4, HOUSE_INVALID) function: case 4: { /* Air */ const MapInfo *mapInfo = &g_mapInfos[g_scenario.mapScale]; ret = Tile_PackXY(mapInfo->minX + Tools_RandomLCG_Range(0, mapInfo->sizeX), mapInfo->minY + Tools_RandomLCG_Range(0, mapInfo->sizeY)); if (houseID == g_playerHouseID && !Map_IsValidPosition(ret)) ret = 0; break;} I think here it checks the valid position for every unit. 1 Quote Link to comment Share on other sites More sharing options...
dynasty Posted June 4, 2013 Share Posted June 4, 2013 If I understand correctly, you're spawning Fremen warriors and sandworms from the Atreides/Fremen palace weapon, yes? Map_FindLocationTile is for picking where to deliver reinforcements. You should be looking at Structure_ActivateSpecial (or Unit_Create). It's as you say, just as units won't be spawned on a structure, sandworms will only be spawned on sand (more accurately, terrain where they have non-zero movementSpeed). BTW, sandworms spawned from palaces only eat one unit before disappearing. If you want to change that, it is the unit's "amount" variable. 1 Quote Link to comment Share on other sites More sharing options...
drnovice Posted June 5, 2013 Share Posted June 5, 2013 Yes but it needs adding bytes on opcode to set "amount" units variable (HarvesterSpiceCapacity into segra's IDA db) for spawned Sandworms, because it isn't there into code. Or simply you can set "amount" to 0 (zero) for pre-placed Sandworms and change the check to disappear: http://forum.dune2k.com/topic/18875-dune-2-exe-editing-programming-issues/page-20#entry375176 I tested with "amount" reaching 6, and it's more interesting.. ;) You can find this change on Hex Editing Collection.Soon new updates! Quote Link to comment Share on other sites More sharing options...
drnovice Posted June 5, 2013 Share Posted June 5, 2013 If I understand correctly, you're spawning Fremen warriors and sandworms from the Atreides/Fremen palace weapon, yes? Map_FindLocationTile is for picking where to deliver reinforcements.You should be looking at Structure_ActivateSpecial (or Unit_Create).It's as you say, just as units won't be spawned on a structure,sandworms will only be spawned on sand (more accurately,terrain where they have non-zero movementSpeed). [...]Yes, the sequence should be...within Structure_ActivateSpecial() function, it reachs case HOUSE_WEAPON_FREMEN (2 value): case HOUSE_WEAPON_FREMEN: { uint16 location; uint16 i; /* Find a random location to appear */ location = Map_FindLocationTile(4, HOUSE_INVALID); for (i = 0; i < 5; i++) { Unit *u; tile32 position; uint16 orientation; uint16 unitType; Tools_Random_256(); position = Tile_UnpackTile(location); position = Tile_MoveByRandom(position, 32, true); orientation = Tools_RandomLCG_Range(0, 3); unitType = (orientation == 1) ? UNIT_TROOPER : UNIT_TROOPERS; g_validateStrictIfZero++; u = Unit_Create(UNIT_INDEX_INVALID, (uint8)unitType, HOUSE_FREMEN, position, (int8)orientation); g_validateStrictIfZero--; if (u == NULL) continue; Unit_SetAction(u, ACTION_HUNT); } s->countDown = g_table_houseInfo[s->o.houseID].specialCountDown; } break; and it's called Map_FindLocationTile() function with 4 locationID parameter ("Fly") to set the position where Fremen appear.Then for 5 times (i=0 -> i=4) it's valued position variable by location found, and it's created unit by Unit_Create() funtion with inside Unit_Allocate() function, but I didn't find where are the checks about correct tile positioning...however the important thing is that it works. :) EDITED: Maybe the checks are here (this function is within Unit_Create() function): bool Unit_IsTileOccupied(Unit *unit){ const UnitInfo *ui; uint16 packed; Unit *unit2; uint16 speed; if (unit == NULL) return true; ui = &g_table_unitInfo[unit->o.type]; packed = Tile_PackTile(unit->o.position); speed = g_table_landscapeInfo[Map_GetLandscapeType(packed)].movementSpeed[ui->movementType]; if (speed == 0) return true; if (unit->o.type == UNIT_SANDWORM || ui->movementType == MOVEMENT_WINGER) return false; unit2 = Unit_Get_ByPackedTile(packed); if (unit2 != NULL && unit2 != unit) { if (House_AreAllied(Unit_GetHouseID(unit2), Unit_GetHouseID(unit))) return true; if (ui->movementType != MOVEMENT_TRACKED) return true; if (g_table_unitInfo[unit2->o.type].movementType != MOVEMENT_FOOT) return true; } return (Structure_Get_ByPackedTile(packed) != NULL);} In particular if "speed = 0", tile is considered occupied or more precisely the terrain type is impracticable for unit type. Quote Link to comment Share on other sites More sharing options...
drnovice Posted January 3, 2014 Share Posted January 3, 2014 Hey!I set all 6 Heralds at the same time and activated movies even for b-sides factions: 1 of 2: 2 of 2: 3 Quote Link to comment Share on other sites More sharing options...
MrFlibble Posted January 3, 2014 Author Share Posted January 3, 2014 That is certainly very impressive, great job! ^_^ Is it still an edited original EXE, or are you working with OpenDUNE's source already? Quote Link to comment Share on other sites More sharing options...
drnovice Posted January 3, 2014 Share Posted January 3, 2014 No, it's a grab by DosBox, I still edited 16bit EXE. To change by c++ opendune code it's too simple, it isn't challenging like opcodes :PThese changes regard even CPS files, (CHOAM.CPS, FAME.CPS, MAPMACH.CPS) in order to obtain all 6 Heralds, setting the EXE with new coordinates (x & y) to redraw the screens: More problematic was FAME.CPS, because there wasn't enough space to put sixth Herald (Mercenary), so I had to draw this herald in original positions and "tell" to EXE doesn't redraw if HouseID is Mercenary (5). Moreover if HouseID is FFh (at the start of the game is set to 'invalidHouse') Harkonnen&Atreides Heralds are drawn to show the Hall of Fame. 2 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.