/// <summary> /// Builds this command collection from a subroutine's binary data. /// </summary> /// <param name="offset">The starting offset of the subroutine's binary data.</param> private void ParseSubroutine(int offset) { switch (Opcode) { case 0x09: // Jump to address int length = 0; while ((offset & 0xFFFF) < 0xFFFF) { // These are unusual cases, seems this is the only way if (offset == 0x356076) { break; } if (offset == 0x356087) { break; } if (offset == 0x3560A9) { break; } if (offset == 0x3560CD) { break; } if (offset == 0x3560FE) { break; } if (offset == 0x356131) { break; } if (offset == 0x356152) { break; } if (offset == 0x35617A) { break; } if (offset == 0x3561AD) { break; } if (offset == 0x3561E0) { break; } if (offset == 0x356213) { break; } if (offset == 0x35624B) { break; } if (offset == 0x3A8A68) { break; } if (offset == 0x3A8AC0) { break; } if (offset == 0x3A8C8A) { break; } if ((offset & 0xFF0000) == 0x3A0000 && offset < 0x3A60D0) { break; } if (offset < ROM.Length - 2) { length = ScriptEnums.GetCommandLength(ROM[offset], ROM[offset + 1]); } else { length = ScriptEnums.GetCommandLength(ROM[offset], 0); } var temp = new Command(Bits.GetBytes(ROM, offset, length), offset, Script, this); Commands.Add(temp); if (ROM[offset] == 0x07 || // End animation packet ROM[offset] == 0x09 || // Jump to address (thus ending this) ROM[offset] == 0x11 || // End subroutine ROM[offset] == 0x5E) // End sprite subroutine { break; } offset += length; } break; case 0x10: goto case 0x09; case 0x5D: goto case 0x09; case 0x64: if (Script.AMEM > 0x10) { Script.AMEM = 0; offset = (offset & 0xFF0000) + Bits.GetShort(ROM, offset); } else { offset = (offset & 0xFF0000) + Bits.GetShort(ROM, offset + (Script.AMEM * 2)); } goto case 0x09; case 0x68: if (Script.AMEM >= 0x40) { Script.AMEM = 0; offset = (offset & 0xFF0000) + Bits.GetShort(ROM, offset); } else { offset = (offset & 0xFF0000) + Bits.GetShort(ROM, offset + (Script.AMEM * 2)); } // if (offset == 0x356919 || offset == 0x356969) { offset += 2; } else { offset = (offset & 0xFF0000) + Bits.GetShort(ROM, offset + Data[3]); } goto case 0x09; default: if (Opcode >= 0x24 && Opcode <= 0x2B) { offset = (offset & 0xFF0000) + Bits.GetShort(Data, 4); goto case 0x09; } break; } }
/// <summary> /// Builds this script's command collection from the ROM buffer. /// </summary> public void ParseScript() { int bank = 0x350000; int start = 0; switch (Set) { case Set.MonsterSpell: start = 0x1026; break; case Set.MonsterEntrance: start = 0x2128; break; case Set.MonsterAttack: start = 0x1493; break; case Set.Item: start = 0xC761; break; case Set.AllySpell: start = 0xC992; break; case Set.Weapon: start = 0xECA2; break; case Set.BattleEvent: start = 0x6004; bank = 0x3A0000; break; } if (Set == Set.MonsterBehavior) { this.BaseOffset = this.behaviorOffsets[Index]; } else { this.BaseOffset = bank + Bits.GetShort(rom, bank + start + Index * 2); } // int offset = BaseOffset, length = 0; if (Set == Set.BattleEvent) { offset = BaseOffset + 2; if (Index == 22) { offset = BaseOffset + 4; } if (Index == 70) { offset = BaseOffset + 6; } if (Index == 85) { offset = BaseOffset + 6; } } this.Commands = new List <Command>(); while (offset < rom.Length) { if (offset == 0x3A6BA1) // Another annoying rare case { break; } // if (offset + 1 < rom.Length) { length = ScriptEnums.GetCommandLength(rom[offset], rom[offset + 1]); } else { length = ScriptEnums.GetCommandLength(rom[offset], 0); } var command = new Command(Bits.GetBytes(rom, offset, length), offset, this, null); // Memory modification commands switch (command.Opcode) { case 0x20: case 0x21: if ((command.Param1 & 0x0F) == 0) { AMEM = command.Data[2]; } break; case 0x2C: case 0x2D: if ((command.Param1 & 0x0F) == 0) { AMEM += command.Data[2]; } break; case 0x2E: case 0x2F: if ((command.Param1 & 0x0F) == 0) { AMEM -= command.Data[2]; } break; case 0x30: case 0x31: if ((command.Param1 & 0x0F) == 0) { AMEM++; } break; case 0x32: case 0x33: if ((command.Param1 & 0x0F) == 0) { AMEM--; } break; case 0x34: case 0x35: if ((command.Param1 & 0x0F) == 0) { AMEM = 0; } break; case 0x6A: case 0x6B: if ((command.Param1 & 0x0F) == 0) { AMEM = (byte)(command.Data[2] - 1); } break; } Commands.Add(command); // Termination commands if (rom[offset] == 0x07 || // end animation packet rom[offset] == 0x09 || // jump directly to address (thus ending this) rom[offset] == 0x11 || // end subroutine rom[offset] == 0x5E) // end sprite subroutine { break; } // offset += length; } }