Lovers of this wonderful game is dedicated to ...

... if there are any. However, I am sure that not everything is so bad and Crysis has not swallowed the brain of mankind entirely and completely.
So, the aforementioned lovers of the old games and in particular one great game of 92 years can remember that the system of saving in the game is made in a somewhat platformer spirit: the levels are scattered (sometimes in rather unexpected and hard-to-reach places) codes that in times of MS-DOS recorded on paper and stored as a treasure. The code entered in the main menu allows you to start the appropriate level from the starting position.
Soshite , in our time, appeared, in some way, a problem for those who would like to play Prehistorik 2. Namely - the need to emulate the game in Dosbox: not everyone has the opportunity to find at a dump or, much less often, pull out mezzanine carefully kept there 486th.
The fact is that when generating codes, the game uses BIOS environment variables. I didn’t understand how it is emulated in Dosbox, I know for sure that with each new emulator launch the codes in the game are different. Accordingly, the piece of paper with the codes becomes useless, and the possibility of a pleasant and non-stressing passing of the game is reduced almost to nothing: completely the game can be completed only in one sitting. Perhaps this is solved by setting Dosbox in detail. But ... this is so trivial, so trivial, that it scares even more than a little digging into the executable file of the game.
Formulation of the problem

Implement a small hack, as a result of which an oldheimer
like me could, instead of the code, enter just the number of the desired level.
Go directly to the results.')
Decision

Most of the time I took away unpacking the game file. The intro of the team that once cracked the copy protection was added to the originally packed game code, and then it was all packed with another algorithm. For help in unpacking, I turned to the article of Mr. Grechnikov:
habrahabr.ru/post/187072 , in which I was interested in the section under the heading "Unpacking", and specifically the following paragraph:
That is, the rest of the loc_19960 procedure is not called if the / ni parameter is passed on the command line. We try, we see that with this parameter the game skips the reminder of the gallant team Hybrid and immediately goes to the actual game. We conclude that the entire seg002 is a screen saver unnecessary for the game, hung on the worker exe's. Rewrite cs: ip in the header with 0000: 0003, ss: sp at 1681: 0080, cut the last 5E90h bytes, adjusting the size and additional memory fields in the header accordingly.
(It was not interesting further, because a ready-made solution is not what I wanted.)After I followed this advice, I found an egg in a duck, previously extracted from a hare ... or how did it usually happen in ancient Russian fairy tales? It is easier to compare it with the doll:


After unpacking the diet program has grown to 90 Kb and nothing has prevented the launch of dirty paws into it. What I did was to open Hiew and immediately find the line of interest to me:

I’ll clarify for those who gain experience (although it’s always worth learning) that searching for a string in Hiew is right after launching F4 - Hex, F7 - ASCII -> “Line of interest to us”.
The address of the line is
15401 . Now I need to find out where the program is accessing this line. Naturally, such treatment with a high degree of probability will be close to the part that I set out to break.
How can you find out? Ways, in fact, many. You can open the file in Ida Pro and examine cross-references. True, first setting up Ida so that she was friends with the type of strings used. But since Id I could not make friends with Dosbox at such a level that it was possible to debug 16-bit files calmly and without annoying factors (Dosbox constantly forgot that it was a debugger and tried to live its life, despite the patch and plug-in) then I decided not to use such heavy artillery at all, where necessary, most likely, just to fix a few bytes.
Therefore, we proceed easier. To find out where the offset to this line is used in the program, you must first find out the offset itself. For this you need to know the database of the data segment. Hiew is more than simple. Click F8 and look at the file header.

So, first open the calculator, switch to the hexadecimal system and enter the Paragraphs in header: 86 value into it, then multiply by 10. Copy this value to the buffer and return to Hiew, where the header window is still not closed. Without exiting, press F5 to go to the entry point. And here we will go into decode mode (F4 - decode). Before us is such a listing:
listing 1.
00000468: FA cli 00000469: FC cld 0000046A: BAFFFF mov dx,0FFFF ;" " 0000046D: BE8000 mov si,00080 ;" " 00000470: AC lodsb 00000471: 98 cbw 00000472: 8BC8 mov cx,ax 00000474: E35E jcxz 0000004D4 ---↓ (1) 00000476: AC lodsb 00000477: 3C2F cmp al,02F ;"/" 00000479: 7404 je 00000047F ---↓ (2) 0000047B: E2F9 loop 000000476 ---↑ (3) 0000047D: EB55 jmps 0000004D4 ---↓ (4) 0000047F: AC lodsb 00000480: 24DF and al,0DF ;"▀" 00000482: 3C46 cmp al,046 ;"F" 00000484: 7506 jne 00000048C ---↓ (5) 00000486: 2E83260300FE and w,cs:[0003],0FFFE ;"■" 0000048C: 3C4D cmp al,04D ;"M"
All this is of no interest to us. We are interested in assigning a value to the ds register. Even without resorting to searching, we scroll the screen quite a bit down and find what we are looking for:
listing 2.
000004D4: B8030A mov ax,00A03 ;"◙" 000004D7: 8ED8 mov ds,ax
We take out 00A03 and stuff it into the calculator, where we also multiply by 10 and add it to the value stored earlier in the buffer. We
get A290 . And now let's subtract A290 from 15401:
171 . This is the offset of the string that will be used inside the program. Now we go to the hex-mapping (F4 - Hex) and press F7, where we enter 71 B1 in the line named by the bashurman word “Neh” (bytes go in the reverse order, remember?). We leave on the following listing:
listing 3.
00009E23: E85801 call 000009F7E ---↓ (1) 00009E26: C606A7B103 mov b,[0B1A7],003 ;"" 00009E2B: BB71B1 mov bx,0B171 ;"▒q" 00009E2E: C706A2B1F20A mov w,[0B1A2],00AF2 ;"◙Є" 00009E34: E8EDFE call 000009D24 ---↑ (2) 00009E37: C606A7B104 mov b,[0B1A7],004 ;"" 00009E3C: BB6CB1 mov bx,0B16C ;"▒l" 00009E3F: C706A2B1C912 mov w,[0B1A2],012C9 ;"╔" 00009E45: E8DCFE call 000009D24 ---↑ (3) 00009E48: 803EA6B101 cmp b,[0B1A6],001 ;"" 00009E4D: 7503 jne 000009E52 ---↓ (4) 00009E4F: E90001 jmp 000009F52 ---↓ (5) 00009E52: 803EA6B102 cmp b,[0B1A6],002 ;"☻" 00009E57: 7503 jne 000009E5C ---↓ (6) 00009E59: E90601 jmp 000009F62 ---↓ (7) 00009E5C: 8A1E7028 mov bl,[2870] 00009E60: F6C380 test bl,-080 ;"" 00009E63: 7403 je 000009E68 ---↓ (8) 00009E65: E91501 jmp 000009F7D ---↓ (9) 00009E68: A02928 mov al,[2829] 00009E6B: 0A060C28 or al,[280C]
At the beginning of this listing, actions occur with the line of interest, and then the same actions occur with the adjacent string "[[[[". Perhaps static observation will not get along. It is necessary to resort to the help of a debugger. In order not to disturb the atmosphere of the console, I will resort to the special edition Dosbox 0.74, containing a debugger. In addition, this option is much more stable than the crutch of the Ida + Dosbox plugin.

So, I open Dosbox-74-debug (after configuring the conf-file, where the commands for mounting the game directory and its launch directive with the debug prefix are simply indicated). Without further ado, we start the game in trace mode and soon find out what's in this place:
listing 4.
022E:014C 7B00 jpo 0000014E ($+0) 022E:014E C606A46C00 mov byte [6CA4],00 022E:0153 B80300 mov ax,0003 022E:0156 E86701 call 000002C0 ($+167) 022E:0159 E8138D call FFFF8E6F ($-72ed) 022E:015C 803E862D08 cmp byte [2D86],08 022E:0161 7234 jc 00000197 ($+34)
After calling the second subfunction, the main menu is started, which “rotates” inside this subfunction. We set the breakpoint at the entrance to the first subfunction and start the game again, sending it first to free flight.
It soon turns out that ...

... drawing the main menu ends on this command. And immediately followed by this listing:
listing 5.
022E:8E99 8ED8 mov ds,ax 022E:8E9B 33C0 xor ax,ax 022E:8E9D A3EC27 mov [27EC],ax 022E:8EA0 A3EE27 mov [27EE],ax 022E:8EA3 32C0 xor al,al 022E:8EA5 3806F227 cmp [27F2],al 022E:8EA9 7548 jne 00008EF3 ($+48) 022E:8EAB 3806F327 cmp [27F3],al 022E:8EAF 7557 jne 00008F08 ($+57) 022E:8EB1 A02928 mov al,[2829] 022E:8EB4 0A060C28 or al,[280C] 022E:8EB8 7539 jne 00008EF3 ($+39) 022E:8EBA 813EEC270E01 cmp word [27EC],010E 022E:8EC0 72E3 jc 00008EA5 ($-1d)
The main menu, I remind you, offers to click either 1 or 2. In the listing there are two transitions. At this point the game loops between 022E: 8EA5 and 022E: 8EC0. Everything is obvious. Set breakpoints for both options:
BP 022E: 8EF3 and
BP 022E: 8F08 , “release” the game in free mode by pressing F5 and press 2 - the menu item that prompts you to enter password.
After some time, the traces arrive at Listing 3. The string "[[[[", drawn together with "ENTER CODE" - can be either the string "_ _ _", which is displayed in this way due to the tricky font, or reserved space code. Assume that the latter is true and set a breakpoint on memory access based on suspicious 4 byte offsets: BPM 0C11: B16C, BPM 0C11: B16D, BPM 0C11: B16E and BPM 0C11: B16F (the current base of the data segment is visible in the debugger). We start the game again, press the key in the code entry menu, enter the symbol of the intended code, and the program stops in the listing:
listing 6.
022E:9A57 FF06A4B1 inc word [B1A4] 022E:9A5B FEC3 inc bl 022E:9A5D 80FB04 cmp bl,04 022E:9A60 7303 jnc 00009A65 ($+3) 022E:9A62 E9B800 jmp 00009B1D ($+b8)
DEBUG: Memory breakpoint: 0C11: B16C - 5B -> 38
Some variable is incremented, then the register increment occurs and the check, apparently, for an excess of 0004, is logically associated with the need to enter 4 characters. According to the results of the check, the transition to either ret or some additional sequence of commands occurs. Including such:

The variable 0C11: B1B5 stores the code “4789” I just entered as a number. Then follows an interesting site:
listing 7.
022E:9AAC 33D2 xor dx,dx 022E:9AAE 8BC2 mov ax,dx 022E:9AB0 E8A6F8 call 00009359 ($-75a) 022E:9AB3 3906B5B1 cmp [B1B5],ax 022E:9AB7 7420 je 00009AD9 ($+20) 022E:9AB9 42 inc dx 022E:9ABA 83FA14 cmp dx,0014 022E:9ABD 76EF jbe 00009AAE ($-11)
Reset dx and ax; subfunction is called, after which the recently cleared register ah is compared with the entered code (in numerical form). If they are identical, then the transition somewhere far away, otherwise dx is increased by one, and if it does not exceed 14, then the operations are repeated.
It is logical to assume that fourteen correct passwords are enumerated and compared with the entered ones (the first 9 levels are for Beginner difficulty, the rest are for Expert, although there are only 2 exclusive levels for this difficulty: Lock and Minotaur, I don’t know what other levels differ from. For example, at number 10 is loaded Ice). All the facts confirm that we are on the right track.
Actually ... everything. There is nowhere to go; it is enough to change the conditional transition to unconditional. In principle, it would be nice to also change the number of characters entered, since if you leave it unchanged, you will have to enter the seventh level number as 0007 - after all, it will be more convenient to enter it as 07. To do this, we change Listing 6 to the following:
Listing 6_1.
022E:9A57 FF06A4B1 inc word [B1A4] 022E:9A5B FEC3 inc bl 022E:9A5D 80FB02 cmp bl,02 022E:9A60 7303 jnc 00009A65 ($+3) 022E:9A62 E9B800 jmp 00009B1D ($+b8)
It was already too lazy to look for where and how a line of four dashes is drawn to replace them with two. Given that Zmiro used the symbol
< to draw an exclamation mark from the font resource, and the comma -
> , the search for “that, I don’t know what” could be very laborious. Having spent some more time on step-by-step execution in the debugger, it was possible to localize this place, but I am not so perfectionist.
Findings. What is done
New executable file of the game prel.exe. Do not forget to check for viruses. ;)Abolished the need to collect passwords in levels. It is possible to select a level from the main menu by entering its two-digit ordinal number instead of four of the password. As unnecessary, letters of the Latin alphabet (AF) are removed from the mask of the characters entered, only numbers are left possible; Added check of the range of input level numbers (01-14). In fact, why should players mistakenly or out of excessive curiosity observe a crash in "
Insert disk with levelFF.sqz " instead of loading a level. The invitation label in the password entry mode from “ENTER CODE” is changed to “SELECT LVL”. At the very beginning of the game cut intro Hybrids. Changed the first intro developer ("Yeaaa ... My game is still working in ..."), - supplemented with information about Hybrids and this modification. Changed the lines of the names of the difficulties.
Pictures are clickable, especially the last.
