Chrono Trigger bytecode for location events
Joel Yliluoma http://iki.fi/bisqwit/
A = $1C00 of cur obj
If A == 7
{
// There are no more threads.
return and loop
}
X = (A << 7) + (obj number)
$7F0580[X] = word(0) // Mark the current thread as completed
<begin>
$1C00 of cur obj += 1
X += #$80
A = $7F0580[X]
<while A==0>
returns X as A (execution position)
return
In room initialization, this ends the initialization.
Otherwise, this opcode returns to the function of bigger priority (less urgent).
There are eight priority levels: 0 1 2 3 4 5 6 7.
If the current prio is 7 when opcode 00 is called, the op will essentially do the same as op B2.
If ( $1C01 for given obj != #0
Or $1100 for given obj & #$80
Or $1000 for given obj & #$80 )
{
return
}
$D9 = $1C00 for given obj // Current thread
$DF = hi nibble
If $DF == $D9
{
// Already executing the selected thread
return
}
If $DF >= $D9
{
// Verify that the thread is undefined
$E1 = ($DF << 7) + param1
A = $7F0580[$E1]
If(!zero)
{
// Already defined.
return
}
// Define it.
$E3 = (param0 << 4) + (lo nibble)*2
$7F0580[$E1] = given actor's pointer from $7F2001[$E3]
}
else
{
// Returning to a previous thread?
// Save current code position
$E1 = ($D9 << 7) + param1
$7F0580[$E1] = $1180 for given obj
// Load new position
$E3 = (param0 << 4) + (lo nibble)*2
$1180 for given obj = given actor's pointer from $7F2001[$E3]
$1C00 for given obj = $DF
$1A80 for given obj = 0 (moving flag)
$1A01 for given obj = 0 (magnitude)
}
return
This function meddles with ANOTHER object. It does not alter the execution of SELF.
If the priority of the current function < %prio
Saves the current execution position
Calls function %func in slot %prio
If the priority of the current function = %prio
Does not do anything
If the priority of the current function > %prio
Sets the function exit address to point to function %func
Only if not defined yet.
Note that bigger priority number = less urgent.
if ( $1C01 for given obj != #0 )
return, loop
If ( $1100 for given obj & #$80
Or $1000 for given obj & #$80 )
{
return
}
$D9 = $1C00 for given obj // Current thread
$DF = hi nibble
If $DF >= $D9
{
return, loop
}
// Save current code position
$E1 = ($D9 << 7) + param1
$7F0580[$E1] = $1180 for given obj
// Load new position
$E3 = (param1 << 4) + (lo nibble)*2
$1180 for given obj = given actor's pointer from $7F2001[$E3]
$1C00 for given obj = $DF
$1A80 for given obj = 0 (moving flag)
$1A01 for given obj = 0 (magnitude)
return
Same as op 02, except that if the given object is currently performing a more urgent task, this op will wait until it's completed and then transfer it to the new one.
$DB = param0 // object number
$D9 = $1C00 for given obj // Current thread
$DD = byte2 (param1 and param2)
$DF = param1
A = $7F0980 for _current_ object
If(A != 0)
{
If ( $1100 for given obj & #$80
Or $1000 for given obj & #$80 )
{
$7F0980 for _current_ object = 0
return
}
If $DF >= $D9:
return, loop
$7F0980 for _current_ obj = 0
return
}
If ( $1C01 for given obj != 0):
return, loop
If ( $1100 for given obj & #$80
Or $1000 for given obj & #$80 )
{
return
}
If $DF >= $D9:
return, loop
// Save current code position
$E1 = ($D9 << 7) + param0
$7F0580[$E1] = $1180 for given obj
// Load new position
$E3 = (param0 << 4) + (param2)*2
$1180 for given obj = given actor's pointer from $7F2001[$E3]
$1C00 for given obj = $DF
$1A80 for given obj = 0 (moving flag)
$1A01 for given obj = 0 (magnitude)
$7F0980 for _current_ obj = 1
return, loop
Same as op 03, except that it will wait until the target object returns from the function.
same as op 02, but uses object number from table.
same as op 03, but uses object number from table.
same as op 04, but uses object number from table.
For given obj,
Sets 1100=$80 (code execution: dead)
And 1A81=$00 (drawing mode: none)
puts 1600=0, 1601=0
Jumps forward by the given number of bytes.
Jumps backward by the given number of bytes.
puts 1600=1, 1601=0
puts 1600=2, 1601=0
puts 1600=3, 1601=0
puts 1600=0, 1601=0
puts 1600=1, 1601=0
param1 = $1801 for given obj (xcoord)
param2 = $1881 for given obj (ycoord)
Same as op 21, but gets object from $97 instead.
Assigns $1600 of given obj to param1.
Same as op 23, but gets object from $97 instead.
puts 1600=2, 1601=0
puts 1600=3, 1601=0
$DB = $1D0A >> 1
$DD = $1D0E >> 1
x = $1801 for given obj
y = $1881 for given obj
if (x - $DB) in (0, 1, >= 14)
or (y - $DD) in (0, 1, >= 13)
{
@ 668F
goto.
}
return
<evilpeer> Seems to be related to the moving Turrents on the Blackbird's Left Wing.
$1D3F = 0
$1D40 = 0
$1D92 = 0
$1D8F = word(param1*8)
$1D91 = word(param2*8)
purpose unknown
writes to 7E2200-> and 7E2000->
7E2200 is the 512-byte buffer of palettes.
DMA 7 writes it to PPU port 2122 (CGRAM) all the time.
calls function 4B2C.
if carry set, returns
if carry clear:
$0520[Y] = param0 // 0x40..0x5F.
$0521[Y] = param1
$0522[Y] = param2
$0523[Y] = 8
$0524[Y] = 0
$0525[Y] = param4
$0526[Y] = param0
$0527[Y] = ((param3 & 0xF0) >> 4) | (param3 & 0xF0)
$0528[Y] = ((param3 & 0x0F) << 4) | (param3 & 0x0F)
@4B2C: This function is referred often.
Y = 0
loop:
A = $0520[Y]
if(zero)
return carry-clear
Y += #$0C
:loop while Y<60
return carry-set
I guess this function allocates a new sprite slot for the particular object.
$0520 = %0 $0521 = %1 $0522 = %2
$0523 = 8 $0524 = 0 $0525 = %4
$0526 = %0
$0527 = double_hi_nibble(%3) $0528 = double_lo_nibble(%3)
See also op 88 40-4F
$54 |= #$80
$0F81 for current obj = (param0 * 2) & 0x0E
Y = ((param0*2) & 0x0E) << 4
X = $1400 for cur obj
Copy 18 bytes from $E4:X to $7E:(#$2102+Y)
Copy 18 bytes from $E4:X to $7E:(#$2302+Y)
return
See also op $88
// accesses $F2
// Checks for current status of button?
// mask $80
// mask $08
// mask $40
// mask $04
// mask $20
// accesses $F2
// mask $10
does something for $50, tests for bit #$02
does something for $50, tests for bit #$80
// button masks:
// $50: 02=left? 80=up?
// $51: 01=start, 02=select, 04=y, 08=b
// 10=r, 20=l, 40=x, 80=a
// accesses $51
// Checks if the button has been pressed?
// mask $80
// mask $08
// mask $40
// mask $04
// mask $20
// accesses $F1
// mask $10
"story line counter"
// firsts checks for a party member.
// if not a party member:
// puts $1100,X <- #$80 object is now dead
// puts $1101,X <- param0
// returns
// if member 1: puts $1100,X <- #$00
// if member 2: puts $1100,X <- #$01
// if member 3: puts $1100,X <- #$02
// puts $1C80,X <- #$00 movement props
// puts $1A81,X <- #$01 drawing mode
// puts $1B01,X <- #$01 solid
// puts $1101,X <- param0
// then continues in a complex way.
"story line counter"
// @41EC
// $8E <- objno
// A <- 1
// goto 421A
// addr |= $FF20[byte]
// addr |= $FF20[byte]
// addr &= $FF28[byte]
// addr_value |= (byte & 0x80) << 1
// addr |= $FF20[byte & 0x0F]
(geometrically "jump")
Waits until 1A01 becomes zero again.
Sets drawing "on"
Sets drawing "off"
Sets drawing "hide"
// does:
// A = ++$7E01F8
// %0 = $FE00[A & 0xFF]
// @421E
// if not a party member:
// puts $1100,X <- #$80 (marks object dead)
// puts $1101,X <- param
// returns
// if the given value is 0..6,
// sets $8D+param = current object number
// Then follows with the actual thing.
// This function is called by opcodes
// 57,5C,62,68,6A,6C and 6D.
//
If the specified character does not exist in current active party, the object is destroyed.
// @4476
// Somehow differs from op 80.
/*
$1100 for cur obj <- 3 (object identifier)
$1B01 for cur obj <- 1
$1101 for cur obj <- param0
$BF = param0 * 5
$A = $E4F001[$BF]
and so on.
*/
Uses function C04557 (A=4)
As for the second param:
The high bit has a special meaning:
If it's set, the $1600 is set as #6, otherwise #5. It could be a "monster niceness" flag.
The high bit generally seems to be set for monsters that don't automatically fight, such as Spekkio.
As for the lower bits:
Assume X = (val & 0x7F) + 1.
$0B88[X] = current object number.
Assume Y = (X & 0xFE)*16 + (X & 1)*8.
$0D00 for current obj = Y. // 008,020,028,040,048,...,7E0,7E8,800
$1700 for current obj = X*32. // 020,040,060,080,0A0,...,FC0,FE0,1000
The lower bits might be some kind of in-battle object number.
The values range between 03-0A. Setting it to 00-02 would probably be an error. But why the weird numbering?
Uses function C04557 (A=5)
@C046DF
Op_83: {8}A = $5
@C046E1 ;jsr $C04557
@C046E4 {8}A = $A
@C046E6 {8}[$4203] = A
@C046E9 {16}[$C7] = Y
@C046EB {16}X = [$6D]
@C046ED {8}A = $1
@C046EF {8}[$1B01+X] = A
@C046F2 {16}X = [$4216]
@C046F5 {16}[$BF] = X
@C046F7 {8}A = [$E4F601+X]
@C046FB ;nop (was: rep)
@C046FD {16}A = A & $FF
@C04700 {16}[$D9] = A
@C04703 {16}A = A+[$D9]
@C04705 {16}A = A adc [$D9]
@C04707 {16}Y = A
@C04708 {16}A = [{24}[$B2+Y]]
@C0470A {16}X = [$6D]
@C0470C {16}[$1380+X] = A
@C0470F ;nop (was: sep)
@C04711 {16}Y = Y+$1
@C04712 {16}Y = Y+$1
@C04713 {8}A = [{24}[$B2+Y]]
@C04715 {8}[$1300+X] = A
@C04718 {16}X = [$BF]
@C0471A {8}A = [$E4F602+X]
@C0471E {8}[$4202] = A
@C04721 {8}A = $18
@C04723 {8}[$4203] = A
@C04726 ;nop
@C04727 ;nop
@C04728 ;nop
@C04729 ;nop (was: rep)
@C0472B {16}A = [$4216]
@C0472F {16}A = A+$0
@C04732 {16}X = [$6D]
@C04734 {16}[$1400+X] = A
@C04737 ;nop (was: sep)
@C04739 {16}X = [$BF]
@C0473B {8}A = [$E4F603+X]
@C0473F ;nop (was: rep)
@C04741 {16}A = A & $FF
@C04744 {16}A = A * $2
@C04745 {16}Y = A
@C04746 {16}Y = Y+$1
@C04747 {16}Y = Y+$1
@C04748 {16}A = [{24}[$B5+Y]]
@C0474A {16}Y = Y-$1
@C0474B {16}Y = Y-$1
@C0474D {16}A = A-[{24}[$B5+Y]]
@C0474F {16}A = A / $2
@C04750 {16}A = A / $2
@C04751 {16}X = [$6D]
@C04753 {16}[$1480+X] = A
@C04756 {16}A = [{24}[$B5+Y]]
@C04758 {16}[$1500+X] = A
@C0475B {16}A = [{24}[$B8+Y]]
@C0475D {16}[$1580+X] = A
@C04760 ;nop (was: sep)
@C04762 {16}X = [$BF]
@C04764 {8}A = [$E4F604+X]
@C04768 {16}X = [$6D]
@C0476A {8}[$1201+X] = A
@C0476D {16}X = [$BF]
@C0476F {8}A = [$E4F600+X]
@C04773 {8}[$E3] = A
@C04775 {16}X = [$6D]
@C04777 {8}A = [$1101+X]
@C0477A {8}cmp A, $F8
@C0477C if not carry then goto $C04781 else goto $C04845
@C04781 ; from $C0477C
;jsr $C05C90
@C04784 if carry then goto $C04789 else goto $C047FE
@C04789 ; from $C04784
;nop (was: rep)
@C0478B {16}A = A & $FF
@C0478E {16}X = A
@C0478F {16}A = [$1280+X]
@C04792 {16}X = [$6D]
@C04794 {16}[$1280+X] = A
@C04797 ;nop (was: sep)
@C04799 ; from $C04840
; from $C04861
{16}X = [$C7]
@C0479B {8}A = [$7F2001+X]
@C0479F {8}[$E1] = A
@C047A1 {8}A = A & $7F
@C047A3 {8}A = A+$1
@C047A4 ;nop (was: sep)
@C047A6 {8}X = A
@C047A7 {8}A = [$6D]
@C047A9 {8}[$B88+X] = A
@C047AC {8}A = X
@C047AD ;nop (was: rep)
@C047AF {16}A = A & $FE
@C047B2 {16}A = A * $2
@C047B3 {16}A = A * $2
@C047B4 {16}A = A * $2
@C047B5 {16}A = A * $2
@C047B6 {16}[$D9] = A
@C047B8 {16}A = X
@C047B9 {16}A = A & $1
@C047BC {16}A = A * $2
@C047BD {16}A = A * $2
@C047BE {16}A = A * $2
@C047C0 {16}A = A+[$D9]
@C047C2 {8}[$D9] = X
@C047C4 {8}X = [$6D]
@C047C6 {16}[$D00+X] = A
@C047C9 ;nop (was: sep)
@C047CB {8}A = [$D9]
@C047CD ;nop (was: rep)
@C047CF {16}A = A & $FF
@C047D2 {16}A = A * $2
@C047D3 {16}A = A * $2
@C047D4 {16}A = A * $2
@C047D5 {16}A = A * $2
@C047D6 {16}A = A * $2
@C047D7 {16}[$1700+X] = A
@C047DA ;nop (was: sep)
@C047DC {8}A = [$1201+X]
@C047DF {8}A = A & $3
@C047E1 {8}cmp A, $3
@C047E3 if not carry then goto $C047EC else goto $C047E5
@C047EC ; from $C047E3
; from $C047E9
{8}A = [$E1]
@C047EE if not sign then goto $C047F7 else goto $C047F0
@C047F7 ; from $C047EE
; from $C047F4
;nop (was: rep)
@C047F9 {16}X = [$C7]
@C047FB {16}X = X+$1
@C047FD sec:rts
@C047F0 ; from $C047EE
{8}A = $6
@C047F2 {8}X = [$6D]
@C047F4 {8}[$1100+X] = A
@C047F4 goto $C047F7
@C047E5 ; from $C047E3
{8}X = [$6D]
@C047E7 {8}[$AE] = X
@C047E9 ;jsr $C0E12A
@C047E9 goto $C047EC
@C047FE ; from $C04784
{8}A = [$E3]
@C04800 ;nop (was: rep)
@C04802 {16}A = A & $FF
@C04805 {16}[$D9] = A
@C04808 {16}A = A+[$D9]
@C0480A {16}A = A adc [$D9]
@C0480C {16}Y = A
@C0480D {16}A = [{24}[$AF+Y]]
@C0480F {16}[$300] = A
@C04812 {16}A = [$71]
@C04814 {16}[$303] = A
@C04817 ;nop (was: sep)
@C04819 {16}Y = Y+$1
@C0481A {16}Y = Y+$1
@C0481B {8}A = [{24}[$AF+Y]]
@C0481D {8}[$302] = A
@C04820 {8}A = $7F
@C04822 {8}[$305] = A
@C04825 ;jsl $C30002
@C04829 ;nop (was: rep)
@C0482B {16}A = [$306]
@C0482F {16}A = A+[$71]
@C04831 {16}[$71] = A
@C04833 {16}cmp A, $8000
@C04836 if not sign then goto $C04840 else goto $C04838
@C04840 ; from $C04836
;nop (was: sep)
@C04840 goto $C04799
@C04838 ; from $C04836
;nop (was: sep)
@C0483A {16}COLOR = $7C1F; CRASH; END
@C04845 ; from $C0477C
{8}A = [$E3]
@C04847 ;nop (was: rep)
@C04849 {16}A = A & $FF
@C0484C {16}[$D9] = A
@C0484F {16}A = A+[$D9]
@C04851 {16}A = A adc [$D9]
@C04853 {16}Y = A
@C04854 {16}A = [{24}[$AF+Y]]
@C04856 {16}X = [$6D]
@C04858 {16}[$1280+X] = A
@C0485B ;nop (was: sep)
@C0485D {16}Y = Y+$1
@C0485E {16}Y = Y+$1
@C0485F {8}A = [{24}[$AF+Y]]
@C04861 {8}[$1200+X] = A
@C04861 goto $C04799
"npc solid props"
// $1000,X &= #$80
// $1000,X |= (param+1)
// $1001,X = $1000,X
@48C0
Y = $7F0B80 for cur obj
if Y & #$80
return
$7F0B80 for cur obj = #$FFFF
$0520[Y] = #$00
Y = ($0F81 for cur obj) << 4
X = ($1400 for cur obj)
Copy 18 bytes from $E4:X to $7E:(#$2102+Y)
Copy 18 bytes from $E4:X to $7E:(#$2302+Y)
return
Seems to load the object's palette from ROM and set it.
See also op $33.
@4919
call $4B2C
if carry set:
return
$7F0B80 for cur obj = Y
$0520[Y] = param0 // the 0x20,0x30 byte.
$0521[Y] = param3 + (($0F81 for cur obj) << 3) + 0x80
$0522[Y] = param2
$0524[Y] = 0
$0525[Y] = param1
return
$0520 = 0x20 $0521 = %3+paletteptr $0522 = %2
$0524 = 0 $0525 = %1
$0520 = 0x30 $0521 = %3+paletteptr $0522 = %2
$0524 = 0 $0525 = %1
@4970
call $4B2C
if carry set:
return
$0520[Y] = param0 & 0xF0 // the 0x40..0x5F byte.
$0521[Y] = param2 + (($0F81 for cur obj) << 3) + 0x80
$0522[Y] = param1
$0523[Y] = 8
$0524[Y] = 0
$0525[Y] = param4
$0526[Y] = param0 & 0x0F
$0527[Y] = ((param3 & 0xF0) >> 4) | (param3 & 0xF0)
$0528[Y] = ((param3 & 0x0F) << 4) | (param3 & 0x0F)
return
$0520 = %0 & 0xF0 $0521 = %2+paletteptr $0522 = %1
$0523 = 8 $0524 = 0 $0525 = %4
$0526 = %0 & 0x0F
$0527 = double_hi_nibble(%3) $0528 = double_lo_nibble(%3)
See also op 2E 40-5F
@49F8
$DB = (($0F81 for cur obj) << 3) + 0x80
$DD = ((param0 & 0x0F) + $DB) * 2
writes the blob into $7E2200+[$DB] and $7E2000+[$DB]
7E2200 is the 512-byte buffer of palettes.
DMA 7 writes it to PPU port 2122 (CGRAM) all the time.
"npc speed"
"npc speed"
// $1800,X = 80xx where xx=%0
// $1880,X = FFxx where xx=%1
> 03 - bottom half
> 0C - ???
> 30 - top half
> 40 - ???
> 80 - determines mode
if ( $1A01 for current object <> 0 )
return, loop this command.
if ( $1100 for given object & #$80 )
{
// if the object is removed?
call $568B
return
}
@5444
[$F2] = $1801 for given obj
[$F3] = $1881 for given obj
[$F0] = $1801 for current object
[$F1] = $1881 for current object
if ( abs([$F1] - [$F3]) <= 1
and abs([$F0] - [$F2]) <= 1 )
{
call $568B
return
}
@547C
$DB = $1D0A >> 1
$DD = $1D0E >> 1
if ($F0 - $DB) in (0, 1, >= 14)
or ($F1 - $DD) in (0, 1, >= 13)
{
@ 54B6
call $ABA2
...
return, loop
}
call $568B
return
.....
Sets drawing "on"
Sets drawing "off"
// included by op B5
/*
if ( $1A01 for current object <> 0 )
return, loop this command.
if ( $1100 for given object & #$80 )
{
// if the object is removed?
call $527B
return
}
@522D
[$F2] = $1801 for given obj
[$F3] = $1881 for given obj
[$F0] = $1801 for current object
[$F1] = $1881 for current object
if ( abs([$F1] - [$F3]) > 1
or abs([$F0] - [$F2]) > 1 )
{
@5281
call $ABA2 // calculate facing
.....
}
@5265
if ( $1C81 for current object & #$02 )
{
@526E
call $30B3
if carry set
{
@527B
call $5614
return, loop
}
}
call $568B
return
// included by op B6
/*
if ( $1A01 for current object <> 0 )
return, loop this command.
load the object number of the party leader
(from $97[param])
then goto op $94.
$97 is a word. The object number of first party member?
Bit $80 means inactive.
Ha! Indeed.
$9B is a word too - it refers to an object. (?)
But it's not used here.
*/
/* Execution continues (maybe) when the goal has been reached. */
Same as op 96 but coordinates are loaded from vars.
/* The same as op 94, except that 1A80
* plays some important part here. */
/*
if ( $1A80 for current object <> 0)
{
if ( $1A01 for current object <> 0 )
return, loop this command.
$1A80 for current object <- 0
return
}
if ( $1100 for given object & #$80 )
{
// if the object is removed?
$1A80 for given object <- 0
call $568B
return
}
@5370
[$F2] = $1801 for given obj
[$F3] = $1881 for given obj
[$F0] = $1801 for current object
[$F1] = $1881 for current object
if ( abs([$F1] - [$F3]) > 1
or abs([$F0] - [$F2]) > 1 )
{
@53CA
call $ABA2
.....
}
@53A8
if ( $1C81 for current object & #$02 )
{
@53B1
call $30B3
if carry set
{
@53C4
call $5614
return, loop
}
}
$1A80 for current object <- 0
call $568B
return
*/
Same as op 92, but with unknown difference
Same as op 9C, but from vars
Same as op 94, but with unknown difference
Same as op 9E, but from var (such as party member)
Used for Robo's following of party members at End of time
$1680 for cur obj = byte1
$1780 for cur obj = 1
$1601 for cur obj = 0
$1681 for cur obj = 0
$7F0B01 for cur obj = 0
op B3 is the same with byte1=0 (standing)
op B4 is the same with byte1=1 (walking)
The character starts repeating the given animation. The script continues executing.
See also ops B3 and B4.
Same as op B7 but with hardcoded parameter 1.
The character performs the given animation once. The script execution will continue after that.
$1301 for cur obj = byte1
$1601 for cur obj = 0
$1681 for cur obj = 0
if($1780 for cur obj <> 0)
{
$1680 for cur obj = #$FF
}
$1780 for cur obj = 3
return
The character will be set into the given frame of animation (still image).
Pauses for given number of cycles.
Actual length depends on object:
For party members, unit is (1/64)s, for others it is (1/16)s.
Your mileage may vary...
Puts 0 to $1680, $1681,
$1780,
$1601 and
$7F0B01 for cur obj.
Same as AA 00 except that writes 0 to $1780 instead of 1.
Runs one cycle of op B0.
Used when the script wants to set special conditions to how the characters can be controlled.
// referred by op B0
If $38 <> 0, returns.
A = $1100 for current obj. (party identity)
switch(A)
{
case 0: // member1
$1A01 for current obj = 1 (movement length)
call 9E29
A = $1600 for current obj (facing)
call 5B8D
if carry set:
call 3154
break;
case 1: // member2
$1A01 for current obj = 1
call A26B
break;
case 2: // member3
$1A01 for current obj = 1
call A2C2
break;
}
return, loop.
Analysis: This opcode lets the player control the party members.
If the object is member1, it responds to controls.
If the object is member2, it imitates member1 with delay.
If the object is member3, it imitates member2 with delay.
I did not disassemble those called functions, but I'm quite sure for this...
This command tells the task manager that this object wants now other objects to execute one cycle of whatever they are doing.
It is usually issued in loops, before rerunning the loop.
This function is used when the current function has nothing to do, but for some reason it doesn't want to [Return] to the lower priority routine.
It simply will [Yield] forever, without altering the object's state.
Same as op AA, but with hardcoded value 0 (neutral state)
Same as op AA, but with hardcoded value 1 (walking state)
Loops op 94 forever
Loops op 95 forever
A = $7F0B01 of cur obj
If(A > 0)
{
--A
If(A == 0)
{
// end loop.
$7F0B01 of cur obj = 0
$1601 of cur obj = 0
$1681 of cur obj = 0
if($1600 of cur obj == #$FF)
{
$1680 of cur obj = #0
$1780 of cur obj = 0
}
else
{
$1780 of cur obj = 1
}
return // end loop.
}
// wait until the animation frame has changed.
if(byte1 == $1781 of cur obj)
{
return, loop
}
}
$1781 of cur obj = byte1
$1681 of cur obj = 0
$1601 of cur obj = 0
if($1780 of cur obj == 0)
{
$1680 of cur obj = #$FF
}
$1780 of cur obj = #2
$7F0B01 of cur obj = byte2 + 1
return, loop
The character performs the given animation %1 times. The script execution will continue after that.
Same as op AD, but with hardcoded value 4
Same as op AD, but with hardcoded value 8
Same as op AD, but with hardcoded value 16
Same as op AD, but with hardcoded value 32
%line = line number
%target = where answer will be stored
%line = line number
%target = where answer will be stored
%line = line number
%target = where answer will be stored
Adds an item from the given location
Shops, name entries and such.
Known flag bits:
8000 = auto-regroup
4000 = map music
2000 = can lose
0080 = no run
0020 = pre-scripted events (attract mode)
0002 = menu at bottom
0001 = no win pose
Moves the party members to the given positions. Writes to 1180...
Causes members 2 and 3 to follow member 1 again. Writes to 1180...
%2: 7654321076543210: stored to $0C. (x and y?)
%0: 7654321076543210
^^^^^^^^^: stored to $0A.
^ ^^^^ : stored to $0E. (b000zzzz)
%2: 7654321076543210: stored to $02. (x and y?)
%0: 7654321076543210
^^^^^^^^^: stored to $00.
^ ^^^^ : stored to $04. (b000zzzz)
Same as op DD, but puts $1E = 1
Same as E1, but puts $1E = 1
Waits until [$17] & 0x80 = 0.
%2: 7654321076543210: stored to $14 (x and y?)
%0: 7654321076543210
^^^^^^^^^: stored to $12.
^ ^^^^ : stored to $16. (b000zzzz)
Sets $17 |= 0x80
Stores $19 = 0x0F
%2: 7654321076543210: stored to $14. (x and y?)
%0: 7654321076543210
^^^^^^^^^: stored to $12.
^ ^^^^ : stored to $16. (b000zzzz)
Waits for vrefresh.
Calls 0B4E.
Sets $05 = 0x0000
Sets $07 = 0x0002
Sets $09 = [$04]
Sets $00 = [$12]
Sets $02 = [$14]
Sets $04 = [$16]
Then restarts the scene (S=0x6FF, goto C0005D).
Same as E0, except the values are loaded from given memory locations.
Op DC: pokes to $0A, $0C, $0E - that's all
Op DD: pokes to $00, $02, $04 - that's all
Op E0: pokes to $12, $14, $16 - waits [$17], writes $17 |= 0x80, $19 = 0x0F, that's all.
Op E1: pokes to $12, $14, $16 waits vrefresh
pokes to $00, $02, $04, $05, $07, $09
Op DE: [$1E=1], then op DD.
Op DF: [$1E=1], then op E1.
"explore mode"
// Pokes the parameters to $3E,$40,$42,$44 and calls $AF4E.
// Pokes the parameters to $3E,$40,$42,$44
// then puts (f & 7) to $45 and does [$17] |= 0x20.
Command E8 pokes $1E00..$1E02 as 18:a:80 and calls a sound function
Command EA pokes $1E00..$1E01 as 10:a
and stores a into $7E29AE
and calls a sound function
Command EA pokes $1E00..$1E03 as 81:l:r:FF
calls a sound function
then pokes $1E00..$1E02 as 82:00:FF
and calls a sound function.
Command EC pokes $1E00..$1E02 as a:b:c and calls a sound function.
Merely op F9 and op FA combined.
/* calls C28004,A=6 */
/* calls C28004,A=7 */
/*
$F4 = byte1
$7F1CE8 = byte1
$C7 = pos
$F0 = 0
$F6 = 0
$F7 = 0
<begin>
pos = [$C7]
$F1 = next byte (high part of $F0)
A = next byte
$C7 = pos
A(word) = ( word.A - word.$F0 ) / byte.$F4
X = [$F6]
[$7F1CF9+X] = word.A
[$7F1CE9+X] = word.$F0
[$F6] = X+2
<loop 8 times>
[$39] = 6
X = [$C7]
The table 7F1CF9 is referred by function at C024A7.
It does adds the first (F9) value to the second (E9).
Therefore, F9 is the speed of change and E9 is the counter.
But why such pointless math with constant values? No idea.
If you want to test it, see Lucca's wondershot scene. She
invokes this event there.
Here is C++ code that simulates this opcode:
unsigned char divider = Stream[0];
for(unsigned pos=1, c=0; c<8; ++c)
{
signed short B = Stream[pos++] << 8;
signed short A = Stream[pos++] << 8;
A = (A-B) / divider;
printf("%d %d\n", F0, A);
}
*/
//sets $39=1, $3A=paramword, $3D=parambyte $3C=0
// >> black circle that opens similar to a portal and covers the entire screen (DNL)
//sets $39=4, $3A=paramword, $3D=parambyte $3C=0
//Calls a Mode 7 scene.
//Causes data at 0x031513 to be decompressed.
//A few values:
// 0x00: - highway race
// 0x01: - none
// 0x02: - title screen
// 0x03: - top of black omen, "blurs" into view (Does Not Load new graphics, may not be visible)
// 0x04: - lavos falls to earth
// 0x0A: - fireworks
// 0x0C: - credits over moving star background
// 0x0D: - programmer's ending credits
// 0x25: - lavos summoned to 600AD (DNL)
// 0x66: - Epoch, first person view
// 0x67: - world globe exploding, "But the future refused to change"
// 0x68: - world globe, "But the future refused to change" (short version)
// 0x69: - attract mode highway race
// 0x80: - long wormhole (first warp to 600 A.D.)
// 0x81: - normal wormhole
// 0x82: - quick wormhole
// 0x89: - wormhole to lavos
// 0x91: sets $39 = 2
// 0x92: may sometimes not progress
- the screen wipe effect used during attract mode (left to right)
// 0x93: may sometimes not progress
- the screen wipe effect used during attract mode (right to left, open)
// 0x94: may sometimes not progress
- left to right wipe (close)
// 0x95: may sometimes not progress
- right to left wipe (close)
// 0x96: does not return (resets the system?)
- Reset (see Castle Magus Inner Sanctum)
// 0x98: sets $39 = 5
- used by Taban during Moonlight Parade ending
// 0x99: sets $39 = 7
- used during Death Peak summit sequence, no noticable effect
// 0x9A: sets $39 = 9
- used after Crono revived in Death Peak sequence
// 0x9B: sets $39 = 0xB
- Massive Portal (see Castle Magus Inner Sanctum)
// 0x9C: sets $39 = 0xE
- Beam upward (Sunstone) (MAYBE)
// 0x9D: sets $54 &= ~2
// 0x9E: if $39==0, sets to 0xC. loops if $39!=0xD.
- Reality Distortion (see Castle Magus Inner Sanctum)
// 0x9F: calls C28004,A=8
- used in Tesseract
// 0xA0, 0xA1: seems like it halts the system
// 0xA2, 0xA3: seems like it halts the system
Opcode counter
# of opcodes to execute in this loop
Index of the currently executing object
Number of objects in the scene
related to palette
?
bitmask of unknown purpose (#$80 is a bit, lower bits are value)
maybe a copy of 1000 (see op 87)
Identity as a party member
// If bit $80 is set, the object is dead
// and its code will not be interpreted.
// #0: member1
// #1: member2
// #2: member3
// #3: out-party PC
// #4: NPC
// #5: monster
// #6: monster, not willing to fight
Identity as a player character
// #0: crono
// #1: marle
// and so on
object's current code pointer
?
?
static animation? (like sleeping)
Pointer to palette in ROM (offset only, page E4)
?
possibly a 'facing is up to date' flag
current animation
possibly a 'animation is up to date' flag
monster-related
?flag
?
?flag for x-coord
?flag for y-coord
?
?
Speed of movement
Length of movement in script ticks
Appears to be a 'is moving?' flag
Allocated? Drawing mode? 1=on, 0=off, $80=hide
?flag
?
?
Priority 0 code pointer (begins as 0)
Priority 1 code pointer (begins as 0)
Priority 2 code pointer (begins as 0)
Priority 3 code pointer (begins as 0)
Priority 4 code pointer (begins as 0)
Priority 5 code pointer (begins as 0)
Priority 6 code pointer (begins as 0)
Priority 7 code pointer (begins as 0)
flag used by opcode $04
Saved code pointer (see op $88)
RAM for the script
Possibly a 'dialog active' flag
Pause counter
'Result' of various tests
used by op B7
Current pose number
The event script data
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18