Difference between revisions of "FF7/Field/Script/Opcodes/14 IFUB"

From Final Fantasy Inside
< FF7‎ | Field‎ | Script‎ | Opcodes
Jump to navigation Jump to search
my_wiki>Synergy Blades
m (If/Else Example)
m (8 revisions imported)
 
(6 intermediate revisions by 2 users not shown)
Line 6: Line 6:
 
{| border="1" cellspacing="1" cellpadding="3" style="border: 1px solid black; border-collapse: collapse;"
 
{| border="1" cellspacing="1" cellpadding="3" style="border: 1px solid black; border-collapse: collapse;"
 
! width="40" | 0x14
 
! width="40" | 0x14
! width="40" | ''B''
+
! width="50" | ''B1 / B2''
 
! width="40" | ''A''
 
! width="40" | ''A''
 
! width="40" | ''V''
 
! width="40" | ''V''
Line 15: Line 15:
 
==== Arguments ====
 
==== Arguments ====
  
* '''const UByte''' ''B'': Memory bank to access.
+
* '''const Bit[4]''' ''B1'': First memory bank to access.
* '''const UByte''' ''A'': Address of the value to retrieve.
+
* '''const Bit[4]''' ''B2'': Second memory bank to access.
* '''const UByte''' ''V'': Unsigned value to compare the retrieved value to.
+
* '''const UByte''' ''A'': Address, from the first bank, of the value to retrieve.
 +
* '''const UByte''' ''V'': Unsigned value to compare the retrieved value to, or address from the second bank of the value to retrieve.
 
* '''const UByte''' ''C'': Type of comparison to perform.
 
* '''const UByte''' ''C'': Type of comparison to perform.
 
* '''const UByte''' ''E'': Amount to jump if the comparison does not hold.
 
* '''const UByte''' ''E'': Amount to jump if the comparison does not hold.
Line 23: Line 24:
 
==== Description ====
 
==== Description ====
  
Performs a comparison between a retrieved value from memory (Bank and Address), and the unsigned byte Value given in the argument list. The type of comparison used is shown in the table below. If the comparison fails, the script pointer jumps forward by the amount specified in the final argument; the starting offset for this jump is just before the jump value argument itself. This is used to implement if/else functionality in scripts, as demonstrated below.
+
Performs a comparison between a retrieved values from memory at specific banks and addresses. If '''B2''' is zero, then the value retrieved from bank '''B1''', address '''A''' is compared with the value specified by '''V'''. If '''B2''' is not zero, then the value retrieved from bank '''B1''', address '''A''' is compared with the value retrieved from bank '''B2''', address '''V'''.
  
If the content of the 'if' block following the IFUB line is longer than 0xFF, the 'else' argument will also need to be longer than 0xFF, and hence you should use [[FF7/Field/Script/Opcodes/15 IFUBL|IFUBL]] instead. If the value or address is larger than 0xFF, you should use the [[FF7/Field/Script/Opcodes/18 IFUW|IFUW]]/[[FF7/Field/Script/Opcodes/19 IFUWL|IFUWL]] variants. If the value you are comparing is negative, you should use the [[FF7/Field/Script/Opcodes/16 IFSW|IFSW]]/[[FF7/Field/Script/Opcodes/17 IFSWL|IFSWL]] variants.
+
The type of comparison used is shown in the table below. If the comparison fails, the script pointer jumps forward by the amount specified in the final argument; the starting offset for this jump is just before the jump value argument itself. This, combined with an appropriate [[FF7/Field/Script/Opcodes/10 JMPF|jump forward]], is used to implement if/else functionality in scripts, as demonstrated below.
 +
 
 +
If the content of the 'if' block following the IFUB line is longer than 0xFF, the jump argument will also need to be longer than 0xFF, and hence the [[FF7/Field/Script/Opcodes/15 IFUBL|IFUBL]] variant is used instead. If the value to compare is larger than 0xFF, the [[FF7/Field/Script/Opcodes/18 IFUW|IFUW]]/[[FF7/Field/Script/Opcodes/19 IFUWL|IFUWL]] variants are used. If the value being compared is negative, the [[FF7/Field/Script/Opcodes/16 IFSW|IFSW]]/[[FF7/Field/Script/Opcodes/17 IFSWL|IFSWL]] variants are used.
  
 
==== Comparison Types ====
 
==== Comparison Types ====
Line 34: Line 37:
 
|-
 
|-
 
| align="center" | 0
 
| align="center" | 0
| A == B
+
| align="center" | A == B
 
|-
 
|-
 
| align="center" | 1
 
| align="center" | 1
| A != B
+
| align="center" | A != B
 
|-
 
|-
 
| align="center" | 2
 
| align="center" | 2
| A > B
+
| align="center" | A > B
 
|-
 
|-
 
| align="center" | 3
 
| align="center" | 3
| A < B
+
| align="center" | A < B
 
|-
 
|-
 
| align="center" | 4
 
| align="center" | 4
| A >= B
+
| align="center" | A >= B
 
|-
 
|-
 
| align="center" | 5
 
| align="center" | 5
| A <= B
+
| align="center" | A <= B
 
|-
 
|-
 
| align="center" | 6
 
| align="center" | 6
| A & B
+
| align="center" | A & B
 
|-
 
|-
 
| align="center" | 7
 
| align="center" | 7
| A ^ B
+
| align="center" | A ^ B
 
|-
 
|-
 
| align="center" | 8
 
| align="center" | 8
| A | B
+
| align="center" | A | B
 
|-
 
|-
 
| align="center" | 9
 
| align="center" | 9
| A & (1<<B)
+
| align="center" | A & (1<<B)
 
|-
 
|-
 
| align="center" | A
 
| align="center" | A
| !((A & (1<<B)))
+
| align="center" | !((A & (1<<B)))
 
|-
 
|-
 
|}
 
|}
 
  
 
==== If/Else Example ====
 
==== If/Else Example ====
  
In this example, if the value found is greater than 0x30, the script halts for a shorter period of time; otherwise, the script halts for a long period of time. Note how the jump forward placed before the longer WAIT ensures that on completion of the 'if' block, execution of the 'else' block is avoided. It jumps forward to just before the 0x200 WAIT, which it then executes, and returns.
+
In this example, if the value found is greater than 0x30, the script halts for a shorter period of time; otherwise, the script halts for a long period of time. Note how the jump forward placed before the longer WAIT (start of the required 'else' block) ensures that on completion of the 'if' block, execution of the 'else' block is avoided. It jumps forward to just before the 0x200 WAIT, which it then executes, and returns.
  
 
The 'else' block only executes if it is jumped into by the final argument of the IFUB argument list (thus avoiding the execution of the 'if' block). Once the 'else' block is executed, script execution just continues and the 0x200 WAIT and RET is executed. Since this is also executed by the 'if' block having jumped forward to skip the else block, this demonstrates that the two code paths converge. In C++ (below) this is the equivalent of the if/else block being completed.
 
The 'else' block only executes if it is jumped into by the final argument of the IFUB argument list (thus avoiding the execution of the 'if' block). Once the 'else' block is executed, script execution just continues and the 0x200 WAIT and RET is executed. Since this is also executed by the 'if' block having jumped forward to skip the else block, this demonstrates that the two code paths converge. In C++ (below) this is the equivalent of the if/else block being completed.

Latest revision as of 05:16, 23 May 2019

  • Opcode: 0x14
  • Short name: IFUB
  • Long name: If (Unsigned Byte)

Memory layout

0x14 B1 / B2 A V C E

Arguments

  • const Bit[4] B1: First memory bank to access.
  • const Bit[4] B2: Second memory bank to access.
  • const UByte A: Address, from the first bank, of the value to retrieve.
  • const UByte V: Unsigned value to compare the retrieved value to, or address from the second bank of the value to retrieve.
  • const UByte C: Type of comparison to perform.
  • const UByte E: Amount to jump if the comparison does not hold.

Description

Performs a comparison between a retrieved values from memory at specific banks and addresses. If B2 is zero, then the value retrieved from bank B1, address A is compared with the value specified by V. If B2 is not zero, then the value retrieved from bank B1, address A is compared with the value retrieved from bank B2, address V.

The type of comparison used is shown in the table below. If the comparison fails, the script pointer jumps forward by the amount specified in the final argument; the starting offset for this jump is just before the jump value argument itself. This, combined with an appropriate jump forward, is used to implement if/else functionality in scripts, as demonstrated below.

If the content of the 'if' block following the IFUB line is longer than 0xFF, the jump argument will also need to be longer than 0xFF, and hence the IFUBL variant is used instead. If the value to compare is larger than 0xFF, the IFUW/IFUWL variants are used. If the value being compared is negative, the IFSW/IFSWL variants are used.

Comparison Types

ID Comparison Performed
0 A == B
1 A != B
2 A > B
3 A < B
4 A >= B
5 A <= B
6 A & B
7 A ^ B
8 A | B
9 A & (1<<B)
A !((A & (1<<B)))

If/Else Example

In this example, if the value found is greater than 0x30, the script halts for a shorter period of time; otherwise, the script halts for a long period of time. Note how the jump forward placed before the longer WAIT (start of the required 'else' block) ensures that on completion of the 'if' block, execution of the 'else' block is avoided. It jumps forward to just before the 0x200 WAIT, which it then executes, and returns.

The 'else' block only executes if it is jumped into by the final argument of the IFUB argument list (thus avoiding the execution of the 'if' block). Once the 'else' block is executed, script execution just continues and the 0x200 WAIT and RET is executed. Since this is also executed by the 'if' block having jumped forward to skip the else block, this demonstrates that the two code paths converge. In C++ (below) this is the equivalent of the if/else block being completed.

IFUB (10,20,30,02,06)
WAIT (00,01)
JMPF (04)
WAIT (00,04)
WAIT (00,02)
RET ()

<cpp>

if(<10>[20] > 30)
{
 WAIT(100);
}
else
{
 WAIT(400);
}
WAIT(200);
return;

</cpp>