As a French person I feel like it's my duty to explain strikes to you. - AdrienIer

Create an account  

 
Mindy - Assembly interface

This thread is intended for the efforts to interface with wizards.exe from an external program.

Thoughts?
--I like ILSe
Reply

Relevant information gathered:

I'm updating this post with the confirmed information about Unit_strategy_exe().

Code:
+0x43 is the target battleunit id (0-18)
+0x54 is the chosen action (100-109)
    100 melee (if unit has non-zero melee)
    101 shoot (if unit has ranged attack type and has shot left)
    102 ?
    103 ?
    104 doom bolt (even without the special)
    105 fireball (even without the special)
    106 healing?? (selected by priests, but as yet it does not work)
    107 cast spell (spell and target yet to be chosen)
    108 cast spell (at this point in Unit_strategy_exe the same as 107)
    109 summon demon (even without the special)
--I like ILSe
Reply

Jtm Wrote:I've made a demo external ai for combatting. You must run MoM under DOSBox. Demo is user controlled. With 'attack <user_id>' command, you can direct the ai units and attack anyone, even ai's own units.

Below is link to the demo and modified wizards.exe:
http://www.smallfiles.org/download/1853/...o.zip.html

Wizards.exe is modified so that without my program combat runs as if nothing is changed, using original ai. But if you run my program, combat would, in real time, change to wait my program. Also, if you exit my program using exit-command during the combat, the original ai is again in use.

Jtm Wrote:By the way, I've updated the external ai demo so that it allows changing the strategy. I suggest trying strategies 104 and 105 lol. Demo also allows manual targeting of any coordinate but the functionality does not work well if at all. Also, unfortunately the 106 does not look like the moving strategy.

I guess we still need to figure out what all the numbers do.

It appears indeed that the x and y coordinates do not seem to do anything as far as strategy is concerned.
It seems that the target battleUnitID (at +0x43) determines where a unit goes.
That would make it a bit harder to make a unit attack the wall.
It may well be that the current code does not allow for it.
--I like ILSe
Reply

Jtm, can you add an extra option <Enter> to accept the current action?
And also show the information what the current target xpos,ypos is (since tweaker does not show that)?
You may also want to show what the currently targeted unit is.
--I like ILSe
Reply

I've tweaked the assembly code that interfaces with MoM.

It now implements the interface Kyrub suggested.
kyrub Wrote:Personnally, I think you (or we) should remake the combat AI setup to:

A = coordinate to where AI moves or attacks
B = type of action
C = other specification value
D = other specification value

---------

example: AI wants to cast Fire bolt on unit at field nr = 35 with mana spent 25
A = 35
B = casting
C = value for Fire bolt
D = 25

another example, you want to crush wall at field = 45
A = 45
B = crush with movement
C = FF
D = FF

etc. This will eventually cover all combat AI situations, when implemented properly. It allows full scale of AI operation, no reliance on (poor) internal mechanics.


The various data is made accessible through the stack.
To achieve it, I've saved the BP register in DS:9294, which I've labeled "baseptr".
To raise or retract the hook the code can be changed directly at the "loc_HOOK" point.
To make MoM wait or release it DS:9296 is used, which I've labeled "bait".

The "parm1" and "parm2" parameters still need to be hooked though.

For those interested, this is the assembly code I wrote.
It's supposed to be written at offset 0x889E4 in WIZARDS.EXE.
Code:
                 .8086             ;Target processor.
0000                 .MODEL LARGE, C         ;Use the flat memory model. Use C calling conventions

0000                 dseg         segment byte public 'DATA'    use16

                 ORG 922Ah
922A  00000000             addr_Battle_unit         dd    0

[COLOR="Orange"]                 ORG 9294h
9294  0000             baseptr             dw    0
                 ORG 9296h
9296  0000             bait             dw    0
[/COLOR]
9298                 dseg         ends

0000                 ovr114         segment byte public 'CODE'    use16
                         assume cs:ovr114
                         assume es:nothing,    ss:nothing, ds:dseg

                 ORG 0344h

0344                 Unit_strategy_exe         proc far        ; CODE XREF: ___69
                                    ; Army_autocombat+2E0
                                    ; Army_autocombat+3A2

[COLOR="Orange"]      =-000A             parm1              =    word ptr -0Ah
      =-0008             parm2              =    word ptr -8
[/COLOR]      =-0006             target_unit_at_gate      =    word ptr -6
      =-0004             casting_failed          =    word ptr -4
      =-0002             targetID_in_gate_OR_moves_left= word ptr -2
[COLOR="orange"]     =0006             battleUnitID          =    word ptr  6
      =0008             target_xpos          =    word ptr  8
      =000A             target_ypos          =    word ptr  0Ah
[/COLOR]
      =SI             si_battleUnitID = si
      =DI             di_target_xpos = di
                         ;;    Original
0344  55                     push    bp
0345  8B EC                     mov     bp, sp
[COLOR="Orange"]0347  83 EC 0A                     sub     sp, 0Ah
[/COLOR]034A  56                     push    si
034B  57                     push    di

[COLOR="Orange"]                         ;;    Added
034C  8B C5                     mov     ax, bp
034E  A3 9294r                     mov     [baseptr],    ax         ; Make    stack variables    accessible
[COLOR="Red"]0351                 loc_HOOK:
0351  B8 0001                     mov     ax, 1             ;; The    "hook"[/COLOR]
0354  A3 9296r                     mov     [bait], ax
0357                 loc_wait_external_AI:
0357  A1 9296r                     mov     ax, [bait]
035A  0B C0                     or         ax, ax
035C  75 F9                     jnz     loc_wait_external_AI

035E  33 C0                     xor     ax, ax
0360  A3 9294r                     mov     [baseptr],    ax         ; Restore dseg:9294
[/COLOR]
                         ;;    Original
0363  8B 76 06                     mov     si_battleUnitID, [bp+battleUnitID]
0366  8B 7E 08                     mov     di_target_xpos, [bp+target_xpos]
0369  0B FF                     or         di_target_xpos, di_target_xpos
036B  75 34                     jnz     short loc_92521

036D  83 7E 0A 00                 cmp     [bp+target_ypos], 0
0371  75 2E                     jnz     short loc_92521

0373  8B C6                     mov     ax, si_battleUnitID
0375  BA 006E                     mov     dx, 6Eh ; 'n'
0378  F7 EA                     imul    dx
037A  C4 1E 922Ar                 les     bx, addr_Battle_unit
037E  03 D8                     add     bx, ax
0380  26: 8A 47    43                 mov     al, es:[bx+43h]
0384  98                     cbw
0385  BA 006E                     mov     dx, 6Eh ; 'n'
0388  F7 EA                     imul    dx
038A  C4 1E 922Ar                 les     bx, addr_Battle_unit
038E  03 D8                     add     bx, ax
0390  26: 8B 7F    44                 mov     di_target_xpos, es:[bx+44h]
0394  89 46 0A                     mov     [bp+target_ypos], ax

                         ;;    Jump to    regular    continuation of    code (could also be NOP's)
0397  EB 08 90                     jmp     loc_92521

                         ;;    Original
                 ORG 03A1h
03A1                 loc_92521:                     ; CODE XREF: Unit_strategy_exe+10
                                     ; Unit_strategy_exe+16
03A1  56                     push   si_battleUnitID ; battleUnitID
                         ;;    call   j_choose_next_unit_for_action
                         ;;    ...

03A2                 Unit_strategy_exe         endp

                         ;;    ...

03A2                 ovr114         ends

                         end
--I like ILSe
Reply

As i wrote, this is work version of int3f interface. The actually code starts from 9c .before it there is a way to attach resident to int3f. It hook any call 380:25 in mom and return ax=10 instead.
This cause mana range penalty=1 in any battle.
How its work?start dosbox, start momint ,start wizards,any version after vanilla. You see range=1 in any battle. Close dosbox after use.if you'll use lhup,this resident will eat significant less memory.
If you want,i can prepare version to change wizards the way you want.
The main advantage this work with any mod,fast and upgrade easily.
Later i'll change this example into any chaneller gets 1/2 mana penalty,like in 1.2 patch.
Reply

Asfex Wrote:As i wrote, this is work version of int3f interface. The actually code starts from 9c .before it there is a way to attach resident to int3f. It hook any call 380:25 in mom and return ax=10 instead.

I've tried to analyze it, but as yet I don't understand the code.
Apparently is starts with a dos call to free memory???

What do you mean by a call 380:25?

Quote:If you want,i can prepare version to change wizards the way you want.
The main advantage this work with any mod,fast and upgrade easily.

Please do.
I am intrigued by the possible advantages your method may bring.
--I like ILSe
Reply

call 380:25 is what you see in the wizards.exe. its "cd 25 00 80 03". this is translated to stub*:25 and then jump to the ovl70h:1d2dh. same as ovl 112:1d2d . its mana_range_penalty prosedure, as it named in the ida database. 112=70h = 380h/8.
about program: first, it frees dos environment ,then hook int 1C (timer user interrupt), then exit and stay resident. then int 1c spy for int 3f in order to find mom there. if it found, it patch mom's int3f ,and this (1ch) interupt do not need more. the last part of code (starts from 9c) is the int3f hook. it spy for the needed call (380:25) when it occur, and translate it into codesegment where this overlay has been loaded already. (at this point it was loaded just, ds is the segment of relocation table; es is the segment of the jumptable). then see the jumptable and found the adress to jump (1d2d). its a start of subroutine "mana_range_penalty". it moves to the begin of this the sequence "mov ax,10;retn". any time this overlay has been loaded in memory,this int3f occur. if it not has not loaded,then it remain unchanged,therefore the changes preserve (mov ax,0a; retn).

Also i plan implement 'int 87 y x',which will call ovlx:y .


Edit:add example for 'edit 889e4',for Ilse mindy,4 post above.
Alas,this does not work with later insecticide,becouse it patch the same place in the mom.
Technicaly,it activates at the
army_autocombat instead of unit_strategy,the last sub havenot own active entry point.
Reply

Very interesting!

I just spend some time on it to try and understand what you are writing.
It looks like something that has a lot of potential.
  1. It's the logical hook to *any* point in MoM code.
  2. It's a perfect candidate to hook external AI into MoM.
    Since we still can't make a call an external program, the loop that waits for external AI could go here.
  3. I might adjust the tweaker to change *only* memory instead of writing wizards.exe.
  4. I might hook it into the building queue mechanism I already have.
    For instance allowing to call functions to buy off buildings according to the rules, and to avoid the building screen from popping up.

However, I'm afraid that it is as yet beyond me.
I'm getting lost in the complexities of the mechanism.

Btw, as an alternative to a terminate-and-stay-resident program, isn't it an option to change the INT 3F routine in MoM directly?
--I like ILSe
Reply

I like Serena Wrote:Btw, as an alternative to a terminate-and-stay-resident program, isn't it an option to change the INT 3F routine in MoM directly?
For what? Can you guarant no int 3f happens,while you are modifying this interrupt?

For creating semaphore the commands like 'lock ;btt *;jz 'is the shortest way.
Reply



Forum Jump: