GameHax - Console Game Hacking

ORC Hackers Handbook



Introduction

Guide to Understanding Programming Terminology

Understanding Data Storage and MemoryTerminology

Understanding MIPS Text and Numeric and Data Types

Cheat Device Reference Guide

Introduction

  1. Goals and Purpose

    The goal and purpose of this guide is to be an ever expanding database of knowledge and reference material, compiled in such a way that both the experienced user and beginner, can both benifit equally from its content.

    The information contained herein is strictly for educational purposes. ORC is not responsible for any use that this information may be used for.

    I will attempt to offer both the vas amount of technical data out there on this subject, but in the same instance try to explain it in an easily understandable manner.

    Keep in mind that this is an on-going project, an as such, more information may be added all the time.. reading this guide once and never returning, may cost you valuable knowledge.. Check back often and always to brush up, relearn or find new infomation.

    All Members are welcome to and incouraged to add any information to this guide providing it is done in such a way as to flow consistantly with the existing guide, and the information is posted in the correct location.

  2. Credits

    Data compiled in this guide came from many places, Not limited to, but including the following sites, and or persons:

    Google, CodeMasters Project.net , Wikipedia, The GSHI , LYS Evil

    Techncial Lingo and terminolgy simplication provided by Xodus.

Back to top

Guide to Understanding Programming Terminology

  1. What is MIPS?

     MIPS- this is the language that Ps2 games are written in. When you load a game file into Ps2dis, you are looking at the assembly code (programming lanaguge) that handles the execution of the game on your PS2. In this guide I will reference COD FH, as it is the game which i am most familar with. However, this material applies equally to any PS2 game you wish to. The following article on this subject is a reprint of one found on codemasters-project.net , however may be helpful.


    This article's for the biginner game hackers, or advanced game hackers who dont know anything about MIPS (is this possible? - ed) who need help understanding the MIPS assembly language.

     This section gets into some more complex stuff as you will learn about the MIPS assembly programming language (the language in which all PS2 games are written in), but is still meant for the beginners who want to understand the code they see in the ps2dis... lets get started.

     When it comes to programming in 'assembly', there is NOT one type of assembly. ALL assembly languages are programming languages in which the source code deals directly with the processor chip. the PS2 runs off of a MIPS processor chip, and for this reason all PS2 games must be written in the MIPS assembly language. there are more than just MIPS assembly however. Every type of processor has its own assembly language. MIPS assembly is the code you see when you open a slus file in the ps2dis. because assembly languages interact directly with the processor chip, they are EXTREMELY fast when it comes to program execution. in fact... when you read about a computer that has, lets say, a 2.4 GHz processor... this is telling you how fast the processor works. the 2.4 GHz is how many processes the processor chip makes per second... lets think about that. theres hertz, mega hertz, and giga hertz. about 1000 hertz in a mega hert and about 1000 mega hertz in a giga hert. that many processes per SECOND... thats REALLY fast. anyway, back to the part that matters.

     There are some complex and key points to the MIPS assembly language which MUST be taken into account when reading MIPS assembly source code (or even more so... writing MIPS assembly source). ill start from the beginning.

     each and every action done by the processor is done by a line of code called an 'instruction'. EVERY instruction in the MIPS assembly language is a 32-bit process. now, a single bit is a single binary digit that can be either '0' or '1' standing for 'false' and 'true'. there are 32 bits (or on/off digits) in every instruction. there are 8 bits in a single byte... and the 8 hex valued digits that make up an address are made up of 4 bytes. you can test this theory by multiplying 4 by 8. in other words you mulitply the 8 bits that make up a byte by the number of bytes... the answer is 32, where you have 32 bits (hence the '32-bit' instructions).

     MIPS assembly uses 'registers' to store data for operation in program execution. there are 31 general purpose registers, 30 double float registers, and 31 single float registers (if you dont know what i mean by 'float', read up on some c++... specifically the types of variables). the general purpose registers are broken down even more though... for instance, there are certain general purpose registers that should be used for certain things. (have you ever seen a register in the ps2dis that was identified with a 't'... i.e. t0, or t1??? these are 'temporary' registers and should ONLY be used within a function.) also, there are 2 (i believe) registers that are not meant to be used to store information... the zero register (known as $0 or zero) ALWAYS holds the value zero. so if you try to store data in it for an important comparison or for a branch... itll compare the other register with the value zero instead of what you tried to store into register $0. and register 'ra' (i think) is the other register that is a special register. this register is used to hold the address for jumps and jump returns and things like that... not to hold values for comparison or anything else.

    There are also little rules that one MUST abide by when using MIPS assembly. the first of the two major issues ill talk about is: the 'PC' (think of this as the 'program counter' which keeps track of which line the program is on) is incrimented by 4 durring the execution of each instruction (it increases by 4 because of the four bytes that make up an address). the PC in increased by four durring the MIDDLE of the instruction... so when the program comes accross a 'j' or jal' or any kind of jump, the PC is increased THEN it executes the line of code which contains the jump instruction. because of this, the program runs and executes the line of code after the line with the jump instruction. and, in the middle of that lines execution, the PC is finally set to the address in which the jump referred to. this is NOT a big deal at all... in fact, because of the one line delay, you can make good use of its time and put an important instruction after the jump. if you dont have an instruction after the jump... who knows what could happen (the program would crash most likely). this is why when you are viewing the code for the games, there is ALWAYS a line of code after the jump, even if its just a 'nop' (nop or no-op stands for 'no operation').

     The second of the two key issues is the 'load/store delay time'. the MIPS assembly language (because it is 32-bit based) has addresses that range from 00000000 all the way to FFFFFFFF. BUT, the MIPS processor sections off certain ranges of addresses for certain usages... one of these usages is memory. MIPS has a section of addresses where you can store data and call upon it at a later time (if you are using the pcSPIM MIPS simulator, the 'memory' range starts at 10000000). there is, however, a delay time when it comes to loading or storing information in the memory. the delay time is only one instruction long... which is NOTHING considering how fast the programs execute. but, due to the delay time... you SHOULD NOT use the register for ANY reason after loading or storing information until at least one more instruction has already been executed. you will also see this in the ps2dis... there is always time between a load and store instruction, and an instruction that uses the registers that held (or hold) the data for loading or storing.

     now ill go over a couple commands for the MIPS assembly language which should really help you when it comes to hacking ps2 games...

     The 'ori' command (or 'logical OR immediate') will 'logical OR' two values and catch the result in the specified register. 'immediate' means that you are going to give a value straight up... one thats not in a register... but just give a value to compare with. the other value, however, must be in a register. for instance, you can do this: ori t0, t1, 0x0008. this would compare the bit patterns (remember that all MIPS instruction are 32 bit, it compares the bits of the two given values) held in register t1 with the bit pattern that represents the value 8 (or 8... the 0x means its a hex value, which in this case doesnt make a difference, but if you were to give it 0x0010, it would be different than to give it 0010). the result of the ori instruction would be caught in register t0. you can also have a value in t0, and do: ori t0, t0, 0x0008. this does the same thing, only spares us the use of another register. if you dont give the 'immediate' instruction, you have to use 2 registers... like this: or t0, t0, t1... which does the same thing, only it compares the value of 2 registers (registers t0 and t1). this instrucion can also be used to simply assign a value into a register... for instance: ori t0, zero, 0x0008... this would compare 0x0008 with zero, and simply assign the 8 to register t0.

     next is the sl's and sr's. you may have seen an instruction in which the command was 'sll'. these are 'shift left' instructions. there are other commands that start with 'sl' and 'sr' like slt (and they are differnet the 'sll'), but generally, when you see a 'sl' or a 'sr', they are shift commands ('l' for left, and 'r' for right). what these do is shift the bit pattern specified to the direction specified and the result is caught in the specified register. for instance: sll t0, t1, 4... this would shift the bit pattern held in register t1 to the left 4 bits and catch the result in register t0. if the value in register t1 is 0008, the result that is caught in t0 after the shift would be 0080 (remember that there are 8 bits in a byte... this 8 moved over half a byte). this can be very useful in many situation (especially for game programs), but as you get more advanced, you will realize that the 'sll' command can be used to simply multiply a value (hint- shifting left 1 bit multiplies by 2, shifting 2 bits multiplies by 4, 3 bits multiplies by 8...). you can also use the same register in these commands... like this: sll t0, t0, 4... in which the value already held in t0 would shift left 4 bits and would then be stored in t0 (in which case the value in t0 would have been multiplied by 16).

     and, as i spoke of earlier, there is a 'slt' command. my may also see it ass 'slti', but remember that the 'i' or 'immediate' only means that you are using a specific value (like $0004 is ALWAYS gonna equal $0004). im not quite sure what the 's' in 'slt'/'slti' stands for, but i do know that the 'lt' stands for 'less than'. this command tests to see if a value is 'lt'/'less than' another, and if so it puts the value '1' into the specified register... otherwise, the specified register will catch '0'. it looks like this: slti t0, t1, 0x0004... this would catch the value '1' in register t0 if the value in t1 is less than 4... if the value in t1 is equal to or greater than 4, zero will be caught in register t0. you can also catch the value in one of the registers being compared like this: slt t0, t0, t1... which will catch '1' in register t0 if the value in t0 is less than the value in t1, otherwise t0 will be assigned the value 0.

    next there are a whole bunch of add, subtration, multiplication, and division commands. these simply carry out the math... add t0, t0, t1 (this would add the values held in t0 and t1 and store the result in t0). there is also an addui (or 'add upper immediate'). normally when adding or subtraction, the values are held in the last four digits of the data... but if you want to add to the first four digits... you use the 'upper' instruction, and once again you can use the 'immediate' to give a constant value. note, however, that addui and addiu are different, and only the addui will work with the first four digits. there are also multiplication and division commands, but these are pretty straight forward as the command is something like 'mult' (which is ovbiously multiply) and div (which is obviously divide). however, with multiplication and division, the answer is stored in something called mfhi and mflo. the values must be called from these to be stored into a register... and im not sure, but i think you must retrieve the values before you carry out another mult. or div. instruction.

    next, we have the load and store commands. there are load and store instructions for bytes, half-words, and words (lb, lh, lw and sb, sh, sw). a word is is the full 00000000 value (address 00000000, where the 0's make up the word). a half word is... well... half of a word. and a byte is simply 00. these are commonly used to set up a call to a desired location in memory, and often coincide with a 'lui' ('load upper immediate') instruction. for instance, you can do this:

    lui t0, 0x0040

    lw t1, $240c(t0)

    the end result would be... the value stored at 0040240c would be stored into register t1. the (t0) part tells the program to load the full word value from the address starting with (t0) and, to be exact, load from 240c (which together equals 0040240c). you can also use 'lb' the same way... and same with the 'lh'.

    well, thats pretty much it... you should now have a pretty good start on understanding a little bit of MIPS assembly. this, of course, is NOWHERE near knowing the language, but when you are hacking, if you keep all these things in mind, you should understand the code a lot more... happy hackin.

    Written by: Codemasters Project Codehacker Team


  2. What does alpha numeric mean?

    ALPHA NUMERIC - this is a term used to describe a combination of letters and numbers. A Codebreaker code is an example of an Alpha numneric: 0D34FE23 89F9B4C2

  3. What is an address?

    ADDRESS - An "address" is an 8 digit alpha nummeric code which serves as a reference point and index for which PS2dis or any editor which might open a executable file, uses to organize the data into a more readable form. The game, and the progamming language itself uses addresses for naviagtion, the addresses themselves do not exist in the raw data. They are formulated using a simple equation in a numbering system called HEX

  4. What does Syntax mean?

    Syntax is a term used to decribe the "default" or expected format for an instruction to be written in. Syntax is to programminglanguage what "grammer" is to written language.

  5. What is a NOP?

    A Nop is an instruction in MIPS.. maybe a better definition would be a 'lack of an instruction"..


    For example we have a segment of a process:

    00100004 3C013F80    Lui At, 3f80

    00100008 03E00008    Jr Ra

    lets say we wish to cancle the instruction Lui.. in this case we change the data (3C013F80) to all zeros.. or 00000000

    Now our inststruction is:

    00100004 00000000    Nop


     


Back to top

Understanding Data Storage and MemoryTerminology

  1. Introduction

    Data storage (information the game is storing in the Ps2's memory) and data retrieval (information the game retrieves from the Ps2's memory during gameplay) can be stored or retrieved in various ways and in various formats and amounts. Lets simplify this by using this model, which i will reference though out this chapter. The game file in its simplest form is a huge amount of data that is millions of pairs of alpha-numeric (letters and numbers) called "bytes" which if viewed in raw form would look something like this:(

    To put the term "byte" into a perspective that u can easily understand think of your Ps2's memory card.. a typical memory card can hold 8 megabytes (8 million bytes) of information. All computer , and game console as well as even your Ipod or flash drives all use this unit of measurement to measure how much information can be stored on it.

    A 10 Gigabyte flash drive for example can hold up to 10 Billion of these 2 digit chunks of data. This data could represent anything from files, to music, to videos.. you name it.. doesnt matter what is stored on any given device, if you looked at that data in raw form it would look like the picture above.

    Lets stop for a second and do the math.. the Bin file for COD FH is 3.5 Megabytes in size.. so technically the game file your opening to hack, contains 3.5 million bytes of information, or 3.5 million chunks of information.

    In the above form however you would certainly get lost really quick trying to naviagte and read this data. When you have nothing but 3 million sets of letters and number combinations, just staring at that data for more than 10 minuntes is enough to give you a headache...

    Fortunatly unless your enjoy pain, you dont have to try to hack just having the data packed together like this. When you view a file in Ps2dis, you will see something that looks more like this:(

    IIn the game file, the "bytes" are arranged in groups (4 bytes per address) So that 3.5 million bytes is reduced to just under a million addresses.

    I know what your thinking.. holy shit, thats still alot! Yes it is, however consider this. I myself have over 150 codes for call of duty. Each one of those codes represents me having altered a single address to achieve whatever result the code is generating.. So think about that for a minute. Out of 1.1 million addresses, I have only altered 150 of them and have accomplished nothing short of totally remaking the game.. every aspect of the game (player settings, weapon settings, map and hud settings, as well as all the other codes i have) only used 150 of the 1.1 million addresses in the file.

    At this point you might be asking.. "hmm if you totally altered every part of the game.. whats the other million addresses for? Well,the simple answer to that is "thats the game itself" The game, while only needing maybe 500 bytes of data to store all of the games settings and values still requires millions of instructions for the program to execute.

    Take for example the simple action of firing your gun.. You think of it in simple terms.. "I press R1 and my gun fires".. But behind the scenes, that simple action, caused possibly thousands of lines of code to be executed. Now, at the same time, you may only have to alter one of those lines of code to make your gun fire rapidly, none the less, the other 10000 lines are equally important to the process of firing your gun..

    It is certainly not necessary to alter all the code required to perform a simple game action. Ok, Lets now examime the technical terms used to describe data storage and retrieval and I will attempt to put them in terms you can easily understand.

  2. Memory granule terms:

    Lets first start off by defining "memory granule".. Think of memory like a pile of sand.. Each grain of sand is a single "granule" of memory. If you measured different amounts of sand (say an Ounce, a Gram, or a Pound) you now have renamed that amount, not by calling it "this much sand" and "that much sand" because that would be non-descriptive and doesn't really absolutly define the amount. So we use "pound". or "gram" or "ounce" to define particular amounts. PS2 memory is no different.

    There are many terms which are used to define units of measurement that are not used by MIPS, so we'll skip those and focus solely on the ones which apply to our needs.

    Byte - A granule of size usually corresponding to the size used to store a single character. Remember each character is represented by a 2 digit hex code thus one byte = 2 digits of data "00"

    Bit - An unambiguous term, short for binary digit, referring to a granule capable of holding two states. Ok.. what does that mean? Think of it like a light switch. A light switch can be either on or off (2 states of being) In the same sense a bit can be either 0 or 1, which could be described also as true/false

    Thats a pretty technical definition, so I'll put it in simple terms.. there are 8 "bits" per every one "byte" (just as there are 28 grams to 1 ounce (dont ask) So when you see the term "16bit" this is referring to 2 bytes of data or "0000"

    Word - MIPS uses 32-bit Registers thus a word is equal to the total amount of data that can be stored in any given register. A word is equivalent to 4 bytes or (x00000000) (8 digits of data) Every address in ps2dis contains 1 word worth of data:

    00100000 3C013F80 <-- 8 digits or 1 "word" or "32 bits"

    Halfword - The term Halfword refers to a granule half the size of a word. (16bit) x0000.. a half word is "16 bits"

    Doubleword - refer to granules the size of two words.

    Quadword - Quadword is the generally accepted term for a granule of size equal to four words.

    Ok.. so lets review by using a diagram to explain how much data equals each unit


  3. What is a Register?

    REGISTER - This is a term which describes a value being given a name in order to be able to uniqely identify that value. In mathmatics (algebra especially) one could compare "register" to any letter or combination of letters used to temporarily store a value, as in the following example:

    X=10 Y = X x 2

     in this equation, X and Y are "registers" they both contain values. X = 10 and Y = (2X) or 20

    Now.. thats simple enough.. but if you wanted to then add a thousand more equations but still maintain the value of X you would instead use other letters or maybe letter combos to assure after all is said and done, that X still equals 10. MIPS works the same way. It uses "registers" to for either temporary or long term storage of values to be used in later equations.

    Mips uses the following registers, each having unique purposes:

    Here is another illustration using word length (00000000) data "slots" to represent the MIPS register structure.. Think of the Registers in this diagram as "addresses" and the "slots" as data.. 8 digits of data (1 word) per register

  4. What is an Offset?

    Offset is a term used to describe the numnerical difference between two addresses. MIPS uses Offsets for one important reason. Since each 4 bytes of data (00 00 00 00) at any given address must not only represent MIPS instructions, Registers, and values, this information is encoded in the smallest possible form (again to use as little of the precious Ps2 memory as possible) and because there are only 4 bytes of memory per address, MIPS can only use 2 of these to store the numeric value representing the offset or "difference" value.

    All data storage and retrival instructions use Offsets to denote where in the physical memory to store or load the information to or from.

     if we had a decimal number 100, and we wanted to know the "offset" value of 50 you would simply add 100 + 50 giving you 150. So if we then think in hex, the equation is the same, the numbering system is all that is different.

    for example: We have an address.. lets say its 001f0010 and then we have an offset of 0345 (0345 in decimal equals 837) so we are looking for what address is "offset" from 001f0010 by the amount of 837 addresses. The Decimal value for 001f0010 is equal to: 2031632.. 2031632 + 837 = 2032469 convert that back to Hex and we have: 001F0355 (our offsetted address)

    Now, lets put this knowledge to use. In this example I'll use a common method found in MIPS for loading a value into a register from an address.

    In addition, I'll use my example from above so you can see its application as it pertains to MIPS. I will include both the MIPS assembly instructions and the mathmatical equivelent of the instruction which will be colored like this  MIPS / Mathmatical Equivilent

    In the simplest terms the instruction being performed here is: V0 = value stored at pointer 001f0010 + offset 0345

Back to top

Understanding MIPS Text and Numeric and Data Types

  1. Understanding HEX

    HEX - Hex is a numbering system that uses both letters and numbers to represent a decimal number. Hex uses only the numbers 0 thru 9 and the letters A thru F to represent any number, no matter how large.

    When you count in decimal, you would count to 100 like this:

    01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

    Using decimal you are forced to add a colum at 100, 1000, 10000, etc In hex however, to compress this information into a smaller more managable form (so you do not end up with addresses that look like : 10,234,566).

    The numbering system is a repetitive cycle of the numbers 0 thru 9 and A thru F so counting to 100 in hex would look like this:

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64

    This pattern would repeat itself until you reached a value of FF before requiring a new column to be added. FF in Hex equals the decimal number 255, so as u can see, you have an additional 155 values which would still only require 2 digits. following FF, a new colum is added and that colum is incremented by 1, and the first and second column would begin its cycle again at 00, so your next value after FF would be 100.

    At this point the numbers and letters in the second and third column would resume their same pattern like this:

    101 102 103 104 105 106 107 108 109 10A 10B 10C 10D 10E 10F 110 111 112 113 114 115 116 117 118 119 11A 11B 11C 11D 11E , ETC At

    At first glance, you might be thinking "well hell, hex seems more complicated than simple decimal numbers, so whats the benefit?"

    If you continue to follow this cycle until you need another aditional colunm (you've reached FFF) If you convert FFF back to decimal, it is equal to: 4095, so its pretty clear as the numbers increase even further, that you get alot more value for your space.

    When it comes to the Ps2s memory capacity, every byte counts. and going back to our previously mentioned example of 10,234,566.. if you convert that to hex, it equals 9DD876, which only requires 6 digits instead 8 doesnt seem like a huge savings does it.. until you consider this: every number after 999,999 (the highest 6 digit decimal number) and before 9,999,999 (the largest 7 digit number) requires that 1 additional digit... after that.. until you reach the end numner of 10,234,566, you require 2 additional digits... l

    lets do the math:

    9,999,999 - 999,999 = 9 million x 1 digit

    10,234,566 - 9,999,999 = 234,567 x 1 digit

    -------------------------------------------

    which equals: 9,234,567 additional digits to represent the values in decimal!! and thats not even counting the digits you wasted just getting to 999,999.  In any case, a basic understanding of HEX is essential when it comes to hacking ps2 games because all values (addresses, offsets, mathmatical formulas) are in HEX format NOT decimal..

  2. Whats a float value?

    A float value is another alpha numeric system using HEX to difine values. Do not mistake a float value with a direct HEX to decimal equivelent.

    For example, lets take the numner 1. In decimal, we represent the number one as its numeric value: 1

    In Hex the equivent of 1 is 1.. doesnt change.. Infact until you get to 10, hex and decimal are basically the same.

    A float value equivenlt of 1 however is a word-length hex representation of the number 1 and would look like this: 3f800000 in word format and 3f80 in halfword format. 

    I know this seems a little confusing. Why not just use straight hex? The simplist explaination that i can give you is that the additional space used in a float value (the difference between representing 1 in hex x00000001 and representing it as a float: 3f800000  is that with a 32 bit representation you have 7 additional digits to define numbers which may not be whole numbers.

    For exampe.. if you wanted to set a value at 1.464544 then a 32 bit value is the best way to do this.

  3. What is a string

    A "string" is a lable or game text that is stored at an address in thr form of byte length HEX codes.

    Now.. You might be asking at this point.. "how do we know what hex combination equals each character?'  To determine this we use the following "Text to HEX conversion chart"

     

Back to top

MIPS programing Language Guide

  1. Data Merging instructions

  2. Branching and Jumping Instructions

    A Branch or jump instruction tells the game program to jump or branch to elsewhere in the file.These functions can be used in calling processes or particularly in the case of branch, can be used in "decision making processes", "Testing conditions" etc.

    Following is some Psuedo Code for a typical game function:

    Ammo Counter:

    1. Did weapon fire --- [Yes] - Reduce Ammo amount by 1

    2. Is clip empty? [No] goto step 3 [Yes] Call Reload Function

    3. Update ammo/clip amounts

    In this example we went through a couple steps the game takes as a result of firing your gun. In MIPS this function may have taken an entire process worth of instructions to complete the task. Part of completing this task requires decisions to be made and a possible change of course for the program execution to take... a fork in the road if you will. This is where "branching" and "jumping" instructions come in.

  3. Data Storage and Retrieval Instructions

    MIP employs many different methods to store and retrieve information from both memory, registers, and addresses.

    Lets first explore the many ways to load data into registers in various amounts:

Back to top

Cheat Device Reference Guide

  1. Guide to Codebreaker Command Types

    Standard Format (CB/GS/XP/AR2)

     

    Code TypeFormat What it does

    Write Commands

    8-bit Constant Write 0aaaaaaa 000000dd

    This command will constantly write the value specified by dd to the address specified by aaaaaaa .

    16-bit Constant Write 1aaaaaaa 0000dddd This command will constantly write the value specified by dddd to the address specified by aaaaaaa .

    32-bit Constant Write

    2aaaaaaa dddddddd

    This command will constantly write the value specified by dddddddd to the address specified by aaaaaaa .

    Increment/Decrement Commands

    8-bit Increment 301000nn aaaaaaaa This command adds the value specified by nn to the value stored at the address aaaaaaaa .
    8-bit Decrement 302000nn aaaaaaaa

    This command subtracts the value specified by nn to the value stored at the address aaaaaaaa .

    16-bit Increment 3030nnnn aaaaaaaa

    This command adds the value specified by nnnn to the value stored at the address aaaaaaaa .

    16-bit Decrement 3040nnnn aaaaaaaa

    This command subtracts the value specified by nnnn to the value stored at the address aaaaaaaa .

    32-bit Increment

    30500000 aaaaaaaa
    nnnnnnnn 00000000

    This command adds the value specified by nnnnnnnn to the value stored at the address aaaaaaaa .

    32-bit Decrement 30600000 aaaaaaaa
    nnnnnnnn 00000000

    This command subtracts the value specified by nnnnnnnn to the value stored at the address aaaaaaaa .

    Test Commands

    16-bit Equal Daaaaaaa 0000dddd

    Only when the value at the address specified by aaaaaaa is equal to the value specified by dddd will the next line of code be executed.

    16-bit Not Equal

    Daaaaaaa 0010dddd

    Only when the value at the address specified by aaaaaaa is not equal to the value specified by dddd will the next line of code be executed.

    16-bit Less Than

    Daaaaaaa 0020dddd

    Only when the value at the address specified by aaaaaaa is less than the value specified by dddd will the next line of code be executed.

    16-bit Greater Than Daaaaaaa 0030dddd Only when the value at the address specified by aaaaaaa is greater than the value specified by dddd will the next line of code be executed.

    16-bit Equal : Multiple Skip

    Ennndddd 0aaaaaaa Only when the value at the address specified by aaaaaaa is equal to the value specified by dddd will the next nnn lines of code be executed. Otherwise, they will be skipped.
    16-bit Not Equal : Multiple Skip Ennndddd 1aaaaaaa

    Only when the value at the address specified by aaaaaaa is not equal to the value specified by dddd will the next nnn lines of code be executed. Otherwise, they will be skipped.

    16-bit Less Than : Multiple Skip

    Ennndddd 2aaaaaaa

    Only when the value at the address specified by aaaaaaa is less than the value specified by dddd will the next nnn lines of code be executed. Otherwise, they will be skipped.

    16-bit Greater Than : Multiple Skip Ennndddd 3aaaaaaa Only when the value at the address specified by aaaaaaa is greater than the value specified by dddd will the next nnn lines of code be executed. Otherwise, they will be skipped.

    Miscellaneous Commands

    Copy Bytes 5aaaaaaa nnnnnnnn
    bbbbbbbb 00000000
    a = Address to copy from
    b = Address to copy to
    n = Number of bytes to copy
    32-bit Multi-Address Write 4aaaaaaa xxxxyyyy
    dddddddd 00000000
    Starting with the address specified by aaaaaaa, this code will write to xxxx addresses. The next address is determined by incrementing the current address by (yyyy * 4). The value specified by dddddddd is written to each calculated address. Also known as a "Patch Code."

    Untested Commands

    Master-Command 8aaaaaaa bbbbbbbb
    cccccccc 00000000
    One Time ActivatorAaaaaaaa 000000xx
    Time Command B0000000 nnnnnnnn v = delay value (32 bit)
    Delay putting on all following codes for v cycles; effect varies between games.
    To act on all codes, put it at the top of the code list!

    B0000000 10000000
    Loop is executed 0x10000000 times.
    Code StopperCaaaaaaa vvvvvvvv a = address (25 bit)
    v = value (32 bit)

    All following codes will be executed only, if 32-bit value at given address, a, is equal to given value, v.
    Otherwise, they will be skipped. Can be used to exit the code sequence at any point.
    To act on all codes (like traditional "Auto Activation"), put it at the top of the code list!
    Example:
    C0153880 03E00008
    If the 32-bit value 0x03E00008 is at the address 0x00153880, then activate all following codes. Otherwise, do nothing.
    Master-Command Faaaaaaa bbbbbbbb
    Master Joker Command E0aabbbb 00xxxxxx


    CB7+
    All above codes also work on CB7+ here are what are added to it some of below codes may work on other devices and lower vers of CB but are untested on CB1-6..

    Code TypeFormat What it does

    Increment/Decrement Commands

    8-bit Increment 300000nn aaaaaaaa This command adds the value specified by nn to the value stored at the address aaaaaaaa .
    8-bit Decrement 301000nn aaaaaaaa This command subtracts the value specified by nn to the value stored at the address aaaaaaaa .
    16-bit Increment 3020nnnn aaaaaaaa This command adds the value specified by nnnn to the value stored at the address aaaaaaaa .
    16-bit Decrement 3030nnnn aaaaaaaa This command subtracts the value specified by nnnn to the value stored at the address aaaaaaaa .
    32-bit Increment 30400000 aaaaaaaa
    nnnnnnnn 00000000
    This command adds the value specified by nnnnnnnn to the value stored at the address aaaaaaaa .
    32-bit Decrement 30500000 aaaaaaaa
    nnnnnnnn 00000000
    This command subtracts the value specified by nnnnnnnn to the value stored at the address aaaaaaaa .

    Test Commands

    16-bit Greater Than : Multiple Skip Ezyyvvvv taaaaaaaA = address to check from
    T = type, 0 = equal to, 1 = not equal to,
                   2 = Less Than, 3 = Greater Than
    V = 16 or 8 bit value
    YY = # of codes to skip if condition is false
    Z = 0 =16-bit, 1 = 8-bit

    Pointer Commands

    8-bit write6aaaaaaa 000000vv
    0000nnnn iiiiiiii
    a = address to load 32-bit base from (25 bit)
    v = value to store at base + offset (8/16/32 bit)
    n = number of times to point (16 bit)
    i = 32-bit offset to add to base (n = 1)
    16-bit write6aaaaaaa 0000vvvv
    0001nnnn iiiiiiii
    a = address to load 32-bit base from (25 bit)
    v = value to store at base + offset (8/16/32 bit)
    n = number of times to point (16 bit)
    i = 32-bit offset to add to base (n = 1)
    32-bit write6aaaaaaa vvvvvvvv
    0002nnnn iiiiiiii
    a = address to load 32-bit base from (25 bit)
    v = value to store at base + offset (8/16/32 bit)
    n = number of times to point (16 bit)
    i = 32-bit offset to add to base (n = 1)
    Extra pointer line3rd lineExample 2:
    602829D8 FFFFFFFF
    00020002 0000071C
    0000FB20 00000000
    - loads base at address 0x002829D8, say base is 0x00290000
    - adds offset 0x0000071C to make address 0x0029071C
    - loads base at address 0x0029071C, say base is 0x002A0000
    - adds offset 0x0000FB20 to make address 0x002AFB20
    - stores 32-bit value 0xFFFFFFFF to address 0x002AFB20

    Note that execution stops, if (base & 0x3FFFFFFC) == 0.

    Boolean Commands  (Code type 7)

    8-bit OR7aaaaaaa 000000vva = address (25 bit)
    8-bit AND7aaaaaaa 000200vvv = value (8/16 bit)
    8-bit XOR 7aaaaaaa 000400vvPerforms a bitwise logical operation between given value, v, and the value stored at
    16-bit OR 7aaaaaaa 0001vvvvgiven address, a. (Example:)
    16-bit AND7aaaaaaa 0003vvvv7048D402 005014A9
    16-bit XOR 7aaaaaaa 0005vvvv0x14A9 is XORed to the 16-bit value at address 0x0048D402.

    Miscellaneous Commands

    Copy Bytes 5aaaaaaa nnnnnnnn
    bbbbbbbb 00000000
    a = Address to copy from
    b = Address to copy to
    n = Number of bytes to copy
    32-bit Multi-Address Write 4aaaaaaa xxxxyyyy
    dddddddd 00000000
    Starting with the address specified by aaaaaaa, this code will write to xxxx addresses. The next address is determined by incrementing the current address by (yyyy * 4). The value specified by dddddddd is written to each calculated address. Also known as a "Patch Code."
    32-bit Multi-Address Write/Value increase (GS/CB6+)4aaaaaaa xxxxyyyy
    dddddddd IIIIIIII
    Same As above but the I = size of value step (32 bit) as in how much it will count up on each address..
    Example
    4099A20C 00060002
    00000000 00100000
    - writes 0x00000000 to 0x0099A20C
    - writes 0x00100000 to 0x0099A214
    - writes 0x00200000 to 0x0099A21C
    - writes 0x00300000 to 0x0099A224
    - writes 0x00400000 to 0x0099A22C
    - writes 0x00500000 to 0x0099A234

    Credit to
    hellion00.thegfcc.com
    Codemasters-Projects (CMP)
    Xploder Freaxs (XFX)



    Tutorials:

    Code Type 6

    Basic Description

     *Function: Pointer/Indirect write.

    *Frequency: Constant.

    *Alignment: Full-word. (Pointer addresses must be full-word aligned. Data alignment depends on how the code is used.)

    *Minimum Version: Not known. Possibly 6.0. Version 7.0 is required for multiple levels of indirection.

     Format and Implementation

     6aaaaaaa xxxxxxxx

    000wcccc oooooooo

    ...additional offsets (valid on devices 7.0 and up only)

     *aaaaaaa: 25-bit pointer address.

    *xxxxxxxx: Value to be written. May be referenced as xx or xxxx as well.

    *w: Width of the data to be written.

    *cccc: Number of levels of indirection. (Number of pointers to be used, and also the number of offsets entered into the code).

    *oooooooo: 32-bit offset from pointer. There can be a variable number of these.

     Implementation: The starting pointer, located at aaaaaaa will be loaded and the offset oooooooo will be added to it, giving the temp_address. The pointer-count, cccc is decremented, and if it is zero, then the value xxxxxxxx will be stored at temp_address. If the pointer-count is not zero, the value at temp_address is loaded as a pointer, and the next offset is added to it. The process is repeated until the pointer-count is zero, at which time whatever value temp_address has will be overwritten with the value xxxxxxxx.

     Allowed Width (w) Values

     *0 - 8-bits.

    *1 - 16-bits.

    *2 - 32-bits.

     Notes

     *Execution of this code type will cease if a pointer ANDed with 0x3FFFFFFC is zero.

    *This code type can permit you to write to uncached and uncached-accelerated mirror-addresses, as well as coprocessor registers. Whether doing this is useful, or crash-prone is a matter that requires testing.

     Examples

     60EE7174 00000064

    00000001 00000020

     1.This code will load the pointer stored at 0x0EE7174, let us say its value is 0x0EB00B5.

    2.The offset 0×00000020 is added to it, giving the temp_address 0x0EB00D5.

    3.The count is decremented, and becomes zero.

    4.Therefore temp_address will be used as the final pointer, and the 8-bit value 0×64 will be stored at 0x0EB00D5.

    60EE7174 05F5E0FF
    00020003 00000020
    00000014 000003E8

     

    1.This code will load the pointer stored at 0x0EE7174, let us say its value is 0x0EB00B4

    2.The offset 0×00000020 is added to it, giving the temp_address 0x0EB00D4.

    3.The count is decremented, and becomes two.

    4.Since the count is not zero, the CodeBreaker will continue to load pointers. So the value at address 0x0EB00D4 is loaded, say it is 0x0EC0070.

    5.The next offset, 0×00000014 is added to 0x0EC0070, giving a new temp_address of 0x0EC0084.

    6.The count is decremented and becomes one.

    7.The value at 0x0EC0084 is loaded as yet another pointer. Say its value is 0x0EA6A00.

    8.The next, and final, offset is added to it, giving a new temp_address of 0x0EA6DE8.

    9.The counter is decremented and becomes zero.

    10. Now that the count is zero, all the pointing is done. The value 32-bit value (w is 2) 0x05F5E0FF is stored at 0x0EA6DE8.

     

    Author: Pyriel


     

     

  2. ARMax Command List

    ARMax Code Types :

    00, 01 - 8-bit Write (also Fill with a value specified in the upper 3 bytes of the VALUE)

    02, 03 - 16-bit Write (also Fill with a value specified in the upper 2 bytes of the VALUE)

    04, 05 - 32-bit Write

    08, 09 - 8-bit Equal

    0A, 0B - 16-bit Equal

    0C, 0D - 32-bit Equal

    10, 11 - 8-bit Not Equal

    12, 13 - 16-bit Not Equal

    14, 15 - 32-bit Not Equal

    18, 19 - 8-bit Less Than (Signed) [DON'T USE?]

    1A, 1B - 16-bit Less Than (Signed)

    1C, 1D - 32-bit Less Than (Signed)

    20, 21 - 8-bit Greater Than (Signed) [DON'T USE?]

    22, 23 - 16-bit Greater Than (Signed)

    24, 25 - 32-bit Greater Than (Signed)

    28, 29 - 8-bit Less Than (Unsigned)

    2A, 2B - 16-bit Less Than (Unsigned)

    2C, 2D - 32-bit Less Than (Unsigned)

    30, 31 - 8-bit Greater Than (Unsigned)

    32, 33 - 16-bit Greater Than (Unsigned)

    34, 35 - 32-bit Greater Than (Unsigned)

    38 to 3D - ???

    40, 41 - 8-bit Pointer Write

    42, 43 - 16-bit Pointer Write

    44, 45 - 32-bit Pointer Write

    48, 49 - 8-bit Equal 2-Code Joker???

    4A, 4B - 16-bit Equal 2-Code Joker???

    4C, 4D - 32-bit Equal 2-Code Joker???

    50, 51 - 8-bit Not Equal 2-Code Joker???

    52, 53 - 16-bit Not Equal 2-Code Joker???

    54, 55 - 32-bit Not Equal 2-Code Joker???

    58, 59 - 8-bit Less Than (Signed) 2-Code Joker??? [DON'T USE?]

    5A, 5B - 16-bit Less Than (Signed) 2-Code Joker???

    5C, 5D - 32-bit Less Than (Signed) 2-Code Joker???

    60, 61 - 8-bit Greater Than (Signed) 2-Code Joker??? [DON'T USE?]

    62, 63 - 16-bit Greater Than (Signed) 2-Code Joker???

    64, 65 - 32-bit Greater Than (Signed) 2-Code Joker???

    68, 69 - 8-bit Less Than (Unsigned) 2-Code Joker???

    6A, 6B - 16-bit Less Than (Unsigned) 2-Code Joker???

    6C, 6D - 32-bit Less Than (Unsigned) 2-Code Joker???

    70, 71 - 8-bit Greater Than (Unsigned) 2-Code Joker???

    72, 73 - 16-bit Greater Than (Unsigned) 2-Code Joker???

    74, 75 - 32-bit Greater Than (Unsigned) 2-Code Joker???

    78 to 7D - ??? 80, 81 - 8-bit Increment

    82, 83 - 16-bit Increment

    84, 85 - 32-bit Increment 88, 89 - 8-bit Equal All-Code Joker???

    8A, 8B - 16-bit Equal All-Code Joker???

    8C, 8D - 32-bit Equal All-Code Joker???

    90, 91 - 8-bit Not Equal All-Code Joker???

    92, 93 - 16-bit Not Equal All-Code Joker???

    94, 95 - 32-bit Not Equal All-Code Joker???

    98, 99 - 8-bit Less Than (Signed) All-Code Joker??? [DON'T USE?]

    9A, 9B - 16-bit Less Than (Signed) All-Code Joker???

    9C, 9D - 32-bit Less Than (Signed) All-Code Joker???

    A0, A1 - 8-bit Greater Than (Signed) All-Code Joker??? [DON'T USE?]

    A2, A3 - 16-bit Greater Than (Signed) All-Code Joker???

    A4, A5 - 32-bit Greater Than (Signed) All-Code Joker???

    A8, A9 - 8-bit Less Than (Unsigned) All-Code Joker???

    AA, AB - 16-bit Less Than (Unsigned) All-Code Joker???

    AC, AD - 32-bit Less Than (Unsigned) All-Code Joker???

    B0, B1 - 8-bit Greater Than (Unsigned) All-Code Joker???

    B2, B3 - 16-bit Greater Than (Unsigned) All-Code Joker???

    B4, B5 - 32-bit Greater Than (Unsigned) All-Code Joker???

    B8 to BD - ???

    C0, C1 - Master Code?

    C2, C3 - Master Code?

    C4, C5 - Master Code?

    C8, C9 - 8-bit Not Equal Turn Off All Codes???

    CA, CB - 16-bit Not Equal Turn Off All Codes???

    CC, CD - 32-bit Not Equal Turn Off All Codes???

    D0, D1 - 8-bit Equal Turn Off All Codes???

    D2, D3 - 16-bit Equal Turn Off All Codes???

    D4, D5 - 32-bit Equal Turn Off All Codes???

    D8, D9 - 8-bit Greater Than (Signed) Turn Off All Codes??? [DON'T USE?]

    DA, DB - 16-bit Greater Than (Signed) Turn Off All Codes???

    DC, DD - 32-bit Greater Than (Signed) Turn Off All Codes???

    E0, E1 - 8-bit Less Than (Signed) Turn Off All Codes??? [DON'T USE?]

    E2, E3 - 16-bit Less Than (Signed) Turn Off All Codes???

    E4, E5 - 32-bit Less Than (Signed) Turn Off All Codes???

    E8, E9 - 8-bit Greater Than (Unsigned) Turn Off All Codes???

    EA, EB - 16-bit Greater Than (Unsigned) Turn Off All Codes???

    EC, ED - 32-bit Greater Than (Unsigned) Turn Off All Codes???

    F0, F1 - 8-bit Less Than (Unsigned) Turn Off All Codes???

    F2, F3 - 16-bit Less Than (Unsigned) Turn Off All Codes???

    F4, F5 - 32-bit Less Than (Unsigned) Turn Off All Codes???

    F8 to FD - ???

Back to top

Ps2Dis Key Reference Guide

  1. Setting Fonts

    Run ps2dis.exe, then choose fonts at first. Focus disassembler window and choose "Preference-fonts...". Focus Hex window and do it in the same way. I think "Courier New - regular" is a good choice

  2. BROWSING and ANALYZING PS2 BINARIES

    Simply drop a PS2 executable. Use following keys to browse,

    KEY                         ACTION

    UP/DOWN                     Moves up and down

    PageUp,PageDown             Next/Prev page

    Ctrl+PageUp,Down            1000h Up/Down

    Alt+PageUp,Down             10000h Up/Down

    g                           Jump to specified address

    Ctrl+g                      Jump to specified label (if there are labels set).

    Right arrow                 (USEFUL!) Jump to address which current line refers to.

    Left arrow                  Return back to referrer.

  3. LABELLING TEXT RESOURCES

    There must be some text resources in .data or .rodata section. If you find them, I sugest you label it with this easy way. Cursor the top of string(s). Then press Shift+b and label is set. If there are more strings after this, continue pressing that key.

  4. LABELLING SYSCALLs

    PS2 kernel supports some system-calls and most executables have these functions. PS2DIS will automatically find and label them. Choose "label syscall" from menu "Analyzer".

  5. LABELLING MEMORY MAPPED I/Os

    ps2.map that comes with ps2dis.exe defines some known I/O addresses. Choose "Load label" from menu "File" then import it. INVOKING ANALYZER PS2DIS has powerful analyzer functions. To use it, you should run Analyzer first. Choose "Invoke analyzer" from menu "Analyzer". It may looks as if it hangs up, but don't worry, wait a while and it should return. You will see another labels like FNC_XXXXXXXX or __XXXXXXXX which are refered from somewhere. FNC_XXXXXXXX are the points that some JALs point to. Mark it using SPACE key then press F3, you will see the referrers. Press Alt+x to return back to marked address.(This exchanges cursor and mark.) Press F3 to jump to next referrer. Press Alt+A to show/hide these labels.

  6. IMPORTING LABELS FROM AN OTHER FILE

    This function will transplant symbols from files which has symbols. You should invoke Analyzer before do this. Try "Import labels from other file" in menu "Analyzer" then choose any file that has symbols. It finds functions that are assumed same, and label them. Check labels using Ctrl+g!

  7. Keys - DATA TYPE RELATED

    b            Set type as BYTE
    Alt+b        Set type of the region between marked aSet type as BYTESet type of the region between region between ursor as BYTEsnd cSet type as BYTESet type of the region between ursor as BYTEs
    Shift+b      Set type as BYTE then label it

    h            Set type as HALF WORD
    Alt+h        Set type of the region between marked and cursor as HALFs
    w            Set type as WORD
    Alt+w        Set type of the region between marked and cursor as WORDs
    d            Set type as DOUBLE WORD
    Alt+d        Set type of the region between marked and cursor as DWORDs
    q            Set type as QUAD WORD
    Alt+q        Set type of the region between marked and cursor as QWORDs
    c            Set type as CODE
    Alt+c        Set type of the region between marked and cursor as CODEs
    f            Set type as FLOAT
    Alt+f        Set type of the region between marked and cursor as FLOATs
    v           (EXPERIMENTAL) Set type as VU MICRO CODE - lower/upper
    Alt+v       (EXPERIMENTAL) Set type of region as VU MICRO CODE
    u           Set type as UNDEFINED(almost same as CODE)
    Alt+u       Set type of the region between marked and cursor as UNDEFs
    Shift+u     Set type as NOT INITIALIZED

  8. Keys - MARK/REGION RELATED

    SPACE         Mark current line, or reset current mark

    Ctrl+t        Save region(lines between current line and marked line) as text file

    Ctrl+c        Copy current function to the clipboard

  9. Keys - ADDRESS STACK RELATED

    Right arrow Push current address into Stack then jump to address where the current line refer to Left arrow Pop an address from Stack then jump to the address. Popped address is still there. See below. Ctrl+Right arrow Jump to the address which has popped recently. It behaves like 'history' function of WWW browsers. Ctrl+Left arrow Back to the Stack. It behaves like 'history' function of WWW browsers. Insert Push current address into Stack

  10. Keys - Editor

    Enter Editor dialog pops up. You can edit label,command and opcode itself. If you edit opcodes, all histories are saved as Patch. See 'p' command.

  11. Keys - PATCH

    p Open 'patch' dialog. You can view all changes, enable/disable each change, and copy that infos to the clip board (for creating chat codes). (Assembler function doesn't work properly with some opcodes, for now.)

  12. Keys - Movement & Search keys

    PageUp or Ctrl+b      Page Up

    PageDown or Ctrl+f    Page Down

    Up                    move up

    Down                  move down

    Ctrl+Up/Down          Up/Down to prev/next function

    Ctrl+PageUp,Down      1000h Up/Down

    Alt+PageUp,Down       10000h Up/Down

    F4                    Find the 32bit word you set. (forward)

    Shift+F4              Find the 32bit word you set. (backward)

    Ctrl+f                Find pattern

    F5                    Find the pattern you set. (forward)

    Shift+F5              Find the pattern you set. (backward)

    Shift+Up/Down         Move cursor up/down with address fixed

    Shift+PageUp/PageDown Move cursor up/down with address fixed

    g     Jump to specified address in hexadecimal. When you hit space key after typed all 8 hex charcters, it decodes the address as AR2 cheat code.

     

    Ctrl+g Jump to the address where the selected symbol belongs to Home Jump to start address Shift+3 Set a 32bit word then find next.


  13. Keys - ANALYZER RELATED

    Alt+x              Exchange current line with marked line F3 Jump to next address where marked line reffers to

    Shift+F3           Jump to previous address where marked line reffers to

    Ctrl+i             Import symbols (of function names) from other file

    Ctrl+Shift+1        Import symbols (of function names) from folder which has PSX Libs(*.lib). This function doesn't support multi-thread so it looks as if it hungs up...

Back to top
Still have questions? Feel free to Contact Us