OldGamesCracking

To unprotect and to preserve

View on GitHub
1 March 2026

The Sims 2 - Parser OpCode Reference

by OldGamesCracking

OpCodes

OpCode 1 Memory Transfer CS -> DS (Load)
Handler Location 66747380
Equivalent RISC Instruction lw

Moves data from the Code Segment to the Data Segment. In relative addressing mode, a value from the Data Segment is used as lookup.

ds:[DEST] = cs:[SRC]
ds:[DEST] = cs:[ds:[SRC_HIGH]]

lw rd, imm(r0)
lw rd, 0(rs1)
OpCode 2 Memory Transfer DS -> CS (Store)
Handler Location 66747260
Equivalent RISC Instruction sw

Moves data from the Data Segment to the Code Segment. In relative addressing mode, a value from the Data Segment is used as lookup. Note that for this command DEST and SRC are swapped or else values past 255 could not be reached.

cs:[SRC] = ds:[DEST]
cs:[ds:[SRC_HIGH]] = ds:[DEST]

sw rs2, imm(r0)
sw rs2, 0(rs1)
OpCode 3 Memory Transfer const/DS -> DS (Load Immediate)
Handler Location 667474B0
Equivalent RISC Instruction li, mv

Moves either a constant value to the Data Segment or copies a value in relative addressing mode.

ds:[DEST] = SRC
ds:[DEST] = ds:[SRC_HIGH]

li rd, imm
mv rd, rs1
OpCode 4 Shift Left
Handler Location 66748860
Equivalent RISC Instruction sll, slli

Left-Shifts a value in the Data Segment. Only the lower part of the operand is used. For relative addressing mode, the value at ds:[SRC_HIGH] is left-shifted, the result is stored in ds:[DEST].

ds:[DEST] = ds:[DEST] << SRC_LOW
ds:[DEST] = ds:[SRC_HIGH] << byte:ds:[SRC_LOW]

slli rd, rs1, shamt
sll rd, rs1, rs2
OpCode 5 Shift Right
Handler Location 66748A30
Equivalent RISC Instruction srl, srli

Right-Shifts a value in the Data Segment. Only the lower part of the operand is used. For relative addressing mode, the value at ds:[SRC_HIGH] is right-shifted, the result is stored in ds:[DEST].

ds:[DEST] = ds:[DEST] >> SRC_LOW
ds:[DEST] = ds:[SRC_HIGH] >> byte:ds:[SRC_LOW]

srli rd, rs1, shamt
srl rd, rs1, rs2
OpCode 6 Bitwise AND
Handler Location 66747B00
Equivalent RISC Instruction and, andi

Performs a bitwise AND on a value in the Data Segment. For relative addressing mode, the value at ds:[SRC_HIGH] is AND-ed, the result is stored in ds:[DEST].

ds:[DEST] = ds:[DEST] & SRC
ds:[DEST] = ds:[SRC_HIGH] & ds:[SRC\_LOW]

andi rd, rs1, imm
and rd, rs1, rs2
OpCode 7 Bitwise OR
Handler Location 66747C70
Equivalent RISC Instruction or, ori

Performs a bitwise OR on a value in the Data Segment. For relative addressing mode, the value at ds:[SRC_HIGH] is OR-ed, the result is stored in ds:[DEST].

ds:[DEST] = ds:[DEST] | SRC
ds:[DEST] = ds:[SRC_HIGH] | ds:[SRC\_LOW]

ori rd, rs1, imm
or rd, rs1, rs2
OpCode 8 Bitwise XOR
Handler Location 66747f50
Equivalent RISC Instruction xor, xori

Performs a bitwise XOR on a value in the Data Segment. For relative addressing mode, the value at ds:[SRC_HIGH] is XOR-ed, the result is stored in ds:[DEST].

ds:[DEST] = ds:[DEST] ^ SRC
ds:[DEST] = ds:[SRC_HIGH] ^ ds:[SRC\_LOW]

xori rd, rs1, imm
xor rd, rs1, rs2
OpCode 9 Bit Invert
Handler Location 66748120
Equivalent RISC Instruction binv, binvi

Inverts a single Bit.

ds:[DEST] = ds:[DEST] ^ (1 << SRC)
ds:[DEST] = ds:[SRC_HIGH] ^ (1 << ds:[SRC_LOW])

binvi rd, rs1, shamt
binv rd, rs1, rs2
OpCode 10 Bit Set
Handler Location 667482F0
Equivalent RISC Instruction bset, bseti

Sets a single Bit.

ds:[DEST] = ds:[DEST] | (1 << SRC)
ds:[DEST] = ds:[SRC_HIGH] | (1 << ds:[SRC_LOW])

bseti rd, rs1, shamt
bset rd, rs1, rs2
OpCode 11 Bit Clear
Handler Location 66748690
Equivalent RISC Instruction bclr, bclri

Clears a single Bit.

ds:[DEST] = ds:[DEST] & ~(1 << SRC)
ds:[DEST] = ds:[SRC_HIGH] & ~(1 << ds:[SRC_LOW])

bclri rd, rs1, shamt
bclr rd, rs1, rs2
OpCode 12 Bit Test
Handler Location 667484c0
Equivalent RISC Instruction bext, bexti

Sets DEST to the value of the selected Bit (0/1).

ds:[DEST] = (ds:[DEST] >> SRC) & 0x1
ds:[DEST] = (ds:[SRC_HIGH] >> ds:[SRC_LOW]) & 0x1

bexti rd, rs1, shamt
bext rd, rs1, rs2
OpCode 14 Add Values
Handler Location 66748c00
Equivalent RISC Instruction add, addi

Adds two values together.

ds:[DEST] = ds:[DEST] + SRC
ds:[DEST] = ds:[SRC_HIGH] + ds:[SRC_LOW]

addi rd,rs1,imm
add rd,rs1,rs2
OpCode 15 Subtract Values
Handler Location 66748DD0
Equivalent RISC Instruction sub, subi

Subtracts two values from each other.

ds:[DEST] = ds:[DEST] - SRC
ds:[DEST] = ds:[SRC_HIGH] - ds:[SRC_LOW]

subi rd, rs1, imm
sub rd, rs1, rs2
OpCode 16 Multiply Values
Handler Location 66748FA0
Equivalent RISC Instruction mul

Multiply two values.

ds:[DEST] = ds:[DEST] * SRC
ds:[DEST] = ds:[SRC_HIGH] * ds:[SRC_LOW]

muli rd, rs1, imm
mul rd, rs1, rs2
OpCode 17 Divide Values
Handler Location 66748FA0
Equivalent RISC Instruction div

Divide two values.

ds:[DEST] = ds:[DEST] / SRC
ds:[DEST] = ds:[SRC_HIGH] / ds:[SRC_LOW]

divi rd, rs1, imm
div rd, rs1, rs2
OpCode 18 Remainder
Handler Location 66749340
Equivalent RISC Instruction rem

Calculates the remainder of a division (mod)

ds:[DEST] = ds:[DEST] % SRC
ds:[DEST] = ds:[SRC_HIGH] % ds:[SRC_LOW]

remi rd, rs1, imm
rem rd, rs1, rs2
OpCode 19 Compare Values for Equality
Handler Location 66749510
Equivalent RISC Instruction seq, seqi (?)

Compares two values and stores the result (0/1) in DEST. I’m not sure if this really is a common RISC instruction.

ds:[DEST] = (ds:[DEST] == SRC) ? 1 : 0
ds:[DEST] = (ds:[SRC_HIGH] == ds:[SRC_LOW]) ? 1 : 0

seqi rd, imm
seq rd, rs1, rs2
OpCode 20 Set Less Than
Handler Location 66749710
Equivalent RISC Instruction slt, slti

Sets DEST to 0/1 if one of the values is lower (unequal).

ds:[DEST] = (ds:[DEST] < SRC) ? 1 : 0
ds:[DEST] = (ds:[SRC_HIGH] < ds:[SRC_LOW]) ? 1 : 0

slti rd, imm
slt rd, rs1, rs2
OpCode 21 Check Overflow - Subtraction
Handler Location 66749AE0
Equivalent RISC Instruction ???

I don’t know if that instruction represents a real RISC instruction. It subtracts the given values and returns the overflow flag.

ds:[DEST] = get_overflow_sub(ds:[DEST], SRC)
ds:[DEST] = get_overflow_sub(ds:[SRC_HIGH], ds:[SRC_LOW])

sofsubi rd, imm
sofsub rd, rs1, rs2 
OpCode 22 Check Carry - Subtraction
Handler Location 667498C0
Equivalent RISC Instruction ???

Same as 21, but returns the Carry Flag

ds:[DEST] = get_carry_sub(ds:[DEST], SRC)
ds:[DEST] = get_carry_sub(ds:[SRC_HIGH], ds:[SRC_LOW])

scfsubi rd, imm
scfsub rd, rs1, rs2 
OpCode 23 Check Overflow - Addition
Handler Location 66749F90
Equivalent RISC Instruction ???

Same as 21, but for addition

ds:[DEST] = get_overflow_add(ds:[DEST], SRC)
ds:[DEST] = get_overflow_add(ds:[SRC_HIGH], ds:[SRC_LOW])

sofaddi rd, imm
sofadd rd, rs1, rs2 
OpCode 24 Check Carry - Addition
Handler Location 66749D20
Equivalent RISC Instruction ???

Same as 23, but returns the Carry Flag

ds:[DEST] = get_carry_add(ds:[DEST], SRC)
ds:[DEST] = get_carry_add(ds:[SRC_HIGH], ds:[SRC_LOW])

scfaddi rd, imm
scfadd rd, rs1, rs2 
OpCode 25 Check Adjust - Addition
Handler Location 6674A1F0
Equivalent RISC Instruction ???

Same as 23, but returns the Adjust Flag (Auxiliary Carry Flag)

ds:[DEST] = get_adjust_add(ds:[DEST], SRC)
ds:[DEST] = get_adjust_add(ds:[SRC_HIGH], ds:[SRC_LOW])

safaddi rd, imm
safadd rd, rs1, rs2 
OpCode 26 Check Adjust - Addition
Handler Location 6674A450
Equivalent RISC Instruction ???

Same as 23, but returns the Adjust Flag (Auxiliary Carry Flag)

ds:[DEST] = get_adjust_add(ds:[DEST], SRC)
ds:[DEST] = get_adjust_add(ds:[SRC_HIGH], ds:[SRC_LOW])

safaddi rd, imm
safadd rd, rs1, rs2 
OpCode 27 Jump if not Zero
Handler Location 6674A610
Equivalent RISC Instruction bnez

This is a complex opcode, it tests DEST for being NOT zero and if so, the value at address 0xff in the Data Segent is set to a value from either the Code Segment (absolute addressing mode) or the Code Segment (relative addressing mode). It’s not obvious right away, but address 0xff is used as the program counter pc, so this really is a bnez. If DEST is 0x00, this becomes a NOP since this address is always set to zero. Also ds:[0xfd] is set to the previous value of ds:[0xff] (EIP) which at that time already points to the next instruction. So ds:[0xfd] can be used as the return address.

IF ds:[DEST] != 0 THEN
    ds:[0xfd] = ds:[0xff]
    ds:[0xff] = cs:[SRC]
FI

IF ds:[DEST] != 0 THEN
    ds:[0xfd] = ds:[0xff]
    ds:[0xff] = ds:[SRC_HIGH];
FI

bnez rs1, rs2, imm
OpCode 28 Jump if Zero
Handler Location 6674a8c0
Equivalent xRISC Instruction beqz

This is the same as OpCode 27, only the logic is inverted. If DEST is 0x00, this becomes a JMP since this address is always set to zero.
Also, if SRC is the t0 register - which is used to store the return address - this can be seen as a ‘return from subroutine’ instruction.

IF ds:[DEST] == 0 THEN
    ds:[0xfd] = ds:[0xff]
    ds:[0xff] = cs:[SRC]
FI

IF ds:[DEST] == 0 THEN
    ds:[0xfd] = ds:[0xff]
    ds:[0xff] = ds:[SRC_HIGH];
FI

beqz rs1, imm
call symbol ; (implicit, if dest == r0)
rts ; (implicit, if src == ra)
OpCode 29 Stop Execution
Handler Location 66747250
Equivalent RISC Instruction RET

This is not a real OpCode, it will set the ‘done’ Flag in the VM and thus stop executing the code. So this is somewhat of a RET instruction.


There are two more instructions (27, 28), but since they are not used, I did not bother to figure out their meaning. If I had to guess I would say they are some kind of jump/call instructions.


tags: The Sims 2 - Game Cracking - Reverse Engineering - SafeDisc - VM - Virtual Machine - DLL Injection - Self Debugging