PATCH: Save one city in Keen 2 to finish (2 patches)

Completed patches for Keen2.
KeenRush
Patch Maker
Posts: 1988
Joined: Sun Aug 31, 2003 2:52 pm
Location: Sand Yego
Contact:

PATCH: Save one city in Keen 2 to finish (2 patches)

Post by KeenRush »

Hi,
I would desperately need this patch. So, as we know, Keen can save a city by just walking on those purple things instead of shooting them. I'd need a patch that would go to the end game sequence if Keen saves the machine in level 16 -- and he doesn't have any other cities saved. So, he would need to finish the game by just saving one city, and finishing the level. Hopefully it's possible!
Oh, and it doesn't need to be level 16, and level is find, at least as Keen can finish by saving one machine.
KeenRush
Patch Maker
Posts: 1988
Joined: Sun Aug 31, 2003 2:52 pm
Location: Sand Yego
Contact:

Post by KeenRush »

Ok, can this be done or not? I'd like to know..
User avatar
adurdin
Site Founder
Posts: 549
Joined: Fri Aug 29, 2003 11:27 pm
Location: Edinburgh, Scotland
Contact:

Post by adurdin »

Finding the patch:

I started by looking at the addresses of the city names in the data segment (by looking at the disassembly):

Code: Select all

511C:222B  4C 6F 6E 64 6F 6E                    db      'London', 0
511C:2231  00
511C:2232  43 61 69 72 6F 00                    db      'Cairo', 0
511C:2238  53 79 64 6E 65 79                    db      'Sydney', 0
511C:223E  00
511C:223F  4E 65 77 20 59 6F                    db      'New York', 0
511C:2245  72 6B 00
etc...
The first one is at $222B. So I now search for this address "222B", as the code that displays 'London' if it's saved will have to get the text from this address, as well as checking if it's saved or not. The first instance is what I'm looking for:

Code: Select all

39A4:1090                       l_39A4_1090::
39A4:1090  83 3E 9AF4 00                        cmp     word ptr ds:d_5AE2_9AF4_e, 0 ; (=0)
39A4:1095  74 15                                je      l_39A4_10AC             ; Jump if equal
39A4:1097  89 36 7FC6                           mov     ds:d_5AE2_7FC6_e, si    ; (=0)
39A4:109B  8B C7                                mov     ax, di
39A4:109D  05 0007                              add     ax, 7
39A4:10A0  A3 8036                              mov     ds:d_5AE2_8036_e, ax    ; (=0)
39A4:10A3  B8 222B                              mov     ax, 222Bh
39A4:10A6 ú50                                   push    ax                      ; PARAMETER_1
39A4:10A7  E8 17FB                              call    s_39A4_28A5
39A4:10AA  44                                   inc     sp
39A4:10AB  44                                   inc     sp
39A4:10AC                       l_39A4_10AC::
39A4:10AC  83 3E 9AF6 00                        cmp     word ptr ds:d_5AE2_9AF6_e, 0 ; (=0)
39A4:10B1  74 15                                je      l_39A4_10C8             ; Jump if equal
etc...
This code examines the word at ds:$9AF4, and if it's nonzero, displays the text 'London'. Immediately following is near-identical code that examines ds:$9AF6, and displays 'Cairo' if it's nonzero.

So I surmise then that the 8 words at ds:$9AF4 to ds:$9B02 store the 8 flags indicating which cities have been saved. Now we need to find where these are checked to see if Keen has won or not. Searching for "9AF4" again reveals this:

Code: Select all

39A4:8421  C7 46 FA 0000                        mov     word ptr [bp+LOCAL_3], 0
39A4:8426  33 F6                                xor     si, si                  ; Zero register
39A4:8428  EB 0C                                jmp     short l_39A4_8436

39A4:842A                       l_39A4_842A::
39A4:842A  8B DE                                mov     bx, si
39A4:842C  D1 E3                                shl     bx, 1                   ; Shift w/zeros fill
39A4:842E  8B 87 9AF4                           mov     ax, ds:d_5AE2_9AF4_e[bx] ; (=0)
39A4:8432  01 46 FA                             add     [bp+LOCAL_3], ax
39A4:8435  46                                   inc     si
39A4:8436                       l_39A4_8436::
39A4:8436  83 FE 08                             cmp     si, 8
39A4:8439  7C EF                                jl      l_39A4_842A             ; Jump if <
39A4:843B  83 7E FA 08                          cmp     word ptr [bp+LOCAL_3], 8
39A4:843F  75 09                                jne     l_39A4_844A             ; Jump if not equal
This is a for loop -- it looks at the 8 words starting at ds:$9AF4, and adds their values to a local variable. After the loop ends, this local variable is checked to see if it is equal to 8 -- sounds like what we want. This line at $834B turns out to be the one we need to patch, so I'll post the patch following this.

Anyway, the pattern shown in this last block of code is worth remembering -- it corresponds exactly to a C "for" loop, and it'll be found throughout the disassembled Keen code:

Code: Select all

                mov     word ptr [bp+LOCAL_3], 0            # sum = 0
                                                            # Here's how a for loop is compiled:
                                                            # for(i = 0; i < 8; i++)
                xor     si, si                              # //The loop initialisation (i = 0)
                jmp     short l_39A4_8436                   # //Jump to the loop test to start with
l_39A4_842A::                                               # { //The loop body begins here
                mov     bx, si                              #    //These four lines correspond to
                shl     bx, 1                               #    //  the line of C code:
                mov     ax, ds:d_5AE2_9AF4_e[bx] ; (=0)     #    sum += saved_cities[i]
                add     [bp+LOCAL_3], ax                    #    //  where saved_cities is an array of words.
                inc     si                                  #    //Here is the loop increment (i++)
l_39A4_8436::                                               # } //The loop body ends here
                cmp     si, 8                               # //And here is the loop test (i < 8);
                jl      l_39A4_842A                         # //  if the test fails, then we execute the body again
User avatar
adurdin
Site Founder
Posts: 549
Joined: Fri Aug 29, 2003 11:27 pm
Location: Edinburgh, Scotland
Contact:

Post by adurdin »

And here is the patch, which changes the '8' in line 843B to a '1':

Code: Select all

%ext ck2
%version 1.31

# Keen only needs to save 1 city
%patch $843E  $01

%end
KeenRush
Patch Maker
Posts: 1988
Joined: Sun Aug 31, 2003 2:52 pm
Location: Sand Yego
Contact:

Post by KeenRush »

BIG THANKS!!
Woah, this is really cool! Big thanks! :) :) :) w00t!!
User avatar
levellord
Crazy pAtChEr
Posts: 1401
Joined: Thu Nov 20, 2003 11:35 pm
Location: NewZealand
Contact:

Post by levellord »

This will forever change the nature of Keen 2 modding.

BTW: Can you give me some idea of where to look to find the background tiles patch? I've tried your method [what I can understand of it.] but I'm just going in circles.
User avatar
adurdin
Site Founder
Posts: 549
Joined: Fri Aug 29, 2003 11:27 pm
Location: Edinburgh, Scotland
Contact:

Post by adurdin »

The background tiles one is complicated -- unlike this one, it doesn't require just changing a number or two, but it requires a total rewrite of a couple of bits of code. I'll try to do it in the next week or so before I go off on holidays, and if I can I'll document it in detail.
KeenRush
Patch Maker
Posts: 1988
Joined: Sun Aug 31, 2003 2:52 pm
Location: Sand Yego
Contact:

Post by KeenRush »

Woah, sounds good! :)
User avatar
levellord
Crazy pAtChEr
Posts: 1401
Joined: Thu Nov 20, 2003 11:35 pm
Location: NewZealand
Contact:

Post by levellord »

Oh thankyo thankyou thankyou oh grand exhaulted master! May I please lick the mud from your shoe?
Ezjay
Posts: 158
Joined: Fri Feb 27, 2004 1:15 pm
Location: Amsterdam

Post by Ezjay »

As LL pointed out, this drasticly changes the posibilities for keen2...

Somehow I feel I have to use this patch, but on the other hand the eight machines are fine the way they are... damn...

Oh and about that background patch: !!!
KeenRush
Patch Maker
Posts: 1988
Joined: Sun Aug 31, 2003 2:52 pm
Location: Sand Yego
Contact:

Post by KeenRush »

"As LL pointed out, this drasticly changes the posibilities for keen2..."
Yes sir!

"Somehow I feel I have to use this patch, but on the other hand the eight machines are fine the way they are... damn..."
Solution: other mod! ;)
Ezjay
Posts: 158
Joined: Fri Feb 27, 2004 1:15 pm
Location: Amsterdam

Post by Ezjay »

Andrew, could you make me a patch to finish the game by completing level16.ck2, like in keen3?

I would like saving the machines to be optional.
User avatar
levellord
Crazy pAtChEr
Posts: 1401
Joined: Thu Nov 20, 2003 11:35 pm
Location: NewZealand
Contact:

Post by levellord »

Set the patch to one machine completion. Make sure Keen touches the tantalus ray sprite [it can be hidden behind a tile and Keen can walk over it.] You'd never even know you'd passed it.

And here is that level, when placed into keen2 with the 1 city patch, you can't possibly fail to finnish the game.

http://www.freewebs.com/gannalev/LEVEL16.zip
KeenRush
Patch Maker
Posts: 1988
Joined: Sun Aug 31, 2003 2:52 pm
Location: Sand Yego
Contact:

Post by KeenRush »

LOL, I entirely forgot that way! Yeah, placing that sprite somewhere and makin' that one can't shoot it, you can have it there. Probably it can be placed to exit door tile as well, and that way when player touches the exit tile he/she will also touch the sprite. :)
User avatar
levellord
Crazy pAtChEr
Posts: 1401
Joined: Thu Nov 20, 2003 11:35 pm
Location: NewZealand
Contact:

Post by levellord »

*ahem*

Shooty shooty...
Post Reply