Jump to content

Recommended Posts

Posted

Recently I'm working to fix 3 bugs:

OpenDune team have shown how fixed them:

https://github.com/OpenDUNE/OpenDUNE/pull/193

https://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.

 

  • Upvote 1
Posted

To fix: capturing structures with deviated units did not unlock tech.
 
seg031:2E88                   loc_2B1E8:                                                  ; CODE XREF: sub_2AFFC+1E7 j
seg031:2E88 C4 5E 0A                          les     bx, [bp+buildingGamePtr]            ; Load Full Pointer to ES:xx
seg031: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, ax
seg031:2E92
seg031:2E92                   loc_2B1F2:
seg031:2E92 FF 76 08                          push    word ptr [bp+unitGamePtr+2]
seg031:2E95 FF 76 06                          push    word ptr [bp+unitGamePtr]           ; unitGamePtr
seg031:2E98 90                                nop                                         ; No Operation
seg031:2E99 0E                                push    cs
seg031:2E9A E8 8D 07                          call    near ptr unitGameHouseIDGet         ; Call Procedure
seg031:2E9D 59                                pop     cx
seg031:2E9E 59                                pop     cx
seg031:2E9F C4 5E 0A                          les     bx, [bp+buildingGamePtr]            ; Load Full Pointer to ES:xx
seg031:2EA2 26 88 47 08                       mov     es:[bx+_buildingGame.houseID], al
seg031:2EA6 56                                push    si                                  ; houseID
seg031:2EA7 9A BD 13 43 0A                    call    buildingPrereqSetup                 ; Call Procedure
seg031:2EAC 59                                pop     cx
seg031:2EAD 50                                push    ax
seg031:2EAE 52                                push    dx
seg031:2EAF 56                                push    si                                  ; houseIndex
seg031:2EB0 9A AB 01 C7 0E                    call    houseGamePtrGet                     ; Call Procedure
seg031:2EB5 59                                pop     cx
seg031:2EB6 8B D8                             mov     bx, ax
seg031:2EB8 8E C2                             mov     es, dx
seg031:2EBA 58                                pop     ax
seg031:2EBB
seg031:2EBB                   loc_2B21B:
seg031:2EBB 26 89 47 10                       mov     es:[bx+_houseGame.preReqs2], ax
seg031:2EBF 58                                pop     ax
seg031:2EC0
seg031:2EC0                   loc_2B220:
seg031:2EC0 26 89 47 0E                       mov     es:[bx+_houseGame.preReqs1], ax
seg031:2EC4
seg031:2EC4                   loc_2B224:                                                  ; Load Full Pointer to ES:xx
seg031:2EC4 C4 5E 06                          les     bx, [bp+unitGamePtr]

seg031:2EC4 C4 5E 0A                          les     bx, [bp+buildingGamePtr]
seg031:2EC7
seg031: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                                  ; houseID
seg031:2ECD 9A BD 13 43 0A                    call    buildingPrereqSetup                 ; Call Procedure
seg031:2ED2 59                                pop     cx
seg031:2ED3 50                                push    ax
seg031:2ED4 52                                push    dx
seg031:2ED5 C4 5E 06                          les     bx, [bp+unitGamePtr]                ; Load Full Pointer to ES:xx

seg031:2EC4 C4 5E 0A                          les     bx, [bp+buildingGamePtr]            ; Load Full Pointer to ES:xx
seg031: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                                  ; houseIndex
seg031:2EDE
seg031:2EDE                   loc_2B23E:                                                  ; Call Procedure
seg031:2EDE 9A AB 01 C7 0E                    call    houseGamePtrGet
seg031:2EE3 59                                pop     cx
seg031:2EE4 8B D8                             mov     bx, ax
seg031:2EE6 8E C2                             mov     es, dx
seg031:2EE8 58                                pop     ax
seg031:2EE9 26 89 47 10                       mov     es:[bx+_houseGame.preReqs2], ax
seg031:2EED 58                                pop     ax
seg031: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.

Posted

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 OR
seg010:1F8D 75 03                             jnz     short loc_1C3C2                     ; Jump if Not Zero (ZF=0)
seg010:1F8F E9 43 01                          jmp     loc_1C505                           ; Jump
seg010:1F92                   ; ---------------------------------------------------------------------------
seg010:1F92
seg010:1F92                   loc_1C3C2:                                                  ; CODE XREF: houseTotalSpicePower+1D j
seg010:1F92 33 FF                             xor     di, di                              ; Logical Exclusive OR
seg010:1F94
seg010:1F94                   loc_1C3C4:
seg010:1F94 C7 46 FE 00 00                    mov     [bp+var_2], 0
seg010:1F99 C4 5E F2                          les     bx, [bp+houseGamePtr]               ; Load Full Pointer
to ES:xx

seg010:1F87                   loc_1C3B7:
seg010:1F87 33 FF                             xor     di, di                              ; Logical Exclusive OR
seg010:1F89 C7 46 FE 00 00                    mov     [bp+var_2], 0
seg010:1F8E C4 5E F2                          les     bx, [bp+houseGamePtr]               ; Load Full Pointer to ES:xx
seg010:1F91 26 C7 47 1A 00 00                 mov     es:[bx+_houseGame.windtrapCount], 0
seg010:1F97
seg010:1F97                   loc_1C3C4:
seg010:1F97 90 90 90 90 90                    nop                                         ; No Operations

seg010:1F9C
seg010:1F9C                   loc_1C3CC:
seg010:1F9C 26 C7 47 14 00 00                 mov     es:[bx+_houseGame.creditsSiloMax], 0
seg010:1FA2 B8 FF FF                          mov     ax, 0FFFFh
seg010:1FA5
seg010:1FA5                   loc_1C3D5:                                                  ; typeIndexFind
seg010:1FA5 50                                push    ax
seg010:1FA6
seg010:1FA6                   loc_1C3D6:                                                  ; houseID
seg010:1FA6 FF 76 06                          push    [bp+houseID]
seg010:1FA9 33 C0                             xor     ax, ax                              ; Logical Exclusive OR
seg010:1FAB 33 D2                             xor     dx, dx                              ; Logical Exclusive OR
seg010:1FAD
seg010:1FAD                   loc_1C3DD:
seg010:1FAD 50                                push    ax
seg010:1FAE 52                                push    dx                                  ; houseGamePtr
seg010:1FAF
seg010:1FAF                   loc_1C3DF:                                                  ; Call Procedure
seg010:1FAF 9A FD 00 8B 0E                    call    buildingGameFind
seg010:1FB4 83 C4 08                          add     sp, 8                               ; Add
seg010:1FB7 E9 AD 00                          jmp     loc_1C497                           ; Jump
seg010:1FBA                   ; ---------------------------------------------------------------------------
seg010:1FBA
seg010:1FBA                   loc_1C3EA:                                                  ; CODE XREF: houseTotalSpicePower:loc_1C4A5 j
seg010:1FBA C4 5E FA                          les     bx, [bp+buildingGamePtr]            ; Load Full Pointer to ES:xx
seg010:1FBD 26 8A 47 02                       mov     al, es:[bx+2]
seg010:1FC1
seg010:1FC1                   loc_1C3F1:                                                  ; AL -> AX (with sign)
seg010:1FC1 98                                cbw
seg010:1FC2
seg010:1FC2                   loc_1C3F2:
seg010:1FC2 BA 60 00                          mov     dx, 60h ; '`'
seg010:1FC5 F7 EA                             imul    dx                                  ; Signed Multiply
seg010:1FC7 05 0A 00                          add     ax, 0Ah                             ; Add
seg010:1FCA C7 46 F8 9D 2A                    mov     word ptr [bp+buildingDataPtr+2], seg seg129
seg010:1FCF
seg010:1FCF                   loc_1C3FF:
seg010:1FCF 89 46 F6                          mov     word ptr [bp+buildingDataPtr], ax
seg010:1FD2 C4 5E F6                          les     bx, [bp+buildingDataPtr]            ; Load Full Pointer to ES:xx
seg010: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:xx
seg010:1FDC 26 01 47 14                       add     es:[bx+_houseGame.creditsSiloMax], ax ; Add
seg010:1FE0 C4 5E F6                          les     bx, [bp+buildingDataPtr]            ; Load Full Pointer to ES:xx
seg010:1FE3 26 83 7F 38 00                    cmp     es:[bx+_buildingData.PowerUsage], 0 ; Compare Two Operands
seg010: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:xx
seg010: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:xx
seg010:1FF4 26 3B 47 10                       cmp     ax, es:[bx+_buildingData.HitPoints] ; Compare Two Operands
seg010:1FF8
seg010:1FF8                   loc_1C428:                                                  ; Jump if Greater or Equal (SF=OF)
seg010:1FF8 7D 49                             jge     short loc_1C473

seg010:1FF1 90 90 90                          nop                                         ; No Operations
seg010:1FF4 90 90 90 90                       nop                                         ; No Operations
seg010:1FF8
seg010:1FF8                   loc_1C428
seg010:1FF8 90 90                             nop                                         ; No Operations

seg010:1FFA
seg010:1FFA                   loc_1C42A:                                                  ; Load Full Pointer to ES:xx
seg010:1FFA C4 5E FA                          les     bx, [bp+buildingGamePtr]
seg010:1FFD
seg010:1FFD                   loc_1C42D:
seg010:1FFD 26 FF 77 0E                       push    es:[bx+_buildingGame.HitPoints]
seg010:2001
seg010:2001                   loc_1C431:                                                  ; Load Full Pointer to ES:xx
seg010:2001 C4 5E F6                          les     bx, [bp+buildingDataPtr]
seg010:2004
seg010: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 Procedure
seg010:200D 59                                pop     cx
seg010:200E 59                                pop     cx
seg010:200F 8B F0                             mov     si, ax

seg010:2011
seg010:2011                   loc_1C441:                                                  ; Compare Two Operands
seg010: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:2017
seg010:2017                   loc_1C447:
seg010:2017 8B C6                             mov     ax, si
seg010:2019
seg010:2019                   loc_1C449:                                                  ; Jump
seg010:2019 EB 03                             jmp     short loc_1C44E
seg010:201B                   ; ---------------------------------------------------------------------------
seg010:201B
seg010:201B                   loc_1C44B:                                                  ; CODE XREF: houseTotalSpicePower+A5 j
seg010:201B B8 80 00                          mov     ax, 80h ; 'Ç'
seg010:201E
seg010:201E                   loc_1C44E:                                                  ; CODE XREF: houseTotalSpicePower:loc_1C449 j
seg010:201E 8B F0                             mov     si, ax
seg010:2020
seg010:2020                   loc_1C450:                                                  ; Compare Two Operands
seg010:2020 81 FE FF 00                       cmp     si, 0FFh
seg010:2024 73 04                             jnb     short loc_1C45A                     ; Jump if Not Below (CF=0)
seg010:2026 8B C6                             mov     ax, si
seg010:2028
seg010:2028                   loc_1C458:                                                  ; Jump
seg010:2028 EB 03                             jmp     short loc_1C45D
seg010:202A                   ; ---------------------------------------------------------------------------
seg010:202A
seg010:202A                   loc_1C45A:                                                  ; CODE XREF: houseTotalSpicePower+B4 j
seg010:202A B8 FF 00                          mov     ax, 0FFh
seg010:202D
seg010:202D                   loc_1C45D:                                                  ; CODE XREF: houseTotalSpicePower:loc_1C458 j
seg010:202D 8B F0                             mov     si, ax

seg010:2011                   loc_1C441:
seg010:2011 90                                nop                                         ; No Operation
seg010:2012 C4 5E F2                          les     bx, [bp+houseGamePtr]               ; Load Full Pointer to ES:xx
seg010:2015 26 FF 47 1A                       inc     es:[bx+_houseGame.windtrapCount]
seg010:2019
seg010:2019                   loc_1C449:
seg010:2019 90 90                             nop                                         ; No Operations
seg010:201B                   ; ---------------------------------------------------------------------------
seg010:201B
seg010:201B                   loc_1C44B:
seg010:201B 90 90 90                          nop                                         ; No Operations
seg010:201E
seg010:201E                   loc_1C44E:
seg010:201E 90 90                             nop                                         ; No Operations
seg010:2020
seg010:2020                   loc_1C450:
seg010:2020 90 90 90 90                       nop                                         ; No Operations
seg010:2024 90 90                             nop                                         ; No Operations
seg010:2026 90 90                             nop                                         ; No Operations
seg010:2028
seg010:2028                   loc_1C458
seg010:2028 90 90                             nop                                         ; No Operations
seg010:202A                   ; ---------------------------------------------------------------------------
seg010:202A
seg010:202A                   loc_1C45A
seg010:202A 90 90 90                          nop                                         ; No Operations
seg010:202D
seg010:202D                   loc_1C45D:
seg010:202D 90 90                             nop                                         ; No Operations

seg010:202F 56                                push    si
seg010:2030
seg010:2030                   loc_1C460:                                                  ; Load Full Pointer to ES:xx
seg010: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 Negation
seg010:2039 50                                push    ax
seg010:203A
seg010:203A                   loc_1C46A:                                                  ; Call Procedure
seg010:203A 9A 20 00 CA 32                    call    j_unknownCalc2
seg010:203F
seg010:203F                   loc_1C46F:
seg010:203F 59                                pop     cx
seg010:2040 59                                pop     cx
seg010:2041 EB 09                             jmp     short loc_1C47C                     ; Jump
seg010:2043                   ; ---------------------------------------------------------------------------
seg010:2043
seg010:2043                   loc_1C473:                                                  ; CODE XREF: houseTotalSpicePower:loc_1C428 j
seg010:2043 C4 5E F6                          les     bx, [bp+buildingDataPtr]            ; Load Full Pointer to ES:xx
seg010:2046 26 8B 47 38                       mov     ax, es:[bx+_buildingData.PowerUsage]
seg010:204A F7 D8                             neg     ax                                  ; Two's Complement Negation
seg010:204C
seg010:204C                   loc_1C47C:                                                  ; CODE XREF: houseTotalSpicePower+D1 j
seg010:204C 03 F8                             add     di, ax                              ; Add
seg010:204E EB 0A                             jmp     short loc_1C48A                     ; Jump
seg010:2050                   ; ---------------------------------------------------------------------------
seg010:2050
seg010:2050                   loc_1C480:                                                  ; CODE XREF: houseTotalSpicePower+78 j
seg010:2050 C4 5E F6                          les     bx, [bp+buildingDataPtr]            ; Load Full Pointer to ES:xx
seg010:2053 26 8B 47 38                       mov     ax, es:[bx+_buildingData.PowerUsage]
seg010:2057 01 46 FE                          add     [bp+var_2], ax                      ; Add
seg010:205A
seg010:205A                   loc_1C48A:                                                  ; CODE XREF: houseTotalSpicePower+DE j
seg010:205A 33 C0                             xor     ax, ax                              ; Logical Exclusive OR
seg010:205C 33 D2                             xor     dx, dx                              ; Logical Exclusive OR
seg010:205E 50                                push    ax
seg010:205F
seg010:205F                   loc_1C48F:                                                  ; houseGamePtr
seg010:205F 52                                push    dx
seg010:2060 9A 3D 01 8B 0E                    call    buildingGameGetNextPtr              ; Call Procedure
seg010:2065 59                                pop     cx
seg010:2066 59                                pop     cx
seg010:2067
seg010:2067                   loc_1C497:                                                  ; CODE XREF: houseTotalSpicePower+47 j
seg010:2067 89 56 FC                          mov     word ptr [bp+buildingGamePtr+2], dx
seg010:206A
seg010:206A                   loc_1C49A:
seg010:206A 89 46 FA                          mov     word ptr [bp+buildingGamePtr], ax
seg010:206D 8B 46 FA                          mov     ax, word ptr [bp+buildingGamePtr]
seg010:2070
seg010:2070                   loc_1C4A0:                                                  ; Logical Inclusive OR
seg010: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:2075
seg010:2075                   loc_1C4A5:                                                  ; Jump
seg010:2075 E9 42 FF                          jmp     loc_1C3EA
seg010:2078                   ; ---------------------------------------------------------------------------
seg010:2078
seg010:2078                   loc_1C4A8:                                                  ; CODE XREF: houseTotalSpicePower+103 j
seg010:2078 C4 5E F2                          les     bx, [bp+houseGamePtr]               ; Load Full Pointer to ES:xx
seg010:207B
seg010: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).

Posted

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... :unsure:

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

Posted

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++;            }        }    }
  • Upvote 1
Posted

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.

Posted

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.

Posted

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... :)

Posted

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?

Posted

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.

  • 3 weeks later...
Posted

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.

  • Upvote 1
Posted

It needs further testing (if someone else can test it would give me more feedback):

 

seg015:000A                   loc_1DEDA:                                                  ; Load Full Pointer to ES:xx
seg015:000A C4 1E 3A 3A                       les     bx, houseHumanGamePtr
seg015:000E
seg015:000E                   loc_1DEDE:
seg015:000E 26 C7 47 0A 00 00                 mov     es:[bx+_houseGame.field_A], 0
seg015:0014
seg015:0014                   loc_1DEE4:                                                  ; Load Full Pointer to ES:xx
seg015:0014 C4 1E 3A 3A                       les     bx, houseHumanGamePtr

seg015:0018
seg015:0018                   loc_1DEE8:
seg015:0018 26 C7 47 0C 00 00                 mov     es:[bx+_houseGame.objectTypeIndex], 0

seg015:001E BF FF FA                          mov     di, FFFAh
seg015:0021 EB 02                             jmp     short loc_1DEEE                     ; Jump
seg015:0023
seg015:0023                   secondInit:
seg015:0023 33 FF                             xor     di, di

seg015:001E
seg015:001E                   loc_1DEEE:                                                  ; Logical Exclusive OR
seg015:001E 33 F6                             xor     si, si
seg015:0020
seg015:0020                   loc_1DEF0:                                                  ; Jump
seg015:0020 E9 0B 01                          jmp     loc_1DFFE

seg015:0023                   ; ---------------------------------------------------------------------------
seg015:0023
seg015:0023                   glb_1DEF3:                                                  ; CODE XREF: unitsSort:loc_1E006 j
seg015:0023                   unitLoop:                                                   ; si = index
seg015:0023 8B DE                             mov     bx, si
seg015:0025
seg015:0025                   loc_1DEF5:
seg015:0025 B1 02                             mov     cl, 2
seg015:0027
seg015:0027                   loc_1DEF7:                                                  ; Shift Logical Left
seg015:0027 D3 E3                             shl     bx, cl
seg015:0029
seg015:0029                   loc_1DEF9:
seg015:0029 8B 87 40 84                       mov     ax, word ptr (unitsGamePtrs+2)[bx]
seg015:002D
seg015:002D                   loc_1DEFD:
seg015:002D 8B 97 3E 84                       mov     dx, word ptr unitsGamePtrs[bx]
seg015:0031
seg015:0031                   loc_1DF01:
seg015:0031 89 46 FE                          mov     word ptr [bp+unitGamePtr+2], ax
seg015:0034
seg015:0034                   loc_1DF04:
seg015:0034 89 56 FC                          mov     word ptr [bp+unitGamePtr], dx
seg015:0037
seg015:0037                   loc_1DF07:
seg015:0037 8B DE                             mov     bx, si
seg015:0039
seg015:0039                   loc_1DF09:
seg015:0039 B1 02                             mov     cl, 2
seg015:003B
seg015:003B                   loc_1DF0B:                                                  ; Shift Logical Left
seg015:003B D3 E3                             shl     bx, cl

seg015:003D
seg015:003D                   loc_1DF0D:
seg015:003D 8B 87 44 84                       mov     ax, word ptr (unitsGamePtrs+6)[bx]
seg015:0041
seg015:0041                   loc_1DF11:
seg015:0041 8B 97 42 84                       mov     dx, word ptr (unitsGamePtrs+4)[bx]
seg015:0045
seg015:0045                   loc_1DF15:
seg015:0045 89 46 FA                          mov     word ptr [bp+unitGamePtr2+2], ax
seg015:0048
seg015:0048                   loc_1DF18:
seg015:0048 89 56 F8                          mov     word ptr [bp+unitGamePtr2], dx
seg015:004B
seg015:004B                  

seg015:0045                   loopCheck1:
seg015:0045 81 FF FF FA                       cmp     di, FFFAh
seg015:0049 75 4B                             jnz     short loc_1DF66                     ; Jump if Not Zero (ZF=0)
seg015:004B
seg015:004B                   loopCheck2:
seg015:004B 3B 36 EC 35                       cmp     si, unitsGameCount
seg015:004F 74 CE                             jz      short secondInit

loc_1DF1B:                                                  ; Load Full Pointer to ES:xx
seg015:004B C4 5E FC                          les     bx, [bp+unitGamePtr]
seg015:004E
seg015:004E                   loc_1DF1E:
seg015:004E 26 8A 47 09                       mov     al, es:[bx+_unitGame.houseRevealed]
seg015:0052
seg015:0052                   loc_1DF22:
seg015:0052 B4 00                             mov     ah, 0
seg015:0054
seg015:0054                   loc_1DF24:
seg015:0054 BA 01 00                          mov     dx, 1
seg015:0057
seg015:0057                   loc_1DF27:
seg015:0057 8A 0E 38 3A                       mov     cl, byte ptr houseHumanID
seg015:005B
seg015:005B                   loc_1DF2B:                                                  ; Shift Logical Left
seg015:005B D3 E2                             shl     dx, cl
seg015:005D
seg015:005D                   loc_1DF2D:                                                  ; Logical Compare
seg015:005D 85 C2                             test    ax, dx
seg015:005F
seg015:005F                   loc_1DF2F:                                                  ; Jump if Zero (ZF=1)
seg015:005F 74
2B                             jz      short loc_1DF66
seg015:0061
seg015:0061                   loc_1DF31:                                                  ; Load Full Pointer to ES:xx
seg015:0061 C4 5E FC                          les     bx, [bp+unitGamePtr]
seg015:0064
seg015:0064                   loc_1DF34:                                                  ; Logical Compare
seg015:0064 26 F7 47 04 04 00                 test    es:[bx+_unitGame.unitState], 4
seg015:006A
seg015:006A                   loc_1DF3A:                                                  ; Jump if Not Zero (ZF=0)
seg015:006A 75
23                             jnz     short loc_1DF66
seg015:006C
seg015:006C                   loc_1DF3C:                                                  ; HumanHouseID
seg015:006C FF 36 38 3A                       push    houseHumanID
seg015:0070
seg015:0070                   loc_1DF40:                                                  ; Load Full Pointer to ES:xx
seg015:0070 C4 5E FC                          les     bx, [bp+unitGamePtr]
seg015:0073
seg015:0073                   loc_1DF43:
seg015:0073 26 8A 47 08                       mov     al, es:[bx+_unitGame.houseID]
seg015:0077 98                                cbw                                         ; AL -> AX (with sign)
seg015:0078
seg015:0078                   loc_1DF48:                                                  ; objectHouseID
seg015:0078 50                                push    ax
seg015:0079
seg015:0079                   loc_1DF49:                                                  ; Call Procedure
seg015:0079 9A 34 0F 2C 12                    call    isFriendly?
seg015:007E
seg015:007E                   loc_1DF4E:
seg015:007E 59                                pop     cx
seg015:007F
seg015:007F                   loc_1DF4F:
seg015:007F 59                                pop     cx

seg015:0080 C4 1E 3A 3A                       les     bx, houseHumanGamePtr

seg015:0080
seg015:0080                   loc_1DF50:                                                  ; Logical Inclusive OR
seg015:0080 0B C0                             or      ax, ax
seg015:0082 74
06                             jz      short loc_1DF5E                     ; Jump if Zero (ZF=1)
seg015:0084
seg015:0084                   loc_1DF54:                                                  ; Load Full Pointer to ES:xx
seg015:0084 C4 1E 3A 3A                       les     bx, houseHumanGamePtr

seg015:0088
seg015:0088                   loc_1DF58:                                                  ; Increment by 1
seg015:0088 26 FF 47 0C                       inc     es:[bx+_houseGame.objectTypeIndex]
seg015:008C EB
04                             jmp     short loc_1DF66                     ; Jump
seg015:008E                   ; ---------------------------------------------------------------------------
seg015:008E
seg015:008E                   loc_1DF5E:                                                  ; CODE XREF: unitsSort+80 j
seg015:008E C4 1E 3A 3A                       les     bx, houseHumanGamePtr               ; Load Full Pointer to ES:xx

seg015:0092
seg015:0092                   loc_1DF62:                                                  ; Increment by 1
seg015:0092 26 FF 47 0A                       inc     es:[bx+_houseGame.field_A]

seg015:0092
seg015:0092 90                                nop                                         ; No Operation
seg015:0193 46                                inc     si                                  ; Increment by 1
seg015:0094 EB 8D                             jmp     unitLoop

seg015:0096
seg015:0096                   loc_1DF66:                                                  ; CODE XREF: unitsSort:loc_1DF2F j
seg015:0096                                                                               ; unitsSort:loc_1DF3A j ...
seg015:0096 C4 5E FC                          les     bx, [bp+unitGamePtr]                ; Load Full Pointer to ES:xx
seg015:0099 26 FF 77 0C                       push    es:[bx+_unitGame.mapTileY]          ; retValue
seg015:009D
seg015:009D                   loc_1DF6D:                                                  ; int
seg015:009D 26 FF 77 0A                       push    es:[bx+_unitGame.mapTileX]
seg015:00A1
seg015:00A1                   loc_1DF71:                                                  ; Call Procedure
seg015:00A1 9A 7E 00 48 0D                    call    returnArg2AsAX
seg015:00A6
seg015:00A6                   loc_1DF76:
seg015:00A6 59                                pop     cx
seg015:00A7 59                                pop     cx
seg015:00A8
seg015:00A8                   loc_1DF78:
seg015:00A8 8B F8                             mov     di, ax
seg015:00AA C4 5E F8                          les     bx, [bp+unitGamePtr2]               ; Load Full Pointer to ES:xx
seg015:00AD 26 FF 77 0C                       push    word ptr es:[bx+0Ch]                ; retValue
seg015:00B1
seg015:00B1                   loc_1DF81:                                                  ; int
seg015:00B1 26 FF 77 0A                       push    word ptr es:[bx+0Ah]
seg015:00B5
seg015:00B5                   loc_1DF85:                                                  ; Call Procedure
seg015:00B5 9A 7E 00 48 0D                    call    returnArg2AsAX
seg015:00BA 59                                pop     cx
seg015:00BB 59                                pop     cx
seg015:00BC
seg015:00BC                   loc_1DF8C:
seg015:00BC 89 46 F6                          mov     [bp+var_A], ax
seg015:00BF
seg015:00BF                   loc_1DF8F:                                                  ; Load Full Pointer to ES:xx
seg015:00BF C4 5E FC                          les     bx, [bp+unitGamePtr]
seg015:00C2
seg015:00C2                   loc_1DF92:
seg015:00C2 26 8A 47 02                       mov     al, es:[bx+2]
seg015:00C6 98                                cbw                                         ; AL -> AX (with sign)
seg015:00C7
seg015:00C7                   loc_1DF97:
seg015:00C7 BA 5A 00                          mov     dx, 5Ah ; 'Z'
seg015:00CA F7 EA                             imul    dx                                  ; Signed Multiply
seg015:00CC BA 10 2B                          mov     dx, seg seg130
seg015:00CF 8B D8                             mov     bx, ax
seg015:00D1
seg015:00D1                   loc_1DFA1:
seg015:00D1 8E C2                             mov     es, dx
seg015:00D3                                   assume es:seg130
seg015:00D3 26 83 BF 3C 00 00                 cmp     es:[bx+_unitData.MovementType], 0   ; Compare Two Operands
seg015:00D9 75 04                             jnz     short loc_1DFAF                     ; Jump if Not Zero (ZF=0)
seg015:00DB 81 EF 00 01                       sub     di, 100h                            ; Integer Subtraction
seg015:00DF
seg015:00DF                   loc_1DFAF:                                                  ; CODE XREF: unitsSort+D7 j
seg015:00DF C4 5E F8                          les     bx, [bp+unitGamePtr2]               ; Load Full Pointer to ES:xx
seg015:00E2                                   assume es:nothing
seg015:00E2 26 8A 47 02                       mov     al, es:[bx+_unitGame.typeIndex]
seg015:00E6
seg015:00E6                   loc_1DFB6:                                                  ; AL -> AX (with sign)
seg015:00E6 98                                cbw
seg015:00E7 BA 5A 00                          mov     dx, 5Ah ; 'Z'
seg015:00EA F7 EA                             imul    dx                                  ; Signed Multiply
seg015:00EC BA 10 2B                          mov     dx, seg seg130
seg015:00EF
seg015:00EF                   loc_1DFBF:
seg015:00EF 8B D8                             mov     bx, ax
seg015:00F1 8E C2                             mov     es, dx
seg015:00F3                                   assume es:seg130
seg015:00F3
seg015:00F3                   loc_1DFC3:                                                  ; Compare Two Operands
seg015:00F3 26 83 BF 3C 00 00                 cmp     es:[bx+_unitData.MovementType], 0
seg015:00F9 75 05                             jnz     short loc_1DFD0                     ; Jump if Not Zero (ZF=0)
seg015:00FB
seg015:00FB                   loc_1DFCB:                                                  ; Integer Subtraction
seg015:00FB 81 6E F6 00 01                    sub     [bp+var_A], 100h
seg015:0100
seg015:0100                   loc_1DFD0:                                                  ; CODE XREF: unitsSort+F7 j
seg015:0100 3B 7E F6                          cmp     di, [bp+var_A]                      ; Compare Two Operands
seg015:0103
seg015:0103                   loc_1DFD3:                                                  ; Jump if Less or Equal (ZF=1 | SF!=OF)
seg015:0103 7E
24                             jle     short loc_1DFFD
seg015:0105 8B DE                             mov     bx, si
seg015:0107
seg015:0107                   loc_1DFD7:
seg015:0107 B1 02                             mov     cl, 2
seg015:0109
seg015:0109                   loc_1DFD9:                                                  ; Shift Logical Left
seg015:0109 D3 E3                             shl     bx, cl
seg015:010B 8B 46 FA                          mov     ax, word ptr [bp+unitGamePtr2+2]
seg015:010E
seg015:010E                   loc_1DFDE:
seg015:010E 8B 56 F8                          mov     dx, word ptr [bp+unitGamePtr2]
seg015:0111
seg015:0111                   loc_1DFE1:
seg015:0111 89 87 40 84                       mov     word ptr (unitsGamePtrs+2)[bx], ax
seg015:0115 89 97 3E 84                       mov     word ptr unitsGamePtrs[bx], dx
seg015:0119 8B DE                             mov     bx, si
seg015:011B B1 02                             mov     cl, 2
seg015:011D D3 E3                             shl     bx, cl                              ; Shift Logical Left

seg015:0119 90 90                             nop                                         ; No Operations

seg015: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], ax
seg015:0129
seg015:0129                   loc_1DFF9:
seg015:0129 89 97 42 84                       mov     word ptr (unitsGamePtrs+4)[bx], dx
seg015:012D
seg015:012D                   loc_1DFFD:                                                  ; CODE XREF: unitsSort:loc_1DFD3 j
seg015:012D 46                                inc     si                                  ; Increment by 1
seg015:012E
seg015:012E                   loc_1DFFE:                                                  ; CODE XREF: unitsSort:loc_1DEF0 j
seg015:012E A1 EC 35                          mov     ax, unitsGameCount

seg015:012D 90 90 90 90                       nop                                         ; No Operations

seg015:0131 48                                dec     ax                                  ; Decrement by 1
seg015:0132 3B C6                             cmp     ax, si                              ; Compare Two Operands
seg015:0134 7E 03                             jle     short loc_1E009                     ; Jump if Less or Equal (ZF=1 | SF!=OF)
seg015:0136
seg015:0136                   loc_1E006:                                                  ; Jump
seg015: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 f6
e9 0b 01 8b de b1 02 d3 e3 8b 87 40 84 8b 97 3e
84 89 46 fe 89 56 fc 8b de b1 02 d3 e3 8b 87 44
84 8b 97 42 84 89 46 fa 89 56 f8 c4 5e fc 26 8a
47 09 b4 00 ba 01 00 8a 0e 38 3a d3 e2 85 c2 74
35 c4 5e fc 26 f7 47 04 04 00 75 2a ff 36 38 3a
c4 5e fc 26 8a 47 08 98 50 9a 34 0f 2c 12 59 59
0b c0 74 0a c4 1e 3a 3a 26 ff 47 0c eb 08 c4 1e
3a 3a 26 ff 47 0a c4 5e fc 26 ff 77 0c 26 ff 77
0a 9a 7e 00 48 0d 59 59 8b f8 c4 5e f8 26 ff 77
0c 26 ff 77 0a 9a 7e 00 48 0d 59 59 89 46 f6 c4
5e fc 26 8a 47 02 98 ba 5a 00 f7 ea ba 10 2b 8b
d8 8e c2 26 83 bf 3c 00 00 75 04 81 ef 00 01 c4
5e f8 26 8a 47 02 98 ba 5a 00 f7 ea ba 10 2b 8b
d8 8e c2 26 83 bf 3c 00 00 75 05 81 6e f6 00 01
3b 7e f6 7e 28 8b de b1 02 d3 e3 8b 46 fa 8b 56
f8 89 87 40 84 89 97 3e 84 8b de b1 02 d3 e3 8b
46 fe 8b 56 fc 89 87 44 84 89 97 42 84 46 a1 ec
35 48 3b c6 7e 03 e9 ea fe

 

Replace with:

            26 c7 47 0c 00 00 bf ff fa eb 02 33
ff 33 f6 8b de b1 02 d3 e3 8b 87 40 84 8b 97 3e
84 89 46 fe 89 56 fc 8b 87 44 84 8b 97 42 84 89
46 fa 89 56 f8 81 ff ff fa 75 4b 3b 36 ec 35 74
ce c4 5e fc 26 8a 47 09 b4 00 ba 01 00 8a 0e 38
3a d3 e2 85 c2 74 2b 26 f7 47 04 04 00 75 23 ff
36 38 3a 26 8a 47 08 98 50 9a 34 0f 2c 12 59 59
c4 1e 3a 3a 0b c0 74 06 26 ff 47 0c eb 04 26 ff
47 0a 90 46 eb 8d c4 5e fc 26 ff 77 0c 26 ff 77
0a 9a 7e 00 48 0d 59 59 8b f8 c4 5e f8 26 ff 77
0c 26 ff 77 0a 9a 7e 00 48 0d 59 59 89 46 f6 c4
5e fc 26 8a 47 02 98 ba 5a 00 f7 ea ba 10 2b 8b
d8 8e c2 26 83 bf 3c 00 00 75 04 81 ef 00 01 c4
5e f8 26 8a 47 02 98 ba 5a 00 f7 ea ba 10 2b 8b
d8 8e c2 26 83 bf 3c 00 00 75 05 81 6e f6 00 01
3b 7e f6 7e 24 8b de b1 02 d3 e3 8b 46 fa 8b 56
f8 89 87 40 84 89 97 3e 84 90 90 8b 46 fe 8b 56
fc 89 87 44 84 89 97 42 84 46 a1 ec 35 90 90 90
90 48 3b c6 7e 03 e9 ea fe

Posted

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 Subtraction
seg031:14F0 83 EC 04                          sub     sp, 4
seg031:14F3 56                                push    si
seg031:14F4 57                                push    di
seg031:14F5 33 F6                             xor     si, si                              ; Logical Exclusive OR
seg031:14F7 8B 46 06                          mov     ax, word ptr [bp+pUnitGamePtr]
seg031:14FA 0B 46 08                          or      ax, word ptr [bp+pUnitGamePtr+2]    ; Logical Inclusive OR
seg031: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 OR
seg031:1505 75 05                             jnz     short unitCheck                     ; Jump if Not Zero (ZF=0)
seg031:1507
seg031:1507                   ret0:                                                       ; CODE XREF: calcTime?Distance?+10 j
seg031:1507 33 C0                             xor     ax, ax                              ; Logical Exclusive OR
seg031:1509
seg031:1509                   loc_29869:                                                  ; CODE XREF: calcTime?Distance?+FD j
seg031:1509 E9 E1 00                          jmp     Done                                ; Jump
seg031:150C                   ; ---------------------------------------------------------------------------
seg031:150C
seg031:150C                   unitCheck:                                                  ; CODE XREF: calcTime?Distance?+18 j
seg031:150C C4 5E 0A                          les     bx, [bp+unitGamePtr]                ; Load Full Pointer to ES:xx
seg031:150F 26 FF 77 0C                       push    es:[bx+_unitGame.mapTileY]          ; posY
seg031:1513 26 FF 77 0A                       push    es:[bx+_unitGame.mapTileX]          ; posX
seg031:1517
seg031:1517                   loc_29877:                                                  ; Call Procedure
seg031:1517 9A 86 00 48 0D                    call    mapIndexFromMapTileXY
seg031:151C 59                                pop     cx
seg031:151D 59                                pop     cx
seg031:151E 50                                push    ax                                  ; mapPos
seg031:151F 9A 4D 00 D0 42                    call    j_mapTileCheckIfFogWar              ; Call Procedure
seg031:1524 59                                pop     cx
seg031:1525 0B C0                             or      ax, ax                              ; Logical Inclusive OR
seg031:1527 75 03                             jnz     short loc_2988C                     ; Jump if Not Zero (ZF=0)
seg031:1529 E9 BC 00                          jmp     retSI                               ; Jump
seg031:152C                   ; ---------------------------------------------------------------------------
seg031:152C
seg031:152C                   loc_2988C:                                                  ; CODE XREF: calcTime?Distance?+3A j
seg031:152C C4 5E 0A                          les     bx, [bp+unitGamePtr]                ; Load Full Pointer to ES:xx
seg031: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, ax
seg031:1537 90                                nop                                         ; No Operation

seg031:1534 BA 5A 00                          mov     dx, size _unitData
seg031:1537 F7 EA                             imul    dx                                  ; Signed Multiply
seg031:1539 05 00 00                          add     ax, 0                               ; Add
seg031:153C C7 46 FE 10 2B                    mov     word ptr [bp+unitDataPtr+2], seg seg130
seg031:1541 89 46 FC                          mov     word ptr [bp+unitDataPtr], ax
seg031:1544 33 F6                             xor     si, si                              ; Logical Exclusive OR
seg031:1546 C4 5E 0A                          les     bx, [bp+unitGamePtr]                ; Load Full Pointer to ES:xx
seg031:1549 26 FF 77 0C                       push    es:[bx+_unitGame.mapTileY]          ; posY
seg031:154D 26 FF 77 0A                       push    es:[bx+_unitGame.mapTileX]          ; posX
seg031:1551 9A 86 00 48 1D                    call    mapIndexFromMapTileXY               ; Call Procedure
seg031:1556 59                                pop     cx
seg031:1557 59                                pop     cx
seg031:1558 50                                push    ax                                  ; mapPosition
seg031:1559 9A 61 00 D0 42                    call    j_mapTileTypeGet                    ; Call Procedure
seg031:155E 59                                pop     cx
seg031:155F
seg031:155F                   loc_298BF:
seg031:155F BA 1C 00                          mov     dx, 1Ch
seg031:1562
seg031:1562                   loc_298C2:                                                  ; Signed Multiply
seg031:1562 F7 EA                             imul    dx
seg031:1564 8B D8                             mov     bx, ax
seg031:1566 83 BF 40 3A 00                    cmp     word_46E60[bx], 0                   ; Compare Two Operands
seg031: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:xx
seg031:1570
seg031: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 cases
seg031:1577 77
14                             ja      short loc_298EF                     ; default
seg031:1579 D1 E3                             shl     bx, 1                               ; Shift Logical Left
seg031:157B
seg031:157B                   loc_298DB:                                                  ; switch jump
seg031:157B 2E FF A7 F3 15                    jmp     cs:off_29953[bx]
seg031:1580
seg031:1580                   Tracked:                                                    ; DATA XREF: seg031:off_29953 o
seg031:1580 BE E8 03                          mov     si, 3E8h                            ; case 0x1
seg031:1583 EB
08                             jmp     short loc_298EF                     ; Jump
seg031:1585                   ; ---------------------------------------------------------------------------
seg031:1585
seg031:1585                   Foot:                                                       ; CODE XREF: calcTime?Distance?:loc_298DB j
seg031:1585                                                                               ; DATA XREF: seg031:off_29953 o
seg031:1585 BE 64 00                          mov     si, 64h ; 'd'                       ; case 0x0
seg031:1588 EB
03                             jmp     short loc_298EF                     ; Jump
seg031:158A                   ; ---------------------------------------------------------------------------
seg031:158A
seg031:158A                   Wheeled:                                                    ; CODE XREF: calcTime?Distance?:loc_298DB j
seg031:158A                                                                               ; DATA XREF: seg031:off_29953 o
seg031:158A BE 88 13                          mov     si, 1388h                           ; case 0x3
seg031:158D EB 04                             jmp     short loc_298F3                     ; Jump
seg031:158F                   ; ---------------------------------------------------------------------------
seg031:158F
seg031:158F                   loc_298EF:                                                  ; CODE XREF: calcTime?Distance?+8A j

seg031:1593 83 FF 02                          cmp     di, 2                               ; Compare Two Operands
seg031:156B 74 05                             jz      short caseFremen                    ; Jump if Zero (ZF=1)
seg031:1593 83 FF 04                          cmp     di, 4                               ; Compare Two Operands
seg031:156B 75 02                             jnz     short loc_298F3                     ; Jump if Not Zero (ZF=0)
seg031:1593                   caseFremen:

seg031:158F 33 F6                             xor     si, si                              ; default
seg031:1591 EB 00                             jmp     short $+2                           ; Jump
seg031:1593
seg031:1593                   loc_298F3:                                                  ; CODE XREF: calcTime?Distance?+96 j
seg031:1593                                                                               ; calcTime?Distance?+9B j ...
seg031:1593 C4 5E 0A                          les     bx, [bp+unitGamePtr]                ; Load Full Pointer to ES:xx
seg031:1596 26 80 7F 6A 00                    cmp     es:[bx+_unitGame.speed3], 0         ; Compare Two Operands
seg031: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:xx
seg031:15A0 26 80 7F 51 00                    cmp     es:[bx+_unitGame.weaponCooldownTimer], 0 ; Compare Two Operands
seg031:15A5 74 04                             jz      short loc_2990B                     ; Jump if Zero (ZF=1)
seg031:15A7
seg031:15A7                   loc_29907:                                                  ; CODE XREF: calcTime?Distance?+AE j
seg031:15A7 B1 02                             mov     cl, 2
seg031:15A9 D3 E6                             shl     si, cl                              ; Shift Logical Left
seg031:15AB
seg031:15AB                   loc_2990B:                                                  ; CODE XREF: calcTime?Distance?+B8 j
seg031:15AB C4 5E 0A                          les     bx, [bp+unitGamePtr]                ; Load Full Pointer to ES:xx
seg031:15AE
seg031:15AE                   loc_2990E:                                                  ; buildingPosY
seg031:15AE 26 FF 77 0C                       push    es:[bx+_unitGame.mapTileY]
seg031:15B2
seg031:15B2                   loc_29912:                                                  ; buildingPosX
seg031:15B2 26 FF 77 0A                       push    es:[bx+_unitGame.mapTileX]
seg031:15B6 C4 5E 06                          les     bx, [bp+pUnitGamePtr]               ; Load Full Pointer to ES:xx
seg031:15B9 26 FF 77 0C                       push    es:[bx+_unitGame.mapTileY]          ; unitPosY
seg031:15BD
seg031:15BD                   loc_2991D:                                                  ; unitPosX
seg031:15BD 26 FF 77 0A                       push    es:[bx+_unitGame.mapTileX]
seg031:15C1
seg031:15C1                   loc_29921:                                                  ; Call Procedure
seg031:15C1 9A 04 01 48 1D                    call    getDistance?
seg031:15C6 83 C4 08                          add     sp, 8                               ; Add
seg031:15C9 8B F8                             mov     di, ax
seg031:15CB 0B FF                             or      di, di                              ; Logical Inclusive OR
seg031:15CD 74 0B                             jz      short loc_2993A                     ; Jump if Zero (ZF=1)
seg031:15CF 0B F6                             or      si, si                              ; Logical Inclusive OR
seg031:15D1
seg031:15D1                   loc_29931:                                                  ; Jump if Zero (ZF=1)
seg031:15D1 74 07                             jz      short loc_2993A
seg031:15D3 8B C6                             mov     ax, si
seg031:15D5 99                                cwd                                         ; AX -> DX:AX (with sign)
seg031:15D6
seg031:15D6                   loc_29936:                                                  ; Signed Divide
seg031:15D6 F7 FF                             idiv    di
seg031:15D8 8B F0                             mov     si, ax
seg031:15DA
seg031:15DA                   loc_2993A:                                                  ; CODE XREF: calcTime?Distance?+E0 j
seg031:15DA                                                                               ; calcTime?Distance?:loc_29931 j
seg031:15DA 83 FF 02                          cmp     di, 2                               ; Compare Two Operands
seg031:15DD 7D 09                             jge     short retSI                         ; Jump if Greater or Equal (SF=OF)
seg031:15DF BA 02 00                          mov     dx, 2
seg031:15E2 8B C6                             mov     ax, si
seg031:15E4 F7 EA                             imul    dx                                  ; Signed Multiply
seg031:15E6 8B F0                             mov     si, ax
seg031:15E8
seg031:15E8                   retSI:                                                      ; CODE XREF: calcTime?Distance?+3C j
seg031:15E8                                                                               ; calcTime?Distance?+7E j ...
seg031:15E8 8B C6                             mov     ax, si
seg031:15EA E9 1C FF                          jmp     loc_29869                           ; Jump

 

Only for expert players! ;)

  • Like 1
Posted

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 ^_^

Posted

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... ;)

 

Posted

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.

  • Upvote 1
Posted

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.

  • Upvote 1
Posted

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!

Posted

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.

  • 6 months later...
Posted

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 :P

These 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:

post-2188-0-75290200-1388771516_thumb.pn post-2188-0-74963600-1388771583_thumb.pn

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.

post-2188-0-49978000-1388771557_thumb.pn

  • Upvote 2

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...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.