Jump to content

EXE editing & programming issues


MrFlibble

Recommended Posts

Here's the code that makes the Mercenaries (player 5) use BENE.PAL for the Mentat screen instead of IBM.PAL:


ovr195:0078 loc_582F8: ; Compare Two Operands
ovr195:0078 83 FF 05 cmp di, 5
ovr195:007B 75 1C jnz short loc_58319 ; Jump if Not Zero (ZF=0)
ovr195:007D
ovr195:007D loc_582FD: ; Logical Exclusive OR
ovr195:007D 33 C0 xor ax, ax
ovr195:007F
ovr195:007F loc_582FF:
ovr195:007F BA 00 03 mov dx, 300h
ovr195:0082
ovr195:0082 loc_58302: ; int
ovr195:0082 50 push ax
ovr195:0083 52 push dx ; fileSize
ovr195:0084
ovr195:0084 loc_58304: ; int
ovr195:0084 FF 36 28 3C push word ptr src+2
ovr195:0088 FF 36 26 3C push word ptr src ; int
ovr195:008C 1E push ds
ovr195:008D
ovr195:008D loc_5830D: ; "BENE.PAL"
ovr195:008D B8 87 25 mov ax, offset aBene_pal_0
ovr195:0090
ovr195:0090 loc_58310: ; fileName
ovr195:0090 50 push ax
ovr195:0091
ovr195:0091 loc_58311: ; Call Procedure
ovr195:0091 9A 0A 00 41 33 call fileLoad_1
ovr195:0096

And a little bit further is the code that resets IBM.PAL for other players (if this is not set to the same player number as the variable above, the game keeps on using BENE.PAL for everything):


ovr195:02E3 loc_58563: ; Compare Two Operands
ovr195:02E3 83 3E 2C 3A 05 cmp houseHumanID, 5
ovr195:02E8
ovr195:02E8 loc_58568: ; Jump if Not Zero (ZF=0)
ovr195:02E8 75 1C jnz short loc_58586
ovr195:02EA

Link to comment
Share on other sites

  • 2 weeks later...
  • 4 weeks later...

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

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

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

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

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

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

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

Link to comment
Share on other sites

Hm... that kinda happens in C&C1 too, but usually only when destroying a building.

So, only the units on Area Guard (typically those guarding the base) will respond to this? Seems fair. The only problem I can see is that they in no way direct their attack at the thing that's attacking the base. If Hunt acts like in C&C1 it means "attack first target you find", meaning, most west one of the most north ones. If your base is in the north this will even lure troops away from the enemy base...

Link to comment
Share on other sites

Wow, TrueBrain, that's yet another impressive find :D Very cool! :)

[Edit] A bit of cross-posting, too :)

Hmm, now I'm really wondering if this is glitch or an intended "quick fix". If such behaviour is reinstated, apparently, all pre-placed units that are supposed to guard the AI base (and are set to "Area Guard") will leave their positions to counter-attack the player whenever an AI-owned structure is attacked. Meaning that when the player first attacks the enemy base, all defending units will go after the player, leaving the base defenceless for future attacks (given that the player survives the onslaught).

Link to comment
Share on other sites

  • 2 weeks later...

While meddling with the GUS patch for SD2, I figured out some things in the code concerning sound devices. First off, the variable that is called SoundEnabled? in Segra's database is actually the sound device for digitized sample (=speech) playback. In most cases, the game checks if it is set to 0 (No digitized samples) to determine if any speech at all is enabled. However, in one case it checks if this variable is set to 4, although I don't know what device this corresponds to.

There are also two adjacent variables, called word_4A239 and word_4A237, which are, respectively, the music and sound effects playback device types. word_4A239 is used to limit music playback for PC speaker and Tandy 3 voice: for PC speaker, there's no in-game music at all (only music in the intro, main menu etc.), and Tandy 3 voice does not switch to "battle" themes during missions. Here's to code for that:

seg001:022C                   loc_146DC:                                                  ; CODE XREF: gameMainLoop+204j
seg001:022C 83 3E 19 6E 04 cmp word_4A239, 4 ; Compare Two Operands
seg001:0231 75 03 jnz short loc_146E6 ; Jump if Not Zero (ZF=0)
seg001:0233 E9 D0 00 jmp loc_147B6 ; Jump
seg001:0236 ; ---------------------------------------------------------------------------
seg001:0236
seg001:0236 loc_146E6: ; CODE XREF: gameMainLoop+225j
seg001:0236 83 3E 19 6E 05 cmp word_4A239, 5 ; Compare Two Operands
seg001:023B 75 03 jnz short loc_146F0 ; Jump if Not Zero (ZF=0)
seg001:023D E9 C6 00 jmp loc_147B6 ; Jump

Also, both word_4A239 and word_4A237 are used for MT-32 initialization sequence

seg001:0AD2 55                                push    bp
seg001:0AD3 8B EC mov bp, sp
seg001:0AD5 56 push si
seg001:0AD6 33 F6 xor si, si ; Logical Exclusive OR
seg001:0AD8 83 3E 19 6E 06 cmp word_4A239, 6 ; Compare Two Operands
seg001:0ADD 74 07 jz short loc_14F96 ; Jump if Zero (ZF=1)
seg001:0ADF 83 3E 17 6E 06 cmp word_4A237, 6 ; Compare Two Operands
seg001:0AE4 75 6F jnz short loc_15005 ; Jump if Not Zero (ZF=0)

The values for these two variables are as follows (they aren't at all the same as the selection option numbers in the setup programme):

4 - PC speaker

5 - Tandy 3 voice

6 - MT-32/LAPC-1

7 - Sound Canvas

In fact, there's a large table that describes what drivers and sound files should be used for each sound device option that the game obtains from DUNE.CFG:

dseg:6398 18 65 42 43       off_497B8       dd aSbdig_adv_0                             ; "SBDIG.ADV"
dseg:639C 22 65 42 43 off_497BC dd aSbpdig_adv_0 ; "SBPDIG.ADV"
dseg:63A0 2D 65 42 43 off_497C0 dd aPasdig_adv_0 ; "PASDIG.ADV"
dseg:63A4 38 65 42 43 off_497C4 dd aAlgdig_adv_0 ; "ALGDIG.ADV"
dseg:63A8 43 65 42 43 off_497C8 dd aIbmbak_com ; "IBMBAK.COM"
dseg:63AC 4E 65 42 43 off_497CC dd aAdlib_com ; "ADLIB.COM"
dseg:63B0 00 unk_497D0 db 0
dseg:63B1 00 db 0
dseg:63B2 00 db 0
dseg:63B3 00 db 0
dseg:63B4 00 unk_497D4 db 0
dseg:63B5 00 db 0
dseg:63B6 00 db 0
dseg:63B7 00 db 0
dseg:63B8 00 db 0
dseg:63B9 00 db 0
dseg:63BA 00 db 0
dseg:63BB 00 db 0
dseg:63BC 5C 65 42 43 off_497DC dd aAlfx_drv_0 ; "ALFX.DRV"
dseg:63C0 65 65 42 43 off_497E0 dd aAdl ; "ADL"
dseg:63C4 48 unk_497E4 db 48h ; H
dseg:63C5 00 db 0
dseg:63C6 00 unk_497E6 db 0
dseg:63C7 00 db 0
dseg:63C8 69 65 42 43 off_497E8 dd aPcsound_drv_0 ; "PCSOUND.DRV"
dseg:63CC 75 65 42 43 off_497EC dd aPcs ; "PCS"
dseg:63D0 24 db 24h ; $
dseg:63D1 01 unk_497F1 db 1
dseg:63D2 00 unk_497F2 db 0
dseg:63D3 00 db 0
dseg:63D4 69 65 42 43 off_497F4 dd aPcsound_drv_0 ; "PCSOUND.DRV"
dseg:63D8 75 65 42 43 off_497F8 dd aPcs ; "PCS"
dseg:63DC 24 unk_497FC db 24h ; $
dseg:63DD 01 db 1
dseg:63DE 01 db 1
dseg:63DF 00 unk_497FF db 0
dseg:63E0 79 65 42 43 off_49800 dd aPcspkr_adv_0 ; "PCSPKR.ADV"
dseg:63E4 75 65 42 43 off_49804 dd aPcs ; "PCS"
dseg:63E8 00 db 0
dseg:63E9 00 db 0
dseg:63EA 00 db 0
dseg:63EB 00 db 0
dseg:63EC 84 65 42 43 off_4980C dd aTandy_adv_0 ; "TANDY.ADV"
dseg:63F0 8E 65 42 43 off_49810 dd aTan ; "TAN"
dseg:63F4 algn_49814:
dseg:63F4 00 00 00 00 align 8
dseg:63F8 92 65 42 43 off_49818 dd aMt32mpu_adv_0 ; "MT32MPU.ADV"
dseg:63FC 9E 65 42 43 off_4981C dd aXmi ; "XMI"
dseg:6400 00 unk_49820 db 0
dseg:6401 00 db 0
dseg:6402 00 db 0
dseg:6403 00 db 0
dseg:6404 92 65 42 43 off_49824 dd aMt32mpu_adv_0 ; "MT32MPU.ADV"
dseg:6408 A2 65 42 43 off_49828 dd aC55 ; "C55"
dseg:640C algn_4982C:
dseg:640C 00 00 00 00 align 8
dseg:6410 A6 65 42 43 off_49830 dd aAdlib_adv ; "ADLIB.ADV"
dseg:6414 65 65 42 43 off_49834 dd aAdl ; "ADL"
dseg:6418 00 db 0
dseg:6419 00 db 0
dseg:641A 00 db 0
dseg:641B 00 db 0
dseg:641C B0 65 42 43 off_4983C dd aAdlibg_adv ; "ADLIBG.ADV"
dseg:6420 65 65 42 43 off_49840 dd aAdl ; "ADL"
dseg:6424 00 00 00 00 align 8
dseg:6428 BB 65 42 43 off_49848 dd aPasfm_adv ; "PASFM.ADV"
dseg:642C 65 65 42 43 off_4984C dd aAdl ; "ADL"
dseg:6430 00 db 0
dseg:6431 00 db 0
dseg:6432 00 unk_49852 db 0
dseg:6433 00 db 0
dseg:6434 C5 65 42 43 off_49854 dd aSbfm_adv ; "SBFM.ADV"
dseg:6438 65 65 42 43 dd aAdl ; "ADL"
dseg:643C algn_4985C:
dseg:643C 00 00 00 00 align 8
dseg:6440 CE 65 42 43 off_49860 dd aSbp1fm_adv ; "SBP1FM.ADV"
dseg:6444 65 65 42 43 off_49864 dd aAdl ; "ADL"
dseg:6448 00 db 0
dseg:6449 00 db 0
dseg:644A 00 db 0
dseg:644B 00 db 0
dseg:644C D9 65 42 43 off_4986C dd aSbp2fm_adv ; "SBP2FM.ADV"
dseg:6450 65 65 42 43 off_49870 dd aAdl ; "ADL"
dseg:6454 00 00 00 00 align 8
dseg:6458 00 unk_49878 db 0
dseg:6459 00 db 0
dseg:645A 00 db 0
dseg:645B 00 db 0
dseg:645C 00 db 0
dseg:645D 00 db 0
dseg:645E 00 unk_4987E db 0
dseg:645F 00 unk_4987F db 0
dseg:6460 00 unk_49880 db 0
dseg:6461 00 db 0
dseg:6462 00 unk_49882 db 0
dseg:6463 00 db 0
dseg:6464 5C 65 42 43 off_49884 dd aAlfx_drv_0 ; "ALFX.DRV"
dseg:6468 65 65 42 43 off_49888 dd aAdl ; "ADL"
dseg:646C 48 unk_4988C db 48h ; H
dseg:646D 00 db 0
dseg:646E 00 unk_4988E db 0
dseg:646F 00 unk_4988F db 0
dseg:6470 69 65 42 43 off_49890 dd aPcsound_drv_0 ; "PCSOUND.DRV"
dseg:6474 75 65 42 43 off_49894 dd aPcs ; "PCS"
dseg:6478 24 db 24h ; $
dseg:6479 01 db 1
dseg:647A 00 db 0
dseg:647B 00 db 0
dseg:647C 69 65 42 43 off_4989C dd aPcsound_drv_0 ; "PCSOUND.DRV"
dseg:6480 75 65 42 43 off_498A0 dd aPcs ; "PCS"
dseg:6484 24 unk_498A4 db 24h ; $
dseg:6485 01 db 1
dseg:6486 01 db 1
dseg:6487 00 db 0
dseg:6488 79 65 42 43 off_498A8 dd aPcspkr_adv_0 ; "PCSPKR.ADV"
dseg:648C 75 65 42 43 off_498AC dd aPcs ; "PCS"
dseg:6490 00 unk_498B0 db 0
dseg:6491 00 db 0
dseg:6492 00 unk_498B2 db 0
dseg:6493 00 db 0
dseg:6494 84 65 42 43 off_498B4 dd aTandy_adv_0 ; "TANDY.ADV"
dseg:6498 8E 65 42 43 off_498B8 dd aTan ; "TAN"
dseg:649C algn_498BC:
dseg:649C 00 00 00 00 align 8
dseg:64A0 92 65 42 43 off_498C0 dd aMt32mpu_adv_0 ; "MT32MPU.ADV"
dseg:64A4 9E 65 42 43 off_498C4 dd aXmi ; "XMI"
dseg:64A8 00 db 0
dseg:64A9 00 db 0
dseg:64AA 00 db 0
dseg:64AB 00 db 0
dseg:64AC 92 65 42 43 off_498CC dd aMt32mpu_adv_0 ; "MT32MPU.ADV"
dseg:64B0 A2 65 42 43 off_498D0 dd aC55 ; "C55"
dseg:64B4 algn_498D4:
dseg:64B4 00 00 00 00 align 8
dseg:64B8 A6 65 42 43 dd aAdlib_adv ; "ADLIB.ADV"
dseg:64BC 65 65 42 43 off_498DC dd aAdl ; "ADL"
dseg:64C0 00 unk_498E0 db 0
dseg:64C1 00 unk_498E1 db 0
dseg:64C2 00 db 0
dseg:64C3 00 db 0
dseg:64C4 B0 65 42 43 off_498E4 dd aAdlibg_adv ; "ADLIBG.ADV"
dseg:64C8 65 65 42 43 off_498E8 dd aAdl ; "ADL"
dseg:64CC algn_498EC:
dseg:64CC 00 00 00 00 align 8
dseg:64D0 BB 65 42 43 off_498F0 dd aPasfm_adv ; "PASFM.ADV"
dseg:64D4 65 65 42 43 off_498F4 dd aAdl ; "ADL"
dseg:64D8 00 unk_498F8 db 0
dseg:64D9 00 db 0
dseg:64DA 00 db 0
dseg:64DB 00 db 0
dseg:64DC C5 65 42 43 off_498FC dd aSbfm_adv ; "SBFM.ADV"
dseg:64E0 65 65 42 43 off_49900 dd aAdl ; "ADL"
dseg:64E4 algn_49904:
dseg:64E4 00 00 00 00 align 8
dseg:64E8 CE 65 42 43 off_49908 dd aSbp1fm_adv ; "SBP1FM.ADV"
dseg:64EC 65 65 42 43 off_4990C dd aAdl ; "ADL"
dseg:64F0 00 unk_49910 db 0
dseg:64F1 00 unk_49911 db 0
dseg:64F2 00 db 0
dseg:64F3 00 db 0
dseg:64F4 D9 65 42 43 off_49914 dd aSbp2fm_adv ; "SBP2FM.ADV"
dseg:64F8 65 65 42 43 off_49918 dd aAdl ; "ADL"
dseg:64FC algn_4991C:
dseg:64FC 00 00 00 00 align 8
dseg:6500 FF FF word_49920 dw 0FFFFh ; DATA XREF: sub_2D9D4+90r
dseg:6500 ; sub_2D9D4+9Er ...

Note that this tables also lists unselectable sound drivers that are absent from SOUND.PAK, but the game is presumably able to use them. We've discussed this some time ago, and I just noticed that TrueBrain has already identified all the sound devices' internal indexes:

Digging up old topics. First, a small introduction. The next list shows which number matches which music driver (the number is in the dune.cfg, after decoding it):

0: NULL (NULL)

1: ALFX.DRV (ADL)

2: PCSOUND.DRV (PCS)

3: PCSOUND.DRV (PCS)

4: PCSPKR.ADV (PCS)

5: TANDY.ADV (TAN)

6: MT32MPU.ADV (XMI)

7: MT32MPU.ADV (C55)

8: ADLIB.ADV (ADL)

9: ADLIBG.ADV (ADL)

10: PASFM.ADV (ADL)

11: SBFM.ADV (ADL)

12: SBP1FM.ADV (ADL)

13: SBP2FM.ADV (ADL)

The name between () is the extension used.

Dune2 1.07eu HARDCODED ignores drivers 8 till 12, and sets it to 1. I guess you can still use 13, but this is most likely a bug, and it was not intended to be used. So I guess that is also the reason the drivers are nowhere to be found :)

Link to comment
Share on other sites

hmm... if you're messing with music code, and switching to battle themes and such... could you tell me how the tracks work exactly? I've noticed some files contain multiple tracks...

I remember having to use a midi editor to take those tracks apart for my Dune II music collection pack.

Taking the midi track dune1.c55 for example... when I play it in winamp I get

-An unused ambient track (ambient01 in my music pack)... could be some kind of credits track? I never found it ingame.

-The defeat themes of all three sides, in order HAO. H and A ones are the same.

-The ambient02 track from my music pack

-a bunch of midi sound effects, including the desert wind used in the intro. It seems ALL tracks (well the .c55 anyway) have those, probably for playing ingame midi sound effects no matter what track is playing.

Similarly, the track dune9.c55 contains the ambient08 and ambient09 track from my music pack (and the sound effects).

I also remember one other (I think the one containing the main menu music) which didn't have its midi tracks played in an order, but had them stored so winamp played them all parallel. I can't find it right away though.

[edit]

Full list:


dune0.c55
- 02_Intro.mid
- 01_Launch.mid
dune1.c55
- 03_ambient01.mid
- 13_defeat_Hark.mid \_ These 2 are the same file (13_defeat_AtrHark.mid) in the music pack, since the tracks are the same.
- 13_defeat_Atr.mid /
- 14_defeat_Ord.mid
- 04_ambient02.mid
dune2.c55
- 05_ambient03.mid
dune3.c55
- 06_ambient04.mid
dune4.c55
- 07_ambient05.mid
dune5.c55
- 08_ambient06.mid
dune6.c55
- 09_ambient07.mid
dune7.c55
- 15_mentat_Harkonnen.mid
- 16_mentat_Atreides.mid
- 17_mentat_Ordos.mid
- 18_mainmenu.mid
dune8.c55
- 19_victory_Atreides.mid
- 20_victory_Harkonnen.mid
dune9.c55
- 10_ambient08.mid
- 11_ambient09.mid
dune10.c55
- 22_attack01.mid
dune11.c55
- 23_attack02.mid
dune12.c55
- 24_attack03.mid
dune13.c55
- 25_attack04.mid
dune14.c55
- 26_attack05.mid
dune15.c55
- 27_attack06.mid
dune16.c55
- 28_conquest.mid
- 29_plotting.mid
dune17.c55
- 21_victory_Ordos.mid
dune18.c55
- 12_ambient10.mid
dune19.c55
- 30_finale_Atreides.mid
- 31_finale_Ordos.mid
- 32_finale_Harkonnen.mid
dune20.c55
- 33_credits.mid

Link to comment
Share on other sites

hmm... if you're messing with music code, and switching to battle themes and such... could you tell me how the tracks work exactly? I've noticed some files contain multiple tracks...

Heh, there wasn't much messing with music code per se, as I only found the exceptions depending on the ID of the selected music device. Music playback isn't documented in detail in Segra's database, but I guess the chunk that disables dynamic music switching for Tandy might reveal something.

I remember having to use a midi editor to take those tracks apart for my Dune II music collection pack.

BTW, always wanted to ask, what editor did you use? :)

Taking the midi track dune1.c55 for example... when I play it in winamp I get

-An unused ambient track (ambient01 in my music pack)... could be some kind of credits track? I never found it ingame.

An unused track? I never noticed if it was or wasn't in-game (I remember hearing it while playing, but that could have been a Dune 2 remake as well, so I'm not sure). It might very well be that a track was left unused; I'm pretty certain it isn't played in any other circumstances (e.g. credits sequence, which only uses the credits track), and it does sound like a regular in-game ambient theme.

-The defeat themes of all three sides, in order HAO. H and A ones are the same.

-The ambient02 track from my music pack

-a bunch of midi sound effects, including the desert wind used in the intro. It seems ALL tracks (well the .c55 anyway) have those, probably for playing ingame midi sound effects no matter what track is playing.

That's most probably the case, otherwise the game would have to switch to the track that contains the sound effects. BTW, this is probably why replacing individual music files didn't work for me (I tried adding the tunes from Sega Mega Drive to DuneX), although I was able to unite multiple MIDIs into one XMI file using MIDIFORM.EXE.

Link to comment
Share on other sites

I honestly don't remember which midi editor I used, only that it was a shareware thing which I installed, used for the Dune tracks, and then uninstalled again because it'd only work for a week or so anyway. It seems I made some errors though; the first notes are missing in some tracks compared to the .c55 versions.

As for the mystery track, I spent a few hours recording the GUS MIDI tracks and noticed it was never, ever played.

Link to comment
Share on other sites

As for the mystery track, I spent a few hours recording the GUS MIDI tracks and noticed it was never, ever played.

BTW, I thought that it could have been easier to play the already extracted MIDIs (the ones at the Game Music Base site seem accurate if you don't like what that editor did for you) through the MIDI player that comes with the Ultrasound patches & drivers, have you tried that? There shouldn't be a significant difference, I suppose, and it can spare a lot of time that way. On the other hand, it's nice that you found out that that track never plays in-game :)

Link to comment
Share on other sites

Yeah, I tried playing them in the GUS midi player, but it didn't work on the raw extracted versions of the track, only on the ones I converted to normal .mid. The reason I didn't use it was that I noticed some of my mid versions were slightly damaged, and missing the first sounds.

Those on that site seem just perfect though... I'll see what GUS recordings of those can give me shocked.gif

Link to comment
Share on other sites

  • 2 months later...

It would be cool if Fremen Palace create Sandworms instead Fremen Troopers. tongue.gif

I've thought of that. Theoretically, it's doable, since Segra had posted the code some time ago (see below). The only possible problem here might arise from the fact that Sandworms obviously have behaviour modifiers, and thus they could screw up when made to do something they're not supposed to.

Well as was mentioned already, the DuneX Fremen trooper is actually a different unit. The Palace superweapon spawns Troopers.

It's pretty easy to see; the new Fremen Warrior is always just one guy, not a squad.

Nope. In fact, the Palace in DuneX spawns Fremen Warriors (that were converted from infantry). Here's Segra's post with relevant data that I used. It's pretty easy to find in any exe, too:

Soldier creation is handled from the UNIT/BUILDING Scripts, however... two internal functions 'scriptFunctionUnitCreateSoldier' and 'scriptFunctionBuildingDestroy' are called from the scripts themselves,

both contain these lines

Hex search: B8040050B8FFFF only 2 locations will show, first should be the unitcreatesoldier function

seg030:2409 B8 04 00 mov ax, 4 ; Soldier

seg030:240C 50 push ax ; TypeIndex

seg030:240D B8 FF FF mov ax, 0FFFFh

seg030:2410 50 push ax ; int

seg030:2411 9A 02 09 36 28 call unitCreate ; Call Procedure

Chance of this happening, is based on the value in the BUILDINGDATA/UNITDATA.'FIELD_E', it compares the value to a ``random`` (from the map seed) number

and will spawn a solider if random is below field_e (Units: Unknown7 in Nyers editor)

EDIT: Palace stuff is handled in

seg023:0519 palaceUnitBuild

From the hardcoded 'houses' data, ('Palace Special' in nyers editor) is used to determine what to do

When mode2 is in use, for Atreides/Fremen, the data located at

dseg:6090 03 00 unitTypeTable dw 3 ; DATA XREF: palaceUnitBuild+1C1r

dseg:6092 05 00 word_494B2 dw 5

dseg:6094 03 00 word_494B4 dw 3

dseg:6096 03 00 dw 3

Troopers/Trooper/Troopers/Troopers

this is used with a ''real'' (not the map seed) random number, to select which type of unit to create for the palace reinforcements... the loop that creates each unit is checked at

seg023:070F 83 FF 05 cmp di, 5 ; Compare Two Operands

seg023:0712 7C 8B jl short loc_228CF ; Jump if Less (SF!=OF)

In fact, I've also contemplated making the Palace spawn a few 'thopters at a time ;)

BTW, here's the code chunk in Segra's database that defines which side should own the units spawned by the Palace:

seg023:06AC                   loc_228DC:                                                  ; add0x80
seg023:06AC 50 push ax
seg023:06AD B8 20 00 mov ax, 20h ; ' '
seg023:06B0 50 push ax ; pRandom
seg023:06B1 56 push si ; mapIndex
seg023:06B2 9A 9D 00 48 1D call mapIndexToXY ; Call Procedure
seg023:06B7 59 pop cx
seg023:06B8 52 push dx ; posY
seg023:06B9 50 push ax ; posX
seg023:06BA 9A A1 01 48 1D call mapXYCorrect ; Call Procedure
seg023:06BF 83 C4 08 add sp, 8 ; Add
seg023:06C2 52 push dx ; posY
seg023:06C3 50 push ax ; posX
seg023:06C4
seg023:06C4 loc_228F4:
seg023:06C4 B8 03 00 mov ax, 3
seg023:06C7 50 push ax ; houseID
seg023:06C8
seg023:06C8 loc_228F8:
seg023:06C8 B8 03 00 mov ax, 3
seg023:06CB 50 push ax

Just change house ID from 3 (Fremen) to whatever you want :)

Link to comment
Share on other sites

Oh fun. Never knew you had that code :)

In this case it's definitely possible to experiment with spawning sandworms. But tbh I don't think it'll ever be valid as superweapon, especially since they'll frequently spawn on rock and get stuck there.

Oh, and btw, drnovice, before you ask, no, I can't add stuff like that to my editor; it's designed to handle lists of uniformly-sized data, not single code hacks. In fact there's even a bit of a restriction in it that makes it unable to list data types which don't have a link to a name string in their data somewhere (to show in the lower part of the left column). So this type of changes is actual hex editing work.

Link to comment
Share on other sites

I change House ID from last post code and it works, but I don't understand HOW change to modify Unit ID reference about "Palace Special"...

[...]

From the hardcoded 'houses' data, ('Palace Special' in nyers editor) is used to determine what to do

When mode2 is in use, for Atreides/Fremen, the data located at

dseg:6090 03 00 unitTypeTable dw 3 ; DATA XREF: palaceUnitBuild+1C1r

dseg:6092 05 00 word_494B2 dw 5

dseg:6094 03 00 word_494B4 dw 3

dseg:6096 03 00 dw 3

Troopers/Trooper/Troopers/Troopers

I try to change 03, 05, 03 and 03 with another values but nothing changing...

I also try to open with IDA and I don't see unitTypeTable string in dseg:6090 row, instead a word_494** string...

Link to comment
Share on other sites

Finally I did it, but I accidentally deleted my post! >:(

More news today...

EDIT:

1) I succeed to change 03 05 03 03 values (obviously in dunex.exe I don't find it 'cause this is changing to 02 04 02 02 as well to produce Warriors units -> MrFlibble's change of Infantry/Soldier) and set to 03 19 03 03... you guess what about value 19: HEX of 25, decimal ID of Sandworm! tongue.gif

So a quarter of probability to produce Sandworm together Fremen (remember that Fremen ride them!) instead single Trooper.

Again produced Sandworms do only ONE "meal" before disappearing... I don't know what is the difference about those pre-placed (3-4 eat before leaving).

2) Another curiosity is see that if you change House ID to Atreides to produce Troopers/Warriors they are stand there to do nothing with no Hunt/Ambush IA... while if try to put another non-Fremen non-Atreides House ID, they attack normally as well.

3) I also find Saboteur ID Unit to change units produced by "saboteur" Palace Special type (just placed in SaboteurCreate function). Maybe you already talking about this so I apologize in advance in that case. angel.gif

However I don't think about changing Saboteur and Missile "Palace Special" type, it's ok by me.

At last many thanks to segra (he's simply a little genius! :D ), MrFlibble and Nyerguds for patience and prompt reply.

P.S. I would like to learn how find exactly a certain specific thing in game by segra's IDA db. How do you create it? With a compiler or made by your hands? wink.gif

  • Upvote 1
Link to comment
Share on other sites

drnovice, I hope you don't mind that I moved this branch of discussion to this topic, which is specifically dedicated to DUNE2.EXE editing issues.

1) I succeed to change 03 05 03 03 values (obviously in dunex.exe I don't find it 'cause this is changing to 02 04 02 02 as well to produce Warriors units -> MrFlibble's change of Infantry/Soldier) and set to 03 19 03 03... you guess what about value 19: HEX of 25, decimal ID of Sandworm! tongue.gif

So a quarter of probability to produce Sandworm together Fremen (remember that Fremen ride them!) instead single Trooper.

Again produced Sandworms do only ONE "meal" before disappearing... I don't know what is the difference about those pre-placed (3-4 eat before leaving).

I remember Segra mentioned something that the worm uses the same variable that is responsible for harvester load count to determine how many units it had eaten. Apparently, spawned Sandworms have it set to 1, or something else interferes with its regular functioning. I remember that once during testing, I destroyed my ConYard at the beginning of the mission and sent all my starting units against the enemy base (I needed to lose the mission to test something). They encountered a Sandworm, and it ate about 6 or 7 units without disappearing.

2) Another curiosity is see that if you change House ID to Atreides to produce Troopers/Warriors they are stand there to do nothing with no Hunt/Ambush IA... while if try to put another non-Fremen non-Atreides House ID, they attack normally as well.

Yep, this isn't resolved yet. If you play the Fremen, you're allied with the Atreides AI, but it isn't hostile to other AI players. So far, I've been unable to find the code that's responsible for this. However, you might find this interesting:

seg023:0BBB                   checkHouseID:                                               ; CODE XREF: sub_22B24+2A9j
seg023:0BBB ; sub_22B24+2B3j
seg023:0BBB C4 5E 06 les bx, [bp+unitGamePtr] ; Load Full Pointer to ES:xx
seg023:0BBE 26 8A 47 08 mov al, es:[bx+_unitGame.houseID]
seg023:0BC2 98 cbw ; AL -> AX (with sign)
seg023:0BC3 3B 06 2C 3A cmp ax, houseHumanID ; Compare Two Operands
seg023:0BC7 74 11 jz short AtreFre ; Jump if Zero (ZF=1)
seg023:0BC9
seg023:0BC9 loc_22DF9: ; Load Full Pointer to ES:xx
seg023:0BC9 C4 5E 06 les bx, [bp+unitGamePtr]
seg023:0BCC 26 80 7F 08 03 cmp es:[bx+_unitGame.houseID], 3 ; Fremen
seg023:0BD1 75 11 jnz short loc_22E14 ; Jump if Not Zero (ZF=0)
seg023:0BD3 83 3E 2C 3A 01 cmp houseHumanID, 1 ; Atre
seg023:0BD8 75 0A jnz short loc_22E14 ; Jump if Not Zero (ZF=0)
seg023:0BDA
seg023:0BDA AtreFre: ; CODE XREF: sub_22B24+2D3j
seg023:0BDA C4 5E 06 les bx, [bp+unitGamePtr] ; unit = fremen and human = atre
seg023:0BDD 26 C6 47 09 FF mov es:[bx+_unitGame.houseRevealed], 0FFh
seg023:0BE2 EB 0A jmp short Done

This piece of code defines the "shared vision" that the Atreides have with the Fremen. Notice that it is also unilateral - the Fremen units will reveal the map for the Atreides player (even if the Atreides player is an AI), but the Atreides units do not reveal the map for a Fremen player. Notice that the Sandworm unit is excluded from this logic, as Fremen Sandworms do not reveal the map to the Atreides player. However, if you play as the Fremen and place an Atreides-owned Sandworm on the map in AMbush, it will rush towards your base and try to eat your units right at the start, as it can see your regular units precisely because of the shared vision.

seg023:0F78                   loc_231A8:                                                  ; CODE XREF: isFriendly?:loc_231A4j
seg023:0F78 83 FA 03 cmp dx, 3 ; DX = object
seg023:0F7B 74 05 jz short isFremen ; Jump if Zero (ZF=1)
seg023:0F7D 83 FB 03 cmp bx, 3 ; BX = human
seg023:0F80
seg023:0F80 loc_231B0: ; Jump if Not Zero (ZF=0)
seg023:0F80 75 0E jnz short notFremen
seg023:0F82
seg023:0F82 isFremen: ; CODE XREF: isFriendly?+20j
seg023:0F82 83 FA 01 cmp dx, 1 ; Compare Two Operands
seg023:0F85
seg023:0F85 loc_231B5: ; Jump if Zero (ZF=1)
seg023:0F85 74 05 jz short isAtreides
seg023:0F87
seg023:0F87 loc_231B7: ; Compare Two Operands
seg023:0F87 83 FB 01 cmp bx, 1
seg023:0F8A
seg023:0F8A loc_231BA: ; if object is Fremen, and Human is Atreides, Ret True
seg023:0F8A 75 02 jnz short notAtreides
seg023:0F8C
seg023:0F8C isAtreides: ; CODE XREF: isFriendly?:loc_231B5j
seg023:0F8C EB 10 jmp short retTrue ; Jump
seg023:0F8E ; ---------------------------------------------------------------------------
seg023:0F8E
seg023:0F8E notAtreides: ; CODE XREF: isFriendly?:loc_231BAj
seg023:0F8E EB DE jmp short retFalse ; Jump
seg023:0F90 ; ---------------------------------------------------------------------------
seg023:0F90
seg023:0F90 notFremen: ; CODE XREF: isFriendly?:loc_231B0j
seg023:0F90 3B 16 2C 3A cmp dx, houseHumanID ; Compare Two Operands
seg023:0F94
seg023:0F94 loc_231C4: ; Jump if Zero (ZF=1)
seg023:0F94 74 06 jz short objectIsHuman
seg023:0F96
seg023:0F96 loc_231C6: ; Compare Two Operands
seg023:0F96 3B 1E 2C 3A cmp bx, houseHumanID
seg023:0F9A
seg023:0F9A loc_231CA: ; if object is not human, and house is not human, ret true
seg023:0F9A 75 02 jnz short retTrue
seg023:0F9C
seg023:0F9C objectIsHuman: ; CODE XREF: isFriendly?:loc_231C4j
seg023:0F9C EB D0 jmp short retFalse ; Jump
seg023:0F9E ; ---------------------------------------------------------------------------
seg023:0F9E
seg023:0F9E retTrue: ; CODE XREF: isFriendly?+1Bj
seg023:0F9E ; isFriendly?:isAtreidesj ...
seg023:0F9E B8 01 00 mov ax, 1
seg023:0FA1
seg023:0FA1 loc_231D1: ; Jump
seg023:0FA1 EB CD jmp short loc_231A0
seg023:0FA3 ; ---------------------------------------------------------------------------
seg023:0FA3
seg023:0FA3 loc_231D3: ; CODE XREF: isFriendly?:loc_231A0j
seg023:0FA3 5D pop bp
seg023:0FA4
seg023:0FA4 locret_231D4: ; Return Far from Procedure
seg023:0FA4 CB retf
seg023:0FA4 isFriendly? endp
seg023:0FA4
seg023:0FA4 seg023 ends

And this chunk is responsible for making Atreides and Fremen units treat each other as allies. Changing it does not, however, have any impact on the fact that the Fremen AI will attack other AI players, but the Atreides AI won't.

3) I also find Saboteur ID Unit to change units produced by "saboteur" Palace Special type (just placed in SaboteurCreate function). Maybe you already talking about this so I apologize in advance in that case. angel.gif

However I don't think about changing Saboteur and Missile "Palace Special" type, it's ok by me.

Nice find! :)

P.S. I would like to learn how find exactly a certain specific thing in game by segra's IDA db. How do you create it? With a compiler or made by your hands? wink.gif

Segra used IDA and a debugger to define most functions. He has left useful notes on them, and many functions can be found thanks to his analysis. But it also requires a lot of guessing and cycling through similar functions to find out what they do. Personally I'm not skilled enough to use a debugger in tandem with IDA, so it's more about analogical reasoning based on already known facts that Segra has revealed :)

Link to comment
Share on other sites

It's a sin that Atreides ally AI don't work. I mind to create a personal Fremen/Atreides campaign. I wanted create a special DUNE.PAK that allows to play by Region+Scenario files a combination of Atreides/Fremen levels, or Ordos/Mercenary or Harkonnen/Sardaukar. In Atreides campaign for example, you can use Atreides as well, but in determinate Scenarios the player can use also Fremen as human!

I think it is possibile if DUNE.PAK is set right to do that.

If someone want to know how change "saboteur" spawn unit type:

SaboteurCreate:                                             ; CODE XREF: palaceUnitBuild+6Dj
seg023:0731 33 C0 xor ax, ax ; Logical Exclusive OR
seg023:0733 50 push ax
seg023:0734 FF 76 08 push word ptr [bp+buildingGamePtr+2]
seg023:0737 FF 76 06 push word ptr [bp+buildingGamePtr]
seg023:073A 9A 7A 24 43 1A call structurePositionGetNear ; Call Procedure
seg023:073F 83 C4 06 add sp, 6 ; Add
seg023:0742 8B F0 mov si, ax
seg023:0744 0B F6 or si, si ; Logical Inclusive OR
seg023:0746 74 6F jz short buildWait ; No ROom?
seg023:0748 FF 06 B0 38 inc unitCreatingInProgress ; Increment by 1
seg023:074C 9A 0E 00 B8 39 call mapSeedRandomGet ; Call Procedure
seg023:0751
seg023:0751 loc_22981: ; Angle
seg023:0751 50 push ax
seg023:0752
seg023:0752 loc_22982: ; mapIndex
seg023:0752 56 push si
seg023:0753 9A 9D 00 48 1D call mapIndexToXY ; Call Procedure
seg023:0758 59 pop cx
seg023:0759 52 push dx ; posY
seg023:075A 50 push ax ; posX
seg023:075B C4 5E 06 les bx, [bp+buildingGamePtr] ; Load Full Pointer to ES:xx
seg023:075E
seg023:075E loc_2298E:
seg023:075E 26 8A 47 08 mov al, es:[bx+_buildingGame.houseID]
seg023:0762 98 cbw ; AL -> AX (with sign)
seg023:0763 50 push ax ; houseID
seg023:0764 B8 06 00 mov ax, 6 ; Saboteur
seg023:0767 50 push ax ; TypeIndex
seg023:0768 B8 FF FF mov ax, 0FFFFh
seg023:076B 50 push ax ; int
seg023:076C 9A 02 09 36 28 call unitCreate ; Call Procedure
seg023:0771 83 C4 0C add sp, 0Ch ; Add
seg023:0774 89 56 FE mov word ptr [bp+unitGamePtr+2], dx
seg023:0777 89 46 FC mov word ptr [bp+unitGamePtr], ax
seg023:077A FF 0E B0 38 dec unitCreatingInProgress ; Decrement by 1
seg023:077E
seg023:077E loc_229AE:
seg023:077E 8B 46 FC mov ax, word ptr [bp+unitGamePtr]
seg023:0781 0B 46 FE or ax, word ptr [bp+unitGamePtr+2] ; Logical Inclusive OR
seg023:0784 75 03 jnz short setBuildTime ; Jump if Not Zero (ZF=0)
seg023:0786 E9 D3 FD jmp ret0 ; Jump

seg023:0764 B8 06 00 mov ax, 6 ; Saboteur

Change 06 (Saboteur ID Unit) with another one. I try with 01 and Palace create an Ornithopter :P

We can only hope that segra find something about a fix to Atreides AI in alliance with human Fremen. rolleyes.gif

  • Upvote 1
Link to comment
Share on other sites

We can only hope that segra find something about a fix to Atreides AI in alliance with human Fremen. rolleyes.gif

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

Link to comment
Share on other sites

This piece of code defines the "shared vision" that the Atreides have with the Fremen. Notice that it is also unilateral - the Fremen units will reveal the map for the Atreides player (even if the Atreides player is an AI), but the Atreides units do not reveal the map for a Fremen player. Notice that the Sandworm unit is excluded from this logic, as Fremen Sandworms do not reveal the map to the Atreides player. However, if you play as the Fremen and place an Atreides-owned Sandworm on the map in AMbush, it will rush towards your base and try to eat your units right at the start, as it can see your regular units precisely because of the shared vision.

I see that Atreides AI units reveal map to Fremen Human player. They reveal less respect own units but they reveal it (like when you "call" Fremen by Atreides Palace).

I also see that Atreides Harvester works unlike other units when human is Fremen, but only if you add Atreides Brain CPU in Scen*.ini relative file. If there is no [Atreides] line in Scenario doesn't work even Harvester.

I'll do some other tests to undestand how fix Atreides AI attack/defence units.

  • Upvote 1
Link to comment
Share on other sites

Join the conversation

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

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

×
×
  • Create New...