OldGamesCracking

To unprotect and to preserve

View on GitHub
1 March 2026

The Sims 2 - VM OpCode Reference

by OldGamesCracking

OpCodes

Note: These are the OpCodes that get derived from the ‘Initialization Vectors’ (IV). They represent the emulated instructions and should be de-virtualizeable back to x86 assembly. They are not to be confused with the internal static Parser OpCodes of the VM.

OpCode 0 Register Transfer
Handler Location 015D
Used Parameters a0: destination, a1: source
Equivalent x86 Instruction MOV, JMP

Moves a value from one register to another. Note that this can be used to perform an unconditional absolute far-jump if EIP is chosen as destination register.

REG[a0] = REG[a1]

MOV <reg>, <reg>
MOV <reg>, IMM
JMP <address>
OpCode 1 Jump
Handler Location 0160
Used Parameters a0: base, a1: offset
Equivalent x86 Instruction JMP

This adds the second operand to the first, so in theory this can be a generic ADD-instruction, but since the flags are not updated, one can guess that only EIP as first operand makes sense, thus it performs a relative jump.

REG[a0] += REG[a1]

JMP <offset>
OpCode 2 CALL
Handler Location 019F
Used Parameters a0: base, a1: offset
Equivalent x86 Instruction CALL

Like JMP, this adds the second operand to the first, so it could be an ADD instruction, but the flags are not updated. So it only makes sense to use this with EIP as first parameter. Note that no return address needs to be pushed onto the stack since it is already on the stack by calling the VM-Entry, ESP just needs to be decremented by 4 so the return address will not get popped of in the cleanup routine.

REG[ESP] -= 4
REG[a0] += REG[a1]

CALL <offset>
OpCode 3 Jump if Equal/Zero
Handler Location 0163
Used Parameters a0: base, a1: offset, a2: EFLAGS
Equivalent x86 Instruction JE/JZ
if ((a2 & (1 << 6)) != 0)
{
    REG[a0] += REG[a1]
}

JE <offset>
OpCode 4 Jump if NOT Equal/Zero
Handler Location 0169
Used Parameters a0: base, a1: offset, a2: EFLAGS
Equivalent x86 Instruction JNE/JNZ
if ((a2 & (1 << 6)) == 0)
{
    REG[a0] += REG[a1]
}

JNE <offset>
OpCode 5 Jump if Below
Handler Location 016F
Used Parameters a0: base, a1: offset, a2: EFLAGS
Equivalent x86 Instruction JB
if ((a2 & (1 << 0)) != 0)
{
    REG[a0] += REG[a1]
}

JB <offset>
OpCode 6 Jump if NOT Below/Above or equal
Handler Location 016F
Used Parameters a0: base, a1: offset, a2: EFLAGS
Equivalent x86 Instruction JNB/JAE
if ((a2 & (1 << 0)) == 0)
{
    REG[a0] += REG[a1]
}

JNB <offset>
OpCode 7 Jump if Overflow
Handler Location 0181
Used Parameters a0: base, a1: offset, a2: EFLAGS
Equivalent x86 Instruction JO
if ((a2 & (1 << 11)) != 0)
{
    REG[a0] += REG[a1]
}

JO <offset>
OpCode 8 Jump if NOT Overflow
Handler Location 017B
Used Parameters a0: base, a1: offset, a2: EFLAGS
Equivalent x86 Instruction JNO
if ((a2 & (1 << 11)) == 0)
{
    REG[a0] += REG[a1]
}

JNO <offset>
OpCode 9 Jump if Parity
Handler Location 0187
Used Parameters a0: base, a1: offset, a2: EFLAGS
Equivalent x86 Instruction JP
if ((a2 & (1 << 2)) != 0)
{
    REG[a0] += REG[a1]
}

JP <offset>
OpCode 10 Jump if NOT Parity
Handler Location 018D
Used Parameters a0: base, a1: offset, a2: EFLAGS
Equivalent x86 Instruction JNP
if ((a2 & (1 << 2)) == 0)
{
    REG[a0] += REG[a1]
}

JNP <offset>
OpCode 11 Jump if Sign
Handler Location 0193
Used Parameters a0: base, a1: offset, a2: EFLAGS
Equivalent x86 Instruction JS
if ((a2 & (1 << 7)) != 0)
{
    REG[a0] += REG[a1]
}

JS <offset>
OpCode 12 Jump if NOT Sign
Handler Location 0199
Used Parameters a0: base, a1: offset, a2: EFLAGS
Equivalent x86 Instruction JNS
if ((a2 & (1 << 7)) == 0)
{
    REG[a0] += REG[a1]
}

JNS <offset>
OpCode 13 TEST
Handler Location 006F
Used Parameters a0: operandA, a1: operandB, a2: EFLAGS
Equivalent x86 Instruction TEST

Bitwise ANDs the operands and updates the EFLAGS according to the result.

result = REG[a0] & REG[a1]
update_eflags(result)

TEST <operandA>, <operandB>
OpCode 14 Bitwise AND
Handler Location 008C
Used Parameters a0: operandA, a1: operandB, a2: EFLAGS
Equivalent x86 Instruction AND

Bitwise ANDs the operands and updates the EFLAGS according to the result. Writes back the result to the first operand.

REG[a0] &= REG[a1]
update_eflags(REG[a0])

AND <operandA>, <operandB>
OpCode 15 Bitwise XOR
Handler Location 00AA
Used Parameters a0: operandA, a1: operandB, a2: EFLAGS
Equivalent x86 Instruction XOR

Bitwise XORs the operands and updates the EFLAGS according to the result. Writes back the result to the first operand.

REG[a0] ^= REG[a1]
update_eflags(REG[a0])

XOR <operandA>, <operandB>
OpCode 16 Bitwise OR
Handler Location 00C8
Used Parameters a0: operandA, a1: operandB, a2: EFLAGS
Equivalent x86 Instruction OR

Bitwise ORs the operands and updates the EFLAGS according to the result. Writes back the result to the first operand.

REG[a0] |= REG[a1]
update_eflags(REG[a0])

OR <operandA>, <operandB>
OpCode 17 Compare values
Handler Location 0136
Used Parameters a0: operandA, a1: operandB, a2: EFLAGS
Equivalent x86 Instruction CMP

Subtracts the operands and updates the EFLAGS according to the result.

result = REG[a0] - REG[a1]
update_eflags(result)

CMP <operandA>, <operandB>
OpCode 18 Subtract values
Handler Location 010E
Used Parameters a0: operandA, a1: operandB, a2: EFLAGS
Equivalent x86 Instruction SUB

Subtracts the operands and updates the EFLAGS according to the result. Writes back the result to the first operand.

REG[a0] -= REG[a1]
update_eflags(REG[a0])

SUB <operandA>, <operandB>
OpCode 20 Add values
Handler Location 00E6
Used Parameters a0: operandA, a1: operandB, a2: EFLAGS
Equivalent x86 Instruction ADD

Add the operands and updates the EFLAGS according to the result. Writes back the result to the first operand.

REG[a0] += REG[a1]
update_eflags(REG[a0])

ADD <operandA>, <operandB>

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