Jump to content

Recommended Posts

Posted

... And here is your problem: the palace has 1000hp. 2hp are repaired every tick. 2 / 1000 * 256 = 0. So, 0% of the cost has to be paid (values are round down). So, repairing palace is for free :) ...

And a typo came :P I guess you meant (2 * 256) / 1000 (otherwise repair for buildings with HP more than 2 would be free).

Posted

TrueBrain, thanks a lot for clearing this for us ;D Once again, this is something people could only be guessing about until recently :)

From campaign 4 and on you don't repair per 3 hitpoints, but per 5 hitpoints. For the same cost ;)

In both cases, you only pay for repairing 2 hitpoints. So an almost destroyed structure cost only 2/3th or 2/5th of the cost to repair.

Do you mean that after mission 3, repair is faster (restoring each 5 hitpoints instead of 3)? Interesting.

The palace shows in a nice way the problem of avoiding floats. It is very common for any (sane) application to avoid floats, but for Dune2 it is more fundamental: it doesn't use any FPU command (old computers didn't have a FPU :P). To still do floating calculations, a simple trick is used: multiple every float by value N. In this case: 256. And here is your problem: the palace has 1000hp. 2hp are repaired every tick. 2 / 1000 * 256 = 0. So, 0% of the cost has to be paid (values are round down). So, repairing palace is for free :) Every structure with the hp of over 512hp has this 'problem'.

I wonder how this all was avoided in v1.0, where the Palace is repaired normally.

Posted

TrueBrain, thanks a lot for clearing this for us ;D Once again, this is something people could only be guessing about until recently :)

It helps a lot to get to know the code by looking for such specific things ;) So if you have any other things you wonder about, just ask :)

Do you mean that after mission 3, repair is faster (restoring each 5 hitpoints instead of 3)? Interesting.

Yup. And I thought so too ;)

I wonder how this all was avoided in v1.0, where the Palace is repaired normally.

I don't know (and I guess only segra (via IDA) can give more insight in that). But if I had to guess, I think one of the following:

1) a higher float-resolution (unlikely)

2) Palace has lower hp (easy to check)

3) using 3 or 5 instead of 2 (so you pay more). I guess this is what 1.0 does, and that for 1.07 they 'tuned' it a bit and made repairs cheaper.

Posted

It helps a lot to get to know the code by looking for such specific things ;) So if you have any other things you wonder about, just ask :)

Ooh, thanks :)

2) Palace has lower hp (easy to check)

3) using 3 or 5 instead of 2 (so you pay more). I guess this is what 1.0 does, and that for 1.07 they 'tuned' it a bit and made repairs cheaper.

The Palace has the same amount of hp in v1.0, so I guess you're right about the repairs being cheaper in v1.07 :)

EDIT: You were right, the repair cost is reduced by a lot in v1.07. For example, to repair a half-damaged Windtrap (placed on bare rock) costs 294 credits in v1.0, and only 42 in v1.07.

Posted

(..)

EDIT: You were right, the repair cost is reduced by a lot in v1.07. For example, to repair a half-damaged Windtrap (placed on bare rock) costs 294 credits in v1.0, and only 42 in v1.07.

I love to be right :)

Posted

Hm, I should really play Dune 1.07... I indeed remember the repairs costing tons of money in my old 1.0... I wonder how much different it'd be to play it through again now.

Though tbh I prefer playing the Sega Megadrive version. It has cooler graphics, different missions and better controls :P

Posted

Segra, where in your Dune2 IDA database are those house specific techtree exceptions? I think I've found a few in the structurebuildlistcreate function but I don't really understand how they work.

Also, you posted some information on the worms disappearing after three swallows but would you mind telling me what to change exactly to disable it?

Many thanks!

Posted

The techtree code exceptions are scattered around various threads. I've linked to most of them here.

As for the worms, the solution is here:

you can change it, but you hav eto change it via the exe not the script.

at a guess its because the weapons are their own "units" and it takes the kills instead of the worm itself

, altho im not 100% sure of this.. id say thats what it is

you just need to find this location

seg015:053B 26 C6 47 58 03                    mov    es:[bx+_unitGame.HarvesterSpiceCapacity], 3

and u can specify how many units u want the worm tobe able to eat

or this line here,

seg030:178C 26 FE 4F 58                      dec    es:[bx+_unitGame.HarvesterSpiceCapacity]

NOP that out and the worm eat count wont ever change

Posted

Ah brilliant, many thanks! I thought I had checked all of segra's posts but guess I wasn't very thorough.

edit: still don't understand how those exceptions work though :) the ordos heavy factory and harkonnen light factory ones are obvious but the others...

Posted

edit: still don't understand how those exceptions work though :) the ordos heavy factory and harkonnen light factory ones are obvious but the others...

That depends on what you want to do with them :) If you want to transfer the same effect (e.g. the building always starts fully upgraded) to another House or another structure, you need to change HouseID and/or TypeIndex. If you want to do something else, I'm afraid I'm not competent enough to help you out.

Posted

If you want to remove the worm code, he said NOP it out. That means, replace it by bytes '90'. They give the program a "do nothing" (NOP = No Operation) command, so it's a handy way to remove code.

Posted

I wonder if it is possible to limit the number of Starports and Palaces that the player can own at a time to one, like in the Sega version. The Saboteurs are limited to 2 (3 in v1.0), and this limit can be disabled, but it has something to do with the values currently known as "Unit array min/max" IIRC.

Posted

Thanks Nyerguds, I actually have some extremely basic knowledge of assembly and managed it myself. I also successfully removed the code that turned squads into single soldiers at 50% hp (I replaced the single soldiers with the Fremen&Sardaukar troopers :) ), keeping the retreat check. I was quite proud of that one. :D

But trying to answer Flibble's post I realize I actually don't have a clear idea of what changes I'd like to do yet. For now I wanted to make the Sardaukar light factory start upgraded just like the Harkonnen (and also keep the harkonnen upgraded light factory). With or without trike doesn't matter. But the other tech tree stuff in that post seems to be aimed at not displaying the upgrade button if certain conditions are met (that's just a guess, I really can't make much of assembly code)

I'll probably have to replace one of the other exceptions but I'm sure I'll find one suitable for that.

Posted

I also successfully removed the code that turned squads into single soldiers at 50% hp (I replaced the single soldiers with the Fremen&Sardaukar troopers :) ), keeping the retreat check. I was quite proud of that one. :D

Could you please post how you did that? In fact, I have even less knowledge and thus won't figure it out on my own :)

But trying to answer Flibble's post I realize I actually don't have a clear idea of what changes I'd like to do yet. For now I wanted to make the Sardaukar light factory start upgraded just like the Harkonnen (and also keep the harkonnen upgraded light factory).

Is it possible to do that without adding a new code chunk?

But the other tech tree stuff in that post seems to be aimed at not displaying the upgrade button if certain conditions are met (that's just a guess, I really can't make much of assembly code)

Makes sense, since the Harkonnen Hi-Tech Factory doesn't need to be upgraded at all (same for the Ordos skipping the 2nd Heavy Factory upgrade, I suppose).

Posted

Sure, I'll post the IDA code as well so someone with some experience can tell me if I've done something stupid :)

I (or rather, segra) found a check for the trooper squad and infantry squad in the UnitTakeDamage function.


seg031:0D66                   loc_290C6:                                                  ; CODE XREF: unitTakeDamage+1DAj
seg031:0D66 C4 5E 06                          les     bx, [bp+unitGamePtr]                ; Load Full Pointer to ES:xx
seg031:0D69 26 80 7F 02 05                    cmp     byte ptr es:[bx+2], 5               ; troopers
seg031:0D6E 74 0A                             jz      short TrooperInfantry               ; Jump if Zero (ZF=1)
seg031:0D70 C4 5E 06                          les     bx, [bp+6]                          ; Load Full Pointer to ES:xx
seg031:0D73 26 80 7F 02 04                    cmp     byte ptr es:[bx+2], 4               ; infantry
seg031:0D78 75 79                             jnz     short loc_29153                     ; Jump if Not Zero (ZF=0)

if true it does some misc stuff I can't figure out but just assumed was the soldier spawning code (I saw some references to the hit points :) ). I just skip it by patching in a jump to the code that follows it, which I guessed was the retreat check since it compares against the house weakness which segra told us is also used for that.


g031:0D7A                   TrooperInfantry:                                            ; CODE XREF: unitTakeDamage+1F6j
seg031:0D7A EB 46                             jmp     short loc_29122                     ; Jump
seg031:0D7A                   ; ---------------------------------------------------------------------------
seg031:0D7C 06                                db    6
seg031:0D7D                   ; ---------------------------------------------------------------------------
seg031:0D7D 26 8A 47 02                       mov     al, es:[bx+2]
seg031:0D81 04 02                             add     al, 2                               ; Add
seg031:0D83 C4 5E 06                          les     bx, [bp+unitGamePtr]                ; Load Full Pointer to ES:xx
seg031:0D86 26 88 47 02                       mov     es:[bx+_unitGame.typeIndex], al
seg031:0D8A C4 5E 06                          les     bx, [bp+unitGamePtr]                ; Load Full Pointer to ES:xx
seg031:0D8D 26 8A 47 02                       mov     al, es:[bx+_unitGame.typeIndex]
seg031:0D91 98                                cbw                                         ; AL -> AX (with sign)
seg031:0D92 BA 5A 00                          mov     dx, size _unitData
seg031:0D95 F7 EA                             imul    dx                                  ; Signed Multiply
seg031:0D97 05 00 00                          add     ax, 0                               ; Add
seg031:0D9A C7 46 FE 0B 3B                    mov     word ptr [bp+unitDataPtr+2], seg seg130
seg031:0D9F 89 46 FC                          mov     word ptr [bp+unitDataPtr], ax
seg031:0DA2 C4 5E FC                          les     bx, [bp+unitDataPtr]                ; Load Full Pointer to ES:xx
seg031:0DA5 26 8B 47 10                       mov     ax, es:[bx+_unitData.HitPoints]
seg031:0DA9 C4 5E 06                          les     bx, [bp+unitGamePtr]                ; Load Full Pointer to ES:xx
seg031:0DAC 26 89 47 0E                       mov     es:[bx+_unitGame.HitPoints], ax
seg031:0DB0 FF 76 08                          push    word ptr [bp+unitGamePtr+2]
seg031:0DB3 FF 76 06                          push    word ptr [bp+unitGamePtr]           ; unitGamePtr
seg031:0DB6 B8 02 00                          mov     ax, 2
seg031:0DB9 50                                push    ax                                  ; funcPtrIndex
seg031:0DBA 9A 8E 00 D0 42                    call    j_sub_566CF                         ; Call Procedure
seg031:0DBF 83 C4 06                          add     sp, 6                               ; Add

The retreat code it jumps to:


g031:0DC2                   loc_29122:                                                  ; CODE XREF: unitTakeDamage:TrooperInfantryj
seg031:0DC2 9A 0E 00 B8 39                    call    mapSeedRandomGet                    ; Call Procedure
seg031:0DC7 25 FF 00                          and     ax, 0FFh                            ; Logical AND
seg031:0DCA
seg031:0DCA                   loc_2912A:                                                  ; Load Full Pointer to ES:xx
seg031:0DCA C4 5E 06                          les     bx, [bp+unitGamePtr]
seg031:0DCD
seg031:0DCD                   loc_2912D:
seg031:0DCD 50                                push    ax
seg031:0DCE
seg031:0DCE                   loc_2912E:
seg031:0DCE 26 8A 47 08                       mov     al, es:[bx+_unitGame.houseID]
seg031:0DD2
seg031:0DD2                   loc_29132:                                                  ; AL -> AX (with sign)
seg031:0DD2 98                                cbw
seg031:0DD3
seg031:0DD3                   loc_29133:
seg031:0DD3 BA 1E 00                          mov     dx, size _houseData
seg031:0DD6
seg031:0DD6                   loc_29136:                                                  ; Signed Multiply
seg031:0DD6 F7 EA                             imul    dx
seg031:0DD8
seg031:0DD8                   loc_29138:
seg031:0DD8 8B D8                             mov     bx, ax
seg031:0DDA
seg031:0DDA                   loc_2913A:
seg031:0DDA 58                                pop     ax
seg031:0DDB 3B 87 F0 37                       cmp     ax, houseData.Weakness[bx]          ; Compare Two Operands
seg031:0DDF 73 12                             jnb     short loc_29153                     ; Jump if Not Below (CF=0)
seg031:0DE1 B8 02 00                          mov     ax, 2
seg031:0DE4 50                                push    ax                                  ; action
seg031:0DE5 FF 76 08                          push    word ptr [bp+unitGamePtr+2]
seg031:0DE8 FF 76 06                          push    word ptr [bp+unitGamePtr]           ; unitGamePtr
seg031:0DEB 9A 05 00 6F 25                    call    unitActionstart                     ; Call Procedure
seg031:0DF0 83 C4 06                          add     sp, 6                               ; Add

To patch it, search the exe for

02 75 79 C4 5E 06 26 8A

and change it to

04 75 79 EB 46 06 26 8A

(I hope that's right)

About the sardaukar light factory, most likely I'll have to replace another exception for that. (house of WOR springs to mind, tech level 5? Come on  ::) ) unless there's some kind of mathematical formula that can check both the Harkonnen and Sardaukar house ID in one line.

Posted

It all depends on the size of the commands, and how much space you got. 'some kind of mathematical formula' usually takes more bytes than 2 small checks :P

The check being 3 bytes and the jump 2, the 2 checks would need 10 bytes.

Posted

You're right :) Actually why did they turn the raider trike into a code exception? It's easy enough to do with the existing parameters in Nyerguds editor, no?

Posted

Problem is that if you disable a Trike from a house, Light Factory will still be available for it (unless Harkonnen with Hardcoded exception) in the Tech Level 2 (producing Carryalls). Anyway what is the Raider Trike exception like?

I don't know how on x86 16bit (cause I only know 32bit x86 and there is no near and far addressing which I can't beat) but mostly visible on ARM the compilers aint perfect, allowing you to restate the disassembled code into less instructions and add some extra. (It is actually easier as the instructions are fixed 2 bytes (Thumb) or 4 bytes (or pair of them is joined).)

Posted

You're right :) Actually why did they turn the raider trike into a code exception? It's easy enough to do with the existing parameters in Nyerguds editor, no?

I can also find no plausible reason for this. No other unit is handled like that in the game. Perhaps it allows to avoid some side-effects we're still unaware of?

Anyway, would be nice if you posted this code exception here (I think it's not mentioned in Segra's posts, unless I'm missing something) :)

Problem is that if you disable a Trike from a house, Light Factory will still be available for it (unless Harkonnen with Hardcoded exception) in the Tech Level 2 (producing Carryalls).

Tha Carryall icon is used whenever you have a production facility with nothing to produce from it. For example, if you give the Atreides player a WOR, you also get a Carryall icon (since the Troopers are disabled for Atreides). However, if I'm not mistaken, this does not grant the ability to actually produce Carryalls from such a building.

Posted

Anyway, would be nice if you posted this code exception here (I think it's not mentioned in Segra's posts, unless I'm missing something) :)

Tha Carryall icon is used whenever you have a production facility with nothing to produce from it. For example, if you give the Atreides player a WOR, you also get a Carryall icon (since the Troopers are disabled for Atreides). However, if I'm not mistaken, this does not grant the ability to actually produce Carryalls from such a building.

You are correct.

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.