Modifications to prince.exe (hex editing)

User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5745
Joined: April 9th, 2009, 10:58 pm

Re: CusPop TODO list

Post by Norbert »

robert wrote:Great info! It should be added to cuspop
I've added it to the CusPop TODO list:
viewtopic.php?p=13133#p13133
David
The Prince of Persia
The Prince of Persia
Posts: 2848
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: Modifications to prince.exe (hex editing)

Post by David »

robert wrote:3) What if I want the rescue level (or prince level 14) to still have time running? Because some mods have the vizier in level 14... (and to see the text "LEVEL 14" below?)
To show "LEVEL 13" and "LEVEL 14"

Code: Select all

seg008:25B4                 or      ax, ax          ; level 0 doesn't show its number
seg008:25B6                 jz      loc_C218
seg008:25B8                 cmp     ax, 0Eh         ; level 14 and above doesn't show its number
seg008:25BB                 jge     loc_C218
seg008:25BD                 cmp     word_20566, 0
seg008:25C2                 jnz     loc_C218
seg008:25C4                 cmp     ax, 0Dh         ; level 13 shows level 12
seg008:25C7                 jnz     loc_C1EE
seg008:25C9                 mov     word ptr [bp+disp_level], 0Ch

Code: Select all

0000C3D4:i0BC0                           or        ax,ax
0000C3D6:i7440                           je        file:0000C418
0000C3D8:i3D0E00                         cmp       ax,000E
0000C3DB:i7D3B                           jnl       file:0000C418 ; <- change to nop
0000C3DD:i833E865800                     cmp (w)   [+5886],+00
0000C3E2:i7534                           jne       file:0000C418
0000C3E4:i3D0D00                         cmp       ax,000D
0000C3E7:i7505                           jne       file:0000C3EE ; <- change to jmp
0000C3E9:iC746FE0C00                     mov       [bp-02],000C
search 3D 0E 00 7D 3B , change 7D 3B to 90 90 -or- 0E to 0F (first level that doesn't show its number)
search 3D 0D 00 75 05 , change 75 to EB (show level 13 (and not level 12) on level 13)


To have level 14 the time running, and make Jaffar's death there stop the time:

Code: Select all

seg008:24BC		    cmp	    current_level, 0Dh ; level 13
seg008:24C1		    jg	    loc_C142
seg008:24C3		    jnz	    loc_C0EC
seg008:24C5		    cmp	    leveldoor_open?, 0 ; Jaffar died?
seg008:24CA		    jnz	    loc_C142

Code: Select all

0000C2DC:i833E9E0F0D                     cmp (w)   [+0F9E],+0D
0000C2E1:i7F5F                           jg        file:0000C342
0000C2E3:i7507                           jne       file:0000C2EC
0000C2E5:i833E9C4000                     cmp (w)   [+409C],+00
0000C2EA:i7556                           jne       file:0000C342
search 83 3E 9E 0F 0D 7F 5F , change 0D to 0E

Note: You also need to change the level in the "Customize Jaffar/guard death: blinking and event trigger" category in CusPoP.
User avatar
robert
Sultan
Sultan
Posts: 194
Joined: August 27th, 2011, 7:16 pm
Location: Argentina

Re: Modifications to prince.exe (hex editing)

Post by robert »

David wrote:
robert wrote:3) What if I want the rescue level (or prince level 14) to still have time running? Because some mods have the vizier in level 14... (and to see the text "LEVEL 14" below?)
To show "LEVEL 13" and "LEVEL 14"

Code: Select all

seg008:25B4                 or      ax, ax          ; level 0 doesn't show its number
seg008:25B6                 jz      loc_C218
seg008:25B8                 cmp     ax, 0Eh         ; level 14 and above doesn't show its number
seg008:25BB                 jge     loc_C218
seg008:25BD                 cmp     word_20566, 0
seg008:25C2                 jnz     loc_C218
seg008:25C4                 cmp     ax, 0Dh         ; level 13 shows level 12
seg008:25C7                 jnz     loc_C1EE
seg008:25C9                 mov     word ptr [bp+disp_level], 0Ch

Code: Select all

0000C3D4:i0BC0                           or        ax,ax
0000C3D6:i7440                           je        file:0000C418
0000C3D8:i3D0E00                         cmp       ax,000E
0000C3DB:i7D3B                           jnl       file:0000C418 ; <- change to nop
0000C3DD:i833E865800                     cmp (w)   [+5886],+00
0000C3E2:i7534                           jne       file:0000C418
0000C3E4:i3D0D00                         cmp       ax,000D
0000C3E7:i7505                           jne       file:0000C3EE ; <- change to jmp
0000C3E9:iC746FE0C00                     mov       [bp-02],000C
search 3D 0E 00 7D 3B , change 7D 3B to 90 90 -or- 0E to 0F (first level that doesn't show its number)
search 3D 0D 00 75 05 , change 75 to EB (show level 13 (and not level 12) on level 13)


To have level 14 the time running, and make Jaffar's death there stop the time:

Code: Select all

seg008:24BC		    cmp	    current_level, 0Dh ; level 13
seg008:24C1		    jg	    loc_C142
seg008:24C3		    jnz	    loc_C0EC
seg008:24C5		    cmp	    leveldoor_open?, 0 ; Jaffar died?
seg008:24CA		    jnz	    loc_C142

Code: Select all

0000C2DC:i833E9E0F0D                     cmp (w)   [+0F9E],+0D
0000C2E1:i7F5F                           jg        file:0000C342
0000C2E3:i7507                           jne       file:0000C2EC
0000C2E5:i833E9C4000                     cmp (w)   [+409C],+00
0000C2EA:i7556                           jne       file:0000C342
search 83 3E 9E 0F 0D 7F 5F , change 0D to 0E

Note: You also need to change the level in the "Customize Jaffar/guard death: blinking and event trigger" category in CusPoP.
Amazing info! Many thanks David
Image
This will be my face if you can't win any of my mods
David
The Prince of Persia
The Prince of Persia
Posts: 2848
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: Modifications to prince.exe (hex editing)

Post by David »

From viewtopic.php?p=12737#p12737
Norbert wrote:Something I ran into while working on Prince of Wateria that I cannot yet explain: in level 2, the two gates in room 10 do not make a sound when slowly going down.
In the original game, when I put gates at these two locations, they do make the normal sound when slowly going down. Strange...
I looked into this. It seems that the problem is caused by that the room is linked to itself on the left side.

The relevant part of the disassembly is:

Code: Select all

seg007:1669 ; int __stdcall far play_door_sound_if_visible(int sound_id)
seg007:1669 play_door_sound_if_visible proc far     ; CODE XREF: animate_door+83p
seg007:1669                                         ; gate_reached_top+Ap
seg007:1669 
seg007:1669 gate_room       = word ptr -6
seg007:1669 tile_pos        = word ptr -4
seg007:1669 has_sound       = word ptr -2
seg007:1669 sound_id        = word ptr  6
seg007:1669 
seg007:1669                 push    bp
seg007:166A                 mov     bp, sp
seg007:166C                 sub     sp, 6
seg007:166F                 mov     al, trob_tile
seg007:1672                 sub     ah, ah
seg007:1674                 mov     [bp+tile_pos], ax
seg007:1677                 mov     al, trob_room
seg007:167A                 mov     [bp+gate_room], ax
seg007:167D                 mov     [bp+has_sound], 0
seg007:1682                 cmp     current_level, 3 ; Special event: sound of closing gates
seg007:1687                 jnz     loc_9BDE
seg007:1689                 cmp     ax, 2           ; room 2
seg007:168C                 jz      sound_yes
seg007:168E 
seg007:168E loc_9BDE:                               ; CODE XREF: play_door_sound_if_visible+1Ej
seg007:168E                 mov     ax, room_L
seg007:1691                 cmp     [bp+gate_room], ax
seg007:1694                 jnz     loc_9BF6
seg007:1696                 mov     ax, [bp+tile_pos]
seg007:1699                 cwd
seg007:169A                 mov     cx, 0Ah
seg007:169D                 idiv    cx
seg007:169F                 cmp     dx, 9           ; right edge of the room to the left: play sound
seg007:16A2                 jnz     sound_no        ; elsewhere in the room to the left: no sound
seg007:16A4                 jmp     short sound_yes
seg007:16A6 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg007:16A6 
seg007:16A6 loc_9BF6:                               ; CODE XREF: play_door_sound_if_visible+2Bj
seg007:16A6                 mov     ax, drawn_room
seg007:16A9                 cmp     [bp+gate_room], ax
seg007:16AC                 jnz     sound_no
seg007:16AE                 mov     ax, [bp+tile_pos]
seg007:16B1                 cwd
seg007:16B2                 mov     cx, 0Ah
seg007:16B5                 idiv    cx
seg007:16B7                 cmp     dx, 9           ; right edge of this room: no sound
seg007:16BA                 jz      sound_no        ; elsewhere in this room: play sound
seg007:16BC 
seg007:16BC sound_yes:                              ; CODE XREF: play_door_sound_if_visible+23j
seg007:16BC                                         ; play_door_sound_if_visible+3Bj
seg007:16BC                 mov     [bp+has_sound], 1
seg007:16C1 
seg007:16C1 sound_no:                               ; CODE XREF: play_door_sound_if_visible+39j
seg007:16C1                                         ; play_door_sound_if_visible+43j ...
seg007:16C1                 cmp     [bp+has_sound], 0
seg007:16C5                 jz      loc_9C1F
seg007:16C7                 push    [bp+sound_id]   ; resource
seg007:16CA                 call    play_sound
seg007:16CF 
seg007:16CF loc_9C1F:                               ; CODE XREF: play_door_sound_if_visible+5Cj
seg007:16CF                 mov     sp, bp
seg007:16D1                 pop     bp
seg007:16D2                 retf    2
seg007:16D2 play_door_sound_if_visible endp
The code assumes that if the gate is in the room to the left, then it can't be in the current room.

With hex codes:

Code: Select all

0000B469:i55                             push      bp
0000B46A:i8BEC                           mov       bp,sp
0000B46C:i83EC06                         sub (w)   sp,+06
0000B46F:iA0BC4C                         mov       al,[+4CBC]
0000B472:i2AE4                           sub       ah,ah
0000B474:i8946FC                         mov       [bp-04],ax
0000B477:iA0BD4C                         mov       al,[+4CBD]
0000B47A:i8946FA                         mov       [bp-06],ax
0000B47D:iC746FE0000                     mov       [bp-02],0000
0000B482:i833E9E0F03                     cmp (w)   [+0F9E],+03
0000B487:i7505                           jne       file:0000B48E
0000B489:i3D0200                         cmp       ax,0002
0000B48C:i742E                           je        file:0000B4BC
0000B48E:iA1C04C                         mov       ax,[+4CC0]
0000B491:i3946FA                         cmp       [bp-06],ax
0000B494:i7510                           jne       file:0000B4A6
0000B496:i8B46FC                         mov       ax,[bp-04]
0000B499:i99                             cwd
0000B49A:iB90A00                         mov       cx,000A
0000B49D:iF7F9                           idiv (w)  cx
0000B49F:i83FA09                         cmp (w)   dx,+09
0000B4A2:i751D                           jne       file:0000B4C1 ; <- this has to be changed
0000B4A4:iEB16                           jmps      file:0000B4BC
0000B4A6:iA19E40                         mov       ax,[+409E]
0000B4A9:i3946FA                         cmp       [bp-06],ax
0000B4AC:i7513                           jne       file:0000B4C1
0000B4AE:i8B46FC                         mov       ax,[bp-04]
0000B4B1:i99                             cwd
0000B4B2:iB90A00                         mov       cx,000A
0000B4B5:iF7F9                           idiv (w)  cx
0000B4B7:i83FA09                         cmp (w)   dx,+09
0000B4BA:i7405                           je        file:0000B4C1
0000B4BC:iC746FE0100                     mov       [bp-02],0001
0000B4C1:i837EFE00                       cmp (w)   [bp-02],+00
0000B4C5:i7408                           je        file:0000B4CF
0000B4C7:iFF7606                         push (w)  [bp+06]
0000B4CA:i9AC5120000                     callf     file:000012C5
0000B4CF:i8BE5                           mov       sp,bp
0000B4D1:i5D                             pop       bp
0000B4D2:iCA0200                         retf      0002
To fix this:
search: 83 FA 09 75 1D, change 1D to 02
User avatar
Jakim
Beylerbey
Beylerbey
Posts: 55
Joined: March 5th, 2011, 2:27 pm
Location: Poland
Contact:

Re: Modifications to prince.exe (hex editing)

Post by Jakim »

I think this topic should be wrote as .pdf file (that means everything what is about hex editing). I could put together into such file. May I?
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5745
Joined: April 9th, 2009, 10:58 pm

Re: Modifications to prince.exe (hex editing)

Post by Norbert »

You should feel free to create any files you want, of course. :)

However, allow me to explain what usually happens with discoveries about the PRINCE.EXE file. This thread but also this thread and some other threads (going back all the way to PoPUW) contain information about how PRINCE.EXE can be changed to alter the game's behavior. Later, that information is being translated to a format suitable for this XML file that is in turn being used by CusPop. The CusPop TODO list contains links to the posts with information that has not yet been embedded in the XML/CusPop. This means that if you'd want to include all information about modifying the PRINCE.EXE file in a document, you'd have to include everything that is already a part of CusPop. This could be a lot of work if done manually. If the XML file is being parsed by software, the document(ation) could be generated. In a way, the XML itself is the document(ation). Most people will probably prefer to use CusPop instead of applying changes manually. On the other hand, some discoveries have not yet been included in the XML/CusPop.
User avatar
Jakim
Beylerbey
Beylerbey
Posts: 55
Joined: March 5th, 2011, 2:27 pm
Location: Poland
Contact:

Re: Modifications to prince.exe (hex editing)

Post by Jakim »

Ok, I'll do that tomorrow :).
David
The Prince of Persia
The Prince of Persia
Posts: 2848
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: Modifications to prince.exe (hex editing)

Post by David »

Allow triggering of any tile

In addition to gates and level doors, you will be able to trigger spikes, chompers and loose floors (but not buttons).
This is similar to how the blue potion and the level 1 special event work.

Note: On the SNES, this is already possible in the original game.
Some SNES mods have buttons that trigger a loose floor, see: viewtopic.php?p=11479#p11479

disassembly:

Code: Select all

seg007:0999 ; int __stdcall far trigger_1(int button_type,int tile,int room,int target_type)
seg007:0999 trigger_1       proc far                ; CODE XREF: do_trigger_list+3A↓p
seg007:0999 
seg007:0999 result          = word ptr -2
seg007:0999 button_type     = word ptr  6
seg007:0999 tile            = word ptr  8
seg007:0999 room            = word ptr  0Ah
seg007:0999 target_type     = word ptr  0Ch
seg007:0999 
seg007:0999                 push    bp
seg007:099A                 mov     bp, sp
seg007:099C                 sub     sp, 2
seg007:099F                 push    si
seg007:09A0                 mov     [bp+result], 0FFFFh
seg007:09A5                 cmp     [bp+target_type], tiles_4_gate ; gate
seg007:09A9                 jnz     loc_8F0D
seg007:09AB                 push    [bp+room]       ; room
seg007:09AE                 push    [bp+tile]       ; tile
seg007:09B1                 push    [bp+button_type] ; button_type
seg007:09B4                 push    cs
seg007:09B5                 call    near ptr trigger_gate
seg007:09B8                 mov     [bp+result], ax
seg007:09BB                 jmp     short loc_8F2B
seg007:09BD ; ───────────────────────────────────────────────────────────────────────────
seg007:09BD 
seg007:09BD loc_8F0D:                               ; CODE XREF: trigger_1+10↑j
seg007:09BD                 cmp     [bp+target_type], tiles_16_level_door_left ; level door
seg007:09C1                 jnz     loc_8F2B
seg007:09C3                 mov     bx, [bp+tile]
seg007:09C6                 mov     si, addr_modif
seg007:09CA                 cmp     byte ptr [bx+si], 0
seg007:09CD                 jz      loc_8F26
seg007:09CF                 mov     [bp+result], 0FFFFh
seg007:09D4                 jmp     short loc_8F2B
seg007:09D6 ; ───────────────────────────────────────────────────────────────────────────
seg007:09D6 
seg007:09D6 loc_8F26:                               ; CODE XREF: trigger_1+34↑j
seg007:09D6                 mov     [bp+result], 1
seg007:09DB 
seg007:09DB loc_8F2B:                               ; CODE XREF: trigger_1+22↑j
seg007:09DB                                         ; trigger_1+28↑j ...
seg007:09DB                 mov     ax, [bp+result]
seg007:09DE                 pop     si
seg007:09DF                 mov     sp, bp
seg007:09E1                 pop     bp
seg007:09E2                 retf    8
seg007:09E2 trigger_1       endp
with hex codes:

Code: Select all

000090E9:i55                             push      bp
000090EA:i8BEC                           mov       bp,sp
000090EC:i83EC02                         sub (w)   sp,+02
000090EF:i56                             push      si
000090F0:iC746FEFFFF                     mov       [bp-02],FFFF
000090F5:i837E0C04                       cmp (w)   [bp+0C],+04
000090F9:i7512                           jne       file:0000910D
000090FB:iFF760A                         push (w)  [bp+0A]
000090FE:iFF7608                         push (w)  [bp+08]
00009101:iFF7606                         push (w)  [bp+06]
00009104:i0E                             push      cs
00009105:iE874FF                         calln     file:0000907C
00009108:i8946FE                         mov       [bp-02],ax
0000910B:iEB1E                           jmps      file:0000912B
0000910D:i837E0C10                       cmp (w)   [bp+0C],+10
00009111:i7518                           jne       file:0000912B ; <-- here
00009113:i8B5E08                         mov       bx,[bp+08]
00009116:i8B36885F                       mov       si,[+5F88]
0000911A:i803800                         cmp       [bx+si],00
0000911D:i7407                           je        file:00009126
0000911F:iC746FEFFFF                     mov       [bp-02],FFFF
00009124:iEB05                           jmps      file:0000912B
00009126:iC746FE0100                     mov       [bp-02],0001
0000912B:i8B46FE                         mov       ax,[bp-02]
0000912E:i5E                             pop       si
0000912F:i8BE5                           mov       sp,bp
00009131:i5D                             pop       bp
00009132:iCA0800                         retf      0008
search: 83 7E 0C 10 75 18, change 75 18 to 90 90
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5745
Joined: April 9th, 2009, 10:58 pm

Re: Modifications to prince.exe (hex editing)

Post by Norbert »

David wrote:In addition to gates and level doors, you will be able to trigger spikes, chompers and loose floors (but not buttons).
This is great. :)
I'm definitely going to use this for my next mod.
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5745
Joined: April 9th, 2009, 10:58 pm

Re: Modifications to prince.exe (hex editing)

Post by Norbert »

David wrote:In addition to gates and level doors, you will be able to trigger spikes, chompers and loose floors (but not buttons).
Certain combinations of buttons have some effect though.

Try this, for example:
- Create a raise button (a; with event 1) and a drop button (b; also event 1); both point to another button (c; also event 1; raise or drop, doesn't matter).
- Stand on a or b, turn around while on the button, then move onto the other button (a or b).
The third button (c) will go down.

[Edit: Or simply create a raise button with event 2 (a) and point it to a drop button with event 1 (b), then stand on a.]
David
The Prince of Persia
The Prince of Persia
Posts: 2848
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: Modifications to prince.exe (hex editing)

Post by David »

Norbert wrote:Or simply create a raise button with event 2 (a) and point it to a drop button with event 1 (b), then stand on a.
Ah, now I know what happens: the triggered tile must have modifier=0. (That is event 1 in Apoplexy.)
The statement "cmp byte ptr [bx+si], 0" checks exactly this. The "hijacked" part of the code originally deals with level doors, and there it makes sense.
You can remove this restriction if you replace 75 18 with 75 13.

It seems to work with all combinations of raise and drop buttons.
Anyway, the (b) button is only drawn pressed, but its events are not triggered.

When I step off the (a) button, the (b) button is sometimes instantly raised, sometimes it waits a bit.

I just checked: on the SNES, it is possible to trigger any button, but, like in the DOS version, it is only *drawn* pressed.
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5745
Joined: April 9th, 2009, 10:58 pm

Re: Modifications to prince.exe (hex editing)

Post by Norbert »

David wrote:Allow triggering of any tile
[...]
search: 83 7E 0C 10 75 18, change 75 18 to 90 90
I'm running into a problem with this, because certain events in a chain of events aren't being fired.

Here's the stuff I've created to replicate the problem: image, mirror
The two images on the left are from level 1 (room 1 is above room 2), the two images in the middle are from level 6 (there room 2 is above room 1).
The events on the right are about level 6. For level 1, the same events apply except where it says room 1 use 2 and vice versa.

Here's what I expect to happen when I walk onto the drop button with event 1, in this order:
- The loose tile at the top left starts falling down.
- The gate closes.
- When the falling loose tile hits event 3, the loose tile in the lower left falls onto event 4.

Here's what actually happens: in level 6, the loose tile above event 4 falls too early and the gate doesn't close; in level 1, the gate closes and nothing else happens.

Any ideas why it's not doing what I want?
David
The Prince of Persia
The Prince of Persia
Posts: 2848
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: Modifications to prince.exe (hex editing)

Post by David »

I tried what you did on level 6:
I figured out that something messes up event 2, because the gate won't shut even if I put a button that triggers event 2 only.
This also happens with the original prince.exe, so it is not related to this hack.

I saved the memory with an unofficial version of DOSBox ( http://ykhwong.x-y.net/xe/143 ) and it showed me that one byte in the door events block is zeroed. This byte affects event 2: the trigger-next bit is also zeroed, so the next event is also triggered, that's why the other loose floor also falls.

So why it is zeroed?
There is one byte in the level which tells which is the last room of the level. (see viewtopic.php?p=12689#p12689)
On level 6, it is 0x19=25. That is one more than it should be.
"Room 25" is actually the modifiers of room 1. (Just like room 26 is the modifiers of room 2: viewtopic.php?p=13246#p13246 )
When the game tries to remap the modifers of "room 25", it finds a wall (0x04) in "room 25". (the event 5 modifier of the drop button)
The modifiers of "room 25" are actually the beginning of the door links!
The drop button with event 5 (modifier 0x04) is second tile, so event 2 will be disabled. Other tiles would disable other events.

The problem disappears if I remove the close button with event 5, or assign a different event to it.
The real solution would be to change that byte (the last room of the level) to 24. In Apoplexy it is sUnknownI[0].

On level 1:
I couldn't reproduce the bug. However, the gate closes *before* the kid falls onto the button, and the button is drawn stuck.
This is probably because of the special event of level 1. The modifier of room 5, tile 3 is zero, because I emptied the whole level. I tried other values but the loose floors always fall. (Though sometimes before the kid touches the button.)
(On level 1, the last room of the level is 24, which is correct. So this is different from the level 6 problem.)
Maybe you could send me the level?
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5745
Joined: April 9th, 2009, 10:58 pm

Re: Modifications to prince.exe (hex editing)

Post by Norbert »

David wrote:The real solution would be to change that byte (the last room of the level) to 24. In Apoplexy it is sUnknownI[0].
Thanks, I'll make sure to fix that.
David wrote:I couldn't reproduce the bug. [...] Maybe you could send me the level?
I no longer have the file, and I just tried to reproduce the problem but now I no longer run into it.
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5745
Joined: April 9th, 2009, 10:58 pm

Re: Modifications to prince.exe (hex editing)

Post by Norbert »

I would like to disable the mirror reflection in the palace environment.
Any ideas? David?
Post Reply