Back to home

Cheat Engine, PCSX2 and cheat tables

Me and other members who are investigating the inner workings of Kya DL (mainly in the KDL speedrunning Discord server) use Cheat engine to find variables and save the findings in a cheat table file, because it's a very powerful and flexible program.
I'll be uploading my cheat tables (which also include contributions from other members of the server) in a separate repo, which includes instructions on how to use CE with PCSX2 1.7 .

Wording regarding pointers, addresses and offsets

All addresses and offsets are always hexadecimal.

When talking about a pointer address, this page uses a terminology similar to CE: to get to the desired address, take the 4-byte number stored at the pointer base address, add the offset to that number, and the result is the actual memory address storing that particular variable.
(eg: pointer base address 10 & offset +2 = take value stored at 10 (X), add +2 to it, actual address is X+2)
When talking about a "normal" address (like with the controller readings), you simply take the beginning address and add the offset to it to get the actual address.
(eg: beginning address 20 & offset 6 = actual address 26 )

Index

Variables and RAM

Game disc files

Save files

Variables and RAM

Important! The addresses refer to the final NTSC build of the game.
The PAL version has different values, which will eventually be documented.

Controller readings (player 1)

Beginning address: 0495B30/0495B9C/0495C1C

Joker commands

Type: 2 byte "integer"
Offset: +00

Joker commands are addresses that contain the button reading from the controller, stored with 2 bytes.
In Kya DL, the buttons have these base values:

Button 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 Hex value
Square Square 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7FFF
X Cross 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 BFFF
Circle Circle 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 DFFF
Triangle Triangle 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 EFFF
R1 R1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 F7FF
L1 L1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 FBFF
R2 R2 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 FDFF
L2 L2 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 FEFF
D-pad left D-pad Left 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 FF7F
D-pad down D-pad Down 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 FFBF
D-pad right D-pad Right 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 FFDF
D-pad up D-pad Up 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 FFEF
Start Start 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 FFF7
R3 R3 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 FFFB
L3 L3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 FFFD
Select Select 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 FFFE

When multiple buttons are pressed, the value gets set to [Button 1] AND [Button 2] AND ... [Button N]; for example when pressing R2 + Triangle + Circle the value gets set to FDFF AND EFFF AND DFFF == CDFF (1100 1101 1111 1111)

Other PS1/PS2 games may store the value in a different way. More info here

Joker command calculator:

Square X Circle Triangle R1 L1 R2 L2 D-pad left D-pad down D-pad right D-pad up Start R3 L3 Select
FFFF (NOT = 0000)

Stick readings

Type: 1 byte unsigned integers
Length: 4 * 1 byte = 4 bytes total

Offset Analog stick Axis
+02 Right X
+03 Right Y
+04 Left X
+05 Left Y

On the X axis, 00 is left and FF is right.
On the Y axis, 00 is up and FF is down.
A stick resting in the neutral position has both set to 7F (127).

Button pressure

If you didn't know: the DualShock 2 (and DS3) has pressure sensitive buttons , except for Select, Start, L3 and R3, meaning that games can actually tell how hard you're pressing a button.
Kya: Dark Lineage requires a DualShock 2 and won't work with an original PS1 DualShock.
This is usually a sign the game requires the pressure sensitive buttons, tho it's unknown in which way the pressure info is used (if at all).
Regardless, this means that we have another way to check for button presses (apart from Select, Start, L3 and R3), which depending on the situation might be easier or better to use.

Type: 1 byte unsigned integers
Size: 12 * 1 byte = 12 bytes total

00 equals not being pressed at all, 01 barely pressed and FF fully pressed.

Offset Button
+06 D-pad right
+07 D-pad left
+08 D-pad up
+09 D-pad down
+0A Triangle
+0B Circle
+0C X
+0D Square
+0E L1
+0F R1
+10 L2
+11 R2

To recap

Controller readings
Address: 0495B30/0495B9C/0495C1C
Size: 12 (currently known!)
Offset Length (bytes) Content
+00 02 Joker command
+02 01 Right analog X axis
+03 01 Right analog Y axis
+04 01 Left analog X axis
+05 01 Left analog Y axis
+06 01 D-pad right pressure
+07 01 D-pad left pressure
+08 01 D-pad up pressure
+09 01 D-pad down pressure
+0A 01 Triangle pressure
+0B 01 Circle pressure
+0C 01 X pressure
+0D 01 Square pressure
+0E 01 L1 pressure
+0F 01 R1 pressure
+10 01 L2 pressure
+11 01 R2 pressure

Controller readings (player 2)

Address: 0495CB0/0495D1C/0495D9C

The order and way in which things are stored are the same as for player one.
Note that the game also requires a DualShock 2 for player two, if you try plugging in an original DualShock in port 2 and try to control P2 in the secret level nothing will happen.

Kya's position and movement

All currenty known variables of this category are stored with pointers.

Position

Type: float
Pointer base value: 06F2D90
Offset (X): 0000030
Offset (Y): 0000034
Offset (Z): 0000038

To give a sense of scale, when Kya jumps by pressing X she peaks at around +1.71 Y.
(it's actually currently unknown which value the game considers to be the X and which one to be the Z, the nomenclature has been chosen based on their order in memory).

Settings read from BWITCH.ini

Some settings are stored in the file BWITCH.ini in the root of the game DVD.
It's possible (and easier) to change these by editing the variables where they're stored after being read from the disc.

Starting level (AddLevel)

The level the game should load when starting a new game (no idea why it's called AddLevel).
Removing the setting completely from the ini file causes it to default to NATIV (even though the ini file itself states otherwise). The folder is set by SetPath, which is set to "CdEuro/Level/" in the final game (on both the NTSC and PAL releases).
Level folder in the table below omits the above mentioned root directory.
If set to a value different from the default value of The Roots, when starting a new game, the intro movie will be skipped, the lines "Hey, look at this"..."Is it dead?" will be played, and then the player will be immediately thrown in the level.

Type: 4 bytes integer (only last byte shown in table)
Address: 06DA5B4
Value Level folder Level Info
00 NATIV Nativ City
01 LEVEL_1 The Roots Default value
02 LEVEL_2 Flying Forest
03 LEVEL_3 Hunter's Domain
04 LEVEL_4 Nativ City when first visiting with Aton
05 LEVEL_5 The Quarry
06 LEVEL_6 Destroyed Nativ City
07 LEVEL_7 The Air Post
08 LEVEL_8 Forgotten Island
09 LEVEL_9 Brazul Lab (Forgotten Island)
0A LEVEL_10 Wolfun City
0B LEVEL_11 The Quarry Brazul miniboss
0C LEVEL_12 The Fortress
0D LEVEL_13 Level Test (secret level)
0E PREINTRO Main menu If choosing this, the intro movie will play first, and then the opening lines will play, before kicking back to the main menu
0F CREDITS Ending credits
Values after 15 make the game try to load levels that don't exist, causing different sorts of weird behaviours
Usually the save file gets set to "UNKNOWN LEVEL (number of level as signed integer)" Below are some examples
10 Game returns to the new game save selector and deletes the save that was selected (resetting to EMPTY)
11 Game immediately freezes after starting new game, without playing lines and without showing any signs of trying to actually load anything from the PCSX2 logs
12 Causes the selected save file to be set to an empty level name
Screenshot of weird levels

Dormant debug features/cheats

There are dormant debug features/cheats left over from when the game was in development; a working implementation of the cheat options menu can most prominently be seen in the September 29 prototype.

Strings pertaining to this menu have been found in the final game, but it's currently unknown if and how that can be accessed in the final build.
However, it is known that it's possible to enable the flying cheat and the invincibility cheat by manually writing to the variables pertaining to them in RAM (the cheat options menu is coded weirdly, as there are two separate variables for these two cheats: the first technically only controls if the cheat is displayed as enabled or disabled in the menu, and the second (the "enable" variable) is what the code actually checks to see if the cheat effect should apply (for example, checking the value of the flying cheat enable when R2+R3 is pressed), and the former gets copied to the latter any moment the cheat options menu is being viewed).
With the aid of the PCSX2 debugger and the September 29 prototype, the code that handles checking the enable variables was found in the final game, and it was confirmed that changing those is enough to restore the functionality.
(Keep in mind that the locations in RAM vary from build to build and version to version, so the values in this page won't work for the September 29 prototype).

These are stored next to each other and are accessed via a pointer.

Pointer base address: 00448AA0
Offset (flying): 0000AA0
Offset (invincibility): 0000AA4

Once flying is enabled, it can be toggled by pressing R2+R3

Another dormant debug menu is documented at tcrf

Game disc files

Level folders

List of all level folders (found in /CDEURO/LEVEL/) "Name" is the name as it appears in the pause menu/save file menu
Folder Level Name No. of SECTx.bin files Info
NATIV Nativ City NATIV CITY 26 SECT3.bnk doesn't exist
LEVEL_1 The Roots THE ROOTS 13
LEVEL_2 Flying Forest FLYING FOREST 11 SECT11.bnk doesn't exist
LEVEL_3 Hunter's Domain HUNTER'S DOMAIN 19 SECT9.bnk, SECT19.bnk and SECT20.bnk don't exist
LEVEL_4 "Nativ City" the first time you visit with Aton NATIV CITY 11 SECTs 2-4, 8-12 don't exist (the whole upper Nativ City doesn't exist in this version, along with minigames)
Doesn't have any shops, elevators etc shown on the L1 map
The game silently loads in the real NATIV map during the cutscene where Atea tells Kya to follow the signs to the Boomy shop
LEVEL_5 The Quarry THE QUARRY 14
LEVEL_6 Destroyed Nativ City NATIV CITY 3
LEVEL_7 The Air Post THE AIR POST 19
LEVEL_8 Forgotten Island FORGOTTEN ISLAND 9
LEVEL_9 Brazul's laboratory (Frank boss fight) FORGOTTEN ISLAND 1 Pretends to be LEVEL_8 in the areas preview in the pause menu
LEVEL_10 Wolfun City WOLFUN CITY 7
LEVEL_11 Brazul miniboss (The Quarry) THE QUARRY 1 Pretends to be LEVEL_5 in the areas preview in the pause menu
It being so distant from it's parent LEVEL_5 may suggest the decision to separate it was taken late in the development?
LEVEL_12 The Fortress THE FORTRES 3
LEVEL_13 Secret level LEVEL TEST 5 More info
PREINTRO Main menu START MENU 1
CREDITS End game credits CREDITS 1

Save files

Important! Data (numerical values, checksums etc) is saved as little endian (LE).
So for example an int32 value of 9 will be saved as 09 00 00 00 inside the file.

Note: files that are standard for all PS2 saves (icon.sys, *.ico) won't be discussed

Save header

All KDL .dat save files start with a header containing at least two checksums.
Even though the header has a size field inside it, due to the fact that the number of data sections it can contain info for is hardcoded to two in the game code, it's believed to have a fixed size in practice

Save file header
In theory variable size
In practice always 1C bytes
Offset Size (bytes) Type Content
+00 04 String "NEDE" ("EDEN" in reverse(?))
+04 04 Unsigned int32 Header checksum (Starting from 08, as to exclude NEDE and the checksum itself, to the address stored in the header size)
+08 04 Unsigned? int32 Header size (in practice always 1C)
+0C 04 Unsigned int32 First data block checksum
+10 04 Unsigned? int32 First data block size
+14 04 Unsigned int32 Second data block checksum
All zeroes if there's no second data block
+18 04 Unsigned? int32 Second data block size

Reverse engineered checksum code can be found here

Settings file

Offset starts from after header (so at 1C).

Settings (settings.dat)
Offset Size (bytes) Type Info
+00 04 String "STGS"
+04 04 Unknown Unknown
Set to 03 by game
+08 04 Signed? int32 Language setting (PAL version)
00 - 04
In order: English, French, German, Spanish, Italian
NTSC version completely ignores this setting
+0C 04 Signed? int32 Audio (00 = mono, 01 = stereo, 02 = surround)
+10 04 Signed? int32 Music volume (00 - 0C)
+14 04 Signed? int32 SFX volume (00 - 0C)
+1C 04 Signed int32 X axis screen adjust
+20 04 Signed int32 Y axis screen adjust
Stored in negative - in-game negative values stored as positive value and vice versa
+24 01 Boolean Enable vibration
+25 01 Boolean Enable subtitles
+26 01 Boolean? Unknown
+27 01 Boolean Aspect ratio
00 = 4:3, 01 = 16:9
+28 D8 Unknown
Won't affect game if filled with garbage, won't even get reset to a default value
+110 1C Unknown
Outside the data block size set in the header, thus doesn't affect checksum
Won't affect game if filled with garbage or even completely removed