Back Previous Next

Basics

"Advanced" is a relative term. Some people may get a headache just reading through this section. Others may snort: "You call this advanced? So when does the hard stuff start?" I don't consider myself a truly advanced hacker; I just write up the info as I discover it. So, in this section, "advanced" means it's not just a question of putting in a few ticks or adding a string; this is programming proper.

A computer programming language serves as a layer between the kind of language humans understand and the machine instructions that a computer understands. There are many computer languages, with different approaches and varying degrees of complexity. Generally, the more a computer language resembles human language, the "higher" it is, and the more effort is needed to translate it back to machine instructions. Computer programs are usually written in plain ASCII (the "source" or "code") and then compiled, producing an executable (usually, a file ending on ".EXE") that will run on the computer, but will only produce blips and funny characters if opened in a text editor. Programs don't always need compiling to be run; java code is semi-compiled to something called "bytecode", and BASIC programs will run from the ASCII file. Whether compiled or not, they may not be able to run independently, but may need additional files to be understandable to the computer, such as the Windows DLLS, or the Java runtime environment. A runtime environment contains all the extra files, programs etc. that enable the computer to run programs written in a certain language; it is like a programming environment without the editing/compiling options.

The computer language of the Sims is called SimAntics. Code is written in hex, rather than ASCII, and the resulting program files usually end on ".IFF". They are interpreted by the executable "Sims.exe", which serves as the Sims runtime environment. The Sim equivalent of the Windows DLLs are the IFF files in GameData\Global\Global.far.

Some basic principles of computer programming: a computer understands only two things, Yes and No, also written as True and False. It natively counts in the binary system, which allows only the numbers 0 and 1 (representing, to the computer, False and True, though the True/False outcome of an expression may refer to different values) and also uses the hexadecimal system, which counts in blocks of sixteen instead of ten, so that 1-9 is followed by A, B, C, D, E, F and "10" in hexadecimal means "16" in the commonly used decimal system. A computer's information unit is a byte, which is eight bits (each bit having the value 0 or 1) and is represented in hexadecimal code as "nn", so that value "A" (10) is written as "0A". The Sims uses double bytes, meaning two times "nn", so that "A" is written "0A 00". Lastly, a computer works by stepping through a list of instructions. Any computer program, be it ever so intricate, uses the basic system of: line 0: do stuff; line 1: do other stuff; line 2: do more stuff - etc. The instructions can be numbered to indicate in which order they should be obeyed, and to allow conditional processing: eg. on the condition that X = Y, jump to line 5, else continue with line 3. When the last line is reached, the program exits. Programs that don't exit, iterate, that is, the last line's instruction reads "start over". (Any part of a program called "main" probably iterates, since it keeps the program in the air, so to speak.) And, being binary creatures, computers start counting at 0.

Applying this to The Sims: binary only really matters for catalogue categories, which instead of being numbered 1 to 8, are numbered 1, 2, 4, 8, 16, 32, 64, 128 or, as it would look in binary: 00000001, 00000010, 00000100, 00001000, 00010000, 00100000, 01000000 and 10000000 (notice the 1 shifting forwards). Instructions, which is what I'll be tinkering with, are coded in hex. The instruction line numbers are in decimal, as are the instruction block numbers, the block types and calls to instruction blocks in other files (the globals, generally). At least, IFF Pencil presents the block and line numbers as decimal; maybe the IFF uses a different system internally.

Looking at a Sims IFF file in an IFF editor, the code is found in the BHAV block, which contains numbered blocks ("trees", as in: Action tree, Test tree) generally starting at #4096, and containing lines of instructions. And in true computer spirit, each instruction line has two outcomes: True and False. True means: the expression (eg. "is local variable 0 equal to constant 1?") is true, or, the instruction (eg. "add 1 to value of variable 0") was carried out succesfully, while false means the opposite, ie. it's not true or it didn't work. Confusingly, these outcomes can be assigned four values: True, False, Error or a line number. And the True outcome can be assigned a False value. This is because the True/False outcomes are simply there to fill in what to do next if the instruction is true/works, or not. And the True/False/Error/Line values are the following decisions:

True: quit tree and say it worked or was true.
False: quit tree and say it wasn't true.
Error: quit tree and say it didn't work.
Line [n]: jump to line [n]

To make this a bit more comprehensible:

line #1: Did you steal the cookies?" Yes/No

This is an expression, which can be true or false. The values assigned to either outcome can be:

Yes: True (I confess)
     False (Let's pretend I didn't)
     Error (Investigation failed)
     Line 8 (proceed to #8, Punishment)

No:  True (I take the blame)
     False (Not guilty)
     Error (What was the question again?)
     Line 9 (proceed to #9, Question others)

Assigning True to a False outcome can have its uses. Suppose the tree containing this line is called "Determine innocence". If this tree is run from another tree which sees True as innocent and False as guilty, then the False outcome of #1 should have the value "True", ie. "It is true that I didn't steal the cookies".


The many programs that go into the object "baby".

In the editing window of IFF Pencil, when I double-click on the BHAV block, the IFF file content shown in the right window is restricted to that belonging to the BHAV block: the code "trees". These are little programs that may be called directly or indirectly after choosing an action from the menu, or that may test whether a menu option should become visible at all, or that may direct events outside the user's control. One program can call another inside the same object, or it can call a common routine in one of the globals, or a "named tree" in another object; the bills call a "Pay bills" program in the mailbox to be paid, for instance. If there was a program "who stole the cookies" as in the example above, if many IFFs use it, it would be in a globals file, and the globals file name would be declared in the GLOB block, and the call to that program would be something like "(semi) who stole the cookies" (where "semi" means semi-global; "glob" is used for the truly global ones from "Global.iff"). If it's only used in this object, it would be another tree in the BHAV block, and the call would go "(priv) who stole the cookies". Whether global or private, the call will always come with an answer True/False/Error, and maybe a new value in the "Temporary storage", what I assume to be a public variable. The private variables available to a tree (private meaning, they can't be read by other trees) are called "Local variable" and like their public counterparts, are numbered from 0 upwards. They're just a row of empty pigeonholes to store data in as needed. Two trees found in almost every object are "init", to put an object into the virtual world, and "main", to keep it there.


A simple tree, with few lines of code.

Double-clicking on a tree opens the editing window for that tree, showing its lines of code. Each line has a number, starting with 0, and two outcomes, either line numbers or True/False/Error, as described above. Selecting a line brings up its outcomes and parameter values in the "data" rectangle to the right. (The header info is generally not important.) Looking at the outcomes, I see that the program always starts at line 0, may go to line 1, and from there, jumps all over the place. Two things give an indication of where a program is going: an outcome of "True,Error" means the program ends after that line, and the outcome "[number],Error" means that the line just leads to a next line. If both outcomes are line numbers, the program may be branching into two different courses of action, or it may be starting a loop.

The editing window has a header rectangle and a data rectangle. The data rectangle only applies to the line of code being edited, the header rectangle to the whole BHAV tree. The header does have a function, I learned on a hacking forum: this is where the number of variables and parameters used in the whole tree is declared. If these are not filled, said variables and parameters are ignored, and the object doesn't work. The average hacker, only torqueing existing code, can modify hundreds of objects and never run into this; it only becomes apparent when adding entirely new code.

The data rectangle is where it all happens. This contains the outcome line numbers, the function, or type of code line (by default 2, Expression; but it can be many things, as the dropdown shows) and the four parameters that determine what the line does, in decimal and hex (double byte) format. Changing the value of the parameters will change the code line: in the "simple tree" example two paragraphs up (though it may be hard to see), if I change the highlighted value of the second parameter, 0, to 1, the expression will become: "is the stack object's attribute 2 equal to 1?" This suggests that parameters 1 and 2 are at both ends of the equation, which is often the case. Parameter 3 is the "sign" in the equation, in this case "is equal to?" and parameter 4 has some say over what's being compared. That's how it works in Expressions (function type 2). In other functions, the parameters have a different purpose or may even be ignored.

To make the line of code I need, I usually look at a line that's close to what I want (as I rarely find directly what I want) and fiddle with the parameters until I see something I like. It's best to alter the hex parameters, as each byte is significant and will change the result; the decimal parameters are just the hex values added up, and changing "1795" to "1796" will probably have no effect.

To find such an "example" line, I look in either a standard Maxis object or a fan-made object that has been declared hackable for general use, like the Virtuoso Chair. There are object programmers who jealously guard their secrets, and while I am unimpressed by their hollow threats about suing for infringement of copyright, I do understand that someone who sees the results of their hard work and research simply snatched up by a lazier artist, will be mightily annoyed. So respect, not fear of copyright, keeps my nose out of fan objects. Not that this will ever prevent fans yelling at me or anyone else: "You stole my object!!" because what object hacking comes down to is finding ways to make the game more playable; and artists will often independently hit on the same way. Making Sims objects buyable is by now an ancient art, and the coffee machine tutorial that came with Constant Contraption has spawned many supercafeine machines. Generally, it simply isn't necessary to peek in fan objects. The objects in my standard Sims installation can provide me with all the examples I need.

I'm assuming that whoever reads this section has already read the previous section, simple object hacking, if only because the first howto of this section is a continuation of the tenth howto in the previous one; but I'll repeat here that hacking should be done with IFF Pencil, not with Script Station or Codex. Not only are they unreliable when it comes to saving files, but Script Station displays less information and has less editing options. It was the first program I heard of that allowed players to program their own objects (Maxis considered putting out a programming utility of their own, but it never happened) but it may now be considered out of date. Codex, version 0.6, is very up to date, but still has bugs. IFF Pencil is compatible with all versions up to Unleashed.





Back Previous Next