Difference between revisions of "GOOL Interpreter"

From Crash Bandicoot Hacking Wiki
Jump to navigation Jump to search
(GOOLv2 Instruction Table: Add missing div tag, broke page layout after this section)
(fix SNDB (crash 1) format)
 
(61 intermediate revisions by 5 users not shown)
Line 8: Line 8:
 
# ''Perform'' the operation specified by the fetched instruction
 
# ''Perform'' the operation specified by the fetched instruction
 
# ''Continue'' repeating steps 1 and 2 until a suspending instruction is fetched
 
# ''Continue'' repeating steps 1 and 2 until a suspending instruction is fetched
(A suspending instruction is typically either a RET, which marks the end of a block, or ANIF/ANIS, which change the object's current frame of animation.)
+
(A suspending instruction is typically either a RET, which marks the end of a block, ANIF/ANIS, which change the object's current frame of animation, CST/CNEZ/CEQZ, which change the object's state, or EVNT/EVNB/EVNU, which send an event to one or multiple objects.)
  
 
A single call to the GOOL interpreter routine with some desired object as its first argument results in a single interpretation of that object's bytecode. The GOOL bytecode interpreter routine expects an object that provides the following information:
 
A single call to the GOOL interpreter routine with some desired object as its first argument results in a single interpretation of that object's bytecode. The GOOL bytecode interpreter routine expects an object that provides the following information:
Line 286: Line 286:
  
 
===== Main Instruction Table =====
 
===== Main Instruction Table =====
The GOOL instruction table below lists the opcode, mnemonic/name, format, operands (based on explicit and/or implicit specification of source origin and/or destination target), general operation (represented with c-style statement), and a description for each GOOL instruction.  
+
The GOOL instruction table below lists the opcode, mnemonic/name, format, operands (based on explicit and/or implicit specification of source origin and/or destination target), general operation (represented with c-style statement), and a description for each GOOL instruction.
<div style="font-family:monospace;font-size:10px;">
+
<div style="font-family:monospace;font-size:11px;">
{| border="1"  
+
{| border="1"
+
 
|-
+
|-
!  Opcode
+
!  Opcode
! Name  
+
! Name
!          Encoding/Format          
+
!          Encoding/Format
!Explicit GOOL ops
+
!Explicit GOOL ops
 
in
 
in
!Explicit IMM. ops
+
!Explicit IMM. ops
 
in
 
in
!Implicit STACK ops
+
!Implicit STACK ops
 
in
 
in
!        Operation      
+
!        Operation
! Implicit STACK out  
+
! Implicit STACK out
!Explicit
+
!Explicit
 
GOOL ops out
 
GOOL ops out
!  Description
+
!  Description
+
 
|-
 
| 0/0x00
 
| ADD 
 
| '''00000000'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L + R       
 
|O 
 
|               
 
|  add
 
 
|-
 
| 1/0x01
 
| SUB 
 
| '''00000001'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L - R       
 
|O 
 
|               
 
|  subtract
 
 
|-
 
| 2/0x02
 
| MUL 
 
| '''00000010'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L * R       
 
|O 
 
|               
 
|  multiply
 
 
|-
 
| 3/0x03
 
| DIV 
 
| '''00000011'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L / R       
 
|O 
 
|               
 
|  divide
 
 
|-
 
| 4/0X04
 
| CEQ 
 
| '''00000100'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = (L == R),
 
O = ((L ^ R) == 0)   
 
|O 
 
|               
 
|  check if equal
 
 
|-
 
| 5/0x05
 
| ANDL
 
| 00000101RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = (L && R),
 
O = (L ? (R > 0) : 0)   
 
|O 
 
|               
 
|  logical and
 
 
|-
 
| 6/0x06
 
| ORL 
 
| 00000110RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|<nowiki>O = (L || R)</nowiki>
 
|O
 
|<br>
 
|  logical or
 
 
|-
 
| 7/0x07
 
| ANDB
 
| 00000111RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L & R       
 
|O
 
|               
 
|  bitwise and
 
 
|-
 
| 8/0x08
 
| ORB 
 
| 00001000RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|<nowiki>O = L | R</nowiki>
 
|O
 
 
|  bitwise or
 
 
|-
 
| 9/0x09
 
| SLT 
 
| 00001001RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L < R       
 
|O
 
|               
 
|  set less than
 
 
|-
 
|10/0x0A
 
| SLE 
 
| 00001010RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = (L <= R)     
 
|O
 
|               
 
|  set less than or equal
 
 
|-
 
|11/0x0B
 
| SGT 
 
| 00001011RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L > R       
 
|O
 
|               
 
|  set greater than
 
 
|-
 
|12/0x0C
 
| SGE 
 
| 00001100RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = (L >= R)     
 
|O
 
|               
 
|  set greater than or equal
 
 
|-
 
|13/0x0D
 
| MOD 
 
| 00001101RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L % R       
 
|O
 
|               
 
|  modulo
 
 
|-
 
|14/0x0E
 
| XOR 
 
| 00001110RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L ^ R       
 
|O
 
|               
 
|  exclusive or
 
 
|-
 
|15/0x0F
 
| TST 
 
| 00001111RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
| O = (((L & R) ^ R) == 0)
 
|O
 
|               
 
|  test bit
 
 
|-
 
|16/0x10
 
| RND 
 
| 00010000AAAAAAAAAAAABBBBBBBBBBBB
 
|  A,B 
 
|                 
 
|                 
 
| O = B+(rand() % (A - B))
 
|O
 
|               
 
|  random
 
 
|-
 
|17/0x11
 
| MOVE
 
| 00010001SSSSSSSSSSSSDDDDDDDDDDDD
 
|  S   
 
|                 
 
|                 
 
|          D = S         
 
|             
 
|  [D] 
 
|  move data
 
 
|-
 
|18/0x12
 
| NOTL
 
| 00010010SSSSSSSSSSSSDDDDDDDDDDDD
 
|  S   
 
|                 
 
|                 
 
|        D = (S == 0)     
 
|             
 
|  D   
 
|  logical not
 
 
|-
 
|19/0x13
 
| PATH 
 
| 00010011AAAAAAAAAAAABBBBBBBBBBBB
 
|  (A),B
 
|R = 0x100
 
|  [R,A] 
 
|          varies       
 
|  P 
 
|  B   
 
|  path progress
 
 
|-
 
|20/0x14
 
| LEA 
 
| 00010100SSSSSSSSSSSSDDDDDDDDDDDD
 
|  S   
 
|                 
 
|                 
 
|          D = &S       
 
|             
 
|  D   
 
|  load effective address
 
 
|-
 
|21/0x15
 
| SHA 
 
| 00010101RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
| O = ((R < 0) ? (L >> -R)
 
<nowiki>:</nowiki> (L << R))
 
|  O 
 
|               
 
|  arithmetic shift
 
 
|-
 
|22/0x16
 
| PSHV 
 
| 00010110AAAAAAAAAAAABBBBBBBBBBBB
 
|  [A,[B]] 
 
|                 
 
|                 
 
|      [arg_buf = A]
 
I = A; J = B;     
 
|[I,[J]]
 
|               
 
|  push value to stack 
 
 
|-
 
|23/0x17
 
| NOTB
 
| 00010111SSSSSSSSSSSSDDDDDDDDDDDD                       
 
|               
 
|                 
 
|                 
 
|                                                    D = ~S
 
|             
 
|                D
 
|  bitwise not
 
 
|-
 
|24/0x18
 
| MOVC
 
| 000110000000RRRRRRIIIIIIIIIIIIII
 
|               
 
|  R,C 
 
|                 
 
|        see docs       
 
|  O 
 
|               
 
|  move code pointer
 
 
|-
 
|25/0x19
 
| ABS 
 
| 00011001SSSSSSSSSSSSDDDDDDDDDDDD
 
|  S   
 
|                 
 
|                 
 
|  D = (S < 0) ? -S: S   
 
|             
 
|  D   
 
|  absolute value
 
 
|-
 
|26/0x1A
 
| PAD 
 
| 00011010000TDDDDSSPPBBBBBBBBBBBB
 
|               
 
|B,P,S,D,T
 
|                 
 
| O = testctrls(instr,0)
 
|  O 
 
|               
 
|  test controller buttons   
 
 
|-
 
|27/0x1B
 
| SPD 
 
| 00011011VVVVVVVVVVVVBBBBBBBBBBBB
 
|  V,B 
 
|                 
 
|                 
 
|S = B + ((V*gvel) >> 10)
 
|  S 
 
|               
 
|  calculate speed
 
 
|-
 
|28/0x1C
 
| MSC 
 
| 00011100PPPPSSSSSLLLXXXXXXXXXXXX
 
|  X   
 
|  P,S,L 
 
|                 
 
|    various; see docs   
 
|  *** 
 
|  *** 
 
|  multi-purpose
 
 
|-
 
|29/0x1D
 
| PRS 
 
| 00011101PPPPPPPPPPPPDDDDDDDDDDDD
 
|  P,D 
 
|                 
 
|                 
 
|    large calc; see docs 
 
|  O 
 
|               
 
|  driven sine wave
 
 
|-
 
|30/0x1E
 
| SSAW 
 
| 00011110DDDDDDDDDDDDPPPPPPPPPPPP
 
|  M,P 
 
|                 
 
|                 
 
| O = (M + frameCount) % P
 
|  O 
 
|               
 
|  synchronized saw wave
 
 
|-
 
|31/0x1F
 
| RGL 
 
| 00011111000000000000IIIIIIIIIIII
 
|  I   
 
|                 
 
|                 
 
|    O = globals[I >> 8] 
 
|  O 
 
|               
 
|  read global variable
 
 
|-
 
|32/0x20
 
| WGL 
 
| 00100000SSSSSSSSSSSSIIIIIIIIIIII
 
|  I,S 
 
|                 
 
|                 
 
|    globals[I << 8] = *S 
 
|             
 
|               
 
|  write global variable
 
 
|-
 
|33/0x21
 
| ANGD 
 
|                                                                          00100001RRRRRRRRRRRRLLLLLLLLLLLL
 
|                L,R
 
|                 
 
|                 
 
|                                                    O = angdist(L,R)
 
|             
 
|               
 
|  angle between
 
 
|-
 
|34/0x22
 
| APCH 
 
| 00100010RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,(R)
 
|                  S = 0x100
 
|  [R,S] 
 
|    O = approach(L,R,S) 
 
|  O 
 
|               
 
|  approach a value
 
 
|-
 
|35/0x23
 
| CVMR
 
|                                                                          00100011000IIIIIILLL000000000000
 
|               
 
|                  I,L
 
|                 
 
|                                                    O = obj.link[L].colors[I]
 
|             
 
|               
 
|color vector or matrix read
 
 
|-
 
|36/0x24
 
| CVMW
 
|                                                                          00100011000IIIIIILLLCCCCCCCCCCCC
 
|                C
 
|                  I,L
 
|                 
 
|                                                    obj.link[L].colors[I] = C
 
|             
 
|               
 
|color vector or matrix write
 
 
|-
 
|37/0x25
 
| ROT
 
| 00100101RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,(R)
 
|                 
 
|  [R,S] 
 
|    O = rotate(L,R,S,0) 
 
|  O 
 
|               
 
|  approach an angle
 
 
|-
 
|38/0x26
 
| PSHP
 
|                                                                          001001100AAAAAAAAAAABBBBBBBBBBBB
 
|                [A,[B]]
 
|                 
 
|                 
 
|                                                    I = &A; J = &B;
 
|             
 
|                [I,[J]]
 
|  push pointer to stack
 
 
|-
 
|39/0X27
 
| ANID 
 
| 00100111FFFFFFFFFFFFDDDDDDDDDDDD
 
|  F   
 
|                 
 
|                 
 
| D=&obj.global.anim[F>>5]
 
|             
 
|  D   
 
|set animation
 
 
|-
 
|128/0x80
 
| DBG 
 
| 10000000RRRRRRRRRRRRLLLLLLLLLLLL
 
|                L,R
 
|                 
 
|                 
 
|                                                   
 
|             
 
|               
 
|  debug print ops (beta only)
 
 
|-
 
|129/0x81
 
| NOP 
 
| 10000001000000000000000000000000
 
|               
 
|                 
 
|                 
 
|                                                   
 
|             
 
|               
 
|  no operation
 
 
|-
 
|130/0x82
 
| CFL 
 
| 10000010TTCCRRRRRRIIIIIIIIIIIIII
 
|               
 
| T,C,R,I
 
|                 
 
|                                                   
 
|             
 
|               
 
|  general control flow
 
 
|-
 
|                   
 
|  BRA 
 
| 100000100000RRRRRRVVVVIIIIIIIIII
 
|               
 
|  R,V,I 
 
|                 
 
|                                                   
 
|             
 
|               
 
|  branch
 
 
|-
 
|                   
 
|  BNEZ
 
| 100000100001RRRRRRVVVVIIIIIIIIII
 
|               
 
|  R,V,I 
 
|                 
 
|                                                   
 
|             
 
|               
 
|  branch not equal zero
 
 
|-
 
|                   
 
|  BEQZ
 
| 100000100010RRRRRRVVVVIIIIIIIIII
 
|               
 
|  R,V,I 
 
|                 
 
|                                                   
 
|             
 
|               
 
|  branch equal zero
 
 
|-
 
|                   
 
|  CST
 
| 100000100100RRRRRRSSSSSSSSSSSSSS
 
|               
 
|  R,S 
 
|                 
 
|                                                   
 
|             
 
|               
 
|  change state
 
 
|-
 
|                   
 
|  CSNZ
 
| 100000100101RRRRRRSSSSSSSSSSSSSS
 
|               
 
|  R,S 
 
|                 
 
|                                                   
 
|             
 
|               
 
|  change state not zero
 
 
|-
 
|                   
 
|  CSEZ
 
| 100000100110RRRRRRSSSSSSSSSSSSSS
 
|               
 
|  R,S 
 
|                 
 
|                                                   
 
|             
 
|               
 
|  change state equal zero
 
 
|-
 
|                   
 
|  RET
 
| 100000101000RRRRRRIIIIIIIIIIIIII
 
|               
 
|                  R,I
 
|                 
 
|                                                   
 
|             
 
|               
 
|  return
 
 
|-
 
|131/0x83
 
| ANIS
 
| 10000011HHTTTTTTSSSSSSSSSFFFFFFF
 
|               
 
| F,S,T,H
 
|                 
 
|                                                   
 
|  W 
 
|               
 
|  change animation sequence
 
 
|-
 
|132/0x84
 
| ANIF
 
| 10000100HHTTTTTTFFFFFFFFFFFFFFFF
 
|  F   
 
|  T,H 
 
|                 
 
|                                                   
 
|  W 
 
|               
 
|  change animation frame
 
 
|-
 
|133/0x85
 
| VECA
 
| 10000101CCCTTTBBBAAAVVVVVVVVVVVV
 
|  V   
 
| T,A,B,C
 
|                 
 
|                                                   
 
|  * 
 
|  ** 
 
|  multi-purpose vector calcs
 
 
|-
 
|134/0x86
 
| JAL 
 
| 10000110VVVV000000IIIIIIIIIIIIII
 
|               
 
|  I,V 
 
|                 
 
|                                                                                     
 
 
|
 
|jump and link
 
 
|-
 
|135/0x87
 
| EVNT 
 
|                                                                          10000111LLLAAARRRRRREEEEEEEEEEEE
 
|                E
 
|                  L,A,R
 
|                 
 
|                                                                                     
 
|   
 
|
 
|send an event
 
 
|-
 
|136/0x88
 
| RSTT 
 
|                                                                          10001000TTCCRRRRRR**************
 
|               
 
|                  R,C,T,*
 
|                  **
 
|
 
|<br>
 
|
 
|state return guard = true variant
 
 
|-
 
|-
|137/0x89
+
|0/0x00
| RSTF 
+
|ADD
|                                                                         10001001TTCCRRRRRR**************
+
|'''00000000'''RRRRRRRRRRRRLLLLLLLLLLLL
|              
+
|L,R
|                 R,C,T,*
+
|
|                 **
+
|
|
+
|O = L + R
|
+
|O
|
+
|
|state return guard = false variant
+
|add
 +
 
 
|-
 
|-
 +
|1/0x01
 +
|SUB
 +
|'''00000001'''RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 +
|
 +
|
 +
|O = L - R
 +
|O
 +
|
 +
|subtract
 +
 
|-
 
|-
|138/0x8A
+
|2/0x02
| CHLD
+
|MUL
| 10001010AAAATTTTTTTTSSSSSSCCCCCC
+
|'''00000010'''RRRRRRRRRRRRLLLLLLLLLLLL
|              
+
|L,R
| C,T,S,A
+
|
|[C],
+
|
arg[0 to A]
+
|O = L * R
|                                                   
+
|O
|             
+
|
|               
+
|multiply
|  spawn children objects
 
 
|-
 
|139/0x8B
 
| NTRY
 
| 10001011TTTTTTTTTTTTEEEEEEEEEEEE
 
|               
 
|  T,E 
 
|                 
 
|                                                                                     
 
 
|
 
|multi-purpose page operation
 
 
|-
 
|140/0x8C
 
| SNDA
 
|                                                                          10001100AAAAAAAAAAAABBBBBBBBBBBB
 
|                A,B
 
|                 
 
|                 
 
|                                                                                     
 
 
|
 
|adjust audio levels
 
 
|-
 
|141/0x8D
 
| SNDB
 
|                                                                          10001101VVVVRRRRRRSSSSSSSSSSSSS
 
|                S
 
|                  V,R
 
|                 
 
|                                                                                     
 
 
|<br>
 
|play sound<br>effect
 
 
|-
 
|142/0x8E
 
| VECB
 
| 10001110CCCTTTBBBAAAVVVVVVVVVVVV
 
|                V
 
|                  T,A,B,C
 
|                 
 
|                                                                                     
 
 
|<br>
 
|multi-purpose vector calcs
 
 
|-
 
|143/0x8F
 
| EVNB
 
|                                                                          10001111LLLAAARRRRRREEEEEEEEEEEE
 
|                E
 
|                  L,A,R
 
|                 
 
|                                                                                     
 
 
|<br>
 
|broadcast an event
 
 
|-
 
|144/0x90
 
| EVNU 
 
|                                                                          10010000LLLAAARRRRRREEEEEEEEEEEE
 
|                E
 
|                  L,A,R
 
|                 
 
|                                                                                     
 
|<br>
 
|<br>
 
|send event unknown variant
 
 
|-
 
|145/0x91
 
| CHLF
 
|                                                                          10100000AAAATTTTTTTTSSSSSSCCCCCC
 
|               
 
|                  C,T,S,A
 
|                  [C],
 
arg[0 to A]
 
|                                                                                     
 
 
|<br>
 
|spawn children objects;
 
no replacement if obj pool full
 
 
|}
 
</div>
 
  
Note that a few instructions can not be represented with a single mnemonic; operations for these instructions are not only determined by their opcode but also their primary operation subtype and possibly secondary operation subtype fields. These instructions have their own tables, which are given in the following sections.
+
|-
 +
|3/0x03
 +
|DIV
 +
|'''00000011'''RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 +
|
 +
|
 +
|O = L / R
 +
|O
 +
|
 +
|divide
  
===== State Return Instruction Table =====
+
|-
<div style="font-family:monospace;font-size:10px;">
+
|4/0X04
{| border="1"
+
|CEQ
!Opcode
+
|'''00000100'''RRRRRRRRRRRRLLLLLLLLLLLL
!Name
+
|L,R
!Encoding/Format
+
|
!Explicit
+
|
IMM. ops
+
|O = (L == R),
 +
O = ((L ^ R) == 0)
 +
|O
 +
|
 +
|check if equal
  
in
 
!Description
 
 
|-
 
|-
|136/0x88
+
|5/0x05
|RSTT
+
|ANDL
|10001000TTCCRRRRRR**************
+
|00000101RRRRRRRRRRRRLLLLLLLLLLLL
|R,C,T,*
+
|L,R
|state return guard = true variant
+
|
 +
|
 +
|O = (L && R),
 +
O = (L ? (R > 0) : 0)
 +
|O
 +
|
 +
|logical and
 +
 
 
|-
 
|-
 +
|6/0x06
 +
|ORL
 +
|00000110RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 
|
 
|
|RST
+
|
|100010000100RRRRRRSSSSSSSSSSSSSS
+
|<nowiki>O = (L || R)</nowiki>
|R,S
+
|O
|state return guard = true
+
|<br>
 +
|logical or
 +
 
 
|-
 
|-
 +
|7/0x07
 +
|ANDB
 +
|00000111RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 +
|
 
|
 
|
|RSNT
+
|O = L & R
|100010000101RRRRRRSSSSSSSSSSSSSS
+
|O
|R,S
+
|
|state return if nonzero guard = true
+
|bitwise and
 +
 
 
|-
 
|-
 +
|8/0x08
 +
|ORB
 +
|00001000RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 
|
 
|
|RSZT
+
|
|100010000110RRRRRRSSSSSSSSSSSSSS
+
|<nowiki>O = L | R</nowiki>
|R,S
+
|O
|state return if equal zero guard = true
+
|
 +
|bitwise or
 +
 
 
|-
 
|-
 +
|9/0x09
 +
|SLT
 +
|00001001RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 
|
 
|
|RSCT
+
|
|100010000111RRRRRRSSSSSSSSSSSSSS
+
|O = L < R
|R,S
+
|O
|state return eval prev cond guard = true
+
|
 +
|set less than
 +
 
 
|-
 
|-
 +
|10/0x0A
 +
|SLE
 +
|00001010RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 
|
 
|
|RNT
+
|
|100010001000RRRRRRxxxxxxxxxxxxxx
+
|O = (L <= R)
|R
+
|O
|null return guard = true
+
|
 +
|set less than or equal
 +
 
 
|-
 
|-
 +
|11/0x0B
 +
|SGT
 +
|00001011RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 +
|
 +
|
 +
|O = L > R
 +
|O
 
|
 
|
|RNNT
+
|set greater than
|100010001001RRRRRRxxxxxxxxxxxxxx
+
 
|R
 
|null return if nonzero guard = true
 
 
|-
 
|-
 +
|12/0x0C
 +
|SGE
 +
|00001100RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 
|
 
|
|RNZT
+
|
|100010001010RRRRRRxxxxxxxxxxxxxx
+
|O = (L >= R)
|R
+
|O
|null return if equal zero guard = true
+
|
 +
|set greater than or equal
 +
 
 
|-
 
|-
 +
|13/0x0D
 +
|MOD
 +
|00001101RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 
|
 
|
|RNCT
+
|
|100010001011RRRRRRxxxxxxxxxxxxxx
+
|O = L % R
|R
+
|O
|null return eval prev cond guard = true
+
|
 +
|modulo
 +
 
 
|-
 
|-
 +
|14/0x0E
 +
|XOR
 +
|00001110RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 
|
 
|
|GDT
+
|
|100010001100RRRRRRxxxxxxxxxxxxxx
+
|O = L ^ R
|R
+
|O
|guard = true
+
|
 +
|exclusive or
 +
 
 
|-
 
|-
 +
|15/0x0F
 +
|TST
 +
|00001111RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 +
|
 
|
 
|
|GNT
+
|O = (((L & R) ^ R) == 0)
|100010001101RRRRRRxxxxxxxxxxxxxx
+
|O
|R
 
|if nonzero guard = true
 
|-
 
 
|
 
|
|GZT
+
|test bit
|100010001110RRRRRRxxxxxxxxxxxxxx
+
 
|R
 
|if equal zero guard = true
 
 
|-
 
|-
 +
|16/0x10
 +
|RND
 +
|00010000AAAAAAAAAAAABBBBBBBBBBBB
 +
|A,B
 
|
 
|
|GCT
+
|
|100010001111RRRRRRxxxxxxxxxxxxxx
+
|O = B+(rand() % (A - B))
|R
+
|O
|eval prev cond guard = true
+
|
 +
|random
 +
 
 
|-
 
|-
 +
|17/0x11
 +
|MOVE
 +
|00010001SSSSSSSSSSSSDDDDDDDDDDDD
 +
|S
 
|
 
|
|GBNT
+
|
|100010000001RRRRRRVVVVIIIIIIIIII
+
|D = S
|R,V,I
+
|
|if nonzero guard = true else branch
+
|[D]
 +
|move data
 +
 
 
|-
 
|-
 +
|18/0x12
 +
|NOTL
 +
|00010010SSSSSSSSSSSSDDDDDDDDDDDD
 +
|S
 +
|
 +
|
 +
|D = (S == 0)
 
|
 
|
|GBZT
+
|D
|100010000010RRRRRRVVVVIIIIIIIIII
+
|logical not
|R,V,I
+
 
|if equal zero guard = true else branch
 
 
|-
 
|-
|137/0x89
+
|19/0x13
| RSTF 
+
|LOOP
|                                                                         10001001TTCCRRRRRR**************
+
|00010011AAAAAAAAAAAABBBBBBBBBBBB
|                 R,C,T,*
+
|(A),B
|state return guard = false variant
+
|R = 0x100
 +
|[R,A]
 +
|B = A >= 0 ? B + R : B - R
 +
if (B > A && A > 0) B = -A + R*2
 +
else if (B < A && A < 0) B = -A - R*2
 +
P = A >= 0 ? abs(B) : -abs(B)
 +
|P
 +
|B
 +
|loop around zero
 +
 
 
|-
 
|-
 +
|20/0x14
 +
|LEA
 +
|00010100SSSSSSSSSSSSDDDDDDDDDDDD
 +
|S
 
|
 
|
|RSF
+
|
|100010000100RRRRRRSSSSSSSSSSSSSS
+
|D = &S
|R,S
+
|
|state return guard = false
+
|D
 +
|load effective address
 +
 
 
|-
 
|-
 +
|21/0x15
 +
|SHA
 +
|00010101RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 
|
 
|
|RSNF
+
|
|100010000101RRRRRRSSSSSSSSSSSSSS
+
|O = ((R < 0) ? (L >> -R)
|R,S
+
<nowiki>:</nowiki> (L << R))
|state return if nonzero guard = false
+
|O
 +
|
 +
|arithmetic shift
 +
 
 
|-
 
|-
 +
|22/0x16
 +
|PUSH
 +
|00010110AAAAAAAAAAAABBBBBBBBBBBB
 +
|[A,[B]]
 +
|
 
|
 
|
|RSZF
+
|[arg_buf = A]
|100010000110RRRRRRSSSSSSSSSSSSSS
+
I = A; J = B;
|R,S
+
|[I,[J]]
|state return if equal zero guard = false
 
|-
 
 
|
 
|
|RSCF
+
|push value to stack
|100010000111RRRRRRSSSSSSSSSSSSSS
+
 
|R,S
 
|state return eval prev cond guard = false
 
 
|-
 
|-
 +
|23/0x17
 +
|NOTB
 +
|00010111SSSSSSSSSSSSDDDDDDDDDDDD
 +
|S
 
|
 
|
|RNF
+
|
|100010001000RRRRRRxxxxxxxxxxxxxx
+
|D = ~S
|R
+
|
|null return guard = false
+
|D
 +
|bitwise not
 +
 
 
|-
 
|-
 +
|24/0x18
 +
|MOVC
 +
|000110000000RRRRRRIIIIIIIIIIIIII
 
|
 
|
|RNNF
+
|R,C
|100010001001RRRRRRxxxxxxxxxxxxxx
+
|
|R
+
|see docs
|null return if nonzero guard = false
+
|O
 +
|
 +
|move code pointer
 +
 
 
|-
 
|-
 +
|25/0x19
 +
|ABS
 +
|00011001SSSSSSSSSSSSDDDDDDDDDDDD
 +
|S
 +
|
 
|
 
|
|RNZF
+
|D = (S < 0) ? -S: S
|100010001010RRRRRRxxxxxxxxxxxxxx
 
|R
 
|null return if equal zero guard = false
 
|-
 
 
|
 
|
|RNCF
+
|D
|100010001011RRRRRRxxxxxxxxxxxxxx
+
|absolute value
|R
+
 
|null return eval prev cond guard = false
 
 
|-
 
|-
 +
|26/0x1A
 +
|PAD
 +
|00011010000TDDDDSSPPBBBBBBBBBBBB
 
|
 
|
|GDF
+
|B,P,S,D,T
|100010001100RRRRRRxxxxxxxxxxxxxx
+
|
|R
+
|O = testctrls(instr,0)
|guard = false
+
|O
 +
|
 +
|test controller buttons
 +
 
 
|-
 
|-
 +
|27/0x1B
 +
|SPD
 +
|00011011VVVVVVVVVVVVBBBBBBBBBBBB
 +
|V,B
 
|
 
|
|GNF
+
|
|100010001101RRRRRRxxxxxxxxxxxxxx
+
|S = B + ((V*grav) >> 10)
|R
+
|S
|if nonzero guard = false
+
|
 +
|calculate speed
 +
 
 
|-
 
|-
 +
|28/0x1C
 +
|MSC
 +
|00011100PPPPSSSSSLLLXXXXXXXXXXXX
 +
|X
 +
|P,S,L
 
|
 
|
|GZF
+
|various; see docs
|100010001110RRRRRRxxxxxxxxxxxxxx
+
|***
|R
+
|***
|if equal zero guard = false
+
|multi-purpose
 +
 
 
|-
 
|-
 +
|29/0x1D
 +
|PSIN
 +
|00011101PPPPPPPPPPPPDDDDDDDDDDDD
 +
|P,D
 
|
 
|
|GCF
+
|
|100010001111RRRRRRxxxxxxxxxxxxxx
+
|large calc; see docs
|R
+
|O
|eval prev cond guard = false
+
|
 +
|periodic sine wave
 +
 
 
|-
 
|-
 +
|30/0x1E
 +
|TICK
 +
|00011110DDDDDDDDDDDDPPPPPPPPPPPP
 +
|M,P
 
|
 
|
|GBNF
+
|
|100010000001RRRRRRVVVVIIIIIIIIII
+
|O = (M + frameCount) % P
|R,V,I
+
|O
|if nonzero guard = false else branch
+
|
 +
|get game time
 +
 
 
|-
 
|-
 +
|31/0x1F
 +
|RGL
 +
|00011111000000000000IIIIIIIIIIII
 +
|I
 
|
 
|
|GBZF
+
|
|100010000010RRRRRRVVVVIIIIIIIIII
+
|O = globals[I >> 8]
|R,V,I
+
|O
|if equal zero guard = false else branch
+
|
 +
|read global variable
 +
 
 
|-
 
|-
|}
+
|32/0x20
</div>
+
|WGL
 +
|00100000SSSSSSSSSSSSIIIIIIIIIIII
 +
|I,S
 +
|
 +
|
 +
|globals[I << 8] = *S
 +
|
 +
|
 +
|write global variable
  
===== Operand Name Table =====
+
|-
<div style="font-family:monospace;font-size:10px;">
+
|33/0x21
 +
|DEGD
 +
|00100001RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 +
|
 +
|
 +
|O = degdist(L,R)
 +
|
 +
|
 +
|angle between
 +
 
 +
|-
 +
|34/0x22
 +
|SEEK
 +
|00100010RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,(R)
 +
|S = 0x100
 +
|[R,S]
 +
|O = seek(L,R,S)
 +
|O
 +
|
 +
|approach a value
  
{| border="1"
 
!
 
Specification Format
 
| rowspan="2" |A
 
|AAAAAAAAAAAA
 
|AAAA
 
|AAA (EVNT/EVNU/EVNB)
 
|AAA (VECA/VECB)
 
 
|-
 
|-
!Name
+
|35/0x23
|Value A
+
|CVMR
|Argument Count
+
|00100011000IIIIIILLL000000000000
|Argument Count
+
|
|Vector A Index
+
|I,L
 +
|
 +
|O = obj.link[L].colors[I]
 +
|
 +
|
 +
|color vector or matrix read
 +
 
 
|-
 
|-
!Specification Format
+
|36/0x24
| rowspan="2" |B
+
|CVMW
|BBBBBBBBBBBB
+
|00100100000IIIIIILLLCCCCCCCCCCCC
|BBBBBBBBBBBB (PAD)
+
|C
|BBBBBBBBBBBB (SPD)
+
|I,L
|BBB
+
|
 +
|obj.link[L].colors[I] = C
 +
|
 +
|
 +
|color vector or matrix write
 +
 
 
|-
 
|-
!Name
+
|37/0x25
|Value B
+
|DSEK
|Controller Buttons
+
|00100101RRRRRRRRRRRRLLLLLLLLLLLL
|Base Speed
+
|L,(R)
|Vector B Index
+
|
 +
|[R,S]
 +
|O = degseek(L,R,S,0)
 +
|O
 +
|
 +
|approach an angle
 +
 
 
|-
 
|-
!Specification Format
+
|38/0x26
| rowspan="2" |C
+
|PSHP
|CCCCCCCCCCCC
+
|00100110AAAAAAAAAAAABBBBBBBBBBBB
|CCCCCC
+
|[A,[B]]
|CCC
+
|
|CC
+
|
 +
|I = &A; J = &B;
 +
|
 +
|[I,[J]]
 +
|push pointer to stack
 +
 
 
|-
 
|-
!Name
+
|39/0X27
|Color Value
+
|ANID
|Spawn Count
+
|00100111FFFFFFFFFFFFDDDDDDDDDDDD
|Vector C Index
+
|F
|Conditional Check Type
+
|
 +
|
 +
|D=&obj.global.anim[F>>5]
 +
|
 +
|D
 +
|set animation
 +
 
 
|-
 
|-
!Specification Format
+
|128/0x80
| rowspan="2" |D
+
|DBG
|DDDDDDDDDDDD
+
|10000000RRRRRRRRRRRRLLLLLLLLLLLL
|DDDDDDDDDDDD (PRS)
+
|L,R
|DDDD
+
|
 
|
 
|
|-
 
!Name
 
|Destination
 
|Wave Phase
 
|Directional Buttons
 
 
|
 
|
|-
 
!Specification Format
 
| rowspan="2" |E
 
|EEEEEEEEEEEE (NTRY)
 
|EEEEEEEEEEEE (EVNT/EVNU/EVNB)
 
 
|
 
|
 
|
 
|
 +
|debug print ops (beta only)
 +
 
|-
 
|-
!Name
+
|129/0x81
|Entry
+
|NOP
|Event
+
|10000001000000000000000000000000
 +
|
 +
|
 +
|
 
|
 
|
 
|
 
|
|-
 
!Specification Format
 
| rowspan="2" |F
 
|FFFFFFFFFFFFFFFF
 
|FFFFFFFFFFFF
 
|FFFFFFF
 
 
|
 
|
 +
|no operation
 +
 
|-
 
|-
!Name
+
|130/0x82
|Animation Frame
+
|CFL
|Animation Descriptor Offset
+
|10000010TTCCRRRRRRIIIIIIIIIIIIII
|Animation Frame
+
|
 +
|T,C,R,I
 +
|
 +
|
 +
|
 
|
 
|
 +
|general control flow
 +
 
|-
 
|-
!
 
Specification Format
 
| rowspan="2" |H
 
|HH
 
 
|
 
|
 +
|BRA
 +
|100000100000RRRRRRVVVVIIIIIIIIII
 
|
 
|
 +
|R,V,I
 
|
 
|
|-
 
!Name
 
|Horizontal Flip
 
 
|
 
|
 
|
 
|
 
|
 
|
 +
|branch
 +
 
|-
 
|-
!
 
Specification Format
 
| rowspan="2" |I
 
|IIIIIIIIIIIIII
 
|IIIIIIIIIIII
 
|IIIIIIIIII
 
|IIIIII
 
|-
 
!Name
 
|Immediate Code Location
 
|Global Variable Index
 
|Immediate Branch Offset
 
|Color Index
 
|-
 
!
 
Specification Format
 
| rowspan="2" |L
 
|LLLLLLLLLLLL
 
|LLL
 
 
|
 
|
 +
|BNEZ
 +
|100000100001RRRRRRVVVVIIIIIIIIII
 +
|
 +
|R,V,I
 
|
 
|
|-
 
!Name
 
|Left Operand
 
|Object Link Index
 
 
|
 
|
 
|
 
|
|-
 
!
 
Specification Format
 
| rowspan="2" |P
 
|PPPPPPPPPPPP
 
|PPPP
 
|PP
 
 
|
 
|
 +
|branch not equal zero
 +
 
|-
 
|-
!Name
 
|Wave Period
 
|Primary Operation Subtype
 
|Primary Check Type
 
 
|
 
|
|-
+
|BEQZ
!
+
|100000100010RRRRRRVVVVIIIIIIIIII
Specification Format
+
|
| rowspan="2" |R
+
|R,V,I
|RRRRRRRRRRRR
+
|
|RRRRRR
+
|
 
|
 
|
 
|
 
|
 +
|branch equal zero
 +
 
|-
 
|-
!Name
+
|
|Right Operand
+
|CST
|Object Register Index
+
|100000100100RRRRRRSSSSSSSSSSSSSS
 +
|
 +
|R,S
 
|
 
|
 
|
 
|
|-
 
!
 
Specification Format
 
| rowspan="4" |S
 
|SSSSSSSSSSSSSS
 
|SSSSSSSSSSSS
 
|SSSSSSSSS
 
|SSSSSS
 
|-
 
!Name
 
|State
 
|Source
 
|Animation Sequence Index
 
|Subtype
 
|-
 
!
 
Specification Format
 
|SSSSS
 
|SS
 
 
|
 
|
 
|
 
|
 +
|change state
 +
 
|-
 
|-
!Name
+
|
|Secondary Operation Subtype
+
|CSNZ
|Secondary Check Type
+
|100000100101RRRRRRSSSSSSSSSSSSSS
 +
|
 +
|R,S
 
|
 
|
 
|
 
|
|-
 
!
 
Specification Format
 
| rowspan="4" |T
 
|TTTTTTTTTTTT
 
|TTTTTTTT
 
|TTTTTT
 
|TTT
 
|-
 
!Name
 
|Operation Subtype
 
|(Object) Type
 
|Time
 
|Operation Subtype
 
|-
 
!
 
Specification Format
 
|TT
 
|T
 
 
|
 
|
 
|
 
|
 +
|change state not zero
 +
 
|-
 
|-
!Name
+
|
|Operation Subtype
+
|CSEZ
|Truth Invert Toggle
+
|100000100110RRRRRRSSSSSSSSSSSSSS
 +
|
 +
|R,S
 +
|
 
|
 
|
 
|
 
|
|-
 
!
 
Specification Format
 
| rowspan="2" |V
 
|VVVVVVVVVVVV
 
|VVVV
 
|VVVV (SNDB)
 
 
|
 
|
 +
|change state equal zero
 +
 
|-
 
|-
!Name
 
|Velocity
 
|Variable Count
 
|Volume
 
 
|
 
|
|}
+
|RET
</div>
+
|100000101000RRRRRRIIIIIIIIIIIIII
 +
|
 +
|R,I
 +
|
 +
|
 +
|
 +
|
 +
|return
  
=== Crash 2 ===
+
|-
The GOOL Interpreter in Crash 2 recognizes a total of 79 GOOL instructions, including two duplicates. Many of the instructions are unknown. The basic arithmetic and logical operations are preserved the same as in Crash 1, but most others have been changed.
+
|131/0x83
 
+
|ANIM
Crash 2 GOOL code may also contain sections of machine code for the MIPS processor architecture (used by the playstation).
+
|10000011HHTTTTTTSSSSSSSSSFFFFFFF
 +
|
 +
|F,S,T,H
 +
|
 +
|
 +
|W
 +
|
 +
|play animation at specified frame
 +
 
 +
|-
 +
|132/0x84
 +
|ANIF
 +
|10000100HHTTTTTTFFFFFFFFFFFFFFFF
 +
|F
 +
|T,H
 +
|
 +
|
 +
|W
 +
|
 +
|change animation frame
  
==== GOOLv2 Instruction Table ====
+
|-
The GOOL instruction table below lists the opcode, mnemonic/name, format, operands (based on explicit and/or implicit specification of source origin and/or destination target), general operation (represented with c-style statement), and a description for each GOOL instruction. 
+
|133/0x85
<div style="font-family:monospace;font-size:10px;">
+
|VECA
{| border="1" 
+
|10000101CCCTTTBBBAAAVVVVVVVVVVVV
+
|V
|-
+
|T,A,B,C
!  Opcode 
+
|
! Name
+
|
!          Encoding/Format         
+
|*
!Explicit GOOL ops
+
|**
in
+
|multi-purpose vector calcs
!Explicit IMM. ops
 
in
 
!Implicit STACK ops
 
in
 
!        Operation       
 
! Implicit STACK out
 
!Explicit
 
GOOL ops out
 
!  Description
 
 
|-
 
| 0/0x00
 
| ADD 
 
| '''00000000'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L + R       
 
|O 
 
|               
 
|  add
 
 
|-
 
| 1/0x01
 
| SUB 
 
| '''00000001'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L - R       
 
|O 
 
|               
 
|  subtract
 
 
|-
 
| 2/0x02
 
| MUL 
 
| '''00000010'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L * R       
 
|O 
 
|               
 
|  multiply
 
 
|-
 
| 3/0x03
 
| DIV 
 
| '''00000011'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L / R       
 
|O 
 
|               
 
|  divide
 
 
|-
 
| 4/0X04
 
| CEQ 
 
| '''00000100'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = (L == R),
 
O = ((L ^ R) == 0)   
 
|O 
 
|               
 
|  check if equal
 
 
|-
 
| 5/0x05
 
| ANDL
 
| '''00000101'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = (L && R),
 
O = (L ? (R > 0) : 0)   
 
|O 
 
|               
 
|  logical and
 
 
|-
 
| 6/0x06
 
| ORL 
 
| '''00000110'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|<nowiki>O = (L || R)</nowiki>
 
|O
 
|<br>
 
|  logical or
 
 
|-
 
| 7/0x07
 
| ANDB
 
| '''00000111'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L & R       
 
|O
 
|               
 
|  bitwise and
 
 
|-
 
| 8/0x08
 
| ORB 
 
| '''00001000'''RRRRRRRRRRRRLLLLLLLLLLLL
 
| L,
 
|                 
 
|                 
 
|<nowiki>O = L | R</nowiki>
 
|O
 
 
|  bitwise or
 
 
|-
 
| 9/0x09
 
| SLT 
 
| '''00001001'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L < R       
 
|O
 
|               
 
|  set less than
 
 
|-
 
|10/0x0A
 
| SLE 
 
| '''00001010'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = (L <= R)     
 
|O
 
|               
 
|  set less than or equal
 
 
|-
 
|11/0x0B
 
| SGT 
 
| '''00001011'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L > R       
 
|O
 
|               
 
|  set greater than
 
 
|-
 
|12/0x0C
 
| SGE 
 
| '''00001100'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = (L >= R)     
 
|O
 
|               
 
|  set greater than or equal
 
 
|-
 
|13/0x0D
 
| MOD 
 
| '''00001101'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L % R       
 
|O
 
|               
 
|  modulo
 
 
|-
 
|14/0x0E
 
| XOR 
 
| '''00001110'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
|        O = L ^ R       
 
|O
 
|               
 
|  exclusive or
 
 
|-
 
|15/0x0F
 
| TST 
 
| '''00001111'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
| O = (((L & R) ^ R) == 0)
 
|O
 
|               
 
|  test bit
 
 
|-
 
|16/0x10
 
| RND 
 
| '''00010000'''AAAAAAAAAAAABBBBBBBBBBBB
 
A,B  
 
|                 
 
|                 
 
| O = B+(rand() % (A - B))
 
|O
 
|               
 
|  random
 
 
|-
 
|17/0x11
 
| MOVE
 
| '''00010001'''SSSSSSSSSSSSDDDDDDDDDDDD
 
|  S   
 
|                 
 
|                 
 
|          D = S         
 
|             
 
|  [D] 
 
|  move data
 
 
|-
 
|18/0x12
 
| NOTL
 
| '''00010010'''SSSSSSSSSSSSDDDDDDDDDDDD
 
|  S   
 
|                 
 
|                 
 
|        D = (S == 0)     
 
|             
 
|  D   
 
|  logical not
 
 
|-
 
|19/0x13
 
| PATH 
 
| '''00010011'''AAAAAAAAAAAABBBBBBBBBBBB
 
|  (A),B
 
|R = 0x100
 
|  [R,A] 
 
|          varies       
 
|  P 
 
|  B   
 
|  path progress (unconfirmed for c2)
 
 
|-
 
|20/0x14
 
| LEA 
 
| '''00010100'''SSSSSSSSSSSSDDDDDDDDDDDD
 
|  S   
 
|                 
 
|                 
 
|          D = &S       
 
|             
 
|  D   
 
|  load effective address (unconfirmed for c2)
 
 
|-
 
|21/0x15
 
| SHA 
 
| '''00010101'''RRRRRRRRRRRRLLLLLLLLLLLL
 
|  L,R 
 
|                 
 
|                 
 
| O = ((R < 0) ? (L >> -R)
 
<nowiki>:</nowiki> (L << R))
 
|  O 
 
|               
 
|  arithmetic shift
 
 
|-
 
|22/0x16
 
| PSHV 
 
| '''00010110'''AAAAAAAAAAAABBBBBBBBBBBB
 
|  [A,[B]] 
 
|                 
 
|                 
 
|      [arg_buf = A]
 
I = A; J = B;     
 
|[I,[J]]
 
|               
 
|  push value to stack (unconfirmed for c2)
 
 
|-
 
|23/0x17
 
| NOTB
 
| '''00010111'''SSSSSSSSSSSSDDDDDDDDDDDD                       
 
|               
 
|                 
 
|                 
 
|                                                    D = ~S
 
|             
 
|                D
 
|  bitwise not
 
 
|-
 
|24/0x18
 
| MOVC
 
| '''00011000'''0000RRRRRRIIIIIIIIIIIIII
 
|               
 
|  R,C  
 
|                
 
|         see docs       
 
|   O 
 
|              
 
|  move code pointer (unconfirmed for c2)
 
 
|-
 
|25/0x19
 
| ABS 
 
| '''00011001'''SSSSSSSSSSSSDDDDDDDDDDDD
 
|  S   
 
|                 
 
|                 
 
|  D = (S < 0) ? -S: S   
 
|             
 
|  D   
 
|  absolute value
 
 
|-
 
|26/0x1A
 
| ?
 
| '''00011010'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|27/0x1B
 
| ?
 
| '''00011011'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|28/0x1C
 
| ?
 
| '''00011100'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|29/0x1D
 
| ?
 
| '''00011101'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|30/0x1E
 
| ?
 
| '''00011110'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|31/0x1F
 
| ?
 
| '''00011111'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|32/0x20
 
| ?
 
| '''00100000'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|33/0x21
 
| ?
 
| '''00100001'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|34/0x22
 
| ?
 
| '''00100010'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|35/0x23
 
| ?
 
| '''00100011'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|36/0x24
 
| ?
 
| '''00100100'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|37/0x25
 
| ?
 
| '''00100101'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|38/0x26
 
| ?
 
| '''00100110'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|39/0x27
 
| ?
 
| '''00100111'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|40/0x28
 
| ?
 
| '''00101000'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|41/0x29
 
| ?
 
| '''00101001'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|42/0x2A
 
| ?
 
| '''00101010'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|43/0x2B
 
| ?
 
| '''00101011'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|44/0x2C
 
| ?
 
| '''00101100'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|45/0x2D
 
| ?
 
| '''00101101'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|46/0x2E
 
| ?
 
| '''00101110'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|47/0x2F
 
| NOP
 
| '''00101111'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  no operation
 
 
|-
 
|48/0x30
 
| ?
 
| '''00110000'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|49/0x31
 
| ?
 
| '''00110001'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|50/0x32
 
| BRA
 
| '''00110010'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  branch
 
 
|-
 
|51/0x33
 
| BNEZ
 
| '''00110011'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  branch not equal zero
 
 
|-
 
|52/0x34
 
| BEQZ
 
| '''00110100'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  branch equal zero
 
 
|-
 
|53/0x35
 
| ?
 
| '''00110101'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|54/0x36
 
| ?
 
| '''00110110'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|55/0x37
 
| ?
 
| '''00110111'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|56/0x38
 
| ?
 
| '''00111000'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|57/0x39
 
| ?
 
| '''00111001'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|58/0x3A
 
| ?
 
| '''00111010'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|59/0x3B
 
| ?
 
| '''00111011'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|60/0x3C
 
| ?
 
| '''00111100'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|61/0x3D
 
| ?
 
| '''00111101'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|62/0x3E
 
| ?
 
| '''00111110'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|63/0x3F
 
| ?
 
| '''00111111'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|64/0x40
 
| ?
 
| '''01000000'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|65/0x41
 
| ?
 
| '''01000001'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|66/0x42
 
| ?
 
| '''01000010'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|67/0x43
 
| ?
 
| '''01000011'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|68/0x44
 
| ?
 
| '''01000100'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|69/0x45
 
| ?
 
| '''01000101'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|70/0x46
 
| ?
 
| '''01000110'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|71/0x47
 
| ?
 
| '''01000111'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|72/0x48
 
| ?
 
| '''01001000'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|73/0x49
 
| NATIVE
 
| '''01001001'''101111100000101111100000
 
|
 
|
 
|
 
|
 
|
 
|
 
|  begin native code
 
 
|-
 
|74/0x4A
 
| ?
 
| '''01001010'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|75/0x4B
 
| ?
 
| '''01001011'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|76/0x4C
 
| ?
 
| '''01001100'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|77/0x4D
 
| ?
 
| '''01001101'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
 
|-
 
|78/0x4E
 
| ?
 
| '''01001110'''????????????????????????
 
|
 
|
 
|
 
|
 
|
 
|
 
|  unknown
 
|}
 
</div>
 
  
=== GOOL Instruction Operands ===
+
|-
...
+
|134/0x86
* In/Source type operands
+
|JAL
** Explicitly specified (i.e. origin = determined by operand's corresponding bitfield from the instruction)
+
|10000110VVVV000000IIIIIIIIIIIIII
*** GOOL in/source operand
+
|
*** Immediate operand
+
|I,V
** Implicitly specified (i.e. origin = top of object's stack; implicitly popped from top of object's stack)
+
|
*** Stack in/source operand
+
|
* Out/Destination type operands
+
|
** Explicitly specified (i.e. target = determined by operand's corresponding bitfield from the instruction)
+
|
*** GOOL out/destination operand
+
|jump and link
** Implicitly specified (i.e. target = top of object's stack; implicitly pushed to top of object's stack)
 
*** Stack out/destination operand/result*
 
<nowiki>*</nowiki>technically not an 'operand', but rather a ''result'' of the instruction's overall operation; it is <i>implied</i> that instructions that use [an] operand(s) of this type always pushes it/them (i.e the result(s)) to the top of the object's stack.
 
  
==== Explicit Operands ====
+
|-
A GOOL instruction's explicit operands are ''explicitly'' specified in its lower 24 bits (operand portion). Each explicitly specified operand is either an immediate operand, or a GOOL operand.
+
|135/0x87
 
+
|EVNT
===== Immediate Operands =====
+
|10000111LLLAAARRRRRREEEEEEEEEEEE
An immediate operand ''directly'' specifies its value in its corresponding bitfield (within the operand portion) of the instruction. The number of immediate operands and their positions/bit-lengths varies between instructions.
+
|E
 +
|L,A,R
 +
|
 +
|
 +
|
 +
|
 +
|send an event
 +
|-
 +
|136/0x88
 +
|EVHR
 +
|10001001TTCCRRRRRR**************
 +
|
 +
|R,C,T,*
 +
|**
 +
|
 +
|
 +
|
 +
|reject event
  
Immediate Operands are in operands (source operands).
+
|-
 +
|137/0x89
 +
|EVHA
 +
|10001000TTCCRRRRRR**************
 +
|
 +
|R,C,T,*
 +
|**
 +
|
 +
|<br>
 +
|
 +
|accept event
 +
|-
 +
|138/0x8A
 +
|CHLD
 +
|10001010AAAATTTTTTTTSSSSSSCCCCCC
 +
|
 +
|C,T,S,A
 +
|[C],
 +
arg[0 to A]
 +
|
 +
|
 +
|
 +
|spawn children objects
  
===== GOOL Operands =====
+
|-
Conversely, a GOOL operand is specified as a ''reference'' to its actual value or destination location. Each GOOL operand is 12 bits in length; a GOOL instruction may require the specification of at most 2 GOOL operands, within the upper and/or lower halves of its operand portion, respectively. The 12 bit GOOL reference that specifies a GOOL operand encodes a [32 bit] pointer to its corresponding source value and/or destination location. Operations for instructions that require GOOL operand specification first <i>translate</i> the corresponding GOOL reference(s) to yield their decoded pointer(s) before accessing pointed data.
+
|139/0x8B
 
+
|NTRY
See the GOOL Reference Translation section for more information.
+
|10001011TTTTTTTTTTTTEEEEEEEEEEEE
 +
|
 +
|T,E
 +
|
 +
|
 +
|
 +
|
 +
|multi-purpose page operation
  
Depending on how a GOOL operand is used by its instruction, it may be an in type (source) operand, an out type (destination) operand, or both (inout operand). If an instruction only reads the [input] value located by its translated GOOL operand (a pointer), it is an in type (source) operand. If an instruction only writes a result/value to the location of its translated GOOL operand, it is an out type (destination) operand. If an operand meets both of these criteria it is an inout operand.
+
|-
 +
|140/0x8C
 +
|SNDP
 +
|10001100AAAAAAAAAAAABBBBBBBBBBBB
 +
|A,B
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|play audio file at volume
  
A GOOL operand can be translated to yield, among several other types of pointers, a pointer to any of the object's fields; for example, this pointer could then be used by the instruction operation to read the value at its [implied] source location and/or to write a value to its implied destination location, deeming the operand a source GOOL operand and/or a destination GOOL operand, respectively. A GOOL operand can also be translated to yield a pointer to the value at the top of the objects stack for, before either decrementing or incrementing its stack pointer, a location that can be dereferenced for reading or writing, effectively popping from or pushing to its stack [based on whether it is a GOOL source operand or a GOOL destination operand]. In these cases, the instruction operand is said to be explicitly popped from or pushed onto the objects stack. 
+
|-
 +
|141/0x8D
 +
|SNDB
 +
|10001101FFFFTTRRRRRRSSSSSSSSSSSS
 +
|S
 +
|F,T,R
 +
|
 +
|
 +
|
 +
|
 +
|adjust voice parameters
 +
|-
 +
|142/0x8E
 +
|VECB
 +
|10001110CCCTTTBBBAAAVVVVVVVVVVVV
 +
|V
 +
|T,A,B,C
 +
|
 +
|
 +
|
 +
|<br>
 +
|multi-purpose vector calcs
  
==== Implicit Operands ====
+
|-
===== Implicit In Operands =====
+
|143/0x8F
Some GOOL instructions may require the ''implicit'' specification of one or more (implicit) in operands. In operands are implicitly specified prior to an instruction's interpretation by pushing their value(s)-which must remain the topmost values at interpretation-to the object's stack. It is <i>implied</i> that these so-called implicit operands will exist on the stack for the instruction to pop and use as input.
+
|EVNB
===== Implicit Out Operands =====
+
|10001111LLLAAARRRRRREEEEEEEEEEEE
For most GOOL instructions, the net effect of their operation involves an implicit push of one or more <i>results</i> to the object's stack. That is-it is <i>implied</i> or expected that these instructions will ultimately push their results to the object's stack.
+
|E
 +
|L,A,R
 +
|
 +
|
 +
|
 +
|<br>
 +
|broadcast an event
  
 +
|-
 +
|144/0x90
 +
|EVNU
 +
|10010000LLLAAARRRRRREEEEEEEEEEEE
 +
|E
 +
|L,A,R
 +
|
 +
|
 +
|<br>
 +
|<br>
 +
|send event unknown variant
  
 +
|-
 +
|145/0x91
 +
|CHLF
 +
|10100000AAAATTTTTTTTSSSSSSCCCCCC
 +
|
 +
|C,T,S,A
 +
|[C],
 +
arg[0 to A]
 +
|
 +
|
 +
|<br>
 +
|spawn children objects;
 +
no replacement if obj pool full
  
....
+
|}
 +
</div>
  
out type operands - By the operation of some specific type of instruction that requires some 
+
Note that a few instructions can not be represented with a single mnemonic; operations for these instructions are not only determined by their opcode but also their primary operation subtype and possibly secondary operation subtype fields. These instructions have their own tables, which are given in the following sections.
  
out-type operand to be specified, data will ultimately be written to [the unsigned long of memory 
+
===== State Return Instruction Table =====
 +
<div style="font-family:monospace;font-size:10px;">
 +
{| border="1"
 +
!Opcode
 +
!Name
 +
!Encoding/Format
 +
!Explicit
 +
IMM. ops
  
at] that operand's 'translated location'. Such data is an expected result of that specific type of 
+
in
 
+
!Description
[instruction's] operation. By the operation of an instruction with specific type/opcode that must 
 
 
 
specify multiple out-type operands, its corresponding expected result(s) will ultimately be written 
 
 
 
at the respective translated location(s) for each specified operand. 
 
 
 
 
 
 
 
=== GOOL Reference Translation ===
 
The following table lists the encoding format, potential type name, and a descriptive type name for each of the possible GOOL reference types:
 
 
 
<div style="font-family:monospace;">
 
{| class="article-table"
 
!Format
 
!Potential Type Name
 
!Descriptive Type Name
 
 
|-
 
|-
|00RRRRRRRRRR
+
|136/0x88
|Ireg Ref
+
|RSTT
|object local executable data pool reference
+
|10001000TTCCRRRRRR**************
 +
|R,C,T,*
 +
|state return guard = true variant
 
|-
 
|-
|01RRRRRRRRRR
+
|
|Pool Ref
+
|RST
|object external executable data pool reference
+
|100010000100RRRRRRSSSSSSSSSSSSSS
 +
|R,S
 +
|state return guard = true
 
|-
 
|-
|100IIIIIIIII
+
|
|Int Ref
+
|RSNT
|constant mult of 16  (range: -8192 - 8176)
+
|100010000101RRRRRRSSSSSSSSSSSSSS
 +
|R,S
 +
|state return if nonzero guard = true
 
|-
 
|-
|1010IIIIFFFF
+
|
|Frac Ref
+
|RSZT
|constant mult of 256 (range: -32768 - 32512)
+
|100010000110RRRRRRSSSSSSSSSSSSSS
 +
|R,S
 +
|state return if equal zero guard = true
 
|-
 
|-
|10110SSSSSSS
+
|
|Stack Ref
+
|RSCT
|object frame argument/local variable reference [peek stack @ location relative to fp]
+
|100010000111RRRRRRSSSSSSSSSSSSSS
 +
|R,S
 +
|state return eval prev cond guard = true
 
|-
 
|-
|101111100000
+
|
|Null Ref
+
|RNT
|null reference (translates to 0)
+
|100010001000RRRRRRxxxxxxxxxxxxxx
 +
|R
 +
|null return guard = true
 
|-
 
|-
|101111110000
+
|
|Sp-Double Ref
+
|RNNT
|double stack pop reference (translates to 1)
+
|100010001001RRRRRRxxxxxxxxxxxxxx
 +
|R
 +
|null return if nonzero guard = true
 
|-
 
|-
|110LLLMMMMMM
+
|
|Reg Ref
+
|RNZT
|object link memory reference
+
|100010001010RRRRRRxxxxxxxxxxxxxx
 +
|R
 +
|null return if equal zero guard = true
 
|-
 
|-
|111MMMMMMMMM (M != 0x1F)
+
|
|Var Ref
+
|RNCT
|object field/memory reference
+
|100010001011RRRRRRxxxxxxxxxxxxxx
 +
|R
 +
|null return eval prev cond guard = true
 +
|-
 +
|
 +
|GDT
 +
|100010001100RRRRRRxxxxxxxxxxxxxx
 +
|R
 +
|guard = true
 
|-
 
|-
|111000011111
+
|
|Stack Pop/Push
+
|GNT
|stack pop/push reference
+
|100010001101RRRRRRxxxxxxxxxxxxxx
|}
+
|R
</div>
+
|if nonzero guard = true
Potential GOOL Reference type names have been deduced based on what appears to be an unreferenced array of GOOL interpreter debug strings at 0x103B8.
+
|-
 
+
|
'''UNFINISHED'''
+
|GZT
 
+
|100010001110RRRRRRxxxxxxxxxxxxxx
Given an instruction with specific type/opcode whose operation expects the [explicit] specification 
+
|R
 
+
|if equal zero guard = true
of at least one GOOL operand (i.e. at least one operand listed in table under explicit GOOL ops in 
+
|-
 
+
|
and/or explicit GOOL ops out for that instruction type/opcode), and with a specific one of its GOOL 
+
|GCT
 
+
|100010001111RRRRRRxxxxxxxxxxxxxx
operands specified as a particular sequence of bits in its corresponding bitfield (12 bit region) 
+
|R
 
+
|eval prev cond guard = true
within the operand portion of the instruction, the following can be used to determine, in that 
+
|-
 
+
|
instruction's operation, the specific steps taken for the necessary translation of that operand to 
+
|GBNT
 
+
|100010000001RRRRRRVVVVIIIIIIIIII
its pointer of a specific type. When specified as some particular sequences of bits, the operand's 
+
|R,V,I
 
+
|if nonzero guard = true else branch
translation can result in a different operation based on whether the instruction table lists that 
+
|-
 
+
|
operand [for the accompanying instruction type/opcode] as an 'in' or an 'out' type GOOL operand. 
+
|GBZT
 
+
|100010000010RRRRRRVVVVIIIIIIIIII
 
+
|R,V,I
 
+
|if equal zero guard = true else branch
i.) 111000011111 - object stack [pop/push]
+
|-
 
+
|137/0x89
 
+
| RSTF 
 
+
|                                                                          10001001TTCCRRRRRR**************
in  - in-type operands of this bit sequence will return a pointer to the top of the object's stack/stack 
+
|                  R,C,T,*
 
+
|state return guard = false variant
pointer prior to popping the value there/decrementing the object's stack pointer. A stack pop will 
+
|-
 
+
|
result from the translation's decrementing of the object's stack pointer and the operation's 
+
|RSF
 
+
|100010000100RRRRRRSSSSSSSSSSSSSS
dereferencing of the returned/translated pointer for a read; this popped value is then used by the 
+
|R,S
 
+
|state return guard = false
operation as the operand's actual/translated value. 
+
|-
 
+
|
 
+
|RSNF
 
+
|100010000101RRRRRRSSSSSSSSSSSSSS
out - out-type operands of this bit sequence will return a pointer to the top of the object's stack/stack 
+
|R,S
 
+
|state return if nonzero guard = false
pointer prior to its extension/incrementing the object's stack pointer. A stack push will result 
+
|-
 
+
|
from the translation's incrementing of the object's stack pointer and the operation's dereferencing 
+
|RSZF
 
+
|100010000110RRRRRRSSSSSSSSSSSSSS
of the returned/translated pointer for a write. The data written at the location of a returned 
+
|R,S
 
+
|state return if equal zero guard = false
pointer/pushed to the stack by an instruction's operation is an expected result of the specific type 
+
|-
 
+
|
of operation. 
+
|RSCF
 
+
|100010000111RRRRRRSSSSSSSSSSSSSS
 
+
|R,S
 
+
|state return eval prev cond guard = false
-- 
+
|-
 
+
|
 
+
|RNF
 
+
|100010001000RRRRRRxxxxxxxxxxxxxx
ii.) 111AAAAAAAAA - object field/memory (A != 0x1F) 
+
|R
 
+
|null return guard = false
 
+
|-
 
+
|
A = object field index (domain = 0    to 0x1FF; 
+
|RNNF
 
+
|100010001001RRRRRRxxxxxxxxxxxxxx
                         range = 0x60 to 0x860, R=4N) 
+
|R
 
+
|null return if nonzero guard = false
 
+
|-
 
+
|
A significant amount of an object's fields lie within its 'process' structure; this structure is 
+
|RNZF
 
+
|100010001010RRRRRRxxxxxxxxxxxxxx
located at a 0x60 byte offset from the beginning of the object's structure. Note that the last of 
+
|R
 
+
|null return if equal zero guard = false
the fields in the object's process structure also includes its array of/address space for its 
+
|-
 
+
|
[local] memory where its stack contents are stored. 
+
|RNCF
 
+
|100010001011RRRRRRxxxxxxxxxxxxxx
 
+
|R
 
+
|null return eval prev cond guard = false
Operands of the bit sequence 111AAAAAAAAA will return a pointer to the 'A'th object field in 
+
|-
 
+
|
relation to an object's process structure; because object fields are 4 bytes/an unsigned long in 
+
|GDF
 
+
|100010001100RRRRRRxxxxxxxxxxxxxx
length and an object's process structure is located at a 0x60 byte offset from the beginning of its 
+
|R
 
+
|guard = false
structure, then the formula: 
+
|-
 
+
|
 
+
|GNF
 
+
|100010001101RRRRRRxxxxxxxxxxxxxx
  0x60 + (A * 4) 
+
|R
 
+
|if nonzero guard = false
 
+
|-
 
+
|
gives the byte offset of the actual field pointed to by the translation's returned pointer, and 
+
|GZF
 
+
|100010001110RRRRRRxxxxxxxxxxxxxx
consequently the actual field referred to by such an operand. The object structure definition listed 
+
|R
 
+
|if equal zero guard = false
in previous sections includes byte offsets for all object fields within the object structure. 
+
|-
 
+
|
 
+
|GCF
 
+
|100010001111RRRRRRxxxxxxxxxxxxxx
Notice that if A [bits] is specified as A = 0x1F, then the bit sequence will have the form 
+
|R
 
+
|eval prev cond guard = false
111000011111; this is, however, the bit sequence whose translation shall instead be processed for a 
+
|-
 
+
|
stack pop/push. If, however, such a sequence were not checked and ultimately processed for a stack 
+
|GBNF
 
+
|100010000001RRRRRRVVVVIIIIIIIIII
pop/push prior to passing the test for the bit sequence 111AAAAAAAAA with A = 0x1F, then the byte 
+
|R,V,I
 
+
|if nonzero guard = false else branch
offset determined by translation of such an operand- 0x60 + (A * 4) = 0x60 + (0x1F * 4) = 0xDC = 
+
|-
 
+
|
byte offset of object's 'stack pointer' field -would refer to the object's stack pointer field. As 
+
|GBZF
 
+
|100010000010RRRRRRVVVVIIIIIIIIII
this is arguably a favourable design choice, it should not be possible to directly modify an 
+
|R,V,I
 
+
|if equal zero guard = false else branch
object's stack pointer field via translation of specified operands-only indirectly, should the 
+
|-
 
+
|}
translation of an such an instruction's GOOL operand when specified in the form 111000011111 
+
</div>
 
 
[111AAAAAAAAA with A = 0x1F] modify the object's stack pointer as a result of the appropriate push 
 
 
 
and/or pop. 
 
 
 
 
 
 
 
in - in-type operands of this bit sequence will return a pointer to the corresponding object field; 
 
 
 
this value is then used by the operation as the operand's actual/translated value. 
 
 
 
 
 
 
 
out - out-type operands of this bit sequence will return a pointer to the corresponding object 
 
 
 
field. Data will ultimately be written to this location as an expected result of the specific type 
 
 
 
of operation. 
 
 
 
 
 
 
 
--
 
 
 
 
 
 
 
iii.) 110BBBAAAAAA
 
 
 
 
 
 
 
A = [link] object field index (domain =     0 to  0x3F;
 
 
 
                               range  =  0x60 to 0x15C, R=4N)
 
 
 
 
 
 
 
B = object link index         (domain =     0 to 7;
 
 
 
                               range  =  0x60 to 0x7C,  R=4N)  
 
  
Operands of the bit sequence 110BBBAAAAAA will return a pointer to the 'A'th' object field in 
+
=== Crash 2 ===
 +
The GOOL Interpreter in Crash 2 recognizes a total of 79 GOOL instructions, including two duplicates. Many of the instructions are known. The basic arithmetic and logical operations are preserved the same as in Crash 1, but most others have been changed.
  
relation to the object's 'B'th' link object's process structure. An object's 'link objects' are 
+
Crash 2 GOOL code may also contain sections of machine code for the MIPS processor architecture (used by the playstation).
  
referred to by the 8 object pointers at the beginning of its process structure; the first of these 
+
==== GOOLv2 Instruction Table ====
 +
The GOOL instruction table below lists the opcode, mnemonic/name, format, operands (based on explicit and/or implicit specification of source origin and/or destination target), general operation (represented with c-style statement), and a description for each GOOL instruction. 
 +
<div style="font-family:monospace;font-size:11px;">
 +
{| border="1" 
  
pointers is the object's 'self link', the second a pointer to its parent object, the third a pointer 
+
|-
 +
!Opcode
 +
!Name
 +
!Encoding/Format
 +
!Explicit GOOL ops
 +
in
 +
!Explicit IMM. ops
 +
in
 +
!Implicit STACK ops
 +
in
 +
!Operation
 +
!Implicit STACK out
 +
!Explicit
 +
GOOL ops out
 +
!Description
  
to its sibling object, and so on. The A bits in the sequence specify the offset of a field in 
+
|-
 
+
|0/0x00
unsigned longs from the link object's process structure; the B bits in the sequence specify the 
+
|ADD
 
+
|'''00000000'''RRRRRRRRRRRRLLLLLLLLLLLL
index of one of the object's 8 link objects that contains the process structure which the returned 
+
|L,R
 
+
|
object field pointer's location will be calculated relative to. Thus, translation of such a bit 
+
|
 
+
|O = L + R
sequence will return a pointer to any of an object's link object's process structure's fields. 
+
|O
 
+
|
 
+
|add
 
+
|-
in - in-type operands of this bit sequence will return a pointer to the corresponding object field; 
+
|1/0x01
 
+
|SUB
this value is then used by the operation as the operand's actual/translated value. 
+
|'''00000001'''RRRRRRRRRRRRLLLLLLLLLLLL
 
+
|L,R
 
+
|
 
+
|
out - out-type operands of this bit sequence will return a pointer to the corresponding object 
+
|O = L - R
 
+
|O
field. Data will ultimately be written to this location, where such data is an expected result of 
+
|
 
+
|subtract
some specific type of [instruction's] operation. For an instruction that can specify multiple 
+
|-
 
+
|2/0x02
out-type operands (with specific type/opcode), by the instruction's operation, its corresponding 
+
|MUL
 
+
|'''00000010'''RRRRRRRRRRRRLLLLLLLLLLLL
expected result(s) will ultimately be written at the respective translated location(s) for each 
+
|L,R
 
+
|
operand specified in this format/with this bit sequence. 
+
|
 
+
|O = L * R
 
+
|O
 
+
|
--
+
|multiply
 
+
|-
iv.) 00AAAAAAAAAA - object global executable static data
+
|3/0x03
 
+
|DIV
 
+
|'''00000011'''RRRRRRRRRRRRLLLLLLLLLLLL
 
+
|L,R
A = object executable static data offset (domain =   0 to 0x3FF;
+
|
 
+
|
                                          range  =   0 to 0xFFC, R=4N)
+
|O = L / R
 
+
|O
 
+
|
 
+
|divide
A GOOL executable's static data (GOOL_data) item is essentially a table of static, predefined 
+
|-
 
+
|4/0x04
'magic' constants that can be used by GOOL operations as the translated values of operands with this 
+
|CEQ
 
+
|'''00000100'''RRRRRRRRRRRRLLLLLLLLLLLL
bit sequence. For example, it includes the EIDs of any entries, preconfigured bitfields, values 
+
|L,R
 
+
|
corresponding to specific bits to test, audio sample parameters (volume, pan, etc), specific speeds 
+
|
 
+
|O = (L == R),
or velocities, and other constants utilized by the operations of instructions in the executable's 
+
O = ((L ^ R) == 0)
 
+
|O
GOOL_code item. It is necessary that a translation can yield these constants for the values of some 
+
|
 
+
|check if equal
GOOL operands since, as it will be seen, the only other types of translation that can yield a 
+
|-
 
+
|5/0x05
specific constant are restricted to yielding constants in certain ranges. 
+
|ANDL
 
+
|'''00000101'''RRRRRRRRRRRRLLLLLLLLLLLL
 
+
|L,R 
 
+
|
[Also, in the case that the bit sequence types for the latter translation can be used in operands, 
+
|
 
+
|O = (L && R),
if the operations for instructions [with the operands] translate them to the same constant [i.e. the 
+
O = (R ? L : R)
 
+
|O
same bit sequence is specified for the operands in each instruction] and utilize that constant in 
+
|
 
+
|logical and
the same fashion, then if an equal change in those operations is desired as some modification during 
+
|-
 
+
|6/0x06
development it would generally involve changing the specified sequence for -each- operand in each 
+
|ORL
 
+
|'''00000110'''RRRRRRRRRRRRLLLLLLLLLLLL
instruction. Then, it is beneficial to keep a table of constants, since the translations for 
+
|L,
 
+
|
different instructions' operands that yield a reference the same constant in the table will, when 
+
|
 
+
|<nowiki>O = (L || R)</nowiki>
changing the single unsigned long/constant in the table, reference the same -changed- constant in 
+
<nowiki>O = L | R</nowiki>
 
+
|O
the table.] 
+
|<br>
 
+
|logical or (same as ORB)
 
+
|-
 
+
|7/0x07
Operands of the bit sequence 00AAAAAAAAAA will return a pointer to the static, predefined constant 
+
|ANDB
 
+
|'''00000111'''RRRRRRRRRRRRLLLLLLLLLLLL
at the offset specified by 'A bits' within/relative to the object's global GOOL executable entry'
+
|L,R 
 
+
|
static data [item]; that is-a translation of this type will return a pointer to the constant at an 
+
|
 
+
|O = L & R
offset of 'A' unsigned longs relative to the third (static data) 'item' (unsigned long array) within 
+
|O
 
+
|
the entry structure referred to by the objects 'global' field. 
+
|bitwise and
 
+
|-
 
+
|8/0x08
 
+
|ORB
in - in-type operands of this bit sequence will return a pointer to the corresponding location in 
+
|'''00001000'''RRRRRRRRRRRRLLLLLLLLLLLL
 
+
|L,R 
the object's global executable [entry's] static data [item]; the unsigned long/constant at this 
+
|
 
+
|
location is then used by the operation as the operand's actual/translated value. 
+
|<nowiki>O = L | R</nowiki>
 
+
|O
 
+
|
 
+
|bitwise or
out - out-type operands of this bit sequence will return a pointer to the corresponding location in 
+
|-
 
+
|9/0x09
the object's global executable [entry's] static data [item]; the operation ultimately replaces the 
+
|SLT
 
+
|'''00001001'''RRRRRRRRRRRRLLLLLLLLLLLL
constant at this location with its respective unsigned long result (designated for the translated 
+
|L,R 
 
+
|
location of that operand.) A write to the executable's static data should generally be avoided 
+
|
 
+
|O = L < R
unless a global change to that constant, and therefore an equal change in behavior for each object 
+
|O
 
+
|
that is an instance of that executable, is desired. 
+
|set less than
 
+
|-
 
+
|10/0x0A
 
+
|SLE
--
+
|'''00001010'''RRRRRRRRRRRRLLLLLLLLLLLL
 
+
|L,R 
 
+
|
 
+
|
Note the distinction from the object's 'global' GOOL entry from it's 'external' GOOL entry. The 
+
|O = (L <= R)
 
+
|O
global entry may or may not contain the byte code [item] that will be interpreted in the object's 
+
|
 
+
|set less than or equal
current state; it contains the corresponding state definition that specifies the GOOL executable 
+
|-
 
+
|11/0x0B
entry which contains the actual GOOL byte code item with the instructions that will be interpreted. 
+
|SGT
 
+
|'''00001011'''RRRRRRRRRRRRLLLLLLLLLLLL
In the object's current state, its 'external' entry will refer to that specified entry. 
+
|L,R 
 
+
|
 
+
|
 
+
|O = L > R
--
+
|O
 
+
|
v.) 01AAAAAAAAAA - object external executable static data
+
|set greater than
 
+
|-
 
+
|12/0x0C
 
+
|SGE
A = object executable static data offset (domain =   0 to 0x3FF;
+
|'''00001100'''RRRRRRRRRRRRLLLLLLLLLLLL
 
+
|L,R 
                                          range  =   0 to 0xFFC, R=4N)
+
|
 
+
|
 
+
|O = (L >= R)
 
+
|O
Operands of the bit sequence 01AAAAAAAAAA will return a pointer to the constant (unsigned long) at 
+
|
 
+
|set greater than or equal
the offset specified by 'A bits' within/relative to the object's external GOOL executable entry'
+
|-
 
+
|13/0x0D
static data [item]; that is-a translation of this type will return a pointer to the constant at an 
+
|MOD
 
+
|'''00001101'''RRRRRRRRRRRRLLLLLLLLLLLL
offset of 'A' unsigned longs relative to the third (static data) 'item' (unsigned long array) within 
+
|L,
 
+
|
the entry structure referred to by the objects 'external' field. 
+
|
 
+
|O = L % R
 
+
|O
 
+
|
in - in-type operands of this bit sequence will return a pointer to the corresponding location in 
+
|modulo
 
+
|-
the object's external executable [entry's] static data [item]; the unsigned long/constant at this 
+
|14/0x0E
 
+
|XOR
location is then used by the operation as the operand's actual /translated value. 
+
|'''00001110'''RRRRRRRRRRRRLLLLLLLLLLLL
 
+
|L,R 
 
+
|
 
+
|
out - out-type operands of this bit sequence will return a pointer to the corresponding location in 
+
|O = L ^ R
 
+
|O
the object's external executable [entry's] static data [item]; the operation ultimately replaces the 
+
|
 
+
|exclusive or
constant at this location with its respective unsigned long result (designated for the translated 
+
|-
 
+
|15/0x0F
location of that operand.) A write to the executable's static data should generally be avoided 
+
|TST
 
+
|'''00001111'''RRRRRRRRRRRRLLLLLLLLLLLL
unless a global change to that constant, and therefore an equal change in behavior for each object 
+
|L,R 
 
+
|
that is an instance of that executable, is desired. 
+
|
 
+
|O = (((L & R) ^ R) == 0)
--
+
|O
 
+
|
vi.) 100AAAAAAAAA - constant mult of 16 
+
|test bit
 
+
|-
 
+
|16/0x10
 
+
|RND
A = constant that will be multiplied by 16 (domain:      0 to  0x1FF)
+
|'''00010000'''AAAAAAAAAAAABBBBBBBBBBBB
 
+
|A,B 
                                           ( range:  -8192 to   8176; R =   16N)
+
|
 
+
|
                                      << 4 (       -0x2000 to 0x1FF0; R = 0x10N)
+
|O = B+(rand() % (A - B))
 
+
|O
Operands of the bit sequence 100AAAAAAAAA will return a pointer to a value that is written as one of 
+
|
 
+
|random
two double-buffered signed long 'constants' in their 2 respective buffers located at offsets 0x40 
+
|-
 
+
|17/0x11
and 0x44 in scratch memory, as referenced by the pointer at memory location 0x56480 [gp$(0x44)]. 
+
|MOVE
 
+
|'''00010001'''SSSSSSSSSSSSDDDDDDDDDDDD
Translation for operands of this bit sequence will first write the value (16*A)-that is, 16 times 
+
|S
 
+
|
the value specified by 'A bits'-to the 'currently active constant buffer'. The currently active 
+
|
 
+
|D = S
constant buffer is indicated by either a 0 or a 1 in the unsigned long at memory location 0x56484 
+
|
 
+
|[D]
[gp$(0x48)], which refers to either the buffer at offset 0x40 or 0x44, respectively, in scratch 
+
|move data
 
+
|-
memory. The currently inactive constant buffer at any instant is always the buffer that is NOT the 
+
|18/0x12
 
+
|NOTL
currently active constant buffer. The translation then proceeds by changing the currently inactive 
+
|'''00010010'''SSSSSSSSSSSSDDDDDDDDDDDD
 
+
|S
constant buffer to the currently active constant buffer (that is, if 0 previously indicated the 
+
|
 
+
|
currently active constant buffer, then this is changed to a 1; conversely, if 1, it is changed to a 
+
|D = (S == 0)
 
+
|
0). The translation finally returns a pointer to the (16*A) signed long value that had been written 
+
|D
 
+
|logical not
to the previously active buffer, at which point is the currently inactive buffer. 
+
|-
 
+
|19/0x13
The double-buffering design allows the sufficient specification of a maximum of 2 (constant) GOOL 
+
|LOOP
 
+
|'''00010011'''AAAAAAAAAAAABBBBBBBBBBBB
operands [with this bit sequence] per instruction, since each of the 2 buffers will keep track of 1 
+
|(A),B
 
+
|R = 0x100
and therefore an overall of 1+1=2 [translated] constants to be used by operations of instructions 
+
|[R,A]
 
+
|B = A >= 0 ? B + R : B - R
with the corresponding operands. 
+
if (B > A && A > 0) B = -A + R*2
 
+
else if (B < A && A < 0) B = -A - R*2
 
+
P = A >= 0 ? abs(B) : -abs(B)
 
+
|P
A can be specified as a negative constant with the appropriate 2's complement format: 
+
|B
 
+
|loop around zero
 
+
|-
 
+
|20/0x14
A = 1NNNNNNNN (-N): V = 11111111111111111111NNNNNNNN0000 (16 * -N)
+
|LEA
 
+
|'''00010100'''SSSSSSSSSSSSDDDDDDDDDDDD
A = 0NNNNNNNN ( N): V = 00000000000000000000NNNNNNNN0000 (16 *  N)
+
|S
 
+
|
 
+
|
 
+
|D = &S
Where V indicates the binary signed long that will be written to the appropriate constant buffer for 
+
|
 
+
|D
the respective specified formats of A. 
+
|load effective address
 
+
|-
 
+
|21/0x15
 
+
|SHA
in - in-type operands of this bit sequence will return a pointer to the [currently inactive constant 
+
|'''00010101'''RRRRRRRRRRRRLLLLLLLLLLLL
 
+
|L,R
buffer after storing the] appropriate constant value (A * 16) [in the active constant buffer and 
+
|
 
+
|
changing the active constant buffer to the currently inactive constant buffer]; the unsigned 
+
|O = ((R < 0) ? (L >> -R)
 
+
<nowiki>:</nowiki> (L << R))
long/instruction at this location is then used by the operation as the operand's actual/ translated 
+
|O
 
+
|
value. 
+
|bit shift
 
+
|-
 
+
|22/0x16
 
+
|PUSH
out-type operands of this bit sequence are useless: they will return a pointer to the currently 
+
|'''00010110'''BBBBBBBBBBBBAAAAAAAAAAAA
 
+
|A,[B]
inactive constant buffer after storing the appropriate constant value (A * 16) in the active 
+
|
 
+
|
constant buffer and changing the active constant buffer to the currently inactive constant buffer, 
+
|
 
+
I = A; J = B;
and that stored constant value in the [then currently] inactive constant buffer will ultimately be 
+
|I,[J]
 
+
|
overwritten by the corresponding expected result of the operation. However, since the data in the 
+
|push value(s) to stack
 
+
|-
constant buffer can be only accessed by translation of operands with this bit sequence, which 
+
|23/0x17
 
+
|NOTB
involves the prior overwriting of the active constant buffer with (A*16), then that result can never 
+
|'''00010111'''SSSSSSSSSSSSDDDDDDDDDDDD
 
+
|
be accessed [without first being overwritten]. 
+
|
 
+
|
 
+
|D = ~S
 
+
|
--
+
|D
 
+
|bitwise not (nor)
 
+
|-
 
+
|24/0x18
vii.) 1010AAAAAAAA - constant mult of 256 
+
|MOVC
 
+
|'''00011000'''RRRRRR000EIIIIIIIIIIIIII
 
+
|
 
+
|R,E,I
A = constant that will be multiplied by 256 (domain:      0 to   0xFF)
+
|
 
+
|see docs
                                            ( range: -32768 to  32512; R =   256N)
+
|O
 
+
|
                                       << 8 (       -0x8000 to 0x7F00; R = 0x100N)
+
|get code pointer
 
+
|-
Operands of the bit sequence 1010AAAAAAAA are translated almost identically to those of bit sequence 
+
|25/0x19
 
+
|ABS
type vi; the only difference is in the calculation for the constant written to the respective 
+
|'''00011001'''SSSSSSSSSSSSDDDDDDDDDDDD
 
+
|S
buffer: 
+
|
 
+
|
 
+
|D = (S < 0) ? -S : S
 
+
|
A = 1NNNNNNN (-N): V = 1111111111111111NNNNNNNN00000000 (256 * -N)
+
|D
 
+
|absolute value
A = 0NNNNNNN ( N): V = 0000000000000000NNNNNNNN00000000 (256 *  N)
+
|-
 
+
|26/0x1A
 
+
|PAD
 
+
|'''00011010'''000TDDDDSSPPBBBBBBBBBBBB
Where V indicates the binary signed long that will be written to the appropriate constant buffer for 
+
|
 
+
|B,P,S,D,T
the respective specified formats of A. 
+
|
 
+
|O = testctrls(instr,0)
 
+
|O
 
+
|
in - in-type operands of this bit sequence will return a pointer to the [currently inactive constant 
+
|test controller buttons
 
+
|-
buffer after storing the] appropriate constant value (A * 256) [in the active constant buffer and 
+
|27/0x1B
 
+
|SPD
changing the active constant buffer to the currently inactive constant buffer]; the unsigned 
+
|'''00011011'''VVVVVVVVVVVVBBBBBBBBBBBB
 
+
|V,B
long/instruction at this location is then used by the operation as the operand's actual/ translated 
+
|
 
+
|
value. 
+
|S = B + ((V*gvel) >> 10)
 
+
|S
 
+
|
 
+
|calculate speed
out-type operands of this bit sequence are useless for the same reasons those of sequence type vi 
+
|-
 
+
|28/0x1C
are. 
+
|MSC
 
+
|'''00011100'''PPPPSSSSSLLLXXXXXXXXXXXX
 
+
|X
 
+
|P,S,L
--
+
|
 
+
|various
 
+
|
 
+
|
viii.) 10110AAAAAAA - object frame argument/local variable [peek stack @ location relative to fp]
+
|multi-purpose
 
+
|-
 
+
|29/0x1D
 
+
|PSIN
A = argument/local variable offset, relative to object FP (domain =      0 to 0x7F)
+
|'''00011101'''PPPPPPPPPPPPDDDDDDDDDDDD
 
+
|P,D
                                                          (range  = -0x100 to 0xFC, -40 args to +39 local vars)
+
|
 
+
|
 
+
|large calc; see docs
 
+
|
Immediately prior to creating a new stack frame for the object, whether it be the initial stack 
+
|
 
+
|driven sine wave
frame [recreated due to a state change], the frame for a non-code thread, or the frame created for a 
+
|-
 
+
|30/0x1E
linked subroutine, a number of 'arguments' [for the new frame] can be pushed to the object's stack 
+
|TICK
 
+
|'''00011110'''RRRRRRRRRRRRLLLLLLLLLLLL
to occupy the locations that will immediately precede that of the new frame. And, after the frame is 
+
|L,R
 
+
|
created, with further interpretation, the results of operations are pushed to the object's stack to 
+
|
 
+
|O = (R + TICKS) % L
extend that frame; usually, these results will have a particular, expected order on the object's 
+
|O
 
+
|
stack based on the expected results of the operations for the interpreted sequence of instructions. 
+
|get ticks
 
+
|-
Then, conceptually, these results are said to be the contents of 'local variables' within that stack 
+
|31/0x1F
 
+
|RGL
frame. 
+
|'''00011111'''101111100000IIIIIIIIIIII
 
+
|I
 
+
|
 
+
|
Operands of the bit sequence 10110AAAAAAA will return a pointer to the [unsigned long/data at the] 
+
|O = globals[I]
 
+
|O
location on the object's stack of the data that is 'A' unsigned longs/units of data (4*A bytes) 
+
|
 
+
|read global variable
relative to the object's current frame pointer. Typically, A is specified as a negative value/offset 
+
|-
 
+
|32/0x20
when a pointer to some argument is desired; this is because the arguments are located -before- the 
+
|WGL
 
+
|'''00100000'''SSSSSSSSSSSSIIIIIIIIIIII
start of the stack frame. A is specified as a positive offset (>3) when a pointer to some local 
+
|I,S 
 
+
|
variable (i.e. operation result) is desired. 
+
|
 
+
|globals[I] = *S
 
+
|
 
+
|
A can be specified as a negative offset with the appropriate 2's complement format: 
+
|write global variable
 
+
|-
 
+
|33/0x21
 
+
|ANGD
A = 1NNNNNN (-N): O = 111111111111111111111111NNNNNN00 (4 * -N)  (argument offset)
+
|'''00100001'''RRRRRRRRRRRRLLLLLLLLLLLL
 
+
|R,L
A = 0NNNNNN ( N): O = 000000000000000000000000NNNNNN00 (4 *  N)  (local variable offset)
+
|
 
+
|
 
+
|O = ((R << 20) - (L << 20)) >> 20
 
+
|O
in - in-type operands of this bit sequence will return a pointer to the [unsigned long/data at the] 
+
|
 
+
|angle distance (note: shifts are for sign extension)
location on the object's stack of the data that is 'A' unsigned longs/units of data (4*A bytes) 
+
|-
 
+
|34/0x22
relative to the object's current frame pointer. The value at this location is then used by the 
+
|APCH
 
+
|'''00100010'''RRRRRRRRRRRRLLLLLLLLLLLL
operation as the operand's actual/translated value. 
+
|L,(R)
 
+
|
 
+
|
 
+
|O = approach(L,R,S)
out - out-type operands of this bit sequence will return a pointer to the [unsigned long/data at 
+
|O
 
+
|
the] location on the object's stack of the data that is 'A' unsigned longs/units of data (4*A bytes) 
+
|approach a value
 
+
|-
relative to the object's current frame pointer. Data will ultimately be written to this location as 
+
|35/0x23
 
+
|CVMR
an expected result of the specific type of operation, overwriting either the argument or local 
+
|'''00100011'''000IIIIIILLL000000000000
 
+
|
variable [at that location]
+
|I,L
 
+
|
--
+
|O = obj.link[L].colors[I]
 
+
|O
 
+
|
 
+
|color vector or matrix read
ix. 10111110**** - 'false' constant (translates to 0)
+
|-
 
+
|36/0x24
   (101111100000 = 0xBE0)
+
|CVMW
 
+
|'''00100100'''000IIIIIILLLCCCCCCCCCCCC
Operands of the bit sequence 10111110**** (where * indicates the possibility of either a 1 or 0) 
+
|C
 
+
|I,L
will, rather than return a pointer to some memory location, return the value 0 (i.e. invalid pointer 
+
|
 
+
|obj.link[L].colors[I] = C
to memory location 0). When specified, operands of this bit sequence will cause the operations of 
+
|
 
+
|
most instructions to return without writing/storing any results or making any calculations. 
+
|color vector or matrix write
 
+
|-
 
+
|37/0x25
 
+
|ROT
For a few other instructions, operands of the sequence will cause the operations to 'implicitly' pop 
+
|'''00100101'''RRRRRRRRRRRRLLLLLLLLLLLL
 
+
|(R),L
a number of additional operands from the object's stack. For the few other instructions, prior to [a 
+
|
 
+
|[R,S]
potentially worthless] translation of some operand, if the operand has been specified in the format 
+
|O = rotate(L,R,S,0)
 
+
|
0xBE0 (i.e. the usual specification for this sequence), its translation will be skipped. Then, in 
+
|
 
+
|approach an angle
exchange for the lack of a translated value for that operand, its value, and possibly the values for 
+
|-
 
+
|38/0x26
a number of additional operands [depends on the particular instruction's operation], will instead be 
+
|PSHP
 
+
|'''00100110'''BBBBBBBBBBBBAAAAAAAAAAAA
popped off of the object's stack. The additional operands will then be factored in an alternative, 
+
|A,[B]
 
+
|
extended calculation for that instruction by the operation. Usually, rather than having to 
+
|
 
+
|I = &A; J = &B;
alternatively perform some extended calculation, when the operand is -not- specified in this format, 
+
|I,[J]
 
+
|
the operation -sets- default values for each of the 'additional operands'. The same specific 
+
|push pointer(s)
 
+
|-
calculations will be performed in the operation for the instruction, factoring in the same operand 
+
|39/0x27
 
+
|ANIS
values [including those of the 'additional operands'], but the default values set for the additional 
+
|'''00100111'''FFFFFFFFFFFFDDDDDDDDDDDD
 
+
|F
operands can be 'overridden' with the specification of this bit sequence for the operand that would 
+
|
 
+
|
cause an implicit popping of their values from the object's stack. 
+
|D=&obj.global.anim[F>>8]
 
+
|
 
+
|D
 
+
|set animation
in  - in-type operands of this bit sequence will return a null pointer (pointer to memory location 
+
|-
 
+
|40/0x28
0). If specified, when translated by the operation for most instructions, the remainder of the 
+
|EFLR
 
+
|'''00101000'''BBBBBBBBBBBBAAAAAAAAAAAA
operation will be skipped. For few other instructions the translation for an operand of this 
+
|A,B
 
+
|
specific sequence will be skipped; this is followed with a pop of the actual value for that operand 
+
|
 
+
|O = GetFieldValue(obj->entity, field: A, row: B)
and a potential pop of the [overriding] values for an additional number of operands that could 
+
|O
 
+
|
otherwise not be explicitly or implicitly specified for the resolution of their values, which 
+
|load entity field row data
 
+
|-
therefore are otherwise directly set to some instruction-specific defaults. 
+
|41/0x29
 
+
|EFLV
 
+
|'''00101001'''SSSSSSSSSSSSDDDDDDDDDDDD
 
+
|S
out-type operands of this bit sequence will return a null pointer; a trap will result with the 
+
|
 
+
|
attempt to access the memory at that location (0), which lies in the kernel code segment. Out-type 
+
|D = GetFieldValue(obj->entity, field: S)
 
+
|
operands should therefore not be specified with this bit sequence. 
+
|D
 
+
|get entity field data
 
+
|-
 
+
|42/0x2A
--
+
|ARRL
 
+
|'''00101010'''RRRRRRRRRRRRLLLLLLLLLLLL
 
+
|L,R
 
+
|
x.  10111111**** - 'true' constant (translates to 1)
+
|
 
+
|O = *(L + R)
   (101111110000 = 0xBF0)
+
o = L[R]
 
+
|O
Operands of the bit sequence 10111111**** (where * indicates the possibility of either a 1 or 0) 
+
|
 
+
|load array value
will, rather than return a pointer to some memory location, return the value 1 (i.e. invalid pointer 
+
|-
 
+
|43/0x2B
to memory location 1). When specified, operands of this bit sequence will cause the operations of 
+
|SIN
 
+
|'''00101100'''SSSSSSSSSSSSDDDDDDDDDDDD
most instructions to trap the system; this is due to their attempt to access the memory at the 
+
|S
 
+
|
operands translated 'location' (1), which lies in the kernel code segment. 
+
|
 
+
|D = sin(S)
 
+
|
 
+
|D
For a few other instructions, operands of the sequence will cause the operations to alternatively, 
+
|sine wave (output: -0x1000 to 0x1000)
 
+
|-
implicitly pop a number of additional operands from the object's stack, just like described for 
+
|44/0x2C
 
+
|COS
those of sequence type ix. However, the difference in sequence type x from type ix is that only the 
+
|'''00101101'''SSSSSSSSSSSSDDDDDDDDDDDD
 
+
|S
operations for a completely different, disjoint set of instructions exhibits this behavior-that is, 
+
|
 
+
|
operations for only some instructions will behave this way when the operand is specified as 0xBE0; 
+
|D = cos(S)
 
+
D = sin(S + PI/2)
conversely, operations for only some other instructions will behave this way when the operand is 
+
|
 
+
|D
specified as 0xBF0. 
+
|cosine wave (output: -0x1000 to 0x1000)
 
+
|-
 
+
|45/0x2D
 
+
|ATAN
To better understand this behavior, consider the instruction PRW: when its explicitly specified 
+
|'''00101110'''YYYYYYYYYYYYXXXXXXXXXXXX
 
+
|X,Y
operand J is specified with any bit sequence type other than type xi or x, the instruction'
+
|
 
+
|
operation will appropriately translate that operand to resolve its actual value; its operand I 
+
|o = atan2(X, Y)
 
+
|o
(which at that point cannot be directly or indirectly specified by the instruction itself) will then 
+
|
 
+
|arc-tangent2, angle to point (confirmation needed)
take on a default value of 0x100. The operation will then perform all the appropriate calculations 
+
|-
 
+
|46/0x2E
with those operand values, ultimately storing one result to the translated location of operand X and 
+
|?
 
+
|'''00101110'''SSSSSSSSSSSSDDDDDDDDDDDD
pushing another result P to the object's stack. However, when its explicitly specified operand J is 
+
|A
 
+
|
specified with bit sequence type x (i.e. BF0), the instruction's operation will instead: skip 
+
|
 
+
|
translation of operand J, implicitly pop the value for operand I off of the object's stack, and 
+
|
 
+
|D
resolve operand J's value by additionally [implicitly] popping it off the object's stack. The 
+
|unknown
 
+
|-
operation will then perform all the appropriate calculations with -those- operand values. 
+
|47/0x2F
 
+
|NOP
 
+
|'''00101111'''101111100000101111100000
 
+
|
Thus, the '[]' brackets around an explicit GOOL operand for an instruction in the table indicate 
+
|
 
+
|
that, when specified in one format of either sequence type ix or x (i.e. 0xBE0 or 0xBF0) but not the 
+
|
 
+
|
other, the instruction's operation performs differently: that same operand and any additional 
+
|
 
+
|no operation
operands if '[]' bracketed and listed under implicit STACK operands (for the instruction in the 
+
|-
 
+
|48/0x30
table) will instead have their values popped off of the object's stack in the order of their 
+
|DBG
 
+
|'''00110000'''BBBBBBBBBBBBAAAAAAAAAAAA
listing. When the explicitly specified operand is -not- of bit sequence type ix or x, the 
+
|
 
+
|
alternative is to resolve its value by translation, and the values of any 'additional' operands that 
+
|
 
+
|
would have otherwise been popped off the object's stack are instead set to the corresponding 
+
|
 
+
|
'default' values as indicated under explicit constant operands for the instruction in the table. 
+
|(debug only) print gool fixed point values
 
+
|-
 
+
|49/0x31
 
+
|RET
in - in-type operands of this bit sequence for a few instructions will skip their translation; this 
+
|'''00110001'''100001100100000000000000
 
+
|
is followed with a pop of the actual value for that operand and a potential pop of the [overriding] 
+
|R,I
 
+
|
values for an additional number of operands that could otherwise not be explicitly or implicitly 
+
|
 
+
|
specified for the resolution of their values, needing to be directly set to some instruction- 
+
|
 
+
|conditionally stop gool execution (R and I ignored)
specific defaults. When translation is not skipped, as in the operations of most other instructions, 
+
|-
 
+
|50/0x32
this bit sequence will return an invalid pointer (pointer to memory location 1). When specified, 
+
|BRA
 
+
|'''00110010'''0000100101VVVVIIIIIIIIII
operands of this bit sequence will cause the operations of most instructions to trap the system; 
+
|
 
+
|R,V,
this is due to their attempt to access the memory at the operands translated 'location' (1), which 
+
|
 
+
|
lies in the kernel code segment. 
+
|
 
+
|
 
+
|branch
 
+
|-
out-type operands of this bit sequence will return an invalid pointer; a trap will result with the 
+
|51/0x33
 
+
|BNEZ
attempt to access the memory at that location (1), which lies in the kernel code segment. Out-type 
+
|'''00110011'''0001RRRRRRVVVVIIIIIIIIII
 
+
|
operands should therefore not be specified with this bit sequence. 
+
|R,V,
 
+
|
 
+
|
 
+
|
--
+
|
 +
|branch not equal zero
 +
|-
 +
|52/0x34
 +
|BEQZ
 +
|'''00110100'''0010RRRRRRVVVVIIIIIIIIII
 +
|
 +
|R,V,I 
 +
|
 +
|
 +
|
 +
|
 +
|branch equal zero
 +
|-
 +
|53/0x35
 +
|CST
 +
|'''00110101'''0100100101AAAASSSSSSSSSS
 +
|
 +
|R,A,S
 +
|
 +
|
 +
|
 +
|
 +
|change object state
 +
|-
 +
|54/0x36
 +
|CNEZ
 +
|'''00110110'''0101RRRRRRAAAASSSSSSSSSS
 +
|
 +
|R,A,S
 +
|
 +
|
 +
|
 +
|
 +
|change state if not zero
 +
|-
 +
|55/0x37
 +
|CEQZ
 +
|'''00110111'''0110RRRRRRAAAASSSSSSSSSS
 +
|
 +
|R,A,S
 +
|
 +
|
 +
|
 +
|
 +
|change state if zero
 +
|-
 +
|56/0x38
 +
|ANIM
 +
|'''00111000'''HHTTTTTTSSSSSSSSSFFFFFFF
 +
|
 +
|F,S,T,H
 +
|
 +
|
 +
|W
 +
|
 +
|set and play animation+frame
 +
|-
 +
|57/0x39
 +
|ANIF
 +
|'''00111001'''HHTTTTTT0000FFFFFFFFFFFF
 +
|F
 +
|H,T
 +
|
 +
|
 +
|W
 +
|
 +
|set and play frame of animation
 +
|-
 +
|58/0x3A
 +
|VECA
 +
|'''00111010'''CCCTTTBBBAAAVVVVVVVVVVVV
 +
|V
 +
|C,T,B,A
 +
|
 +
|
 +
|*
 +
|**
 +
|multi-purpose vector calcs
 +
|-
 +
|59/0x3B
 +
|JAL
 +
|'''00111011'''VVVV00000EIIIIIIIIIIIIII
 +
|
 +
|I,V
 +
|
 +
|
 +
|
 +
|
 +
|jump and link
 +
|-
 +
|60/0x3C
 +
|EVNT
 +
|'''00111100'''LLLAAARRRRRREEEEEEEEEEEE
 +
|E
 +
|L,A,R
 +
|
 +
|
 +
|
 +
|
 +
|send an event
 +
|-
 +
|61/0x3D
 +
|EVHR
 +
|'''00111101'''TTCCRRRRRR**************
 +
|
 +
|R,C,T,*
 +
|**
 +
|
 +
|
 +
|
 +
|event handler: reject event
 +
|-
 +
|62/0x3E
 +
|EVHA
 +
|'''00111110'''TTCCRRRRRR**************
 +
|
 +
|R,C,T,*
 +
|**
 +
|
 +
|
 +
|
 +
|event handler: accept event
 +
|-
 +
|63/0x3F
 +
|CHLD
 +
|'''00111111'''AAAATTTTTTTTSSSSSSCCCCCC
 +
|
 +
|C,T,S,A
 +
|[C],
 +
arg[0 to A]
 +
|
 +
|
 +
|
 +
|spawn children objects
 +
|-
 +
|64/0x40
 +
|NTRY
 +
|'''01000000'''TTTTTTTTTTTTEEEEEEEEEEEE
 +
|T,E
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|multi-purpose page operation
 +
|-
 +
|65/0x41
 +
|SNDP
 +
|'''01000001'''VVVVVVVVVVVVAAAAAAAAAAAA
 +
|A,V
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|play sound effect
 +
|-
 +
|66/0x42
 +
|SNDA
 +
|'''01000010'''VVVVFFRRRRRRSSSSSSSSSSSS
 +
|S
 +
|V,F,R
 +
|
 +
|
 +
|
 +
|
 +
|adjust voice parameters
 +
|-
 +
|67/0x43
 +
|VECB
 +
|'''01000011'''CCCTTTBBBAAAVVVVVVVVVVVV
 +
|V
 +
|C,T,B,A
 +
|
 +
|
 +
|
 +
|
 +
|multi-purpose vector calcs
 +
|-
 +
|68/0x44
 +
|EVNB
 +
|'''01000101'''LLLAAARRRRRREEEEEEEEEEEE
 +
|E
 +
|L,A,R
 +
|
 +
|
 +
|
 +
|
 +
|send an event to all objects
 +
|-
 +
|69/0x45
 +
|EVNC
 +
|'''01000100'''LLLAAARRRRRREEEEEEEEEEEE
 +
|E
 +
|L,A,R
 +
|
 +
|
 +
|
 +
|
 +
|send an event, cascading
 +
|-
 +
|70/0x46
 +
|CHLF
 +
|'''01000110'''AAAATTTTTTTTSSSSSSCCCCCC
 +
|
 +
|A,T,S,C
 +
|[C],
 +
arg[0 to A]
 +
|
 +
|
 +
|
 +
|spawn children objects; forcefully?
 +
|-
 +
|71/0x47
 +
|JALR
 +
|'''01000111'''AAAAAAAAAAAAPPPPPPPPPPPP
 +
|P,A
 +
|
 +
|arg[0 to A]
 +
|
 +
|
 +
|
 +
|jump and link to instruction pointed at by P
 +
|-
 +
|72/0x48
 +
|CMSG
 +
|'''01001000'''AAAAAAAAAAAAMMMMMMMMMMMM
 +
|M,A
 +
|
 +
|
 +
|AddCamMessage(M, &A)
 +
|
 +
|
 +
|add message to camera queue (if not full), cam-message is M, its operands (dependant on message) are pointed to by A
 +
|-
 +
|73/0x49
 +
|NATIVE
 +
|'''01001001'''101111100000101111100000
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|begin native (psx mips) code
 +
|-
 +
|74/0x4A
 +
|?
 +
|'''01001010'''------------AAAAAAAAAAAA
 +
|A
 +
|
 +
|
 +
|
 +
|O
 +
|
 +
|unknown VIDO operation
 +
|-
 +
|75/0x4B
 +
|?
 +
|'''01001011'''------------AAAAAAAAAAAA
 +
|A
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|unknown
 +
|-
 +
|76/0x4C
 +
|?
 +
|'''01001100'''AAAAAAAAAAAABBBBBBBBBBBB
 +
|A,B
 +
|
 +
|
 +
|
 +
|
 +
|
 +
|unknown
 +
|-
 +
|77/0x4D
 +
|?
 +
|'''01001101'''AAAAAAAAAAAABBBBBBBBBBBB
 +
|A,B
 +
|
 +
|P,T
 +
|
 +
|
 +
|
 +
|unknown
 +
|-
 +
|78/0x4E
 +
|ARRS
 +
|'''00101011'''RRRRRRRRRRRRLLLLLLLLLLLL
 +
|L,R
 +
|
 +
|S
 +
|*(L + R) = S
 +
L[R] = S
 +
|
 +
|
 +
|store array value
 +
|-
 +
|}
 +
</div>
  
 +
==== GOOLv3 Instruction Table ====
 +
The GOOL instruction table below lists the opcode, mnemonic/name, format, operands (based on explicit and/or implicit specification of source origin and/or destination target), general operation (represented with c-style statement), and a description for each GOOL instruction added in ''Crash 3''.
 +
<div style="font-family:monospace;font-size:11px;">
 +
{| border="1"
 +
|-
 +
!Opcode
 +
!Name
 +
!Encoding/Format
 +
!Explicit GOOL ops
 +
in
 +
!Explicit IMM. ops
 +
in
 +
!Implicit STACK ops
 +
in
 +
!Operation
 +
!Implicit STACK out
 +
!Explicit
 +
GOOL ops out
 +
!Description
 +
|-
 +
| 79/0x4F
 +
| ?
 +
| '''01001100'''AAAAAAAAAAAABBBBBBBBBBBB
 +
| B
 +
|
 +
|
 +
|
 +
|
 +
| A
 +
| unknown
 +
|-
 +
| 80/0x50
 +
| ?
 +
| '''01001101'''AAAAAAAAAAAABBBBBBBBBBBB
 +
| B
 +
|
 +
|
 +
|
 +
|
 +
| A
 +
| unknown
 +
|-
 +
| 81/0x51
 +
| ?
 +
| '''01001100'''AAAAAAAAAAAABBBBBBBBBBBB
 +
| A,B
 +
|
 +
|
 +
|
 +
|
 +
|
 +
| unknown matrix math
 +
|-
 +
|}
 +
</div>
  
 
+
=== GOOL Instruction Operands ===
...
+
...  
 +
* In/Source type operands
 +
** Explicitly specified (i.e. origin = determined by operand's corresponding bitfield from the instruction)
 +
*** GOOL in/source operand
 +
*** Immediate operand
 +
** Implicitly specified (i.e. origin = top of object's stack; implicitly popped from top of object's stack)
 +
*** Stack in/source operand
 +
* Out/Destination type operands
 +
** Explicitly specified (i.e. target = determined by operand's corresponding bitfield from the instruction)
 +
*** GOOL out/destination operand
 +
** Implicitly specified (i.e. target = top of object's stack; implicitly pushed to top of object's stack)
 +
*** Stack out/destination operand/result*
 +
<nowiki>*</nowiki>technically not an 'operand', but rather a ''result'' of the instruction's overall operation; it is <i>implied</i> that instructions that use [an] operand(s) of this type always pushes it/them (i.e the result(s)) to the top of the object's stack.
 +
 
 +
==== Explicit Operands ====
 +
A GOOL instruction's explicit operands are ''explicitly'' specified in its lower 24 bits (operand portion). Each explicitly specified operand is either an immediate operand, or a GOOL operand.
 +
 
 +
===== Immediate Operands =====
 +
An immediate operand ''directly'' specifies its value in its corresponding bitfield (within the operand portion) of the instruction. The number of immediate operands and their positions/bit-lengths varies between instructions.
 +
 
 +
Immediate Operands are in operands (source operands).
 +
 
 +
===== GOOL Operands =====
 +
Conversely, a GOOL operand is specified as a ''reference'' to its actual value or destination location. Each GOOL operand is 12 bits in length; a GOOL instruction may require the specification of at most 2 GOOL operands, within the upper and/or lower halves of its operand portion, respectively. The 12 bit GOOL reference that specifies a GOOL operand encodes a [32 bit] pointer to its corresponding source value and/or destination location. Operations for instructions that require GOOL operand specification first <i>translate</i> the corresponding GOOL reference(s) to yield their decoded pointer(s) before accessing pointed data.
 +
 
 +
See the GOOL Reference Translation section for more information.
 +
 
 +
Depending on how a GOOL operand is used by its instruction, it may be an ''in'' (source) operand, an ''out'' (destination) operand, or both (''inout'' operand). If an instruction only reads the [input] value located by its translated GOOL operand (a pointer), it is an ''in'' (source) operand. If an instruction only writes a result/value to the location of its translated GOOL operand, it is an ''out'' (destination) operand. If an operand meets both of these criteria it is an ''inout'' operand.
 +
 
 +
==== Implicit Operands ====
 +
===== Implicit In Operands =====
 +
Some GOOL instructions may require the ''implicit'' specification of one or more (implicit) in operands. In operands are implicitly specified prior to an instruction's interpretation by pushing their value(s)-which must remain the topmost values at interpretation-to the object's stack. It is <i>implied</i> that these so-called implicit operands will exist on the stack for the instruction to pop and use as input.
 +
===== Implicit Out Operands =====
 +
For most GOOL instructions, the net effect of their operation involves an implicit push of one or more <i>results</i> to the object's stack. That is-it is <i>implied</i> or expected that these instructions will ultimately push their results to the object's stack.
 +
 
 +
=== GOOL Reference Translation ===
 +
The following table lists the encoding format, potential type name, and a descriptive type name for each of the possible GOOL reference types:
 +
 
 +
<div style="font-family:monospace;">
 +
{| class="article-table"
 +
!Format
 +
!Potential Type Name
 +
!Descriptive Type Name
 +
|-
 +
|00RRRRRRRRRR
 +
|Ireg Ref
 +
|object local executable data pool reference
 +
|-
 +
|01RRRRRRRRRR
 +
|Pool Ref
 +
|object external executable data pool reference
 +
|-
 +
|100IIIIIIIII
 +
|Int Ref
 +
|constant mult of 256 (range: -32768 - 32512)
 +
|-
 +
|1010IIIIFFFF
 +
|Frac Ref
 +
|constant mult of 16  (range: -8192 - 8176)
 +
|-
 +
|10110SSSSSSS
 +
|Stack Ref
 +
|object frame argument/local variable reference [peek stack @ location relative to fp]
 +
|-
 +
|101111100000
 +
|Null Ref
 +
|null reference (translates to 0)
 +
|-
 +
|101111110000
 +
|Sp-Double Ref
 +
|double stack pop reference (translates to 1)
 +
|-
 +
|110LLLMMMMMM
 +
|Reg Ref
 +
|object link memory reference
 +
|-
 +
|111MMMMMMMMM (M != 0x1F)
 +
|Var Ref
 +
|object field/memory reference
 +
|-
 +
|111000011111
 +
|Stack Pop/Push
 +
|stack pop/push reference
 +
|}
 +
</div>
 +
Potential GOOL Reference type names have been deduced based on what appears to be an unreferenced array of GOOL interpreter debug strings at 0x103B8.
 +
 
 +
==== Stack Pop/Push ====
 +
{| class="article-table" border="1" style="font-family:monospace;"
 +
!Format
 +
! colspan="3" |Description
 +
|-
 +
|111000011111
 +
| colspan="3" |Stack Pop/Push Reference
 +
|}
 +
A GOOL reference of this format translates differently depending on whether the operand that specifies it is an ''in'' operand or an ''out'' operand:
 +
* ''In'' operands specified as a reference of this type translate to a pointer to the top of the object's stack after an ensuing pop of the value located there (i.e. stack pointer is decremented).
 +
* ''Out'' operands specified as a reference of this type translate to a pointer to the top of the object's stack prior to an incrementation of its stack pointer. A stack push will result from the translation's incrementing of the object's stack pointer and the instruction's ultimate dereferencing of the returned/translated pointer for a write.
 +
 
 +
==== Var Ref ====
 +
{| class="article-table" border="1" style="font-family:monospace;"
 +
! colspan="2" |Format
 +
! colspan="3" |Description
 +
|-
 +
| colspan="2" |111FFFFFFFFF
 +
| colspan="3" |Object Field/Memory Reference
 +
|-
 +
!Field
 +
!Description
 +
!Domain
 +
!Range
 +
!
 +
|-
 +
|F
 +
|Object Field Index
 +
|0 to 0x1FF
 +
|0x60 to 0x860
 +
|R = 4N
 +
|}
 +
GOOL References of this format translate to a pointer to the <code>A</code>th object field in relation to the object's <code>self</code> field.
 +
                       
 +
Most of an object's significant fields are located past a <code>0x60</code> byte offset from the beginning of its structure-i.e. past its <code>self</code> field. Note that the last of these fields is the object's array of/address space for its [local] memory where its global variables and stack contents are stored. Because object fields are 4 bytes in size and an object's <code>self </code>field is located at a 0x60 byte offset from the beginning of its structure, then the formula: 
 +
 
 +
<code>0x60 + (A * 4)</code>
 +
 
 +
gives the byte offset of the actual field located by the translated pointer.
 +
 
 +
If <code>A</code> = <code>0x1F</code>, then the reference will have the format <code>111000011111</code>; this is, however, already defined as the format for a stack pop/push reference-the processing of which takes precedence over that of var references. Notice that if such a reference were not instead translated as a stack pop/push reference, its translated pointer would locate the field at byte offset <code>0x60 + (0x1F * 4) = 0xDC</code>-the object's stack pointer. Then, it should not be possible to directly modify an object's stack pointer by accessing a translated reference. Only indirectly via translation of a stack push/pop reference should the object's stack pointer be modified.
 +
 
 +
==== Reg Ref ====
 +
{| class="article-table" border="1" style="font-family:monospace;"
 +
! colspan="2" |Format
 +
! colspan="3" |Description
 +
|-
 +
| colspan="2" |110LLLFFFFFF
 +
| colspan="3" |Object Link Field/Memory Reference
 +
|-
 +
!Field
 +
!Description
 +
!Domain
 +
!Range
 +
!
 +
|-
 +
|F
 +
|Link Object Field Index
 +
|0 to 0x3F
 +
|0x60 to 0x15C
 +
|R = 4N
 +
|-
 +
|L
 +
|Object Link Index
 +
|0 to 7
 +
|0x60 to 0x7C
 +
|R = 4N
 +
|}
 +
GOOL references of this format translate to a pointer to the <code>A</code>th object field in relation to the object's <code>B</code>th link object's <code>self</code> field. An object's ''link objects'' are referred to by the group of 8 object pointers beginning with its <code>self</code> field; the first of these pointers is the object's <code>self</code> link, the second a pointer to its <code>parent</code> object, the third a pointer to its <code>sibling</code> object, and so on.
 +
 
 +
==== Ireg Ref ====
 +
{| class="article-table" border="1" style="font-family:monospace;"
 +
! colspan="2" |Format
 +
! colspan="3" |Description
 +
|-
 +
| colspan="2" |00RRRRRRRRRR
 +
| colspan="3" |Object Local Executable Data Pool Reference
 +
|-
 +
!Field
 +
!Description
 +
!Domain
 +
!Range
 +
!
 +
|-
 +
|R
 +
|Index of Value in Pool
 +
|0 to 0x3FF
 +
|0 to 0xFFC
 +
|R = 4N
 +
|}
 +
GOOL references of this format translate to a pointer to the predefined constant long at an offset of <code>R</code> longs relative to the beginning of the object's local executable's constant data pool item.
 +
 
 +
A GOOL executable's constant data pool item is essentially a table of predefined constants. For example, it includes the EIDs of any entries, preconfigured bitfields and bit selectors, audio sample parameters (volume, pan, etc), specific speeds or velocities, and other constants referenced by this type.
 +
 
 +
NOTE: if an instruction's ''out'' operand is specified as a reference of this type, its operation will ultimately replace the constant at the translated location with its output result. A write to the executable's data pool should generally be avoided unless a global change to that constant, and therefore an equal change in behavior for each object that is an instance of that executable, is desired. 
 +
 
 +
==== Pool Ref ====
 +
{| class="article-table" border="1" style="font-family:monospace;"
 +
! colspan="2" |Format
 +
! colspan="3" |Description
 +
|-
 +
| colspan="2" |01RRRRRRRRRR
 +
| colspan="3" |Object External Executable Data Pool Reference
 +
|-
 +
!Field
 +
!Description
 +
!Domain
 +
!Range
 +
!
 +
|-
 +
|R
 +
|Index of Value in Pool
 +
|0 to 0x3FF
 +
|0 to 0xFFC
 +
|R = 4N
 +
|}
 +
GOOL references of this format translate to a pointer to the predefined constant long at an offset of <code>R</code> longs relative to the beginning of the object's external executable's constant data pool item.
 +
 
 +
The same considerations for ireg refs apply to pool refs.
 +
 
 +
==== Frac Ref ====
 +
{| class="article-table" border="1" style="font-family:monospace;"
 +
! colspan="2" |Format
 +
! colspan="3" |Description
 +
|-
 +
| colspan="2" |100CCCCCCCCC or
 +
100IIIIIFFFF
 +
| colspan="3" |Reference to Constant Multiple of 16
 +
|-
 +
!Field
 +
!Description
 +
!Domain
 +
!Range
 +
!
 +
|-
 +
|C
 +
|Constant that will
 +
be multiplied by 16
 +
|0 to 0x1FF
 +
| -8192 to 8176
 +
-0x2000 to 0x1FF0
 +
 
 +
-16.0 to 15.9375?
 +
|R = 16N
 +
R = 0x10N
 +
 
 +
R = 0.0625N
 +
|-
 +
|I
 +
|Integral Portion?
 +
|0 to 0x1F
 +
| -15 to 16
 +
|R = 1N
 +
|-
 +
|F
 +
|Fractional Portion?
 +
|0 to 15
 +
|0 to 0.9375
 +
|R = 0.0625N
 +
|}
 +
GOOL references of this format translate to a pointer to the value <code>(16*C)</code>.
 +
 
 +
Two signed long ''constant buffers'' are located at offsets <code>0x40</code> and <code>0x44</code>, respectively, in scratch memory (as referenced by the pointer at memory location <code>0x56480</code> [<code>gp$(0x44)</code>].) At any point during the game's execution, the ''currently active constant buffer'' is either the buffer at offset <code>0x40</code> or <code>0x44</code>, and is indicated by either a <code>0</code> or a <code>1</code> in the unsigned long at memory location <code>0x56484</code> [<code>gp$(0x48)</code>]. Translation for references of this format consists of the following steps:
 +
*Write the value <code>(16*C)</code>-that is, 16 times the value specified by the <code>C</code> bits-to the currently active constant buffer.
 +
*Swap the currently active and inactive constant buffers (that is, if <code>0</code> previously indicated the currently active constant buffer, change it to a <code>1</code>; conversely, if it is a <code>1</code>, change it to a <code>0</code>).
 +
*Return a pointer to the <code>(16*C)</code> signed long value in the buffer it was written to (which, after the swap, will always be the currently inactive buffer.)
 +
                         
 +
This double-buffer allows the sufficient specification of up to 2 constant type GOOL references per instruction; each of the 2 buffers will keep track of up to 2 constants to be used by operations of instructions with the corresponding operands.
 +
 
 +
<code>C</code> can be specified as a negative constant with the following 2's complement format:
 +
 
 +
* <code>C = 1NNNNNNNN (-N): V = 11111111111111111111NNNNNNNN0000 (16 * -N)</code>
 +
* <code>C = 0NNNNNNNN ( N): V = 00000000000000000000NNNNNNNN0000 (16 *  N)</code>
 +
 
 +
Where <code>V</code> is the calculated signed long that will be written to the appropriate constant buffer for the specified formats of <code>C</code>.
 +
 
 +
Note: ''out'' operands are not meant to specify a reference of this type; any that do so are useless. Translation of this reference type returns a pointer to the currently inactive constant buffer after storing the appropriate constant value <code>(C * 16)</code> in the currently active constant buffer and then swapping the 2 buffers. The constant value in the inactive constant buffer would ultimately be overwritten with an expected result of the instruction with the out operand. However, since that buffer could only be accessed via subsequent translation of another frac or int ref, which would involve first overwriting its current value (the result) with a new constant value, then that result could never be accessed [without first being overwritten]. 
 +
 
 +
==== Int Ref ====
 +
{| class="article-table" border="1" style="font-family:monospace;"
 +
! colspan="2" |Format
 +
! colspan="3" |Description
 +
|-
 +
| colspan="2" |1010IIIIIIII
 +
| colspan="3" |Reference to Constant Multiple of 256
 +
|-
 +
!Field
 +
!Description
 +
!Domain
 +
!Range
 +
!
 +
|-
 +
|I
 +
|Constant (int) that will
 +
be multiplied by 256
 +
|0 to 0xFF
 +
| -32768 to 32512
 +
-0x8000 to 0x7F00
 +
|R = 256N
 +
R = 0x100N
 +
|}
 +
GOOL references of this format are translated almost identically to frac refs; the only difference is in the calculation for the constant written to the buffer:
 +
 
 +
* <code>I = 1NNNNNNN (-N): V = 1111111111111111NNNNNNNN00000000 (256 * -N)</code>
 +
* <code>I = 0NNNNNNN ( N): V = 0000000000000000NNNNNNNN00000000 (256 *  N)</code>
 +
 
 +
The same considerations for frac refs apply to int refs.
 +
 
 +
==== Stack Ref ====
 +
{| class="article-table" border="1" style="font-family:monospace;"
 +
! colspan="2" |Format
 +
! colspan="3" |Description
 +
|-
 +
| colspan="2" |10110SSSSSSS
 +
| colspan="3" |Object Frame Argument/Local Variable Reference [peek stack at location relative to fp]
 +
|-
 +
!Field
 +
!Description
 +
!Domain
 +
!Range
 +
!
 +
|-
 +
|S
 +
|Argument/Local Variable Index/Offset
 +
relative to object fp
 +
|0 to 0x7F
 +
-64 args to +63 local vars
 +
| -0x100 to 0xFC
 +
|R = 4N
 +
|}
 +
GOOL references of this format translate to a pointer to the long that is <code>S</code> longs (<code>4*S</code> bytes) relative to the object's current frame pointer. If <code>S</code> is specified as a negative value/offset, it refers to an argument; this is because arguments are located ''before'' the start of the stack frame. If <code>S</code> is specified as a positive offset (> 3), it refers to a local variable (i.e. operation result).
 +
 
 +
<code>S</code> can be specified as a negative offset with the following 2's complement format:
 +
 
 +
* <code>S = 1NNNNNN (-N): O = 111111111111111111111111NNNNNN00 (4 * -N)</code> (argument offset)
 +
* <code>S = 0NNNNNN ( N): O = 000000000000000000000000NNNNNN00 (4 *  N)</code> (local variable offset)
 +
 
 +
==== Null Ref ====
 +
{| class="article-table" border="1" style="font-family:monospace;"
 +
! colspan="2" |Format
 +
! colspan="3" |Description
 +
|-
 +
| colspan="2" |101111100000 = 0xBE0
 +
| colspan="3" |Null Reference
 +
(translates to <code>0</code>)
 +
|}
 +
GOOL references of this format translate to the value <code>0</code> (i.e. invalid pointer to address <code>0</code>). Some instructions will return without making any calculations or pushing any results if an operand is specified as a reference of this type.
 +
 
 +
Most other instructions do not account for translated references of this type. They assume that a translated reference will always point to a valid memory location. After these instructions translate a null ref, they will attempt to access the memory at address <code>0x0</code>-which lies in the kernel code segment-thus resulting in a trap.
 +
 
 +
In the instruction table, brackets '[]' around one or more of an instruction's explicit operands (*given that parenthesis '()' are not listed around any other operand) indicate that, if any of those operands are specified as null refs, the instruction will return before performing their associated calculations. Brackets '[]' around one or more of an instruction's implicit operands (*given that parenthesis '()' are not listed around any other operand) indicate that, if the 'corresponding' explicit operands are specified as null refs, they (the implicit operands) do not actually exist. The order in which associated calculations are performed is indicated by the nested bracketing of operands.
 +
 
 +
For example, the <code>PSHV</code> instruction is listed with explicit GOOL in operands <code>[A,[B]]</code>, and implicit stack out operands <code>[I,[J]]</code>-aliases for the respective destinations of two subsequent stack pushes. These operand nestings indicate that:
 +
 
 +
* If only operand <code>B</code> is specified as a null ref, the instruction returns before operation <code>J = B</code> (equivalently, <code>push(obj,B)</code>) is performed. As a result, only operation <code>I = A</code> (equivalently, <code>push(obj,A)</code>) is performed.
 +
* If operand <code>A</code> is specified as a null ref, the instruction returns before <code>push(obj,A)</code> is performed; then <code>push(obj,B)</code> is also never performed-so the instruction does nothing. It does not matter whether or not <code>B</code> is a null ref because its associated calculation/operation (i.e. push to stack) is never performed.
 +
* If neither operand <code>A</code> nor operand <code>B</code> are specified as null refs, both/all operations-<code>push(obj,A)</code> followed by <code>push(obj,B)</code>-are performed.
 +
 
 +
==== SP-Double Ref ====
 +
{| class="article-table" border="1" style="font-family:monospace;"
 +
! colspan="2" |Format
 +
! colspan="3" |Description
 +
|-
 +
| colspan="2" |101111110000 = 0xBF0
 +
| colspan="3" |Double Stack Pop Reference
 +
(translates to <code>1</code>)
 +
|}
 +
GOOL references of this format translate to the value <code>1</code> (i.e. invalid pointer to address <code>1</code>). Specification of sp-double refs is exclusive to a few specific instructions. Most instructions do not account for translated references of this type. They assume that a translated reference will always point to a valid memory location. After these instructions translate an sp-double ref, they will attempt to access the memory at address <code>0x1</code>-which lies in the kernel code segment-thus resulting in a trap.
 +
 
 +
For a few instructions, if [a specific] one of their operands is explicitly specified as an sp-double ref, the actual values for both that operand and some other operand will be implicitly popped (in 2 subsequent pops) from the object's stack; no actual translation of the reference is performed. Alternatively, if that operand is not specified as an sp-double ref, then it is a valid reference to its actual value (and will be translated to a pointer that can be dereferenced to resolve that value); the other operand will then instead take on some ''default'' value.
 +
 
 +
In the instruction table, parenthesis '()' around one of an instruction's explicit operands indicate that: if that operand is specified as an sp-double ref, the instruction will pop the actual values for the bracketed '[]' pair of implicit stack in operands including that operand, in the order listed; otherwise the operand is a valid reference to its actual value, and its paired operand-for example, <code>P</code>-will take on a default value of <code>V</code>, where <code>P = V</code> is listed as an explicit immediate operand for that instruction.
 +
 
 +
For example, the <code>PATH</code> instruction is listed with explicit GOOL in operands <code>(A),B</code>, explicit immediate in operand <code>R = 0x100</code>, and implicit stack in operands <code>[R,A]</code>. If operand <code>A</code> is specified as an sp-double ref, the values for <code>R</code> and <code>A</code> will be popped from the object's stack, in that order. Otherwise, <code>R</code> [rate of path travel] will take on a default value of <code>0x100</code> (<code>1.0</code>) and <code>A</code>'s reference will be translated to resolve its value (by dereferencing, just as the majority of other instructions do for GOOL operands.)
 +
 
 +
=== Operand Name Table ===
 +
<div style="font-family:monospace;font-size:11px;">
 +
 
 +
{| border="1"
 +
!
 +
Specification Format
 +
| rowspan="2" |A
 +
|AAAAAAAAAAAA
 +
|AAAA
 +
|AAA (EVNT/EVNU/EVNB)
 +
|AAA (VECA/VECB)
 +
|-
 +
!Name
 +
|Value A
 +
|Argument Count
 +
|Argument Count
 +
|Vector A Index
 +
|-
 +
!Specification Format
 +
| rowspan="2" |B
 +
|BBBBBBBBBBBB
 +
|BBBBBBBBBBBB (PAD)
 +
|BBBBBBBBBBBB (SPD)
 +
|BBB
 +
|-
 +
!Name
 +
|Value B
 +
|Controller Buttons
 +
|Base Speed
 +
|Vector B Index
 +
|-
 +
!Specification Format
 +
| rowspan="2" |C
 +
|CCCCCCCCCCCC
 +
|CCCCCC
 +
|CCC
 +
|CC
 +
|-
 +
!Name
 +
|Color Value
 +
|Spawn Count
 +
|Vector C Index
 +
|Conditional Check Type
 +
|-
 +
!Specification Format
 +
| rowspan="2" |D
 +
|DDDDDDDDDDDD
 +
|DDDDDDDDDDDD (PRS)
 +
|DDDD
 +
|
 +
|-
 +
!Name
 +
|Destination
 +
|Wave Phase
 +
|Directional Buttons
 +
|
 +
|-
 +
!Specification Format
 +
| rowspan="2" |E
 +
|EEEEEEEEEEEE (NTRY)
 +
|EEEEEEEEEEEE (EVNT/EVNU/EVNB)
 +
|E (Crash 2 MOVC)
 +
|
 +
|-
 +
!Name
 +
|Entry
 +
|Event
 +
|External Executable Flag
 +
|
 +
|-
 +
!Specification Format
 +
| rowspan="2" |F
 +
|FFFFFFFFFFFFFFFF
 +
|FFFFFFFFFFFF
 +
|FFFFFFF
 +
|
 +
|-
 +
!Name
 +
|Animation Frame
 +
|Animation Descriptor Offset
 +
|Animation Frame
 +
|
 +
|-
 +
!
 +
Specification Format
 +
| rowspan="2" |H
 +
|HH
 +
|
 +
|
 +
|
 +
|-
 +
!Name
 +
|Horizontal Flip
 +
|
 +
|
 +
|
 +
|-
 +
!
 +
Specification Format
 +
| rowspan="2" |I
 +
|IIIIIIIIIIIIII
 +
|IIIIIIIIIIII
 +
|IIIIIIIIII
 +
|IIIIII
 +
|-
 +
!Name
 +
|Immediate Code Location
 +
|Global Variable Index
 +
|Immediate Branch Offset
 +
|Color Index
 +
|-
 +
!
 +
Specification Format
 +
| rowspan="2" |L
 +
|LLLLLLLLLLLL
 +
|LLL
 +
|
 +
|
 +
|-
 +
!Name
 +
|Left Operand
 +
|Object Link Index
 +
|
 +
|
 +
|-
 +
!
 +
Specification Format
 +
| rowspan="2" |P
 +
|PPPPPPPPPPPP
 +
|PPPP
 +
|PP
 +
|
 +
|-
 +
!Name
 +
|Wave Period
 +
|Primary Operation Subtype
 +
|Primary Check Type
 +
|
 +
|-
 +
!
 +
Specification Format
 +
| rowspan="2" |R
 +
|RRRRRRRRRRRR
 +
|RRRRRR
 +
|
 +
|
 +
|-
 +
!Name
 +
|Right Operand
 +
|Object Register Index
 +
|
 +
|
 +
|-
 +
!
 +
Specification Format
 +
| rowspan="4" |S
 +
|SSSSSSSSSSSSSS
 +
|SSSSSSSSSSSS
 +
|SSSSSSSSS
 +
|SSSSSS
 +
|-
 +
!Name
 +
|State
 +
|Source
 +
|Animation Sequence Index
 +
|Subtype
 +
|-
 +
!
 +
Specification Format
 +
|SSSSS
 +
|SS
 +
|
 +
|
 +
|-
 +
!Name
 +
|Secondary Operation Subtype
 +
|Secondary Check Type
 +
|
 +
|
 +
|-
 +
!
 +
Specification Format
 +
| rowspan="4" |T
 +
|TTTTTTTTTTTT
 +
|TTTTTTTT
 +
|TTTTTT
 +
|TTT
 +
|-
 +
!Name
 +
|Operation Subtype
 +
|(Object) Type
 +
|Time
 +
|Operation Subtype
 +
|-
 +
!
 +
Specification Format
 +
|TT
 +
|T
 +
|
 +
|
 +
|-
 +
!Name
 +
|Operation Subtype
 +
|Truth Invert Toggle
 +
|
 +
|
 +
|-
 +
!
 +
Specification Format
 +
| rowspan="2" |V
 +
|VVVVVVVVVVVV
 +
|VVVV
 +
|VVVV (SNDB)
 +
|
 +
|-
 +
!Name
 +
|Velocity
 +
|Variable Count
 +
|Volume
 +
|
 +
|}
 +
</div>
 +
 
 +
=== GOOL Instruction Operations ===
 +
TBD

Latest revision as of 15:52, 19 January 2024

In the Crash games, the GOOL Interpreter is responsible for interpreting an object's executable bytecode. This bytecode instructs the interpreter to perform a specific sequence of operations that can conditionally or unconditionally alter specific characteristics of the object (ex. appearance, location, status, etc.), and should ultimately render the object according to its changing characteristics. As a result, the player observes a lively, animated, and interactive enemy, box, collectible item, or whatever other kind of in-game object it may be.

Interpretation

A single interpretation of an object's bytecode consists of the following steps:

  1. Fetch the instruction at the object's program counter location
    • Read the instruction at the object's program counter location
    • Point the object's program counter to the location of the following instruction
  2. Perform the operation specified by the fetched instruction
  3. Continue repeating steps 1 and 2 until a suspending instruction is fetched

(A suspending instruction is typically either a RET, which marks the end of a block, ANIF/ANIS, which change the object's current frame of animation, CST/CNEZ/CEQZ, which change the object's state, or EVNT/EVNB/EVNU, which send an event to one or multiple objects.)

A single call to the GOOL interpreter routine with some desired object as its first argument results in a single interpretation of that object's bytecode. The GOOL bytecode interpreter routine expects an object that provides the following information:

  • The location in its bytecode at which the interpreter shall begin its interpretation = object's program counter
  • The location in its memory of a stack frame created for the interpretation = object's frame pointer
  • The location in its memory at which the interpreter shall begin pushing the results of/popping the operands for interpreted instructions = object's stack pointer

Prior to an interpretation, each of these fields (program counter, frame pointer, stack pointer) is modified according to the object's current state [descriptor] and the type of interpretation.

Types of interpretation

Many separate interpretations of an object's bytecode can occur within a single frame. The GOOL interpreter routine can be called with the same object from up to 7 distinct locations in a single iteration of the game loop. Each of the 7 calls to the interpreter routine with that object, and thus the ensuing interpretations of its bytecode, occurs under a separate condition. The 7 interpretations are identified based on the conditions under which they occur, and are as follows:

  • One that occurs at a specified rate, i.e. after a specific amount of time has elapsed since its previous occurrence. (Code Block interpretation)
  • One that [always] occurs [for each frame]. (Trans Block interpretation)
  • One that occurs whenever the object is sent an event and its current state specifies the location of an event service routine. (Event Block interpretation)
  • One that occurs whenever the object is sent an event and: its current state does not specify an event service routine or its event service routine failed to return an event, and the event sent maps to an event handler. (Handles Block interpretation)
  • One that occurs whenever the object changes state. (Head Block interpretation)
  • One that occurs whenever the object changes state and its recent Trans Block interpretation was unsuccessful (*Trans Block interpretation)
  • One that occurs when the object minimizes the distance during another object's query to 'find the nearest object', and the event sent for asynchronous handling (from the querying object) maps to an event handler. (*Handles Block interpretation)

Ignoring the details for now, the latter 2 types are just a Trans Block and Handles Block interpretation, respectively, although their calls cross-reference the interpreter routine from different locations. Thus, there are a total of 5 types. These 5 types are more simply viewed as 5 separate threads of execution of the object's bytecode. To demonstrate, here is the expanded game loop routine with only the calls to routines that have a descendant call to the interpreter routine:

 sub_80011FC4(levelid)
 { 
   ...	  
   C) sub_80011DD0 - Load entries and/or create universal game objects 
                     (HUD/display, Crash, Aku Aku, Shadows, Boxes, Fruit)
     1) sub_8001C6C8 - CreateObject() [called once for each object created]
     ...
   GAME LOOP:
   {
     1) Code for handling game pause/start button press
       A) If start pressed...
          i) If pause menu object does not exist....
             1) sub_8001C6C8 - CreateObject() [create pause menu object]
             ...
             else
             1) sub_80024040 - SendEvent() [destroy pause menu object]
             ...
     2) If Crash object does not exist: 
       A) sub_8002E98C - Create HUD and initialize level
          i) sub_8001C6C8 - CreateObject() [create HUD object]
          ii)sub_80026650 - Reinitialize Level
             1) sub_8001C6C8 - CreateObject() [create Crash object]
             ...
     3) Code for loading a new level if necessary
       A) If new level to load
          ...
          ii)sub_80011DD0 - Load entries and/or create universal game objects 
             1) sub_8001C6C8 - CreateObject() [called once for each object created]
             ...
     ...
     5) Spawn all objects in current zone [for those that have their respawn bit set]
       A) sub_80025928 - Spawn objects
          1) sub_8001BCC8 - SpawnObject() [called for each object spawned]
          ...
     ...
     9) Update all objects and create transformed primitives for them
       A) sub_8001D5EC - UpdateObjects()
          1) sub_8001DA0C - UpdateObject() [called for each existing object]
     ...
   } 
 }

Based on the above, consider an arbitrary frame of execution in terms of a single object. CreateObject() or SpawnObject() will not be called more than once [to create that object] in that frame; that is-the object is not created or spawned more than once, or even spawned after it is created and vice-versa. The object may not even be created/spawned in that frame because it either already exists or does not exist since the game has not requested it be created/spawned. If it is an existing object, it will also be updated only once in that frame. For a single object, the above can be reduced the following series of potential calls:

 sub_80011FC4(levelid)
 { 
   ...	  
   GAME LOOP:
   {
     ...
     CreateObject(obj,...) or SpawnObject(obj,...)
     ...
     SendEvent(src,obj,...)
     ...
     UpdateObject(obj)
   } 
 }

What the above leaves out, however, are the number of other locations at which a call to the SendEvent() routine reside. Some are located before the CreateObject or SpawnObject routine calls, some after, some within the UpdateObject routine itself, and even some within the interpreter routine, since there exist several types of GOOL instructions that allow another object to send an event to the recipient object. In fact, there is nothing preventing the object from being the recipient of more than one event sent (from potentially multiple sources) in a single frame. There may be an interpretation for each event sent to the object during that frame, and there is no limit on the number of events that can be sent. Thus, there may be many calls to SendEvent() [with the object as the recipient] in a single frame, but still only at most one call to CreateObject/SpawnObject() and UpdateObject(). Without getting too far off track, it is simply necessary to understand that each of these routines contains (or calls a routine that calls a routine that contains) a call to the interpreter routine:

 sub_80011FC4(levelid)
 { 
   ...	  
   GAME LOOP:
   {
     ...
     CreateObject(obj,...) or SpawnObject(obj,...)
       InitObject(obj, ...)
         ChangeObjectState(obj, ...)
           CreateObjectStackFrame(obj); // *create initial stack frame
           -if there is a head block to interpret for the object
             CreateObjectStackFrame(obj);
             obj->pc = obj->pchead;
             InterpretObject(obj, 0x13, &stateref); // # 1 (head block interpretation)
         
     SendEvent(src,obj,...) // there may be multiple calls to this
        -if there is an event service routine for the object (in its current state)
           CreateObjectStackFrame(obj);
           obj->pc = obj->pcevent;
           InterpretObject(obj, 0x8, &stateref);    // # 2 (event block interpretation)
        -if there is not an event service routine for the object (in its current state)
         or the event service routine failed to return an event
          -if the event maps to an event handler in the event->state/handler map
           CreateObjectStackFrame(obj);
           obj->pc = handlerlocation;
           InterpretObject(obj, 0x3, &stateref);    // # 3 (handles block interpretation)
          -else
           ChangeObjectState(obj,state,...); // *

     UpdateObject(obj)
      -if the object is able to animate
        -if there is a trans block to interpret for the object (in its current state)
           CreateObjectStackFrame(obj);
           obj->pc = obj->pctrans;
           InterpretObject(obj, 0x3, &stateref);   // # 4 (trans block interpretation)
        -if at least n ticks have elapsed, where n is given by the 'wait' operand of the 
         most recently suspending animation type instruction of the object's code block 
           InterpretObject(obj, 0x4, &stateref);   // # 5 (code block interpretation)

   } 
 }

 

Notice that immediately prior to each call [to the interpreter routine], with the exception of #5, a new stack frame is created for the object (which includes pointing its frame pointer and stack pointer, respectively, to the beginning and ending of its new frame), and its program counter is pointed to a distinct location within its bytecode. If each bytecode instruction is represented by a pseudo-instruction, a potential sequence of calls to the interpreter routine in a single frame [for only that object] might be represented by the following:

label  | address | pseudo-instruction

pcevent: 0x34      N  // call A
         0x38      N
         0x3C      S
...
pchead:   0x0      N  // call B
          0x4      N
          0x8      N
          0xC      S
...
pctrans: 0x50      N  // call C
         0x54      N
         0x58      N
         0x5C      N
         0x60      N
         0x64      N
         0x68      S
...
*pccode: 0x70      N  // call D
         0x74      N
         0x78      N
         0x7C      N
         0x80      S
...
pcevent: 0x34      N  // call E
         0x38      N
         0x3C      S
...
pcevent: 0x34      N  // call F
         0x38      N
         0x3C      S

Each call above to the interpreter routine is represented by the sequence of instructions (represented as pseudo-instructions) fetched during its interpretation. An N pseudo-instruction represents an instruction that did not suspend the interpreter, causing the next instruction in sequence to be fetched and interpreted. An S pseudo-instruction represents an instruction that did suspend the interpreter, causing the interpreter routine to end the interpretation/return to its caller. Each pseudo-instruction is listed with the address of the instruction it represents in the object's bytecode [relative to the beginning].

The first instruction fetched in each interpretation is also marked with a label; this label is given the name of the object field that points to its associated instruction. Immediately prior to each interpretation, with the exception of the one marked *pccode, the object's program counter is pointed to the location in this particular field; it is this operation that causes each interpretation to begin at the location it does. This particular object field is also primarily responsible for determining the type of interpretation:

Field Interpretation Type
pctrans Trans Block Interpretation
pcevent Event Block Intepretation
pchead Head Block Interpretation
pc Code Block Interpretation

The pctrans, pcevent, and pchead fields each contain a pointer to/the absolute location of an individual block in the object's bytecode. These fields locate the respective entry points for 3 separate threads of interpretation for the object-a trans thread, an event thread, and a head thread. Whenever the object changes state, its pctrans and pcevent fields are modified according to the state descriptor for its new state; its pchead field is then cleared. (If the object wishes to modify its pchead field, it does so via a MOVC instruction in its bytecode.)

Whenever the object changes state, its program counter (pc field) is also set directly to the location of the code block specified by the pccode field of the state descriptor for its new state. The entirety of the object's stack contents are then unwound, or the object's stack pointer is reset to its initial location, and an initial stack frame is [re]created. This program counter location and stack configuration is then restored after each subsequent non-code block interpretation is completed. (That is-since those interpretations require the program counter value to be replaced with a new location and a new stack frame to be created, after they are completed, the original program counter location and initial stack frame are restored). When the interpretation marked #5 in the above pseudo-code (the code block interpretation) finally occurs, the object's program counter will point to its code block and its stack frame will be the initial frame. The code block interpretation is yet another thread of interpretation for the object-a code thread.

For the sake of explanation, handles blocks are viewed as being equivalent to event blocks, so handles interpretations and threads are simply ignored. The timeline to the right shows an arbitrary frame of execution in terms of the times elapsed for the various interpretations of a single object's bytecode. Towards the beginning of the frame, the interpreter has performed a code block interpretation and a trans block interpretation for the object. Towards the end of the frame, the interpreter has performed an event block interpretation for that object, as it has been sent an event from some [unknown] source. The following timeline extends this timeline [to the right] to 6 arbitrary frames of execution:


The extended timeline makes it clear that this particular object has been configured to have its code block interpretation occur every other frame. It also shows the performance of more than one event block interpretation for that object during the second frame. The following timeline shows the same 6 frames of execution in terms of the times elapsed for all interpretations of each existing object's bytecode; in this particular instance, there are only 2 existing objects.

Stack Frame (incomplete)

A new stack frame is created for an object immediately prior to an interpretation of its bytecode. It is also created when jumping to and linking a bytecode routine via the JAL instruction. An object's initial stack frame is created when it enters its initial state, and is recreated for each subsequent state change (after the unwinding the stack). The initial stack frame is used for the object's code block interpretation. At any given point in time, an object's frame pointer and stack pointer, respectively, locate the beginning and end of its current stack frame.

Format

A stack frame has the following format:

Offset Field Size Value
-0x4 x a **Argument a 4 bytes *
0x0 Preserved Interpreter Mode Flags 4 bytes 0xFFFF for initial frame; * otherwise
0x4 Preserved Program Counter 4 bytes *
0x8 Preserved Frame Pointer Relative Offset 2 bytes f
0xA Preserved Stack Pointer Relative Offset 2 bytes s
0xC Frame Data * x 4 bytes *

(**Arguments come before frames and are not actually 'part' of them)

Initial Stack Frame

When the object is first created/spawned, or when it changes state, its program counter is pointed to the code block with offset pccode (given by the state descriptor for its initial or new state), its frame pointer is cleared, and its stack pointer is reset to its initial location:

The object's initial stack frame is then [re]created by pushing the following sequence of values to the stack:

  • 0x0000FFFF - Interpreter Mode Flags. Not an actual interpreter mode flags value but rather an indicator that an unwinding of this frame shall not restore interpreter mode flags.
  • obj->pc - Program Counter. At this point, it points to the code block for the object's initial/new state.
  • (((unsigned long)obj->fp - (unsigned long)&obj->self) << 16) | ((unsigned long)obj->sp - (unsigned long)&obj->self)) Frame Pointer and Stack Pointer relative offsets. At this point, frame pointer (obj->fp) is 0 and stack pointer points to its initial location; this combined value should be of the form 0x0000****.

The object's frame pointer is then pointed to the beginning of that frame. With these values having been pushed to its stack, the object's stack pointer now points to the end of that frame. Thus, immediately following the instantiation or state change, the object's current stack frame is its initial stack frame.

During the object's code block interpretation, this frame is then extended with additional data, including stack operands and/or the results of interpreted instructions.

Non-Initial Stack Frame

After an object's initial stack frame is created, but before its next code block interpretation occurs, several other non-code block interpretations may be performed. Immediately prior to performing any of these interpretations, a new stack frame is created on top of the initial stack frame, and then the current program counter value (which contains the code block location) is replaced with the location of the non-code block. This frame is created by pushing the following sequence of values to the stack:

  • modeflags - Interpreter Mode Flags
  • obj->pc - Program Counter. At this point, it points to the code block for the object's initial/new state.
  • (((unsigned long)obj->fp - (unsigned long)&obj->self) << 16) | ((unsigned long)obj->sp - (unsigned long)&obj->self)) Frame Pointer and Stack Pointer relative offsets. At this point, frame pointer points to the beginning of the initial frame, and stack pointer points to the end of the initial frame.

The object's frame pointer is then pointed to the beginning of that frame. With these values having been pushed to its stack, the object's stack pointer now points to the end of that frame. Thus, immediately following the creation of the frame, it is the object's current stack frame-that is, the initial stack frame is no longer the current stack frame.

When the following interpretation finishes, the object's program counter is restored to the code block location preserved in the current frame, and the preserved frame pointer and stack pointer offsets are used to restore the initial stack frame as the current frame.

UNFINISHED

Interpreter Mode Flags

TBD

GOOL Instructions

Crash 1

The GOOL Interpreter in Crash 1 recognizes a total of 58 different GOOL instructions: 

  • 6 Arithmetic Instructions (incl SHA*) 
  • 4 Non-bitwise Logical/Logical Comparison Instructions 
  • 4 Bitwise Logical Instructions 
  • 5 Comparison Instructions 
  • 5 Data Transfer Instructions 
  • 8 Mathematical Function Instructions 
  • 4 Control Flow Instructions 
  • 19 Miscellaneous/Multi-Purpose Instructions 

GOOL Instruction Tables

Main Instruction Table

The GOOL instruction table below lists the opcode, mnemonic/name, format, operands (based on explicit and/or implicit specification of source origin and/or destination target), general operation (represented with c-style statement), and a description for each GOOL instruction.

Opcode Name Encoding/Format Explicit GOOL ops

in

Explicit IMM. ops

in

Implicit STACK ops

in

Operation Implicit STACK out Explicit

GOOL ops out

Description
0/0x00 ADD 00000000RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L + R O add
1/0x01 SUB 00000001RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L - R O subtract
2/0x02 MUL 00000010RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L * R O multiply
3/0x03 DIV 00000011RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L / R O divide
4/0X04 CEQ 00000100RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (L == R),

O = ((L ^ R) == 0)

O check if equal
5/0x05 ANDL 00000101RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (L && R),

O = (L ? (R > 0) : 0)

O logical and
6/0x06 ORL 00000110RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (L || R) O
logical or
7/0x07 ANDB 00000111RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L & R O bitwise and
8/0x08 ORB 00001000RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L | R O bitwise or
9/0x09 SLT 00001001RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L < R O set less than
10/0x0A SLE 00001010RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (L <= R) O set less than or equal
11/0x0B SGT 00001011RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L > R O set greater than
12/0x0C SGE 00001100RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (L >= R) O set greater than or equal
13/0x0D MOD 00001101RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L % R O modulo
14/0x0E XOR 00001110RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L ^ R O exclusive or
15/0x0F TST 00001111RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (((L & R) ^ R) == 0) O test bit
16/0x10 RND 00010000AAAAAAAAAAAABBBBBBBBBBBB A,B O = B+(rand() % (A - B)) O random
17/0x11 MOVE 00010001SSSSSSSSSSSSDDDDDDDDDDDD S D = S [D] move data
18/0x12 NOTL 00010010SSSSSSSSSSSSDDDDDDDDDDDD S D = (S == 0) D logical not
19/0x13 LOOP 00010011AAAAAAAAAAAABBBBBBBBBBBB (A),B R = 0x100 [R,A] B = A >= 0 ? B + R : B - R

if (B > A && A > 0) B = -A + R*2 else if (B < A && A < 0) B = -A - R*2 P = A >= 0 ? abs(B) : -abs(B)

P B loop around zero
20/0x14 LEA 00010100SSSSSSSSSSSSDDDDDDDDDDDD S D = &S D load effective address
21/0x15 SHA 00010101RRRRRRRRRRRRLLLLLLLLLLLL L,R O = ((R < 0) ? (L >> -R)

: (L << R))

O arithmetic shift
22/0x16 PUSH 00010110AAAAAAAAAAAABBBBBBBBBBBB [A,[B]] [arg_buf = A]

I = A; J = B;

[I,[J]] push value to stack
23/0x17 NOTB 00010111SSSSSSSSSSSSDDDDDDDDDDDD S D = ~S D bitwise not
24/0x18 MOVC 000110000000RRRRRRIIIIIIIIIIIIII R,C see docs O move code pointer
25/0x19 ABS 00011001SSSSSSSSSSSSDDDDDDDDDDDD S D = (S < 0) ? -S: S D absolute value
26/0x1A PAD 00011010000TDDDDSSPPBBBBBBBBBBBB B,P,S,D,T O = testctrls(instr,0) O test controller buttons
27/0x1B SPD 00011011VVVVVVVVVVVVBBBBBBBBBBBB V,B S = B + ((V*grav) >> 10) S calculate speed
28/0x1C MSC 00011100PPPPSSSSSLLLXXXXXXXXXXXX X P,S,L various; see docs *** *** multi-purpose
29/0x1D PSIN 00011101PPPPPPPPPPPPDDDDDDDDDDDD P,D large calc; see docs O periodic sine wave
30/0x1E TICK 00011110DDDDDDDDDDDDPPPPPPPPPPPP M,P O = (M + frameCount) % P O get game time
31/0x1F RGL 00011111000000000000IIIIIIIIIIII I O = globals[I >> 8] O read global variable
32/0x20 WGL 00100000SSSSSSSSSSSSIIIIIIIIIIII I,S globals[I << 8] = *S write global variable
33/0x21 DEGD 00100001RRRRRRRRRRRRLLLLLLLLLLLL L,R O = degdist(L,R) angle between
34/0x22 SEEK 00100010RRRRRRRRRRRRLLLLLLLLLLLL L,(R) S = 0x100 [R,S] O = seek(L,R,S) O approach a value
35/0x23 CVMR 00100011000IIIIIILLL000000000000 I,L O = obj.link[L].colors[I] color vector or matrix read
36/0x24 CVMW 00100100000IIIIIILLLCCCCCCCCCCCC C I,L obj.link[L].colors[I] = C color vector or matrix write
37/0x25 DSEK 00100101RRRRRRRRRRRRLLLLLLLLLLLL L,(R) [R,S] O = degseek(L,R,S,0) O approach an angle
38/0x26 PSHP 00100110AAAAAAAAAAAABBBBBBBBBBBB [A,[B]] I = &A; J = &B; [I,[J]] push pointer to stack
39/0X27 ANID 00100111FFFFFFFFFFFFDDDDDDDDDDDD F D=&obj.global.anim[F>>5] D set animation
128/0x80 DBG 10000000RRRRRRRRRRRRLLLLLLLLLLLL L,R debug print ops (beta only)
129/0x81 NOP 10000001000000000000000000000000 no operation
130/0x82 CFL 10000010TTCCRRRRRRIIIIIIIIIIIIII T,C,R,I general control flow
BRA 100000100000RRRRRRVVVVIIIIIIIIII R,V,I branch
BNEZ 100000100001RRRRRRVVVVIIIIIIIIII R,V,I branch not equal zero
BEQZ 100000100010RRRRRRVVVVIIIIIIIIII R,V,I branch equal zero
CST 100000100100RRRRRRSSSSSSSSSSSSSS R,S change state
CSNZ 100000100101RRRRRRSSSSSSSSSSSSSS R,S change state not zero
CSEZ 100000100110RRRRRRSSSSSSSSSSSSSS R,S change state equal zero
RET 100000101000RRRRRRIIIIIIIIIIIIII R,I return
131/0x83 ANIM 10000011HHTTTTTTSSSSSSSSSFFFFFFF F,S,T,H W play animation at specified frame
132/0x84 ANIF 10000100HHTTTTTTFFFFFFFFFFFFFFFF F T,H W change animation frame
133/0x85 VECA 10000101CCCTTTBBBAAAVVVVVVVVVVVV V T,A,B,C * ** multi-purpose vector calcs
134/0x86 JAL 10000110VVVV000000IIIIIIIIIIIIII I,V jump and link
135/0x87 EVNT 10000111LLLAAARRRRRREEEEEEEEEEEE E L,A,R send an event
136/0x88 EVHR 10001001TTCCRRRRRR************** R,C,T,* ** reject event
137/0x89 EVHA 10001000TTCCRRRRRR************** R,C,T,* **
accept event
138/0x8A CHLD 10001010AAAATTTTTTTTSSSSSSCCCCCC C,T,S,A [C],

arg[0 to A]

spawn children objects
139/0x8B NTRY 10001011TTTTTTTTTTTTEEEEEEEEEEEE T,E multi-purpose page operation
140/0x8C SNDP 10001100AAAAAAAAAAAABBBBBBBBBBBB A,B play audio file at volume
141/0x8D SNDB 10001101FFFFTTRRRRRRSSSSSSSSSSSS S F,T,R adjust voice parameters
142/0x8E VECB 10001110CCCTTTBBBAAAVVVVVVVVVVVV V T,A,B,C
multi-purpose vector calcs
143/0x8F EVNB 10001111LLLAAARRRRRREEEEEEEEEEEE E L,A,R
broadcast an event
144/0x90 EVNU 10010000LLLAAARRRRRREEEEEEEEEEEE E L,A,R

send event unknown variant
145/0x91 CHLF 10100000AAAATTTTTTTTSSSSSSCCCCCC C,T,S,A [C],

arg[0 to A]


spawn children objects;

no replacement if obj pool full

Note that a few instructions can not be represented with a single mnemonic; operations for these instructions are not only determined by their opcode but also their primary operation subtype and possibly secondary operation subtype fields. These instructions have their own tables, which are given in the following sections.

State Return Instruction Table
Opcode Name Encoding/Format Explicit

IMM. ops

in

Description
136/0x88 RSTT 10001000TTCCRRRRRR************** R,C,T,* state return guard = true variant
RST 100010000100RRRRRRSSSSSSSSSSSSSS R,S state return guard = true
RSNT 100010000101RRRRRRSSSSSSSSSSSSSS R,S state return if nonzero guard = true
RSZT 100010000110RRRRRRSSSSSSSSSSSSSS R,S state return if equal zero guard = true
RSCT 100010000111RRRRRRSSSSSSSSSSSSSS R,S state return eval prev cond guard = true
RNT 100010001000RRRRRRxxxxxxxxxxxxxx R null return guard = true
RNNT 100010001001RRRRRRxxxxxxxxxxxxxx R null return if nonzero guard = true
RNZT 100010001010RRRRRRxxxxxxxxxxxxxx R null return if equal zero guard = true
RNCT 100010001011RRRRRRxxxxxxxxxxxxxx R null return eval prev cond guard = true
GDT 100010001100RRRRRRxxxxxxxxxxxxxx R guard = true
GNT 100010001101RRRRRRxxxxxxxxxxxxxx R if nonzero guard = true
GZT 100010001110RRRRRRxxxxxxxxxxxxxx R if equal zero guard = true
GCT 100010001111RRRRRRxxxxxxxxxxxxxx R eval prev cond guard = true
GBNT 100010000001RRRRRRVVVVIIIIIIIIII R,V,I if nonzero guard = true else branch
GBZT 100010000010RRRRRRVVVVIIIIIIIIII R,V,I if equal zero guard = true else branch
137/0x89 RSTF 10001001TTCCRRRRRR************** R,C,T,* state return guard = false variant
RSF 100010000100RRRRRRSSSSSSSSSSSSSS R,S state return guard = false
RSNF 100010000101RRRRRRSSSSSSSSSSSSSS R,S state return if nonzero guard = false
RSZF 100010000110RRRRRRSSSSSSSSSSSSSS R,S state return if equal zero guard = false
RSCF 100010000111RRRRRRSSSSSSSSSSSSSS R,S state return eval prev cond guard = false
RNF 100010001000RRRRRRxxxxxxxxxxxxxx R null return guard = false
RNNF 100010001001RRRRRRxxxxxxxxxxxxxx R null return if nonzero guard = false
RNZF 100010001010RRRRRRxxxxxxxxxxxxxx R null return if equal zero guard = false
RNCF 100010001011RRRRRRxxxxxxxxxxxxxx R null return eval prev cond guard = false
GDF 100010001100RRRRRRxxxxxxxxxxxxxx R guard = false
GNF 100010001101RRRRRRxxxxxxxxxxxxxx R if nonzero guard = false
GZF 100010001110RRRRRRxxxxxxxxxxxxxx R if equal zero guard = false
GCF 100010001111RRRRRRxxxxxxxxxxxxxx R eval prev cond guard = false
GBNF 100010000001RRRRRRVVVVIIIIIIIIII R,V,I if nonzero guard = false else branch
GBZF 100010000010RRRRRRVVVVIIIIIIIIII R,V,I if equal zero guard = false else branch

Crash 2

The GOOL Interpreter in Crash 2 recognizes a total of 79 GOOL instructions, including two duplicates. Many of the instructions are known. The basic arithmetic and logical operations are preserved the same as in Crash 1, but most others have been changed.

Crash 2 GOOL code may also contain sections of machine code for the MIPS processor architecture (used by the playstation).

GOOLv2 Instruction Table

The GOOL instruction table below lists the opcode, mnemonic/name, format, operands (based on explicit and/or implicit specification of source origin and/or destination target), general operation (represented with c-style statement), and a description for each GOOL instruction.

Opcode Name Encoding/Format Explicit GOOL ops

in

Explicit IMM. ops

in

Implicit STACK ops

in

Operation Implicit STACK out Explicit

GOOL ops out

Description
0/0x00 ADD 00000000RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L + R O add
1/0x01 SUB 00000001RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L - R O subtract
2/0x02 MUL 00000010RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L * R O multiply
3/0x03 DIV 00000011RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L / R O divide
4/0x04 CEQ 00000100RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (L == R),

O = ((L ^ R) == 0)

O check if equal
5/0x05 ANDL 00000101RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (L && R),

O = (R ? L : R)

O logical and
6/0x06 ORL 00000110RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (L || R)

O = L | R

O
logical or (same as ORB)
7/0x07 ANDB 00000111RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L & R O bitwise and
8/0x08 ORB 00001000RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L | R O bitwise or
9/0x09 SLT 00001001RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L < R O set less than
10/0x0A SLE 00001010RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (L <= R) O set less than or equal
11/0x0B SGT 00001011RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L > R O set greater than
12/0x0C SGE 00001100RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (L >= R) O set greater than or equal
13/0x0D MOD 00001101RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L % R O modulo
14/0x0E XOR 00001110RRRRRRRRRRRRLLLLLLLLLLLL L,R O = L ^ R O exclusive or
15/0x0F TST 00001111RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (((L & R) ^ R) == 0) O test bit
16/0x10 RND 00010000AAAAAAAAAAAABBBBBBBBBBBB A,B O = B+(rand() % (A - B)) O random
17/0x11 MOVE 00010001SSSSSSSSSSSSDDDDDDDDDDDD S D = S [D] move data
18/0x12 NOTL 00010010SSSSSSSSSSSSDDDDDDDDDDDD S D = (S == 0) D logical not
19/0x13 LOOP 00010011AAAAAAAAAAAABBBBBBBBBBBB (A),B R = 0x100 [R,A] B = A >= 0 ? B + R : B - R

if (B > A && A > 0) B = -A + R*2 else if (B < A && A < 0) B = -A - R*2 P = A >= 0 ? abs(B) : -abs(B)

P B loop around zero
20/0x14 LEA 00010100SSSSSSSSSSSSDDDDDDDDDDDD S D = &S D load effective address
21/0x15 SHA 00010101RRRRRRRRRRRRLLLLLLLLLLLL L,R O = ((R < 0) ? (L >> -R)

: (L << R))

O bit shift
22/0x16 PUSH 00010110BBBBBBBBBBBBAAAAAAAAAAAA A,[B]

I = A; J = B;

I,[J] push value(s) to stack
23/0x17 NOTB 00010111SSSSSSSSSSSSDDDDDDDDDDDD D = ~S D bitwise not (nor)
24/0x18 MOVC 00011000RRRRRR000EIIIIIIIIIIIIII R,E,I see docs O get code pointer
25/0x19 ABS 00011001SSSSSSSSSSSSDDDDDDDDDDDD S D = (S < 0) ? -S : S D absolute value
26/0x1A PAD 00011010000TDDDDSSPPBBBBBBBBBBBB B,P,S,D,T O = testctrls(instr,0) O test controller buttons
27/0x1B SPD 00011011VVVVVVVVVVVVBBBBBBBBBBBB V,B S = B + ((V*gvel) >> 10) S calculate speed
28/0x1C MSC 00011100PPPPSSSSSLLLXXXXXXXXXXXX X P,S,L various multi-purpose
29/0x1D PSIN 00011101PPPPPPPPPPPPDDDDDDDDDDDD P,D large calc; see docs driven sine wave
30/0x1E TICK 00011110RRRRRRRRRRRRLLLLLLLLLLLL L,R O = (R + TICKS) % L O get ticks
31/0x1F RGL 00011111101111100000IIIIIIIIIIII I O = globals[I] O read global variable
32/0x20 WGL 00100000SSSSSSSSSSSSIIIIIIIIIIII I,S globals[I] = *S write global variable
33/0x21 ANGD 00100001RRRRRRRRRRRRLLLLLLLLLLLL R,L O = ((R << 20) - (L << 20)) >> 20 O angle distance (note: shifts are for sign extension)
34/0x22 APCH 00100010RRRRRRRRRRRRLLLLLLLLLLLL L,(R) O = approach(L,R,S) O approach a value
35/0x23 CVMR 00100011000IIIIIILLL000000000000 I,L O = obj.link[L].colors[I] O color vector or matrix read
36/0x24 CVMW 00100100000IIIIIILLLCCCCCCCCCCCC C I,L obj.link[L].colors[I] = C color vector or matrix write
37/0x25 ROT 00100101RRRRRRRRRRRRLLLLLLLLLLLL (R),L [R,S] O = rotate(L,R,S,0) approach an angle
38/0x26 PSHP 00100110BBBBBBBBBBBBAAAAAAAAAAAA A,[B] I = &A; J = &B; I,[J] push pointer(s)
39/0x27 ANIS 00100111FFFFFFFFFFFFDDDDDDDDDDDD F D=&obj.global.anim[F>>8] D set animation
40/0x28 EFLR 00101000BBBBBBBBBBBBAAAAAAAAAAAA A,B O = GetFieldValue(obj->entity, field: A, row: B) O load entity field row data
41/0x29 EFLV 00101001SSSSSSSSSSSSDDDDDDDDDDDD S D = GetFieldValue(obj->entity, field: S) D get entity field data
42/0x2A ARRL 00101010RRRRRRRRRRRRLLLLLLLLLLLL L,R O = *(L + R)

o = L[R]

O load array value
43/0x2B SIN 00101100SSSSSSSSSSSSDDDDDDDDDDDD S D = sin(S) D sine wave (output: -0x1000 to 0x1000)
44/0x2C COS 00101101SSSSSSSSSSSSDDDDDDDDDDDD S D = cos(S)

D = sin(S + PI/2)

D cosine wave (output: -0x1000 to 0x1000)
45/0x2D ATAN 00101110YYYYYYYYYYYYXXXXXXXXXXXX X,Y o = atan2(X, Y) o arc-tangent2, angle to point (confirmation needed)
46/0x2E ? 00101110SSSSSSSSSSSSDDDDDDDDDDDD A D unknown
47/0x2F NOP 00101111101111100000101111100000 no operation
48/0x30 DBG 00110000BBBBBBBBBBBBAAAAAAAAAAAA (debug only) print gool fixed point values
49/0x31 RET 00110001100001100100000000000000 R,I conditionally stop gool execution (R and I ignored)
50/0x32 BRA 001100100000100101VVVVIIIIIIIIII R,V,I branch
51/0x33 BNEZ 001100110001RRRRRRVVVVIIIIIIIIII R,V,I branch not equal zero
52/0x34 BEQZ 001101000010RRRRRRVVVVIIIIIIIIII R,V,I branch equal zero
53/0x35 CST 001101010100100101AAAASSSSSSSSSS R,A,S change object state
54/0x36 CNEZ 001101100101RRRRRRAAAASSSSSSSSSS R,A,S change state if not zero
55/0x37 CEQZ 001101110110RRRRRRAAAASSSSSSSSSS R,A,S change state if zero
56/0x38 ANIM 00111000HHTTTTTTSSSSSSSSSFFFFFFF F,S,T,H W set and play animation+frame
57/0x39 ANIF 00111001HHTTTTTT0000FFFFFFFFFFFF F H,T W set and play frame of animation
58/0x3A VECA 00111010CCCTTTBBBAAAVVVVVVVVVVVV V C,T,B,A * ** multi-purpose vector calcs
59/0x3B JAL 00111011VVVV00000EIIIIIIIIIIIIII I,V jump and link
60/0x3C EVNT 00111100LLLAAARRRRRREEEEEEEEEEEE E L,A,R send an event
61/0x3D EVHR 00111101TTCCRRRRRR************** R,C,T,* ** event handler: reject event
62/0x3E EVHA 00111110TTCCRRRRRR************** R,C,T,* ** event handler: accept event
63/0x3F CHLD 00111111AAAATTTTTTTTSSSSSSCCCCCC C,T,S,A [C],

arg[0 to A]

spawn children objects
64/0x40 NTRY 01000000TTTTTTTTTTTTEEEEEEEEEEEE T,E multi-purpose page operation
65/0x41 SNDP 01000001VVVVVVVVVVVVAAAAAAAAAAAA A,V play sound effect
66/0x42 SNDA 01000010VVVVFFRRRRRRSSSSSSSSSSSS S V,F,R adjust voice parameters
67/0x43 VECB 01000011CCCTTTBBBAAAVVVVVVVVVVVV V C,T,B,A multi-purpose vector calcs
68/0x44 EVNB 01000101LLLAAARRRRRREEEEEEEEEEEE E L,A,R send an event to all objects
69/0x45 EVNC 01000100LLLAAARRRRRREEEEEEEEEEEE E L,A,R send an event, cascading
70/0x46 CHLF 01000110AAAATTTTTTTTSSSSSSCCCCCC A,T,S,C [C],

arg[0 to A]

spawn children objects; forcefully?
71/0x47 JALR 01000111AAAAAAAAAAAAPPPPPPPPPPPP P,A arg[0 to A] jump and link to instruction pointed at by P
72/0x48 CMSG 01001000AAAAAAAAAAAAMMMMMMMMMMMM M,A AddCamMessage(M, &A) add message to camera queue (if not full), cam-message is M, its operands (dependant on message) are pointed to by A
73/0x49 NATIVE 01001001101111100000101111100000 begin native (psx mips) code
74/0x4A ? 01001010------------AAAAAAAAAAAA A O unknown VIDO operation
75/0x4B ? 01001011------------AAAAAAAAAAAA A unknown
76/0x4C ? 01001100AAAAAAAAAAAABBBBBBBBBBBB A,B unknown
77/0x4D ? 01001101AAAAAAAAAAAABBBBBBBBBBBB A,B P,T unknown
78/0x4E ARRS 00101011RRRRRRRRRRRRLLLLLLLLLLLL L,R S *(L + R) = S

L[R] = S

store array value

GOOLv3 Instruction Table

The GOOL instruction table below lists the opcode, mnemonic/name, format, operands (based on explicit and/or implicit specification of source origin and/or destination target), general operation (represented with c-style statement), and a description for each GOOL instruction added in Crash 3.

Opcode Name Encoding/Format Explicit GOOL ops

in

Explicit IMM. ops

in

Implicit STACK ops

in

Operation Implicit STACK out Explicit

GOOL ops out

Description
79/0x4F ? 01001100AAAAAAAAAAAABBBBBBBBBBBB B A unknown
80/0x50 ? 01001101AAAAAAAAAAAABBBBBBBBBBBB B A unknown
81/0x51 ? 01001100AAAAAAAAAAAABBBBBBBBBBBB A,B unknown matrix math

GOOL Instruction Operands

...

  • In/Source type operands
    • Explicitly specified (i.e. origin = determined by operand's corresponding bitfield from the instruction)
      • GOOL in/source operand
      • Immediate operand
    • Implicitly specified (i.e. origin = top of object's stack; implicitly popped from top of object's stack)
      • Stack in/source operand
  • Out/Destination type operands
    • Explicitly specified (i.e. target = determined by operand's corresponding bitfield from the instruction)
      •  GOOL out/destination operand
    • Implicitly specified (i.e. target = top of object's stack; implicitly pushed to top of object's stack)
      • Stack out/destination operand/result*

*technically not an 'operand', but rather a result of the instruction's overall operation; it is implied that instructions that use [an] operand(s) of this type always pushes it/them (i.e the result(s)) to the top of the object's stack.

Explicit Operands

A GOOL instruction's explicit operands are explicitly specified in its lower 24 bits (operand portion). Each explicitly specified operand is either an immediate operand, or a GOOL operand.

Immediate Operands

An immediate operand directly specifies its value in its corresponding bitfield (within the operand portion) of the instruction. The number of immediate operands and their positions/bit-lengths varies between instructions.

Immediate Operands are in operands (source operands).

GOOL Operands

Conversely, a GOOL operand is specified as a reference to its actual value or destination location. Each GOOL operand is 12 bits in length; a GOOL instruction may require the specification of at most 2 GOOL operands, within the upper and/or lower halves of its operand portion, respectively. The 12 bit GOOL reference that specifies a GOOL operand encodes a [32 bit] pointer to its corresponding source value and/or destination location. Operations for instructions that require GOOL operand specification first translate the corresponding GOOL reference(s) to yield their decoded pointer(s) before accessing pointed data.

See the GOOL Reference Translation section for more information.

Depending on how a GOOL operand is used by its instruction, it may be an in (source) operand, an out (destination) operand, or both (inout operand). If an instruction only reads the [input] value located by its translated GOOL operand (a pointer), it is an in (source) operand. If an instruction only writes a result/value to the location of its translated GOOL operand, it is an out (destination) operand. If an operand meets both of these criteria it is an inout operand.

Implicit Operands

Implicit In Operands

Some GOOL instructions may require the implicit specification of one or more (implicit) in operands. In operands are implicitly specified prior to an instruction's interpretation by pushing their value(s)-which must remain the topmost values at interpretation-to the object's stack. It is implied that these so-called implicit operands will exist on the stack for the instruction to pop and use as input.

Implicit Out Operands

For most GOOL instructions, the net effect of their operation involves an implicit push of one or more results to the object's stack. That is-it is implied or expected that these instructions will ultimately push their results to the object's stack.

GOOL Reference Translation

The following table lists the encoding format, potential type name, and a descriptive type name for each of the possible GOOL reference types:

Format Potential Type Name Descriptive Type Name
00RRRRRRRRRR Ireg Ref object local executable data pool reference
01RRRRRRRRRR Pool Ref object external executable data pool reference
100IIIIIIIII Int Ref constant mult of 256 (range: -32768 - 32512)
1010IIIIFFFF Frac Ref constant mult of 16 (range: -8192 - 8176)
10110SSSSSSS Stack Ref object frame argument/local variable reference [peek stack @ location relative to fp]
101111100000 Null Ref null reference (translates to 0)
101111110000 Sp-Double Ref double stack pop reference (translates to 1)
110LLLMMMMMM Reg Ref object link memory reference
111MMMMMMMMM (M != 0x1F) Var Ref object field/memory reference
111000011111 Stack Pop/Push stack pop/push reference

Potential GOOL Reference type names have been deduced based on what appears to be an unreferenced array of GOOL interpreter debug strings at 0x103B8.

Stack Pop/Push

Format Description
111000011111 Stack Pop/Push Reference

A GOOL reference of this format translates differently depending on whether the operand that specifies it is an in operand or an out operand:

  • In operands specified as a reference of this type translate to a pointer to the top of the object's stack after an ensuing pop of the value located there (i.e. stack pointer is decremented).
  • Out operands specified as a reference of this type translate to a pointer to the top of the object's stack prior to an incrementation of its stack pointer. A stack push will result from the translation's incrementing of the object's stack pointer and the instruction's ultimate dereferencing of the returned/translated pointer for a write.

Var Ref

Format Description
111FFFFFFFFF Object Field/Memory Reference
Field Description Domain Range
F Object Field Index 0 to 0x1FF 0x60 to 0x860 R = 4N

GOOL References of this format translate to a pointer to the Ath object field in relation to the object's self field.

Most of an object's significant fields are located past a 0x60 byte offset from the beginning of its structure-i.e. past its self field. Note that the last of these fields is the object's array of/address space for its [local] memory where its global variables and stack contents are stored. Because object fields are 4 bytes in size and an object's self field is located at a 0x60 byte offset from the beginning of its structure, then the formula:

0x60 + (A * 4)

gives the byte offset of the actual field located by the translated pointer.

If A = 0x1F, then the reference will have the format 111000011111; this is, however, already defined as the format for a stack pop/push reference-the processing of which takes precedence over that of var references. Notice that if such a reference were not instead translated as a stack pop/push reference, its translated pointer would locate the field at byte offset 0x60 + (0x1F * 4) = 0xDC-the object's stack pointer. Then, it should not be possible to directly modify an object's stack pointer by accessing a translated reference. Only indirectly via translation of a stack push/pop reference should the object's stack pointer be modified.

Reg Ref

Format Description
110LLLFFFFFF Object Link Field/Memory Reference
Field Description Domain Range
F Link Object Field Index 0 to 0x3F 0x60 to 0x15C R = 4N
L Object Link Index 0 to 7 0x60 to 0x7C R = 4N

GOOL references of this format translate to a pointer to the Ath object field in relation to the object's Bth link object's self field. An object's link objects are referred to by the group of 8 object pointers beginning with its self field; the first of these pointers is the object's self link, the second a pointer to its parent object, the third a pointer to its sibling object, and so on.

Ireg Ref

Format Description
00RRRRRRRRRR Object Local Executable Data Pool Reference
Field Description Domain Range
R Index of Value in Pool 0 to 0x3FF 0 to 0xFFC R = 4N

GOOL references of this format translate to a pointer to the predefined constant long at an offset of R longs relative to the beginning of the object's local executable's constant data pool item.

A GOOL executable's constant data pool item is essentially a table of predefined constants. For example, it includes the EIDs of any entries, preconfigured bitfields and bit selectors, audio sample parameters (volume, pan, etc), specific speeds or velocities, and other constants referenced by this type.

NOTE: if an instruction's out operand is specified as a reference of this type, its operation will ultimately replace the constant at the translated location with its output result. A write to the executable's data pool should generally be avoided unless a global change to that constant, and therefore an equal change in behavior for each object that is an instance of that executable, is desired. 

Pool Ref

Format Description
01RRRRRRRRRR Object External Executable Data Pool Reference
Field Description Domain Range
R Index of Value in Pool 0 to 0x3FF 0 to 0xFFC R = 4N

GOOL references of this format translate to a pointer to the predefined constant long at an offset of R longs relative to the beginning of the object's external executable's constant data pool item.

The same considerations for ireg refs apply to pool refs.

Frac Ref

Format Description
100CCCCCCCCC or

100IIIIIFFFF

Reference to Constant Multiple of 16
Field Description Domain Range
C Constant that will

be multiplied by 16

0 to 0x1FF -8192 to 8176

-0x2000 to 0x1FF0

-16.0 to 15.9375?

R = 16N

R = 0x10N

R = 0.0625N

I Integral Portion? 0 to 0x1F -15 to 16 R = 1N
F Fractional Portion? 0 to 15 0 to 0.9375 R = 0.0625N

GOOL references of this format translate to a pointer to the value (16*C).

Two signed long constant buffers are located at offsets 0x40 and 0x44, respectively, in scratch memory (as referenced by the pointer at memory location 0x56480 [gp$(0x44)].) At any point during the game's execution, the currently active constant buffer is either the buffer at offset 0x40 or 0x44, and is indicated by either a 0 or a 1 in the unsigned long at memory location 0x56484 [gp$(0x48)]. Translation for references of this format consists of the following steps:

  • Write the value (16*C)-that is, 16 times the value specified by the C bits-to the currently active constant buffer.
  • Swap the currently active and inactive constant buffers (that is, if 0 previously indicated the currently active constant buffer, change it to a 1; conversely, if it is a 1, change it to a 0).
  • Return a pointer to the (16*C) signed long value in the buffer it was written to (which, after the swap, will always be the currently inactive buffer.)

This double-buffer allows the sufficient specification of up to 2 constant type GOOL references per instruction; each of the 2 buffers will keep track of up to 2 constants to be used by operations of instructions with the corresponding operands.

C can be specified as a negative constant with the following 2's complement format:

  • C = 1NNNNNNNN (-N): V = 11111111111111111111NNNNNNNN0000 (16 * -N)
  • C = 0NNNNNNNN ( N): V = 00000000000000000000NNNNNNNN0000 (16 * N)

Where V is the calculated signed long that will be written to the appropriate constant buffer for the specified formats of C.

Note: out operands are not meant to specify a reference of this type; any that do so are useless. Translation of this reference type returns a pointer to the currently inactive constant buffer after storing the appropriate constant value (C * 16) in the currently active constant buffer and then swapping the 2 buffers. The constant value in the inactive constant buffer would ultimately be overwritten with an expected result of the instruction with the out operand. However, since that buffer could only be accessed via subsequent translation of another frac or int ref, which would involve first overwriting its current value (the result) with a new constant value, then that result could never be accessed [without first being overwritten].

Int Ref

Format Description
1010IIIIIIII Reference to Constant Multiple of 256
Field Description Domain Range
I Constant (int) that will

be multiplied by 256

0 to 0xFF -32768 to 32512

-0x8000 to 0x7F00

R = 256N

R = 0x100N

GOOL references of this format are translated almost identically to frac refs; the only difference is in the calculation for the constant written to the buffer:

  • I = 1NNNNNNN (-N): V = 1111111111111111NNNNNNNN00000000 (256 * -N)
  • I = 0NNNNNNN ( N): V = 0000000000000000NNNNNNNN00000000 (256 * N)

The same considerations for frac refs apply to int refs.

Stack Ref

Format Description
10110SSSSSSS Object Frame Argument/Local Variable Reference [peek stack at location relative to fp]
Field Description Domain Range
S Argument/Local Variable Index/Offset

relative to object fp

0 to 0x7F

-64 args to +63 local vars

-0x100 to 0xFC R = 4N

GOOL references of this format translate to a pointer to the long that is S longs (4*S bytes) relative to the object's current frame pointer. If S is specified as a negative value/offset, it refers to an argument; this is because arguments are located before the start of the stack frame. If S is specified as a positive offset (> 3), it refers to a local variable (i.e. operation result).

S can be specified as a negative offset with the following 2's complement format:

  • S = 1NNNNNN (-N): O = 111111111111111111111111NNNNNN00 (4 * -N) (argument offset)
  • S = 0NNNNNN ( N): O = 000000000000000000000000NNNNNN00 (4 * N) (local variable offset)

Null Ref

Format Description
101111100000 = 0xBE0 Null Reference

(translates to 0)

GOOL references of this format translate to the value 0 (i.e. invalid pointer to address 0). Some instructions will return without making any calculations or pushing any results if an operand is specified as a reference of this type.

Most other instructions do not account for translated references of this type. They assume that a translated reference will always point to a valid memory location. After these instructions translate a null ref, they will attempt to access the memory at address 0x0-which lies in the kernel code segment-thus resulting in a trap.

In the instruction table, brackets '[]' around one or more of an instruction's explicit operands (*given that parenthesis '()' are not listed around any other operand) indicate that, if any of those operands are specified as null refs, the instruction will return before performing their associated calculations. Brackets '[]' around one or more of an instruction's implicit operands (*given that parenthesis '()' are not listed around any other operand) indicate that, if the 'corresponding' explicit operands are specified as null refs, they (the implicit operands) do not actually exist. The order in which associated calculations are performed is indicated by the nested bracketing of operands.

For example, the PSHV instruction is listed with explicit GOOL in operands [A,[B]], and implicit stack out operands [I,[J]]-aliases for the respective destinations of two subsequent stack pushes. These operand nestings indicate that:

  • If only operand B is specified as a null ref, the instruction returns before operation J = B (equivalently, push(obj,B)) is performed. As a result, only operation I = A (equivalently, push(obj,A)) is performed.
  • If operand A is specified as a null ref, the instruction returns before push(obj,A) is performed; then push(obj,B) is also never performed-so the instruction does nothing. It does not matter whether or not B is a null ref because its associated calculation/operation (i.e. push to stack) is never performed.
  • If neither operand A nor operand B are specified as null refs, both/all operations-push(obj,A) followed by push(obj,B)-are performed.

SP-Double Ref

Format Description
101111110000 = 0xBF0 Double Stack Pop Reference

(translates to 1)

GOOL references of this format translate to the value 1 (i.e. invalid pointer to address 1). Specification of sp-double refs is exclusive to a few specific instructions. Most instructions do not account for translated references of this type. They assume that a translated reference will always point to a valid memory location. After these instructions translate an sp-double ref, they will attempt to access the memory at address 0x1-which lies in the kernel code segment-thus resulting in a trap.

For a few instructions, if [a specific] one of their operands is explicitly specified as an sp-double ref, the actual values for both that operand and some other operand will be implicitly popped (in 2 subsequent pops) from the object's stack; no actual translation of the reference is performed. Alternatively, if that operand is not specified as an sp-double ref, then it is a valid reference to its actual value (and will be translated to a pointer that can be dereferenced to resolve that value); the other operand will then instead take on some default value.

In the instruction table, parenthesis '()' around one of an instruction's explicit operands indicate that: if that operand is specified as an sp-double ref, the instruction will pop the actual values for the bracketed '[]' pair of implicit stack in operands including that operand, in the order listed; otherwise the operand is a valid reference to its actual value, and its paired operand-for example, P-will take on a default value of V, where P = V is listed as an explicit immediate operand for that instruction.

For example, the PATH instruction is listed with explicit GOOL in operands (A),B, explicit immediate in operand R = 0x100, and implicit stack in operands [R,A]. If operand A is specified as an sp-double ref, the values for R and A will be popped from the object's stack, in that order. Otherwise, R [rate of path travel] will take on a default value of 0x100 (1.0) and A's reference will be translated to resolve its value (by dereferencing, just as the majority of other instructions do for GOOL operands.)

Operand Name Table

Specification Format

A AAAAAAAAAAAA AAAA AAA (EVNT/EVNU/EVNB) AAA (VECA/VECB)
Name Value A Argument Count Argument Count Vector A Index
Specification Format B BBBBBBBBBBBB BBBBBBBBBBBB (PAD) BBBBBBBBBBBB (SPD) BBB
Name Value B Controller Buttons Base Speed Vector B Index
Specification Format C CCCCCCCCCCCC CCCCCC CCC CC
Name Color Value Spawn Count Vector C Index Conditional Check Type
Specification Format D DDDDDDDDDDDD DDDDDDDDDDDD (PRS) DDDD
Name Destination Wave Phase Directional Buttons
Specification Format E EEEEEEEEEEEE (NTRY) EEEEEEEEEEEE (EVNT/EVNU/EVNB) E (Crash 2 MOVC)
Name Entry Event External Executable Flag
Specification Format F FFFFFFFFFFFFFFFF FFFFFFFFFFFF FFFFFFF
Name Animation Frame Animation Descriptor Offset Animation Frame

Specification Format

H HH
Name Horizontal Flip

Specification Format

I IIIIIIIIIIIIII IIIIIIIIIIII IIIIIIIIII IIIIII
Name Immediate Code Location Global Variable Index Immediate Branch Offset Color Index

Specification Format

L LLLLLLLLLLLL LLL
Name Left Operand Object Link Index

Specification Format

P PPPPPPPPPPPP PPPP PP
Name Wave Period Primary Operation Subtype Primary Check Type

Specification Format

R RRRRRRRRRRRR RRRRRR
Name Right Operand Object Register Index

Specification Format

S SSSSSSSSSSSSSS SSSSSSSSSSSS SSSSSSSSS SSSSSS
Name State Source Animation Sequence Index Subtype

Specification Format

SSSSS SS
Name Secondary Operation Subtype Secondary Check Type

Specification Format

T TTTTTTTTTTTT TTTTTTTT TTTTTT TTT
Name Operation Subtype (Object) Type Time Operation Subtype

Specification Format

TT T
Name Operation Subtype Truth Invert Toggle

Specification Format

V VVVVVVVVVVVV VVVV VVVV (SNDB)
Name Velocity Variable Count Volume

GOOL Instruction Operations

TBD