htamas @ popuw.com (Thu Aug 17, 2006 8:17 pm) wrote: This post is in response to the vpalace.dat thread, but I think it's quite off-topic there, so I've started a new one.As poirot already noted in this thread, all versions of prince.exe are packed using MS ExePack 4.06, therefore some of the modifications are only available if you unpack it. You can use the upackexe.exe tool in the lzexe distribution to achieve this.programmer wrote: htamas, I see you have managed to change many aspects of game by editing the executable. Can you write more details for any of those?
There are three versions of prince.exe commonly available: 1.0, 1.3 and 1.4. You can use the packed (original) or unpacked versions. I'm trying to give the modifications as generally as possible, so that you can use them for any version, though it is not always feasible. To make the description shorter, I'll denote the versions as p0, p3, p4 and u0, u3, u4 in the logical way.
For the assembly snippets, I use the u0 version. I'll give a hexadecimal listing to search for, where the bytes to change are marked with bold. A byte written as .. is a wildcard, it matches any byte.
Time available and starting hit points:
Search for: c7 06 .. .. 3c 00 c7 06 .. .. cf 02 c7 06 .. .. 03 00Code: Select all
12e5:002f c7 06 7e 4f 3c 00 mov word ptr [4f7e], 003c 12e5:0035 c7 06 82 4f cf 02 mov word ptr [4f82], 02cf 12e5:003b c7 06 08 46 03 00 mov word ptr [4608], 0003
(offsets are p0:0x04a1f, u0:0x060cf, p3:0x04e9f, u3:0x055df, p4:0x0495b, u4:0x05a8b)
and replace
3c 00 for the number of minutes (+1)
cf 02 for the number of ticks (1 second = 12 ticks)
03 00 for the number of hit points
These values use the format used in the save files. For example, the original settings of 60, 719 and 3 mean that you have 59 minutes 719 ticks (1 tick less than 60 minutes -> that is 60 minutes, since for 0 minutes 0 ticks you have 1 tick) and 3 hit points when the game starts.
Starting level:
Search for: c7 06 .. .. 01 00 b8 .. .. 1e 50 2b c0 50Code: Select all
0e66:0503 c7 06 b8 42 01 00 mov word ptr [42b8], 0001 0e66:0509 b8 5e 29 mov ax, 295e 0e66:050c 1e push ds 0e66:050d 50 push ax 0e66:050e 2b c0 sub ax, ax 0e66:0510 50 push ax
(offsets are p0:0x00703, u0:0x01db3, p3:0x007d7, u3:0x00f17, p4:0x0079b, u4:0x018cb)
and replace 01 00 with the starting level
This is the level you start everytime you press Ctrl+R also. Since there are quite few levels, only the first byte is meaningful.
Maximal number of hit points:
Search for: a1 .. .. 40 3d 0a 00 7e 03 b8 0a 00 a3 .. ..Code: Select all
0e66:11ec a1 f2 5f mov ax, [5ff2] 0e66:11ef 40 inc ax 0e66:11f0 3d 0a 00 cmp ax, 000a 0e66:11f3 7e 03 jle 11f8 0e66:11f5 b8 0a 00 mov ax, 000a 0e66:11f8 a3 f2 5f mov [5ff2], ax
(offsets are p0:0x013ec, u0:0x02a9c, p3:0x015a7, u3:0x01ce7, p4:0x0149e, u4:0x025ce)
and replace both occurences of 0a 00 with the maximal number of hit points that can be achieved
Warning: setting a value larger than 10 (0a 00) will cause the hit points display in the lower left corner of the screen to be overlapped by the remaining time messages, so it is discouraged. However, from the point of view of the game, its value is handled correctly.
Minimal and maximal level where you can save:
Search for: 83 3e .. .. 02 7e .. 83 3e .. .. 0e 7d ..Code: Select all
0e66:05c4 83 3e 9e 0f 02 cmp word ptr [0f9e], 0002 0e66:05c9 7e d0 jle 059b 0e66:05cb 83 3e 9e 0f 0e cmp word ptr [0f9e], 000e 0e66:05d0 7d c9 jnl 059b
(offsets are p0:0x007c4, u0:0x01e74, p3:0x008b0, u3:0x00ff0, p4:0x00874, u4:0x019a4)
and replace
02 with one less than the minimal level where it is allowed to save
0e with one more than the maximal level where it is allowed to save
In the original set, you can save from level 3 to level 13. Note that by changing the assembly code, you can achieve some other logic as well (e.g. you can only save on levels whose number is an odd number) as long as it fits the place.
Dungeon and palace levels:
Search for: 74 00 00 00 00 00 01 01 01 00 00 00 01 01 00 00 01 00Code: Select all
2934:02b2 00 00 00 00 01 01 01 00 2934:02ba 00 00 01 01 00 00 01 00
(offsets are p0:0x1ace8, u0:0x1c840, p3:0x1b9ac, u3:0x1c5c4, p4:0x17d4a, u4:0x18f3a)
Each of the 16 bytes corresponds to a level (0=demo, ..., 12=shadow, 13=jaffar, 14=princess, 15=potions), where 00 means dungeon and 01 means palace. I've prepended two bytes before the search string, since otherwise it can be found two times in the unpacked versions.
Guard base hit points:
Search for: 04 03 03 03 03 04 05 04 04 05 05 05 04 06 00 00Code: Select all
2934:0eda 04 03 03 03 03 04 05 04 2934:0ee2 04 05 05 05 04 06 00 00
(offsets are p0:0x1b8a8, u0:0x1d46a, p3:0x1c6c5, u3:0x1d35c, p4:0x18a97, u4:0x19d06)
For each level, a single byte stores the number of hit points a guard has by default. The level file can increment this for individual guards.
Guard types:
Search for: 00 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 04 00 03 00 ff ff ff ffCode: Select all
2934:03d4 00 00 00 00 00 00 02 00 2934:03dc 00 00 00 00 01 00 00 00 2934:03e4 00 00 00 00 00 00 00 00 2934:03ec 04 00 03 00 ff ff ff ff
(offsets are u0:0x1c964, u3:0x1c702, u4:0x1905e; this is not available in packed versions in this way)
For each level, two bytes are stored. The possible values are:
0000 default guard, using guard.dat
0100 fat guard, using fat.dat
0200 skeleton, using skel.dat
0300 Jaffar, using vizier.dat
0400 shadow, using shadow.dat
ffff no guard, don't load resources
Note that this only affects the resource file that is loaded and therefore the bitmaps that are displayed. For example, if you change level 3 to use the Jaffar sprite, it will remain unkillable. Killing guards using the skeleton or shadow sprite or meeting a guard when no resource is loaded causes the game to crash, since it would need to load a nonexistent resource.
Changing palace levels to use the dungeon wall-drawing algorithm:
This requires multiple modifications:Code: Select all
1828:0993 8b 1e 9e 0f mov bx, [0f9e] 1828:0997 38 a7 b2 02 cmp [bx+02b2], ah 1828:099b 74 07 je 09a4 change to: 1828:099b eb 07 jmp 09a4 1828:26f3 8b 1e 9e 0f mov bx, [0f9e] 1828:26f7 80 bf b2 02 01 cmp byte ptr [bx+02b2], 01 1828:26fc 1b c0 sbb ax, ax 1828:26fe f7 d8 neg ax 1828:2700 89 46 fe mov [bp-02], ax change to: 1828:26fc b8 01 00 mov ax, 0001 1828:26ff 90 nop 1828:0e72 8b 1e 9e 0f mov bx, [0f9e] 1828:0e76 80 bf b2 02 00 cmp byte ptr [bx+02b2], 00 1828:0e7b 74 07 je 0e84 change to: 1828:0e7b eb 07 jmp 0e84
Search for: 8b 1e .. .. 38 a7 .. .. 74 07
(offsets are p0:0x0a7b3, u0:0x0be63, p3:0x0ac5f, u3:0x0b39f, p4:0x0a71b, u4:0x0b84b)
and change 74 07 to eb 07
Search for: 8b 1e .. .. 80 bf .. .. 01 1b c0 f7 d8 89 46 fe
(offsets are p0:0x0c513, u0:0x0dbc3, p3:0x0ca07, u3:0x0d147, p4:0x0c4c3, u4:0x0d5f3)
and change 1b c0 f7 d8 to b8 01 00 90
Search for: 8b 1e .. .. 80 bf .. .. 00 74 07
(offsets are p0:0x0ac92, u0:0x0c342, p3:0x0b13e, u3:0x0b87e, p4:0x0abfa, u4:0x0bd2a)
and change 74 07 to eb 07
This will cause the dungeon WDA to be used for palace levels, though, the tiles and palettes will be taken from vpalace.dat. This also changes the way resources from vpalace.dat are interpreted, so that file must also be changed accordingly. For more details, see the vpalace.dat thread.
That's all that comes to my mind now. Feel free to expand this list.
programmer @ popuw.com (Thu Aug 17, 2006 8:41 pm) wrote: Thanks for the informations, I'm going to edit the prince.exe file now
KingOfPersia @ popuw.com (Thu Aug 17, 2006 9:27 pm) wrote: Looks very interesting!
I will see if I can use this information for my new mod.
How do you discover this kind of things?
I discovered a lot of things about The levels.dat (after a lot of chashes)
and stopped with it when I found a level editor. But Prince.exe seems very more difficult.
I'm hoping you will discover more
programmer @ popuw.com (Thu Aug 17, 2006 9:36 pm) wrote: htamas, I have been watching your video... Have you modified the demo sequence (I mean the 00 level)? If yes, how?
And I think this topic should be marked as important.
[+]And another question - is it possible to remove the intro sequence or force application to quit after passing some level?
htamas @ popuw.com (Thu Aug 17, 2006 10:25 pm) wrote:I was using Turbo Debugger, which, besides regular debugging, can be used for reverse engineering. It shows the disassembly of the program code (like the code snippets shown above) and allows you to set breakpoints or use single-stepping. Assembly language is equivalent to machine code (those hexadecimal number sequences), but it is easier for humans to read. Even if you know 16-bit assembly, reverse engineering can be quite a challenge, and it involves some guesswork. But it is fun as well. Theoretically you see everything the program does, but it is composed from so small instructions that it is hard to follow.KingOfPersia wrote: How do you discover this kind of things?
I discovered a lot of things about The levels.dat (after a lot of chashes)
and stopped with it when I found a level editor. But Prince.exe seems very more difficult.
If you mean the level itself, it isn't modified, only the movements. I've used pr to copy level 0 to level 2 and then played it . After that, I've placed it where the demo would normally come. Btw, didn't you want to post this to the other thread?programmer wrote: htamas, I have been watching your video... Have you modified the demo sequence (I mean the 00 level)?
And I think this topic should be marked as important.
It should be possible. It is already partly implemented, since when you start the game using e.g. "prince megahit 8" or "prince improved 8", the given level is loaded without the title sequence (if you start level 2, level 15 will be loaded). I'll try to find some offsets for these modifications too.programmer wrote: [+]And another question - is it possible to remove the intro sequence or force application to quit after passing some level?
programmer @ popuw.com (Thu Aug 17, 2006 10:44 pm) wrote:Yes, but I were thinking about making a demonstration with, lets say 2 levels, that let players try the game. Starting on selected by me level isn't hard, as you said, the megahit/improved cheat code + batch file can be used, but I was thinkink about self-exiting game when those 2 levels will be passed.It should be possible. It is already partly implemented, since when you start the game using e.g. "prince megahit 8" or "prince improved 8", the given level is loaded without the title sequence (if you start level 2, level 15 will be loaded). I'll try to find some offsets for these modifications too.
[+] and the introduction sequence - I saw that it isn't modified but how to add the prince movement into game? (I succesfully replaced the intro and level2 files by PR but what next?) I never tried to change this, so, can you write exactly how to change it?
htamas @ popuw.com (Sat Aug 19, 2006 12:21 am) wrote:Ok, here are some more for you:programmer wrote: Yes, but I were thinking about making a demonstration with, lets say 2 levels, that let players try the game. Starting on selected by me level isn't hard, as you said, the megahit/improved cheat code + batch file can be used, but I was thinkink about self-exiting game when those 2 levels will be passed.
Skipping the title sequence and starting with a specific level:
This requires multiple modifications:Code: Select all
0e66:01af 74 36 je 01e7 0e66:01b1 c7 46 f8 0e 00 mov word ptr [bp-08], 000e 0e66:01b6 eb 03 jmp 01bb 0e66:01b8 ff 4e f8 dec word ptr [bp-08] e066:01bb 83 7e f8 00 cmp word ptr [bp-08], 0000 0e66:01bf 7c 26 jl 01e7 0e66:01e1 8b 46 f8 mov ax, [bp-08] 0e66:01e4 a3 b8 42 mov [42b8], ax
Search for: 74 36 c7 46 f8 0e 00 eb 03 ff 4e f8 83 7e f8 00 7c 26
(offsets are p0:0x003af, u0:0x01a5f, p3:0x00438, u3:0x00b78, p4:0x00422, u4:0x01552)
and replace 36 with 30 and 26 with 20
Search for: 8b 46 f8 a3 .. ..
(offsets are p0:0x003e1, u0:0x01a91, p3:0x0046a, u3:0x00baa, p4:0x00454, u4:0x01584)
and replace 8b 46 f8 with b8 xx 00 where xx is the level you would like to load instead of the title sequence
When starting prince, this level will load instantly. Note that pressing Ctrl+R will return to the level that was specified above, in the Starting level hack. If it is not level 1, you'd better set that one as well.
Exiting automatically after a given level:
This is quite a complicated hack, since we needed to write some extra code that handles the quit condition. Therefore, we had to hijack a function call and overwrite another procedure. I've chosen the one where you finish and meet the princess, since this won't play anyway when you quit after finishing a level < 14.Code: Select all
12e5:055e 9a 14 72 df 1a call 1adf:7214 change to: 12e5:055e 9a d7 09 b5 10 call 10b5:09d7 10b5:09d7 55 push bp 10b5:09d8 8b ec mov bp, sp 10b5:09da 83 ec 44 sub sp, 0044 10b5:09dd 56 push si 10b5:09de c7 46 fa 00 00 mov word ptr [bp-06], 0000 10b5:09e3 c7 46 fc 0f 00 mov word ptr [bp-04], 000f 10b5:09e8 b8 01 00 mov ax, 0001 10b5:09eb 50 push ax change to: 10b5:09d7 83 3e 9e 0f xx cmp word ptr [0f9e], 00xx 10b5:09dc 75 08 jne 09e6 10b5:09de 2b c0 sub ax, ax 10b5:09e0 50 push ax 10b5:09e1 9a 7a 0c df 1a call 1adf:0c7a 10b5:09e6 9a 14 72 df 1a call 1adf:7214 10b5:09eb cb retf
Such a modification requires function pointers to be written in some places in the code, but they are different for each version. I've chosen to only modify the unpacked 1.0 version, since probably one version is enough for you. (Therefore, this hack won't work for other versions.)
At offset 0x4777, replace
55 8b ec 83 ec 44 56 c7 46 fa 00 00 c7 46 fc 0f 00 b8 01 00 50
with
83 3e 9e 0f xx 75 08 2b c0 50 9a 7a 0c df 1a 9a 14 72 df 1a cb
where xx is the level after which you would like to quit.
Also, at offset 0x65ff, replace 14 72 79 0c with d7 09 4f 02.
Reading your question, I assume that you would like to minimize the impact of the original story on your levels. You can also quit when time expires and you can disable the cutscenes.
Quitting when time expires: at offset 0x2261, replace 94 0c 4f 02 with 7a 0c df 1a
(note: you won't see the scene with the hourglass in the princess' room when the time expires)
The table of cutscenes is starting at offset 0x1d530. For each level, 4 bytes is used. Note that these are offset:segment values, so you might not just write anything there, but you may swap them or disable them by writing 00 00 00 00. (Note that for levels starting from 3, the princess is animated, while before that, Jaffar is animated, if applicable. It's quite strange, but you'll see if you try it. So you should avoid swapping one before 3 to one after 2.)
I don't know, but probably the beginning is using a hardcoded list of keypresses or actions (function calls), and at the end, the fight is using the same ai for the kid and for the guard (that is the only randomized part of the demo sequence).programmer wrote: [+] and the introduction sequence - I saw that it isn't modified but how to add the prince movement into game? (I succesfully replaced the intro and level2 files by PR but what next?) I never tried to change this, so, can you write exactly how to change it?
ecco @ popuw.com (Sun Aug 20, 2006 6:07 pm) wrote: Is there anyway in changing the default background colour from black to something else in all that code?
This would mainly so one could choose a bg colour to match the overall colour scheme. In my vpalace for example which is quite a bright environment in relation to the dungeons I made, a thick black line running over the floor tiles kind of stands out. I've been fiddling with the palette colour this morning too, but no good.
Or even being able to make a repeating pattern for the background would be even more excellent. More or less like the snes version.
I've searched and found a few references to a brown or yellow background in The Great Escape, but I've just played it and nothings different. I've also read that a future editor for PoP2 might be able to edit backgrounds or something somewhere.
Thanks
poirot @ popuw.com (Sun Aug 20, 2006 6:26 pm) wrote: that's really good stuff, I'd like to code an editor or something for that
Last edited by poirot on Mon Aug 21, 2006 1:02 am; edited 1 time in total
poirot @ popuw.com (Mon Aug 21, 2006 12:56 am) wrote: oh, btw, don't you want to write a technical document (like the format specifications of .dat files) with all this stuff including the code you've posted in the other threads? I could give you access to the cvs if you want.
htamas @ popuw.com (Mon Aug 21, 2006 7:26 am) wrote:Yes, there is, but it changes the background colour everywhere. That is, on the loading screen, in the cutscenes, and also in the bottom row where your hit points are. Therefore, e.g. the same colour is used for dungeon and palace levels.ecco wrote: Is there anyway in changing the default background colour from black to something else in all that code?
Note: As you probably know, the game uses a 256 colour vga (mcga) mode, but bitmaps are using 16 colour palettes. These are loaded in the main palette at offsets divisible by 16. I have identified the following palettes:
00: This contains the background colour (index 0) and the colour used when printing texts: loading, level %d, %d minutes remaining, press any key to continue, etc. (index 15). Palette values are hardcoded.
20: Only two nonzero colours are present (indexes 6 and 15) and they are used for the sword when it is held by someone, i.e. not on the floor. Loaded from prince.dat/prince/sword/fighting/sword.pal.
30: Used for the fire of torches and potion vases, maybe some other objects as well. Loaded from prince.dat/prince/main.pal.
50: This is the generic dungeon/palace palette, including everything except the walls. Loaded from vdungeon.dat/vdungeon/palette/dungeon.pal or vpalace.dat/vpalace/palettes/palace.pal.
60: This is the dungeon/palace wall palette. Loaded from vdungeon.dat/vdungeon/binary/other.pal (shouldn't it be vdungeon.dat/vdungeon/palettes/wall.pal?) or vpalace.dat/vpalace/palettes/wall.pal.
70: Used for the prince, his hit points and the mouse. Loaded from kid.dat/kid/kid.pal.
80: This palette is used for the guards. It is reloaded everytime you go to another room and changed to the palette for that guard. As there is at most one guard per room, this is not a problem. Loaded from different files depending on the guard type and colour.
90: Used in the throne room. In the introduction, it is used for the princess (to be checked).
a0: Used in the throne room. In the introduction, it is used for Jaffar. In the cutscene before level 4, it's used for the princess (to be checked).
b0: Used in the intro sequences. Probably corresponds to title.dat/title/main titles/text background.pal.
c0: Used in the intro sequences. Probably corresponds to title.dat/title/main titles/titles.pal.
d0: Palette of the throne room background. Loaded from pv.dat/pv/objects/room and clock.pal.
e0: Palette of the bed in the throne room. Loaded from pv.dat/pv/objects/room bed.pal.
Here, you need to modify the hardcoded palette.
Search for: 00 00 00 00 00 2a 00 2a 00 00 2a 2a 2a 00 00 2a 00 2a 2a 15 00 2a 2a 2a 15 15 15 15 15 3f 15 3f 15 15 3f 3f 3f 15 15 3f 15 3f 3f 3f 15 3f 3f 3f
(offsets are p0:0x1d141, u0:0x1f136, p3:0x1df5e, u3:0x1f02a, p4:0x1a335, u4:0x1b9de)
Each palette entry corresponds to a 3-byte rgb triplet. Each byte contains a value from 00 to 3f (0 to 63), that is, a valid vga palette entry. If you would like to change the background colour, modify the first three bytes. Changing the text colour requires editing of the three last.
You can't modify the background colour of dungeon and palace levels separately, or at least, not using this way. It might be possible to change the palette index used when clearing the screen to an 5x or 6x one, so that it is loaded from the dungeon or palace palette, but I don't see an easy way of doing that now.ecco wrote: In my vpalace for example which is quite a bright environment in relation to the dungeons I made, a thick black line running over the floor tiles kind of stands out.
Well, it would be nice, but injecting a not-yet-existing procedure into binary code is definitely not an easy task. And it would require hijacking another resource, too. Using modifiers on background tiles and editing their bitmaps (vpalace.dat/vpalace/background/bricksxx.bmp) might help, but we'll need to change their size as they don't fit exactly. I don't know yet where the offset and size information for these sprites is stored, so it would require some extra research.ecco wrote: Or even being able to make a repeating pattern for the background would be even more excellent. More or less like the snes version.
Probably PV4. But PoP2, in this aspect, is entirely different. There, backgrounds are used in the original game as well, so the problem is reduced to that of a resource replacement (and of course, reverse-engineering their format first ).ecco wrote: I've also read that a future editor for PoP2 might be able to edit backgrounds or something somewhere.
I think it's more like a collection of random hacks than any sort of specification. Anyway, feel free to copy it and post it anywhere. If you have some idea about what format would be better suited for it, I can change it to that format, but at the moment, I think it's just right this way .poirot wrote: oh, btw, don't you want to write a technical document (like the format specifications of .dat files) with all this stuff including the code you've posted in the other threads? I could give you access to the cvs if you want.
Yes, it would be cool to edit the settings in an xml or text file and run a program, which commits them to prince.exe. Since the list of offsets in my posts are already generated by a script, it would be no problem to convert it to the program's import format. The most compatible (but comparably slow) way would be to search for the given expression, including wildcards, check that it is the only occurence, and then replace certain bytes from the found location with ones generated from the edited values. Using an offset table is easier, but then it has to be created for each version and we'll have to identify them.poirot wrote: that's really good stuff, I'd like to code an editor or something for that
ecco @ popuw.com (Mon Aug 21, 2006 1:41 pm) wrote:htamas wrote:
Well, it would be nice, but injecting a not-yet-existing procedure into binary code is definitely not an easy task. And it would require hijacking another resource, too. Using modifiers on background tiles and editing their bitmaps (vpalace.dat/vpalace/background/bricksxx.bmp) might help, but we'll need to change their size as they don't fit exactly. I don't know yet where the offset and size information for these sprites is stored, so it would require some extra research.ecco wrote: Or even being able to make a repeating pattern for the background would be even more excellent. More or less like the snes version.
Actually this is something I already researched way back when I developed my high detail vdungeon02 graphics. I had replied here but realised I was off topic, so I've turned that into a new topic:
Making Custom Graphics
Thanks again for the info htamas. I'll try sometime to understand all that stuff and change some colours.
..
poirot @ popuw.com (Mon Aug 21, 2006 8:36 pm) wrote: great!
poirot @ popuw.com (Mon Aug 21, 2006 8:52 pm) wrote: I was thinking about the dungeon wall generating algorithm, I've coded it for FP, and understood how it works, but there is a seed that the game uses and I think it is saved inside the game. The seeds I extracted from the game (just looking on the images and not the code) are in http://cvs.lug.fi.uba.ar/cgi-bin/cvsweb ... freeprince
The algorithm is in the format specifications http://cvs.lug.fi.uba.ar/cgi-bin/cvsweb ... freeprince
I was thinking if it is possible to find the offsets of this seeds. There are four different types of 63 different wall blocks. Each block has modifiers like the position of the middle separator, etc. The four types are called SWS, WWS, SWW, WWW (where the middle W is the wall and the S is empty space).
I'd like to know if it is possible to find those offsets and see how and where they are saved in the game. They could be very interesting to edit
I have also found offsets of all resources in the .exe, all animations, etc. So editing them could add new frames to animations, etc. I don't remember where they were, but I do remember it was near the end of the file. It's easy to find them because they where encoded as unsigned short int and they were all sequenced numbers. That could also be interesting to edit
jora @ popuw.com (Mon Aug 21, 2006 9:37 pm) wrote: Hi
could someone help me changing the starting time?, I am new to hex editing
htamas @ popuw.com (Tue Aug 22, 2006 2:50 am) wrote:I don't know where to start from, but perhaps it'll help.jora wrote: Hi
could someone help me changing the starting time?, I am new to hex editing
All files, regardless of their file type, are stored as a sequence of bytes (integers from 0 to 255). They can be further decomposed to bits (0 or 1), but they are quite rarely used separately. While editors you generally use deal with these files according to their type (text, image, archive, etc.), this approach is limited to files using a specific set of formats, and for each type, you'll need a separate application. Hex editors, on the other hand, display and let you modify the data in its raw form. For regular files, it's kind of inconvenient compared to, say, an image manipulator, but where you have no other choice, hex editors come in handy. Editing executables for which you don't have the source or files using an unknown format typically fall in this category.
Hex editors typically divide your screen to three vertical fields. The first displays the offset, that is, how many bytes far are you from the beginning of the file. The second shows the bytes in base 16. For example, the character 'x', which is has an ascii code of 120 (decimal) is displayed as 78. The third field shows the character itself, in this case, 'x'.
You can find the offset of a certain byte by adding the number at the beginning of the line (hexadecimal) to the one at the top of the column. Most, if not all, hex editors allow you to jump to a specific offset. When you need to apply the patch, you have to go to the given offset and modify the byte there to the one you see in the patch description.
If you don't have a hex editor yet, you can download e.g. hxd, frhed, hexplorer or xvi32. There are really lots of hex editors, the ones I provided links for are free ones.
In this case, you would like to modify the time to complete your mod. I'll show you the easy way - using the offsets I've given for the specific versions. You'll need to know the exact version you are using. For example, if you downloaded prince.zip from http://popuw.com/download.html, you are using the p0 version. Let's assume this in the examples. Make a backup of your prince.exe so that you can revert to it if you make something wrong.
Start your hex editor and open prince.exe. Scroll to the "Time available and starting hit points" section of my post. You see that "offsets are p0:0x04a1f, u0:0x060cf, p3:0x04e9f, u3:0x055df, p4:0x0495b, u4:0x05a8b". Since you are using the p0 version, the offset is 0x04a1f. Here, "0x" simply means hexadecimal. It depends on which hex editor you use that you'll need to write the "0x". Therefore, you'll either have to write "0x04a1f" or simply "4a1f" in the go to dialog.
The cursor should jump to a cell containing a byte "c7". If you continue to read from this cell to the right, continuing in the next line when you reach the end of the central field, you should see "c7 06 .. .. 3c 00 c7 06 .. .. cf 02 c7 06 .. .. 03 00" where the ".." means an arbitrary byte. If you see something different, then you are either using a wrong version or have missed something. If you see that, take a closer look to the bytes I've marked with bold. These are the ones to modify.
You would like to modify the starting time to 180 minutes. You need to subtract one tick, as noted in the instruction, so that you get 179 minutes 719 ticks. In the first two bytes, instead of 3c 00, you'll have to write the number of minutes +1. That is, 180. But you have to write it in hexadecimal. You can use the windows calculator (start -> run -> "calc") to convert decimal values to hexadecimal. You get b4. But you have two bytes for it, so you'll have to write b4 00. (This is because the so-called little-endian system that the x86 cpu uses writes the least significant byte at the beginning). Now do that conversion again for the number of ticks. 719 ticks convert to 2cf. Here, 02 is the most significant byte and cf is the least significant byte. Therefore, you'll have cf 02.
Now comes the modification itself. Go to the "3c 00" you have just found and overwrite it with "b4 00". Most hex editors will automatically overwrite it, but if yours inserts these bytes instead then you'll have to delete the original "3c 00". Now go to the "cf 02". In this case, you don't have to modify it, since the new value we've just calculated is the same. But if we'd have to, this would be the way to do it.
Save the file and try to launch it. It should start with "180 minutes left".
jora @ popuw.com (Tue Aug 22, 2006 1:36 pm) wrote: Thanks 8-)
david @ popuw.com (Tue Aug 22, 2006 4:54 pm) wrote: Modifying the number of hit points of the Prince on demo level:Search for: C7 46 FE 04 00 8B 46 FECode: Select all
00004C25: C7 46 FE 04 00 mov [bp-02],0004 change to: 00004C25: C7 46 FE xx 00 mov [bp-02],00xx 00004C2A: 8B 46 FE mov ax,[bp-02] 00004C2D: A3 98 4C mov [+4C98],ax 00004C30: A3 F2 5F mov [+5FF2],ax
(offsets are p0:0x4C25, p3:0x50AD, p4:0x4B69, u0:0x62D5, u3:0x57ED, u4:0x5C99)
and replace 04 with the number of hit points you want.
htamas @ popuw.com (Tue Aug 22, 2006 6:48 pm) wrote:I'm still looking for these, but meanwhile, I've found the order in which the sprites are placed. It's quite interesting, different from what I thought.poirot wrote: I was thinking about the dungeon wall generating algorithm, I've coded it for FP, and understood how it works, but there is a seed that the game uses and I think it is saved inside the game. The seeds I extracted from the game (just looking on the images and not the code) are in http://cvs.lug.fi.uba.ar/cgi-bin/cvsweb ... freeprince
The algorithm is in the format specifications http://cvs.lug.fi.uba.ar/cgi-bin/cvsweb ... freeprince
poirot @ popuw.com (Wed Aug 23, 2006 8:11 am) wrote: great, it's the same order I use in freeprince except for the wall separators, I don't draw them twice.
I've coded the program that reads the .xml and edits the .exe. Take a look at http://www.princed.com.ar/customexe.jsp I'm sure all you people will love it!
btw, There are only three hacks for the moment, blackchar will add more, it's just copy/paste from the information in this thread
oh, forgot to say: works only for p0, but it has support for all the files, I only need the original.exe's (it would be great if anybody can send them to me)
oh, and about the source, I'll publish it, but for the moment feel free to ask for it.
jalal @ popuw.com (Wed Aug 23, 2006 8:21 am) wrote: Nice! And why don't you make it a tool...
Ok I will try to send it or publish it a.s.a.p.poirot wrote: oh, forgot to say: works only for p0, but it has support for all the files, I only need the original.exe's (it would be great if anybody can send them to me)
Btw, I have a question, what's the difference between packed and unpacked version of prince.exe?
htamas: Is there a way not to reduce the "time left" to 15 minutes and to block in level 4 if we are playing normally (Shift-L) with no cheats...?
poirot @ popuw.com (Wed Aug 23, 2006 9:18 am) wrote: yes, I will make it a tool, but coding php is much faster, I've made it in two hours and I think it will be very easy to use for people who don't want to download and install complicated programs. There is much still comming
htamas @ popuw.com (Wed Aug 23, 2006 5:52 pm) wrote:I think they are drawn twice because they have to be drawn for the top 3 pixels of the screen as well if they are the base tiles of walls that are on the screen one above. And they don't draw the main wall tiles for them, so it's probably the easiest if they are drawn with the base tiles, not with the main tiles. However, they'll need to repeat the ones overlapped by the main tiles again. It's true that it is unnecessary to draw them twice if we are using some different logic.poirot wrote: great, it's the same order I use in freeprince Wink except for the wall separators, I don't draw them twice.
Yes, definitely. There seems to be a bug with the seconds in the time, the division/multiplication seems not to work.poirot wrote: I've coded the program that reads the .xml and edits the .exe. Take a look at http://www.princed.com.ar/customexe.jsp I'm sure all you people will love it!
There probably is. I'll look after it, but I'll also have to track down some of the previous questions.jalal wrote: htamas: Is there a way not to reduce the "time left" to 15 minutes and to block in level 4 if we are playing normally (Shift-L) with no cheats...?
Packed ones are the original, distributed versions. They are packed (compressed/encrypted) with ms exepack in such a way that when the program starts, it decompresses/decrypts some parts of it in memory. Unpacked versions can be generated from the packed versions using an unpacker, and there's no difference between the packed and unpacked versions from the POV of an user. But for hex editors, there is. Most of the code of prince.exe is unaffected by packing (some packers completely obfuscate code, but seemingly this one doesn't), so most of the hacks work with packed versions too.jalal wrote: Btw, I have a question, what's the difference between packed and unpacked version of prince.exe?
poirot @ popuw.com (Wed Aug 23, 2006 6:17 pm) wrote: done, I've uploaded all the versions!
My p0 version differed :s but it seems to work. I have to test it.
poirot @ popuw.com (Wed Aug 23, 2006 6:21 pm) wrote:Indeed, it is in my todo list (to code a little form processor to transform the hex codes into a human readable input)htamas wrote:
There seems to be a bug with the seconds in the time, the division/multiplication seems not to work.
I've also added a field for help
jalal @ popuw.com (Wed Aug 23, 2006 6:29 pm) wrote:ah, ok. thanks for clearing this uphtamas wrote:Packed ones are the original, distributed versions. They are packed (compressed/encrypted) with ms exepack in such a way that when the program starts, it decompresses/decrypts some parts of it in memory. Unpacked versions can be generated from the packed versions using an unpacker, and there's no difference between the packed and unpacked versions from the POV of an user. But for hex editors, there is. Most of the code of prince.exe is unaffected by packing (some packers completely obfuscate code, but seemingly this one doesn't), so most of the hacks work with packed versions too.jalal wrote: Btw, I have a question, what's the difference between packed and unpacked version of prince.exe?
poirot @ popuw.com (Thu Aug 24, 2006 1:04 am) wrote: htamas, do you have a clue on where to look for the max level limitation? Adding levels to level.dat is very easy with PR, but it needs a lot of work in the .exe: move the dunveon/palace type array to a bigger address space at the end of the file; move the resource loading array, etc
poirot @ popuw.com (Thu Aug 24, 2006 1:17 am) wrote: For those who are interested all sources are GPL: http://www.princed.com.ar/gethack/ (it's not very much, coding was very fast, but it works)
I've added more hacks to the xml and support of combo boxes.
BlackChar @ popuw.com (Thu Aug 24, 2006 3:38 pm) wrote: Aww, poirot how did you add all those data so fast? I barely managed to add those in first message and even then it's full of typo errors. I guess XML won't be my friend for much longer .
And by the way, the generated files now don't work. Not even with default settings. You probably know that, but anyway... DosBox crashes after entering PRINCE command with this:Code: Select all
Exit to error: CPU:GRP5:Illegal call 7
jora @ popuw.com (Thu Aug 24, 2006 7:40 pm) wrote: Is it possible to add levels to the game
programmer @ popuw.com (Thu Aug 24, 2006 8:00 pm) wrote: Yes, it is, but it's very difficult and requires changing resources format. As poirot said, this won't be difficult, but adding new level support into .exe file may be a hard work.
poirot @ popuw.com (Thu Aug 24, 2006 9:20 pm) wrote:I just did copy/paste from the thread and used vim.BlackChar wrote: Aww, poirot how did you add all those data so fast? I barely managed to add those in first message and even then it's full of typo errors. I guess XML won't be my friend for much longer .
And by the way, the generated files now don't work. Not even with default settings. You probably know that, but anyway... DosBox crashes after entering PRINCE command with this:Code: Select all
Exit to error: CPU:GRP5:Illegal call 7
Yes, the packed versions won't work because some settings aren't supported un packed exes, I'll code a javascript that disables the unsupported fields when you choose the base exe.
programmer @ popuw.com (Thu Aug 24, 2006 9:34 pm) wrote: poirot - you can add options that allow to change the cheat activation code (megahit/improved) and the text that is displayed when exiting the game. I know that it's easy to change, but adding this may be useful
jalal @ popuw.com (Thu Aug 24, 2006 9:40 pm) wrote:Or better, an option that translates the game to other languages. Like level, minutes left, game version, etc. So we avoid 'killing ourselves' by the use of a hex editor!programmer wrote: poirot - you can add options that allow to change the cheat activation code (megahit/improved) and the text that is displayed when exiting the game. I know that it's easy to change, but adding this may be useful
programmer @ popuw.com (Thu Aug 24, 2006 9:42 pm) wrote: Game version change may be useful too, but changing all the text in game? Why not, but... when using a hex editor, it is a bit more interesting, I think
jalal @ popuw.com (Thu Aug 24, 2006 9:43 pm) wrote:Yes you're right, like taking spaces from other words and so on ...programmer wrote: Game version change may be useful too, but changing all the text in game? Why not, but... when using a hex editor, it is a bit more interesting, I think
poirot @ popuw.com (Thu Aug 24, 2006 11:11 pm) wrote: the next improvement will be string support, but for the moment I'm working in the xml parsing to support multiple editions per hack.
Editing a string will have a problem: you can't add text that is bigger than the text in the original game, if you want a bigger text you have to rewrite the pointer and add the text at the end of the file. It will take some time to find the pointers to the text. But for the moment I think I can add an option for string editing limiting the strings to the original size.
htamas @ popuw.com (Fri Aug 25, 2006 7:47 pm) wrote: poirot: The levels where saving is allowed are shifted by one (due to difference between < and <= in the code). In princehack.xml, you'll need to change
toCode: Select all
<read type="unsigned char" name="minimal level" default="2" minval="0" maxval="65535"/> <check codes="7e .. 83 3e .. .."/> <read type="unsigned char" name="maximal level" default="14" minval="0" maxval="65535"/>
and add the subtract option in parsecommands.php.Code: Select all
<read type="unsigned char" name="minimal level" default="3" minval="1" maxval="65535" readoperation="add(1);" writeoperation="subtract(1);"/> <check codes="7e .. 83 3e .. .."/> <read type="unsigned char" name="maximal level" default="13" minval="0" maxval="65534" readoperation="subtract(1);" writeoperation="add(1);"/>
poirot @ popuw.com (Fri Aug 25, 2006 9:16 pm) wrote: it's fixed
btw, can you rin the offset script to these values:
(note the 00 to find only null terminated strings)Code: Select all
strings prince.exe|while read a; do echo "looking for $a";echo -n "check ($a) ";echo $a|od -t x1|head -n 1|awk '{for (i=2;i<NF;i++) printf("%s ",$i);}';echo '00';done
(if you can't there's no problem, I'll run it as soon as I get home )
I'd like to add all of them to the xml (at least to be replaced with smallest or same-sized strings).
htamas @ popuw.com (Sat Aug 26, 2006 12:01 am) wrote:Well, I can, but `strings prince.exe | wc -l` is 588 for me, that sounds bit too much (not for running the script but for the set of possible changes). I think there isn't more than about 50 that makes sense.poirot wrote: btw, can you rin the offset script to these values:
Code: Select all
strings prince.exe|while read a; do echo "looking for $a";echo -n "check ($a) ";echo $a|od -t x1|head -n 1|awk '{for (i=2;i<NF;i++) printf("%s ",$i);}';echo '00';done
You can change:
- the loading message
- messages in the status bar (%d minutes remaining, game saved, etc.)
- message dialogs (drink potion matching..., insert disk, etc.)
- error messages (e.g. stack overflow)
The "hope you enjoyed it" message in cracked versions is originally a two-part error message. But for some reason, that error condition triggers on every exit. But it can lead to strange results as well, I've once received "Hope you enjoye- integer divide by 0".
You can also change the filenames the game uses, but you'll have to be cautious, since some of them occur more than once and have to refer to the same file; others occur both as a whole and put together from parts, e.g. "%s%s.DAT", "V", "PALACE".
It would be better to decide on the safe strings and run the offset script on them.
poirot @ popuw.com (Sat Aug 26, 2006 1:38 am) wrote: ok, yes, for the repeated strings, I was planning to use the duplicated attribute in the read option. I'll make a list of interesting offsets and post them into a file.
poirot @ popuw.com (Sat Aug 26, 2006 2:03 am) wrote: I've made this list: http://www.princed.com.ar/gethack/strings
For the problems with duplicated records that differs in the char case, I'll add two operations (uppercase and lowercase) in the xml to work in conjunction with the duplicated field. I still don't know how to handle in the xml advanced functions like string concatenations, etc.
poirot @ popuw.com (Tue Aug 29, 2006 5:54 am) wrote: for all who are interested, I've uploaded the latest version of the custom exe generator to http://www.princed.com.ar/cuspop.jsp
It has a script that makes the verification of the fields that are allowed to be modified in each version.
I will add the latest hacks asap
PS: more hacks are welcome
poirot @ popuw.com (Tue Aug 29, 2006 7:03 am) wrote:What version are those offsets for? do you have the offsets for the other versions (I'm interested especially in the cutscenes, because it is very difficult to find an hex string because it will differ on each version.htamas wrote: At offset 0x4777, replace
55 8b ec 83 ec 44 56 c7 46 fa 00 00 c7 46 fc 0f 00 b8 01 00 50
with
83 3e 9e 0f xx 75 08 2b c0 50 9a 7a 0c df 1a 9a 14 72 df 1a cb
where xx is the level after which you would like to quit.
Also, at offset 0x65ff, replace 14 72 79 0c with d7 09 4f 02.
Reading your question, I assume that you would like to minimize the impact of the original story on your levels. You can also quit when time expires and you can disable the cutscenes.
Quitting when time expires: at offset 0x2261, replace 94 0c 4f 02 with 7a 0c df 1a
(note: you won't see the scene with the hourglass in the princess' room when the time expires)
The table of cutscenes is starting at offset 0x1d530. For each level, 4 bytes is used. Note that these are offset:segment values, so you might not just write anything there, but you may swap them or disable them by writing 00 00 00 00. (Note that for levels starting from 3, the princess is animated, while before that, Jaffar is animated, if applicable. It's quite strange, but you'll see if you try it. So you should avoid swapping one before 3 to one after 2.)
david @ popuw.com (Tue Aug 29, 2006 9:05 pm) wrote: How to change tile incompatibilities
Offsets: p0:0x1AC3F, u0:0x1C782, p3:0x1B8F3, u3:0x1C4F6, p4:0x17C95, u4:0x18E70
You'll find a table like this:
level
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | tile
00 00 00 00 01 01 01 00 00 00 01 00 00 00 01 00 | lattice (0x1A-0x1D)
00 01 00 01 00 00 00 01 01 00 00 00 01 00 00 00 | skeleton (0x15)
00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 | mirror (0x1D)
00 00 00 00 01 01 01 00 00 00 01 01 00 00 01 00 | tapestry patterns (0x07, 0x0C)
01 00 01 00 00 01 00 00 00 01 01 00 01 01 00 00 | big pillar (0x08-0x09)
01 00 00 01 01 01 01 01 01 01 01 01 00 00 00 00 | chomper (0x12)
01 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 | spike (0x02)
00 00 00 00 00 00 01 00 00 00 00 00 00 00 01 00 | big window (0x17-0x18)
If a byte is 01, the tile can appear on the level, if 00 then it can't.
Note: in compressed versions, some parts of this table are compressed, so it's difficult to edit.