diff options
author | Paul Gilbert | 2010-11-19 10:23:33 +0000 |
---|---|---|
committer | Paul Gilbert | 2010-11-19 10:23:33 +0000 |
commit | 16ee411187608220e936b366bfa8afb5da5bce19 (patch) | |
tree | 9a3492f050c95b3f6cb0888551d197d311c84cfe /tools | |
parent | 763ddd220361e9764b19ccbe05be80ce5f897d5f (diff) | |
download | scummvm-rg350-16ee411187608220e936b366bfa8afb5da5bce19.tar.gz scummvm-rg350-16ee411187608220e936b366bfa8afb5da5bce19.tar.bz2 scummvm-rg350-16ee411187608220e936b366bfa8afb5da5bce19.zip |
TOOLS: Added create_mads tool for MADS/M4 engine
svn-id: r54363
Diffstat (limited to 'tools')
-rw-r--r-- | tools/create_mads/Makefile | 4 | ||||
-rw-r--r-- | tools/create_mads/dists/msvc9/create_mads.sln | 20 | ||||
-rw-r--r-- | tools/create_mads/dists/msvc9/create_mads.vcproj | 187 | ||||
-rw-r--r-- | tools/create_mads/main.cpp | 130 | ||||
-rw-r--r-- | tools/create_mads/module.mk | 14 | ||||
-rw-r--r-- | tools/create_mads/parser.cpp | 942 | ||||
-rw-r--r-- | tools/create_mads/parser.h | 31 | ||||
-rw-r--r-- | tools/create_mads/scripts/rex_nebular.txt | 2243 |
8 files changed, 3571 insertions, 0 deletions
diff --git a/tools/create_mads/Makefile b/tools/create_mads/Makefile new file mode 100644 index 0000000000..c2776f5d17 --- /dev/null +++ b/tools/create_mads/Makefile @@ -0,0 +1,4 @@ +# $Id$ + +all: + g++ -I../.. main.cpp parser.cpp -o create_mads diff --git a/tools/create_mads/dists/msvc9/create_mads.sln b/tools/create_mads/dists/msvc9/create_mads.sln new file mode 100644 index 0000000000..5ddd18cffe --- /dev/null +++ b/tools/create_mads/dists/msvc9/create_mads.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "create_mads", "create_mads.vcproj", "{0332F6FD-D511-4AF6-ABCC-24A85F1489A4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0332F6FD-D511-4AF6-ABCC-24A85F1489A4}.Debug|Win32.ActiveCfg = Debug|Win32 + {0332F6FD-D511-4AF6-ABCC-24A85F1489A4}.Debug|Win32.Build.0 = Debug|Win32 + {0332F6FD-D511-4AF6-ABCC-24A85F1489A4}.Release|Win32.ActiveCfg = Release|Win32 + {0332F6FD-D511-4AF6-ABCC-24A85F1489A4}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/tools/create_mads/dists/msvc9/create_mads.vcproj b/tools/create_mads/dists/msvc9/create_mads.vcproj new file mode 100644 index 0000000000..1f33faa418 --- /dev/null +++ b/tools/create_mads/dists/msvc9/create_mads.vcproj @@ -0,0 +1,187 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9.00" + Name="create_mads" + ProjectGUID="{0332F6FD-D511-4AF6-ABCC-24A85F1489A4}" + RootNamespace="create_mads" + Keyword="Win32Proj" + TargetFrameworkVersion="131072" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="Debug" + IntermediateDirectory="Debug" + ConfigurationType="1" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalOptions="/wd4996" + Optimization="0" + AdditionalIncludeDirectories="../../../../" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + UsePrecompiledHeader="0" + WarningLevel="3" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="$(OutDir)/create_mads.exe" + LinkIncremental="2" + IgnoreDefaultLibraryNames="libc.lib;libcmt.lib" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(OutDir)/create_mads.pdb" + SubSystem="1" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="Release" + IntermediateDirectory="Release" + ConfigurationType="1" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalOptions="/wd4996" + Optimization="3" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" + UsePrecompiledHeader="0" + WarningLevel="3" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="$(OutDir)/create_mads.exe" + LinkIncremental="1" + IgnoreDefaultLibraryNames="libc.lib;libcmt.lib" + GenerateDebugInformation="true" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <File + RelativePath="..\..\main.cpp" + > + </File> + <File + RelativePath="..\..\parser.cpp" + > + </File> + <File + RelativePath="..\..\parser.h" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/tools/create_mads/main.cpp b/tools/create_mads/main.cpp new file mode 100644 index 0000000000..26ae2a7558 --- /dev/null +++ b/tools/create_mads/main.cpp @@ -0,0 +1,130 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// HACK to allow building with the SDL backend on MinGW +// see bug #1800764 "TOOLS: MinGW tools building broken" +#ifdef main +#undef main +#endif // main + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "parser.h" + +#define BUFFER_SIZE 8192 + +void link(const char *destFilename, char **srcFilenames, int srcCount) { + if (srcCount <= 0) + return; + + FILE *destFile = fopen(destFilename, "wb"); + if (!destFile) + return; + unsigned int v = 0; + const char *headerStr = "MADS"; + int fileOffset = 4 * (srcCount + 2); + + // Write header bit + fwrite(headerStr, 1, 4, destFile); + for (int i = 0; i <= srcCount; ++i) + fwrite(&v, 1, 4, destFile); + + // Set up buffer for copying + void *tempBuffer = malloc(BUFFER_SIZE); + + // Loop through copying each source file and setting it's file offset in the header + for (int i = 0; i < srcCount; ++i) { + // Add any extra padding to ensure that each file starts on a paragraph boundary + if ((fileOffset % 16) != 0) { + v = 0; + while ((fileOffset % 16) != 0) { + fwrite(&v, 1, 1, destFile); + ++fileOffset; + } + } + + FILE *srcFile = fopen(srcFilenames[i], "rb"); + if (!srcFile) { + printf("Could not locate file '%s'\n", srcFilenames[i]); + break; + } + + // Set the starting position of the file + fseek(destFile, 4 + (i * 4), SEEK_SET); + fwrite(&fileOffset, 1, 4, destFile); + + // Move back to the end of the destination and copy the source file contents over + fseek(destFile, 0, SEEK_END); + while (!feof(srcFile)) { + int bytesRead = fread(tempBuffer, 1, BUFFER_SIZE, srcFile); + fwrite(tempBuffer, 1, bytesRead, destFile); + fileOffset += bytesRead; + } + + fclose(srcFile); + } + + fclose(destFile); + free(tempBuffer); + printf("Done.\n"); +} + +int main(int argc, char *argv[]) { + if (argc == 1) { + printf("%s - ScummVM MADS Game script compiler v 1.0\n\n", argv[0]); + printf("Parameters: %s src_filename.txt [dest_filename.bin] - Compiles a script text file to an output binary\t", argv[0]); + printf("\t%s /link mads.dat filename1.bin [filename2.bin ..] - Joins one or more compiled Bin files to make\n", argv[0]); + printf("an output suitable for running in ScummVM.\n\n"); + } else if (!strcmp(argv[1], "/link")) { + // Link intermediate files into a final mads.dat file + if (argc < 4) + printf("Insufficient parameters\n"); + else + link(argv[2], &argv[3], argc - 3); + + } else { + // Compile a file + char buffer[256]; + const char *destFilename = buffer; + if (argc >= 3) + destFilename = argv[2]; + else { + // Use the source filename, but change the extension to '.bin' + strcpy(buffer, argv[1]); + char *p = buffer + strlen(buffer) - 1; + while ((p >= buffer) && (*p != '.')) --p; + if (p > buffer) + // Change the extension + strcpy(p, ".bin"); + } + + // Compile the specified source file + bool result = Compile(argv[1], destFilename); + return result ? 0 : 1; + } + + return 0; +}
\ No newline at end of file diff --git a/tools/create_mads/module.mk b/tools/create_mads/module.mk new file mode 100644 index 0000000000..17722951d5 --- /dev/null +++ b/tools/create_mads/module.mk @@ -0,0 +1,14 @@ +# $URL$ +# $Id$ + +MODULE := tools/create_mads/create_mads + +MODULE_OBJS := \ + main.o \ + parser.o + +# Set the name of the executable +TOOL_EXECUTABLE := create_mads + +# Include common rules +include $(srcdir)/rules.mk diff --git a/tools/create_mads/parser.cpp b/tools/create_mads/parser.cpp new file mode 100644 index 0000000000..be0d78f988 --- /dev/null +++ b/tools/create_mads/parser.cpp @@ -0,0 +1,942 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define MAX_SOURCE_LINE_LENGTH 256 +#define MAX_TOKEN_STRING_LENGTH MAX_SOURCE_LINE_LENGTH +#define MAX_DIGIT_COUNT 20 +#define MAX_SYMBOLS 1024 +#define MAX_SUBROUTINES 1024 +#define MAX_SUBROUTINE_SIZE 4096 +#define MAX_SUBROUTINE_JUMPS 256 + +#define OPSIZE8 0x40 ///< when this bit is set - the operand size is 8 bits +#define OPSIZE16 0x80 ///< when this bit is set - the operand size is 16 bits +#define OPSIZE32 0x00 ///< when no bits are set - the operand size is 32 bits + +#define VERSION 1 + +enum CharCode { + LETTER, DIGIT, SPECIAL, EOF_CODE, EOL_CODE +}; + +enum TokenCode { + NO_TOKEN, WORD, NUMBER, IDENTIFIER, END_OF_FILE, END_OF_LINE, + RW_DEFINE, RW_COLON, RW_SUB, RW_END, RW_OPCODE, + ERROR +}; + +enum LiteralType { + INTEGER_LIT +}; + +struct Literal { + LiteralType type; + union { + int integer; + } value; +}; + +struct SymbolEntry { + char symbol[MAX_TOKEN_STRING_LENGTH]; + char value[MAX_TOKEN_STRING_LENGTH]; +}; + +struct SubEntry { + char name[MAX_TOKEN_STRING_LENGTH]; + int fileOffset; +}; + +struct JumpSource { + char name[MAX_TOKEN_STRING_LENGTH]; + int line_number; + int offset; +}; + +struct JumpDest { + char name[MAX_TOKEN_STRING_LENGTH]; + int offset; +}; + +enum Opcodes { + OP_HALT = 0, OP_IMM = 1, OP_ZERO = 2, OP_ONE = 3, OP_MINUSONE = 4, OP_STR = 5, OP_DLOAD = 6, + OP_DSTORE = 7, OP_PAL = 8, OP_LOAD = 9, OP_GLOAD = 10, OP_STORE = 11, OP_GSTORE = 12, + OP_CALL = 13, OP_LIBCALL = 14, OP_RET = 15, OP_ALLOC = 16, OP_JUMP = 17, OP_JMPFALSE = 18, + OP_JMPTRUE = 19, OP_EQUAL = 20, OP_LESS = 21, OP_LEQUAL = 22, OP_NEQUAL = 23, OP_GEQUAL = 24, + OP_GREAT = 25, OP_PLUS = 26, OP_MINUS = 27, OP_LOR = 28, OP_MULT = 29, OP_DIV = 30, + OP_MOD = 31, OP_AND = 32, OP_OR = 33, OP_EOR = 34, OP_LAND = 35, OP_NOT = 36, OP_COMP = 37, + OP_NEG = 38, OP_DUP = 39, + TOTAL_OPCODES = 40 +}; + +typedef unsigned char byte; + +const unsigned char EOF_CHAR = (unsigned char)255; +const unsigned char EOL_CHAR = (unsigned char)254; + +/*----------------------------------------------------------------------*/ +/* Reserved words tables */ +/*----------------------------------------------------------------------*/ + +enum OpcodeParamType {OP_NO_PARAM, OP_IMM_PARAM, OP_TRANSFER_PARAM}; + +struct OpcodeEntry { + const char *str; + OpcodeParamType paramType; +}; + +OpcodeEntry OpcodeList[OP_DUP + 1] = { + {"HALT", OP_NO_PARAM}, {"IMM", OP_IMM_PARAM}, {"ZERO", OP_NO_PARAM}, {"ONE", OP_NO_PARAM}, + {"MINUSONE", OP_NO_PARAM}, {"STR", OP_IMM_PARAM}, {"DLOAD", OP_IMM_PARAM}, {"DSTORE", OP_IMM_PARAM}, + {"PAL", OP_IMM_PARAM}, {"LOAD", OP_IMM_PARAM}, {"GLOAD", OP_IMM_PARAM}, {"STORE", OP_IMM_PARAM}, + {"GSTORE", OP_IMM_PARAM}, {"CALL", OP_IMM_PARAM}, {"LIBCALL", OP_IMM_PARAM}, {"RET", OP_NO_PARAM}, + {"ALLOC", OP_IMM_PARAM}, {"JUMP", OP_TRANSFER_PARAM}, {"JMPFALSE", OP_TRANSFER_PARAM}, + {"JMPTRUE", OP_TRANSFER_PARAM}, {"EQUAL", OP_NO_PARAM}, {"LESS", OP_NO_PARAM}, + {"LEQUAL", OP_NO_PARAM}, {"NEQUAL", OP_NO_PARAM}, {"GEQUAL", OP_NO_PARAM}, + {"GREAT", OP_NO_PARAM}, {"PLUS", OP_NO_PARAM}, {"MINUS", OP_NO_PARAM}, + {"LOR", OP_NO_PARAM}, {"MULT", OP_NO_PARAM}, {"DIV", OP_IMM_PARAM}, {"MOD", OP_NO_PARAM}, + {"AND", OP_NO_PARAM}, {"OR", OP_NO_PARAM}, {"EOR", OP_NO_PARAM}, {"LAND", OP_NO_PARAM}, + {"NOT", OP_NO_PARAM}, {"COMP", OP_NO_PARAM}, {"NEG", OP_NO_PARAM}, {"DUP", OP_NO_PARAM} +}; + + +const char *symbol_strings[] = {"#DEFINE", ":", "SUB", "END"}; + +/*----------------------------------------------------------------------*/ +/* Globals */ +/*----------------------------------------------------------------------*/ + +unsigned char ch; // Current input character +TokenCode token; // code of current token +Opcodes opcode; // Current instruction opcode +OpcodeParamType paramType; // Parameter type opcode expects +Literal literal; // Value of literal +int buffer_offset; // Char offset into source buffer +int level = 0; // current nesting level +int line_number = 0; // current line number + +char source_buffer[MAX_SOURCE_LINE_LENGTH]; // Source file buffer +char token_string[MAX_TOKEN_STRING_LENGTH]; // Token string +char *bufferp = source_buffer; // Source buffer ptr +char *tokenp = token_string; // Token string ptr + +int digit_count; // Total no. of digits in number +bool count_error; // Too many digits in number? + +FILE *source_file; +FILE *dest_file; +CharCode char_table[256]; + +SymbolEntry symbolTable[MAX_SYMBOLS]; +int symbolCount = 0; + +int game_number = 0; +int language = 0; + +int indexSize = 0; +int fileOffset = 0; +SubEntry subroutinesTable[MAX_SUBROUTINES]; +int subroutinesCount = 0; + +byte subroutineData[MAX_SUBROUTINE_SIZE]; +int subroutineSize = 0; + +JumpSource jumpSources[MAX_SUBROUTINE_JUMPS]; +int jumpSourceCount = 0; +JumpDest jumpDests[MAX_SUBROUTINE_JUMPS]; +int jumpDestCount = 0; + +#define char_code(ch) char_table[ch] + +void get_char(); +void get_token(); + +/*----------------------------------------------------------------------*/ +/* Miscellaneous support functions */ +/*----------------------------------------------------------------------*/ + +void strToUpper(char *string) { + while (*string) { + *string = toupper(*string); + ++string; + } +} + +void strToLower(char *string) { + while (*string) { + *string = tolower(*string); + ++string; + } +} + +int strToInt(const char *s) { + unsigned int tmp; + + if (!*s) + // No string at all + return 0; + else if (toupper(s[strlen(s) - 1]) == 'H') + // Hexadecimal string with trailing 'h' + sscanf(s, "%xh", &tmp); + else if (*s == '$') + // Hexadecimal string starting with '$' + sscanf(s + 1, "%x", &tmp); + else + // Standard decimal string + return atoi(s); + + return (int)tmp; +} + +/*----------------------------------------------------------------------*/ +/* Initialisation / De-initialisation code */ +/*----------------------------------------------------------------------*/ + +/** + * Open the input file for parsing + */ +void open_source_file(const char *name) { + if ((source_file = fopen(name, "r")) == NULL) { + printf("*** Error: Failed to open source file.\n"); + exit(0); + } + + // Fetch the first character + bufferp = ""; + get_char(); +} + +/** + * Close the source file + */ +void close_source_file() { + fclose(source_file); +} + +/** + * Initialises the scanner + */ +void init_scanner(const char *name) { + // Initialise character table + int ch; + for (ch = 0; ch < 256; ++ch) char_table[ch] = SPECIAL; + for (ch = '0'; ch <= '9'; ++ch) char_table[ch] = DIGIT; + for (ch = 'A'; ch <= 'Z'; ++ch) char_table[ch] = LETTER; + for (ch = 'a'; ch <= 'z'; ++ch) char_table[ch] = LETTER; + char_table[EOF_CHAR] = EOF_CODE; + char_table[EOL_CHAR] = EOL_CODE; + char_table[(int)'$'] = DIGIT; // Needed for hexadecimal number handling + + open_source_file(name); +} + +/** + * Shuts down the scanner + */ +void quit_scanner() { + close_source_file(); +} + +/*----------------------------------------------------------------------*/ +/* Output routines */ +/*----------------------------------------------------------------------*/ + + +/** + * Initialises the output + */ +void init_output(const char *destFilename) { + dest_file = fopen(destFilename, "wb"); + if (dest_file == NULL) { + printf("Could not open file for writing\n"); + exit(0); + } +} + +/** + * Closes the output file + */ +void close_output() { + fclose(dest_file); +} + +/** + * Writes a single byte to the output + */ +void write_byte(byte v) { + fwrite(&v, 1, 1, dest_file); + ++fileOffset; +} + +/** + * Writes a word to the output + */ +void write_word(int v) { + write_byte(v & 0xff); + write_byte((v >> 8) & 0xff); +} + +/** + * Writes a 32-bit value to the output + */ +void write_long(int v) { + write_byte(v & 0xff); + write_byte((v >> 8) & 0xff); + write_byte((v >> 16) & 0xff); + write_byte((v >> 24) & 0xff); +} + +/** + * Writes a sequence of bytes to the output + */ +void write_bytes(byte *v, int len) { + fwrite(v, 1, len, dest_file); + fileOffset += len; +} + +/** + * Writes a repeat sequence of a value to the output + */ +void write_byte_seq(byte v, int len) { + byte *tempData = (byte *)malloc(len); + memset(tempData, v, len); + write_bytes(tempData, len); + free(tempData); +} + +/** + * Writes out the header and allocates space for the symbol table + */ +void write_header() { + // Write out three bytes - game Id, language Id, and version number + if (game_number == 0) { + game_number = 1; + printf("No game specified, defaulting to Rex Nebular\n"); + } + write_byte(game_number); + + if (language == 0) { + language = 1; + printf("No language specified, defaulting to English\n"); + } + write_byte(language); + + write_byte(VERSION); + + // Write out space to later come back and store the list of subroutine names and offsets + if (indexSize == 0) { + indexSize = 4096; + printf("No index size specified, defaulting to %d bytes\n", indexSize); + } + write_byte_seq(0, indexSize - 3); + + fileOffset = indexSize; +} + +/** + * Goes back and writes out the subroutine list + */ +void write_index() { + fseek(dest_file, 3, SEEK_SET); + + int bytesRemaining = indexSize - 3; + for (int i = 0; i < subroutinesCount; ++i) { + int entrySize = strlen(subroutinesTable[i].name) + 5; + + // Ensure there is enough remaining space + if ((bytesRemaining - entrySize) < 0) { + printf("Index has exceeded allowable size.\n"); + token = ERROR; + } + + // Write out the name and the file offset + write_bytes((byte *)&subroutinesTable[i].name, strlen(subroutinesTable[i].name) + 1); + write_long(subroutinesTable[i].fileOffset); + } +} + +/*----------------------------------------------------------------------*/ +/* Processing routines */ +/*----------------------------------------------------------------------*/ + +int symbolFind() { + for (int i = 0; i < symbolCount; ++i) { + if (!strcmp(symbolTable[i].symbol, token_string)) + return i; + } + return -1; +} + +int subIndexOf() { + for (int i = 0; i < subroutinesCount; ++i) { + if (!strcmp(subroutinesTable[i].name, token_string)) + return i; + } + return -1; +} + +int jumpIndexOf(const char *name) { + for (int i = 0; i < jumpDestCount; ++i) { + if (!strcmp(jumpDests[i].name, name)) + return i; + } + return -1; +} + +void handle_define() { + // Read the variable name + get_token(); + if (token != IDENTIFIER) { + token = ERROR; + return; + } + + // Make sure it doesn't already exist + if (symbolFind() != -1) { + printf("Duplicate symbol encountered.\n"); + token = ERROR; + return; + } + + // Store the new symbol name + strcpy(symbolTable[symbolCount].symbol, token_string); + + // Get the value + get_token(); + if (token == END_OF_LINE) { + printf("Unexpected end of line.\n"); + token = ERROR; + } + if ((token != NUMBER) && (token != IDENTIFIER)) { + printf("Invalid define value.\n"); + token = ERROR; + } + if (token == ERROR) + return; + + // Handle special symbols + if (!strcmp(symbolTable[symbolCount].symbol, "GAME_ID")) { + // Specify game number + if (!strcmp(token_string, "REX")) + game_number = 1; + else + token = ERROR; + } else if (!strcmp(symbolTable[symbolCount].symbol, "LANGUAGE")) { + // Specify the language + if (!strcmp(token_string, "ENGLISH")) + language = 1; + else + token = ERROR; + } else if (!strcmp(symbolTable[symbolCount].symbol, "INDEX_BLOCK_SIZE")) { + // Specifying the size of the index + indexSize = strToInt(token_string); + } else { + // Standard symbol - save it's value + strcpy(symbolTable[symbolCount].value, token_string); + ++symbolCount; + } + + if (token == ERROR) + return; + + // Ensure the next symbol is the end of line + get_token(); + if (token != END_OF_LINE) { + printf("Extraneous information on line.\n"); + token = ERROR; + } +} + +/** + * Handles getting a parameter for an opcode + */ +void get_parameter() { + int nvalue; + + if (token == NUMBER) { + literal.value.integer = strToInt(token_string); + return; + } + + if (token != IDENTIFIER) + return; + + nvalue = symbolFind(); + if (nvalue != -1) { + // Found symbol, so get it's numeric value and return + token = NUMBER; + literal.value.integer = strToInt(symbolTable[nvalue].value); + return; + } + + // Check if the parameter is the name of an already processed subroutine + strToLower(token_string); + nvalue = subIndexOf(); + if (nvalue == -1) { + token = ERROR; + return; + } + + // Store the index (not the offset) of the subroutine to call + token = NUMBER; + literal.value.integer = nvalue; +} + +#define INC_SUB_PTR if (++subroutineSize == MAX_SUBROUTINE_SIZE) { \ + printf("Maximum allowable subroutine size exceeded\n"); \ + token = ERROR; \ + return; \ + } + +#define WRITE_SUB_BYTE(v) subroutineData[subroutineSize] = (byte)(v) + +/** + * Handles a single instruction within the sub-routine + */ +void handle_instruction() { + // Write out the opcode + WRITE_SUB_BYTE(opcode); + INC_SUB_PTR; + + get_token(); + + if (OpcodeList[opcode].paramType == OP_IMM_PARAM) { + get_parameter(); + + if (token != NUMBER) { + printf("Incorrect opcode parameter encountered\n"); + token = ERROR; + return; + } + + // Apply the correct opcode size to the previously stored opcode and save the byte(s) + if (literal.value.integer <= 0xff) { + subroutineData[subroutineSize - 1] |= OPSIZE8; + WRITE_SUB_BYTE(literal.value.integer); + INC_SUB_PTR; + } else if (literal.value.integer <= 0xffff) { + subroutineData[subroutineSize - 1] |= OPSIZE16; + WRITE_SUB_BYTE(literal.value.integer); + INC_SUB_PTR; + WRITE_SUB_BYTE(literal.value.integer >> 8); + INC_SUB_PTR; + + } else { + subroutineData[subroutineSize - 1] |= OPSIZE32; + int v = literal.value.integer; + for (int i = 0; i < 4; ++i, v >>= 8) { + WRITE_SUB_BYTE(v); + INC_SUB_PTR; + } + } + + get_token(); + } else if (OpcodeList[opcode].paramType == OP_TRANSFER_PARAM) { + + if (token != IDENTIFIER) { + printf("Incorrect opcode parameter encountered\n"); + token = ERROR; + return; + } + + // Check to see if it's a backward jump to an existing label + int idx = jumpIndexOf(token_string); + if (idx != -1) { + // It's a backwards jump whose destination is already known + if (jumpDests[idx].offset < 256) { + // 8-bit destination + subroutineData[subroutineSize - 1] |= OPSIZE8; + subroutineData[subroutineSize] = jumpDests[idx].offset; + INC_SUB_PTR; + } else { + // 16-bit destination + subroutineData[subroutineSize - 1] |= OPSIZE16; + INC_SUB_PTR; + subroutineData[subroutineSize] = jumpDests[idx].offset & 0xff; + INC_SUB_PTR; + subroutineData[subroutineSize] = (jumpDests[idx].offset >> 8) & 0xff; + } + } else { + // Unknown destination, so save it for later resolving + strcpy(jumpSources[jumpSourceCount].name, token_string); + jumpSources[jumpSourceCount].line_number = line_number; + jumpSources[jumpSourceCount].offset = subroutineSize; + if (++jumpSourceCount == MAX_SUBROUTINE_JUMPS) { + printf("Maximum allowable jumps size exceeded\n"); + token = ERROR; + return; + } + + // Store a 16-bit placeholder + subroutineData[subroutineSize - 1] |= OPSIZE16; + WRITE_SUB_BYTE(0); + INC_SUB_PTR; + WRITE_SUB_BYTE(0); + INC_SUB_PTR; + } + + get_token(); + } + + if (token != END_OF_LINE) + token = ERROR; +} + +/** + * Called at the end of the sub-routine, fixes the destination of any forward jump references + */ +void fix_subroutine_jumps() { + for (int i = 0; i < jumpSourceCount; ++i) { + // Scan through the list of transfer destinations within the script + int idx = jumpIndexOf(jumpSources[i].name); + if (idx == -1) { + token = ERROR; + line_number = jumpSources[i].line_number; + return; + } + + // Replace the placeholder bytes with the new destination + subroutineData[jumpSources[i].offset] = jumpDests[idx].offset & 0xff; + subroutineData[jumpSources[i].offset + 1] = (jumpDests[idx].offset >> 8) & 0xff; + } +} + +/** + * Handles parsing a sub-routine + */ +void handle_sub() { + // Get the subroutine name + get_token(); + if (token != IDENTIFIER) { + printf("Missing subroutine name.\n"); + token = ERROR; + return; + } + + strToLower(token_string); + if (subIndexOf() != -1) { + printf("Duplicate sub-routine encountered\n"); + token = ERROR; + return; + } + + // If this is the first subroutine, start writing out the data + if (subroutinesCount == 0) + write_header(); + + // Save the sub-routine details + strcpy(subroutinesTable[subroutinesCount].name, token_string); + subroutinesTable[subroutinesCount].fileOffset = fileOffset; + if (++subroutinesCount == MAX_SUBROUTINES) { + printf("Exceeded maximum allowed subroutine count\n"); + token = ERROR; + return; + } + + // Ensure the line end + get_token(); + if (token != END_OF_LINE) { + token = ERROR; + return; + } + + // Initial processing arrays + memset(subroutineData, 0, MAX_SUBROUTINE_SIZE); + subroutineSize = 0; + jumpSourceCount = 0; + jumpDestCount = 0; + + // Loop through the lines of the sub-routine + while (token != ERROR) { + get_token(); + + if (token == END_OF_LINE) continue; + if (token == RW_OPCODE) { + // Handle instructions + handle_instruction(); + + } else if (token == IDENTIFIER) { + // Save identifier, it's hopefully a jump symbol + strcpy(jumpDests[jumpDestCount].name, token_string); + get_token(); + if (token != RW_COLON) + token = ERROR; + else { + // Save the jump point + jumpDests[jumpDestCount].offset = subroutineSize; + + if (++jumpDestCount == MAX_SUBROUTINE_JUMPS) { + printf("Subroutine exceeded maximum allowable jump points\n"); + token = ERROR; + return; + } + + // Ensure it's the last value on the line + get_token(); + if (token != END_OF_LINE) + token = ERROR; + } + } else if (token == RW_END) { + // End of subroutine reached + get_token(); + if (token != ERROR) + fix_subroutine_jumps(); + write_bytes(&subroutineData[0], subroutineSize); + break; + + } else { + token = ERROR; + printf("Unexpected error\n"); + } + } +} + +/*----------------------------------------------------------------------*/ +/* Character routines */ +/*----------------------------------------------------------------------*/ + +/** + * Read the next line from the source file. + */ +bool get_source_line() { + if ((fgets(source_buffer, MAX_SOURCE_LINE_LENGTH, source_file)) != NULL) { + return true; + } + + return false; +} + +/** + * Set ch to the next character from the source buffer + */ +void get_char() { + // If at the end of current source line, read another line. + // If at end of file, set ch to the EOF character and return + if (*bufferp == '\0') { + if (!get_source_line()) { + ch = EOF_CHAR; + return; + } + bufferp = source_buffer; + buffer_offset = 0; + ++line_number; + ch = EOL_CHAR; + return; + } + + ch = *bufferp++; // Next character in the buffer + + if ((ch == '\n') || (ch == '\t')) ch = ' '; +} + +/** + * Skip past any blanks in the current location in the source buffer. + * Set ch to the next nonblank character + */ +void skip_blanks() { + while (ch == ' ') get_char(); +} + +/*----------------------------------------------------------------------*/ +/* Token routines */ +/*----------------------------------------------------------------------*/ + +bool is_reserved_word() { + for (int i = 0; i < 4; ++i) { + if (!strcmp(symbol_strings[i], token_string)) { + token = (TokenCode)(RW_DEFINE + i); + return true; + } + } + return false; +} + +bool is_opcode() { + for (int i = 0; i < TOTAL_OPCODES; ++i) { + if (!strcmp(OpcodeList[i].str, token_string)) { + token = RW_OPCODE; + opcode = (Opcodes)i; + paramType = OpcodeList[i].paramType; + return true; + } + } + return false; +} + +/** + * Extract a word token and set token to IDENTIFIER + */ +void get_word() { + // Extract the word + while ((char_code(ch) == LETTER) || (char_code(ch) == DIGIT) || (ch == '_')) { + *tokenp++ = ch; + get_char(); + } + + *tokenp = '\0'; + + strToUpper(token_string); + token = WORD; + if (!is_reserved_word() && !is_opcode()) token = IDENTIFIER; +} + +/** + * Extract a number token and set literal to it's value. Set token to NUMBER + */ +void get_number() { + int nvalue = 0; // Value of number + int digit_count = 0; // Total no. of digits in number */ + bool count_error = false;// Too many digits in number? + + do { + *tokenp++ = ch; + + if (++digit_count > MAX_DIGIT_COUNT) { + count_error = true; + break; + } + + get_char(); + } while ((char_code(ch) == DIGIT) || (toupper(ch) == 'X') || ((toupper(ch) >= 'A') && (toupper(ch) <= 'F'))); + + if (count_error) { + token = ERROR; + return; + } + + literal.type = INTEGER_LIT; + literal.value.integer = strToInt(token_string); + *tokenp = '\0'; + token = NUMBER; +} + +/** + * Extract a special token + */ +void get_special() { + *tokenp++ = ch; + if (ch == ':') { + token = RW_COLON; + get_char(); + return; + } else if (ch == '/') { + *tokenp++ = ch; + get_char(); + if (ch == '/') { + // Comment, so read until end of line + while ((ch != EOL_CHAR) && (ch != EOF_CHAR)) + get_char(); + token = END_OF_LINE; + return; + } + } + + // Extract the rest of the word + get_char(); + while ((char_code(ch) == LETTER) || (char_code(ch) == DIGIT)) { + *tokenp++ = ch; + get_char(); + } + *tokenp = '\0'; + + strToUpper(token_string); + if (token_string[0] == '@') + token = IDENTIFIER; + else if (!is_reserved_word()) + token = ERROR; +} + +/** + * Extract the next token from the source buffer + */ +void get_token() { + skip_blanks(); + tokenp = token_string; + + switch (char_code(ch)) { + case LETTER: get_word(); break; + case DIGIT: get_number(); break; + case EOL_CODE: { token = END_OF_LINE; get_char(); break; } + case EOF_CODE: token = END_OF_FILE; break; + default: get_special(); break; + } +} + +/** + * Handles processing a line outside of subroutines + */ +void process_line() { + if ((token == ERROR) || (token == END_OF_FILE)) return; + + switch (token) { + case RW_DEFINE: + handle_define(); + break; + case RW_SUB: + handle_sub(); + break; + case END_OF_LINE: + break; + default: + token = ERROR; + break; + } + + if (token == END_OF_LINE) { + get_token(); + } +} + +/*----------------------------------------------------------------------*/ +/* Interface methods */ +/*----------------------------------------------------------------------*/ + +/** + * Main compiler method + */ +bool Compile(const char *srcFilename, const char *destFilename) { + init_scanner(srcFilename); + init_output(destFilename); + + get_token(); + while ((token != END_OF_FILE) && (token != ERROR)) + process_line(); + + if (token != ERROR) { + write_index(); + } + + quit_scanner(); + + if (token == ERROR) + printf("Error encountered on line %d\n", line_number); + else + printf("Compilation complete\n"); + return token != ERROR; +} diff --git a/tools/create_mads/parser.h b/tools/create_mads/parser.h new file mode 100644 index 0000000000..d404e8395f --- /dev/null +++ b/tools/create_mads/parser.h @@ -0,0 +1,31 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef CREATE_MADS_PARSER +#define CREATE_MADS_PARSER + +bool Compile(const char *srcFilename, const char *destFilename); + +#endif diff --git a/tools/create_mads/scripts/rex_nebular.txt b/tools/create_mads/scripts/rex_nebular.txt new file mode 100644 index 0000000000..f177720398 --- /dev/null +++ b/tools/create_mads/scripts/rex_nebular.txt @@ -0,0 +1,2243 @@ +// MADS Script Engine auto-generated script file + +// Special #defines +#define INDEX_BLOCK_SIZE 8192 +#define GAME_ID REX +#define LANGUAGE ENGLISH + +// List of data variables +#define Scene_abortTimersMode2 1 +#define Scene_abortTimers 2 +#define Player_stepEnabled 3 +#define Scene_nextScene 4 +#define Scene_priorSceneId 5 +#define Player_playerPos_x 6 +#define Player_playerPos_y 7 +#define Player_direction 8 +#define Player_visible 9 +#define Scene_activeAnimation 10 +#define Animation_currentFrame 11 + +// Library function list +#define dialog_show 1 +#define SequenceList_remove 2 +#define start_reversible_sprite_sequence 3 +#define SequenceList_setAnimRange 4 +#define SequenceList_addSubEntry 5 +#define start_cycled_sprite_sequence 6 +#define quotes_get_pointer 7 +#define KernelMessageList_add 8 +#define SequenceList_unk3 9 +#define start_sound 10 +#define SceneLogic_formAnimName 11 +#define SpriteList_addSprites 12 +#define hotspot_activate 13 +#define DynamicHotspots_add 14 +#define SequenceList_setDepth 15 +#define quotes_load 16 +#define form_resource_name 17 +#define MadsScene_loadAnimation 18 +#define Action_isAction 19 +#define start_sprite_sequence3 20 +#define DynamicHotspots_remove 21 +#define object_is_present 22 +#define inventory_add 23 +#define dialog_picture_show 24 +#define object_is_in_inventory 25 + +// Script functions start here + +sub scene101_sub1 + ONE + DSTORE Scene_abortTimersMode2 // 2ecf2h + ZERO + DSTORE Player_stepEnabled // 2ecf8h + DLOAD Scene_abortTimers // 2ecfeh + STORE 0 + JUMP @2edc0 // 2ed01h +@2ed04: + DLOAD $546E // 2ed04h + STORE 0 + LOAD 0 + LIBCALL SequenceList_remove + ZERO + ZERO + IMM 6 // 2ed10h + DLOAD $5450 // 2ed12h + STORE 0 + IMM 3 + ZERO + LOAD 0 + LIBCALL start_reversible_sprite_sequence + STORE 0 // 2ed1ah + LOAD 0 // 2ed1fh + DSTORE $546E + IMM 21 + IMM 17 + LOAD 0 + LIBCALL SequenceList_setAnimRange + IMM 72 // 2ed2dh + DLOAD $546E // 2ed2fh + STORE 0 + ZERO + ZERO + LOAD 0 + LIBCALL SequenceList_addSubEntry + STORE 0 // 2ed36h + IMM 17 // 2ed3bh + LIBCALL start_sound + ZERO + ZERO + IMM 2 // 2ed49h + DLOAD $544A // 2ed4bh + STORE 0 + IMM 3 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2ed53h + LOAD 0 // 2ed58h + DSTORE $5468 + RET +@2ed5c: + ZERO + ZERO + ZERO + DLOAD $5450 // 2ed62h + STORE 0 + IMM 6 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2ed6ah + LOAD 0 // 2ed6fh + DSTORE $546E + IMM 17 // 2ed75h + IMM 17 + IMM 17 + LOAD 0 + LIBCALL SequenceList_setAnimRange + IMM 57 + LIBCALL quotes_get_pointer + ZERO + IMM 60 // 2ed90h + ZERO + ZERO + IMM $1110 + IMM 61 + IMM 143 + LIBCALL KernelMessageList_add + STORE 0 // 2ed9fh + IMM 120 + LIBCALL SequenceList_unk3 + STORE 0 // 2edaah + RET +@2edb0: + IMM $2785 + ZERO + LIBCALL dialog_show + MINUSONE + DSTORE Player_stepEnabled // 2edb9h + RET +@2edc0: + LOAD 0 // 2edc0h + DUP + STORE 4 + IMM 73 + DUP + STORE 5 + EQUAL + JMPTRUE @2edb0 // 2edc3h + LOAD 4 // 2edc5h + LOAD 5 + GREAT + JMPTRUE @2edd2 + LOAD 0 // 2edc7h + ZERO + NEQUAL + JMPTRUE @2edce // 2edc9h + JUMP @2ed04 // 2edcbh +@2edce: + LOAD 0 // 2edceh + IMM 72 + MINUS + STORE 0 + LOAD 0 // 2edd0h + STORE 4 + LOAD 4 + ZERO + EQUAL + JMPTRUE @2ed5c +@2edd2: + RET +end + + +sub low_rooms_entry_sound + DLOAD $5A00 // 2b48ch + ZERO + NEQUAL + JMPTRUE @2b49e // 2b491h + IMM 2 // 2b493h +@2b495: + LIBCALL start_sound + RET +@2b49e: + DLOAD Scene_nextScene // 2b49eh + STORE 0 + JUMP @2b4d8 // 2b4a1h +@2b4a4: + IMM 11 // 2b4a4h + JUMP @2b495 // 2b4a6h +@2b4a8: + IMM 12 // 2b4a8h + JUMP @2b495 // 2b4aah +@2b4ac: + IMM 3 // 2b4ach + LIBCALL start_sound + IMM 25 // 2b4b6h + JUMP @2b495 // 2b4b8h +@2b4ba: + DLOAD Scene_priorSceneId // 2b4bah + IMM 104 + LESS + JMPTRUE @2b4c8 // 2b4bfh + DLOAD Scene_priorSceneId // 2b4c1h + IMM 108 + LEQUAL + JMPTRUE @2b500 // 2b4c6h +@2b4c8: + IMM 10 // 2b4c8h + JUMP @2b495 // 2b4cah +@2b4cc: + IMM 13 // 2b4cch + JUMP @2b495 // 2b4ceh +@2b4d0: + IMM 3 // 2b4d0h + JUMP @2b495 // 2b4d2h +@2b4d4: + IMM 15 // 2b4d4h + JUMP @2b495 // 2b4d6h +@2b4d8: + LOAD 0 // 2b4d8h + IMM 101 + MINUS + STORE 0 + LOAD 0 // 2b4dbh + IMM 11 + GREAT + JMPTRUE @2b500 // 2b4deh + LOAD 0 // 2b4e0h + IMM 2 + MULT + LOAD 0 // 2b4e2h + LOAD 1 + STORE 0 +//--- Begin Jump Table --- + LOAD 1 + ZERO + EQUAL + JMPTRUE @2b4a4 + LOAD 1 + ONE + EQUAL + JMPTRUE @2b4a8 + LOAD 1 + IMM 2 + EQUAL + JMPTRUE @2b4ac + LOAD 1 + IMM 3 + EQUAL + JMPTRUE @2b4ba + LOAD 1 + IMM 4 + EQUAL + JMPTRUE @2b4ba + LOAD 1 + IMM 5 + EQUAL + JMPTRUE @2b4ba + LOAD 1 + IMM 6 + EQUAL + JMPTRUE @2b4ba + LOAD 1 + IMM 7 + EQUAL + JMPTRUE @2b4ba + LOAD 1 + IMM 8 + EQUAL + JMPTRUE @2b4cc + LOAD 1 + IMM 9 + EQUAL + JMPTRUE @2b4c8 + LOAD 1 + IMM 10 + EQUAL + JMPTRUE @2b4d0 + LOAD 1 + IMM 11 + EQUAL + JMPTRUE @2b4d4 +//--- End Jump Table --- +@2b500: + RET +end + + +sub scene101_enter + ONE + IMM 120 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2c985h + LOAD 0 // 2c98ah + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2c98eh + LOAD 0 // 2c993h + DSTORE $543C + IMM 2 + IMM 120 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2c99bh + LOAD 0 // 2c9a0h + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2c9a4h + LOAD 0 // 2c9a9h + DSTORE $543E + IMM 3 + IMM 120 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2c9b1h + LOAD 0 // 2c9b6h + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2c9bah + LOAD 0 // 2c9bfh + DSTORE $5440 + IMM 4 + IMM 120 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2c9c7h + LOAD 0 // 2c9cch + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2c9d0h + LOAD 0 // 2c9d5h + DSTORE $5442 + IMM 5 + IMM 120 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2c9ddh + LOAD 0 // 2c9e2h + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2c9e6h + LOAD 0 // 2c9ebh + DSTORE $5444 + IMM 6 + IMM 120 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2c9f3h + LOAD 0 // 2c9f8h + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2c9fch + LOAD 0 // 2ca01h + DSTORE $5446 + IMM 7 + IMM 120 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2ca09h + LOAD 0 // 2ca0eh + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2ca12h + LOAD 0 // 2ca17h + DSTORE $5448 + MINUSONE + IMM 109 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2ca1fh + LOAD 0 // 2ca24h + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2ca28h + LOAD 0 // 2ca2dh + DSTORE $544A + ONE + IMM 98 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2ca35h + LOAD 0 // 2ca3ah + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2ca3eh + LOAD 0 // 2ca43h + DSTORE $544C + IMM 2 + IMM 98 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2ca4bh + LOAD 0 // 2ca50h + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2ca54h + LOAD 0 // 2ca59h + DSTORE $544E + ZERO + IMM 97 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2ca60h + LOAD 0 // 2ca65h + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2ca69h + LOAD 0 // 2ca6eh + DSTORE $5450 + ONE + IMM 97 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2ca76h + LOAD 0 // 2ca7bh + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2ca7fh + LOAD 0 // 2ca84h + DSTORE $5452 + IMM 8 + IMM 120 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2ca8ch + LOAD 0 // 2ca91h + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2ca95h + LOAD 0 // 2ca9ah + DSTORE $5454 + ZERO + IMM 120 + LIBCALL SceneLogic_formAnimName + STORE 0 // 2caa1h + LOAD 0 // 2caa6h + STORE 1 + ZERO + LOAD 1 + LIBCALL SpriteList_addSprites + STORE 0 // 2caaah + LOAD 0 // 2caafh + DSTORE $5456 + IMM 25 // 2cab2h + ZERO + ZERO + DLOAD $543C // 2cab8h + STORE 0 + IMM 5 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2cac0h + LOAD 0 // 2cac5h + DSTORE $545A + ZERO + ONE + ZERO + DLOAD $543E // 2caceh + STORE 0 + IMM 4 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2cad6h + LOAD 0 // 2cadbh + DSTORE $545C + ZERO + IMM 2 // 2cae0h + ZERO + DLOAD $5440 // 2cae4h + STORE 0 + IMM 6 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2caech + LOAD 0 // 2caf1h + DSTORE $545E + IMM 70 // 2caf4h + IMM 7 + IMM 2 + LOAD 0 + LIBCALL SequenceList_addSubEntry + STORE 0 // 2cafch + IMM 60 // 2cb01h + ZERO + ZERO + DLOAD $5442 // 2cb07h + STORE 0 + IMM 10 + ZERO + LOAD 0 + LIBCALL start_reversible_sprite_sequence + STORE 0 // 2cb0fh + LOAD 0 // 2cb14h + DSTORE $5460 + ZERO + ONE + ZERO + DLOAD $5444 // 2cb1dh + STORE 0 + IMM 5 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2cb25h + LOAD 0 // 2cb2ah + DSTORE $5462 + ZERO + IMM 2 // 2cb2fh + ZERO + DLOAD $5446 // 2cb33h + STORE 0 + IMM 10 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2cb3bh + LOAD 0 // 2cb40h + DSTORE $5464 + ZERO + ZERO + ZERO + DLOAD $5448 // 2cb49h + STORE 0 + IMM 6 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2cb51h + LOAD 0 // 2cb56h + DSTORE $5466 + IMM 4 // 2cb59h + IMM 10 // 2cb5bh + ZERO + DLOAD $544C // 2cb5fh + STORE 0 + IMM 6 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2cb67h + LOAD 0 // 2cb6ch + DSTORE $546A + IMM 47 // 2cb6fh + IMM 32 // 2cb71h + ZERO + DLOAD $544E // 2cb75h + STORE 0 + IMM 6 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2cb7dh + LOAD 0 // 2cb82h + DSTORE $546C + ZERO + IMM 311 + LIBCALL hotspot_activate + ZERO + DSTORE $547E // 2cb8eh + DLOAD Scene_priorSceneId // 2cb94h + MINUSONE + EQUAL + JMPTRUE @2cba1 // 2cb99h + ZERO + GSTORE 10 // 2cb9bh +@2cba1: + DLOAD Scene_priorSceneId // 2cba1h + IMM $FFFE + EQUAL + JMPTRUE @2cbb4 // 2cba6h + IMM 100 // 2cba8h + DSTORE Player_playerPos_x + IMM 152 // 2cbaeh + DSTORE Player_playerPos_y +@2cbb4: + DLOAD Scene_priorSceneId // 2cbb4h + IMM 112 + EQUAL + JMPTRUE @2cbc9 // 2cbb9h + DLOAD Scene_priorSceneId // 2cbbbh + IMM $FFFE + NEQUAL + JMPTRUE @2cc36 // 2cbc0h + DLOAD $5476 // 2cbc2h + ZERO + EQUAL + JMPTRUE @2cc36 // 2cbc7h +@2cbc9: + IMM 161 // 2cbcfh + DSTORE Player_playerPos_x + IMM 123 // 2cbd5h + DSTORE Player_playerPos_y + IMM 9 // 2cbdbh + DSTORE Player_direction + ZERO + ZERO + ZERO + DLOAD $5450 // 2cbe7h + STORE 0 + ZERO + DSTORE Player_visible // 2cbech + IMM 3 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2cbf3h + LOAD 0 // 2cbf8h + DSTORE $546E + IMM 17 // 2cbfeh + IMM 17 + IMM 17 + LOAD 0 + LIBCALL SequenceList_setAnimRange + ZERO + IMM 71 + LIBCALL hotspot_activate + IMM 159 // 2cc0eh + IMM 84 // 2cc11h + IMM 33 // 2cc13h + IMM 36 // 2cc15h + MINUSONE + IMM 319 + IMM 71 + LIBCALL DynamicHotspots_add + STORE 0 // 2cc20h + LOAD 0 // 2cc25h + DSTORE $5478 + DLOAD Scene_priorSceneId // 2cc28h + IMM 112 + NEQUAL + JMPTRUE @2cc54 // 2cc2dh + CALL scene101_sub1 + JUMP @2cc54 // 2cc34h +@2cc36: + ZERO + ZERO + ZERO + DLOAD $5452 // 2cc3ch + STORE 0 + IMM 6 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2cc44h + LOAD 0 // 2cc49h + DSTORE $5470 + IMM 4 + LOAD 0 + LIBCALL SequenceList_setDepth +@2cc54: + ZERO + IMM 56 // 2cc56h + IMM 55 // 2cc58h + IMM 54 // 2cc5ah + IMM 57 // 2cc5ch + IMM 50 // 2cc5eh + IMM 49 // 2cc60h + LIBCALL quotes_load + STORE 0 // 2cc62h + LOAD 0 // 2cc6ah + DSTORE $5674 + GLOAD 10 // 2cc71h + ZERO + EQUAL + JMPTRUE @2ccb8 // 2cc76h + ZERO + ZERO + IMM 2 // 2cc7ch + MINUSONE + IMM 83 + IMM 101 + LIBCALL form_resource_name + STORE 0 // 2cc86h + LOAD 0 // 2cc8bh + STORE 1 + LOAD 1 + IMM 71 + LIBCALL MadsScene_loadAnimation + IMM 68 // 2cc95h + DSTORE Player_playerPos_x + IMM 140 // 2cc9bh + DSTORE Player_playerPos_y + IMM 4 // 2cca1h + DSTORE Player_direction + ZERO + DSTORE Player_visible // 2cca9h + ZERO + DSTORE Player_stepEnabled // 2ccach + ZERO + DSTORE $5482 // 2ccafh + IMM 30 // 2ccb2h + DSTORE $5484 +@2ccb8: + ZERO + DSTORE $5486 // 2ccb8h + CALL low_rooms_entry_sound + RET +end + + +sub scene101_step + DLOAD $56E4 // 2eb30h + STORE 0 + DLOAD $5486 // 2eb33h + LOAD 0 + EQUAL + JMPTRUE @2eb4e // 2eb37h + LOAD 0 // 2eb39h + DSTORE $5486 + LOAD 0 // 2eb3ch + ZERO + EQUAL + JMPTRUE @2eb44 // 2eb3eh + IMM 39 // 2eb40h + JUMP @2eb46 // 2eb42h +@2eb44: + IMM 11 // 2eb44h +@2eb46: + LIBCALL start_sound +@2eb4e: + DLOAD Scene_abortTimers // 2eb4eh + STORE 0 + JUMP @2eb92 // 2eb51h +@2eb54: + IMM 9 // 2eb54h + LIBCALL start_sound + JUMP @2eba0 // 2eb5eh +@2eb60: + ZERO + GSTORE 10 // 2eb60h + MINUSONE + DSTORE Player_visible // 2eb69h + MINUSONE + DSTORE Player_stepEnabled // 2eb6ch + DLOAD $56E8 // 2eb6fh + STORE 0 + DLOAD $542A // 2eb73h + STORE 2 + ZERO + STORE 1 // 2eb77h + LOAD 2 // 2eb7bh + LOAD 0 + MINUS + STORE 2 + LOAD 2 // 2eb7fh + DSTORE $57D0 + JUMP @2eba0 // 2eb87h +@2eb8a: + CALL scene101_sub1 + JUMP @2eba0 // 2eb8fh +@2eb92: + LOAD 0 // 2eb92h + IMM 70 + MINUS + STORE 0 + LOAD 0 // 2eb95h + STORE 4 + LOAD 4 + ZERO + EQUAL + JMPTRUE @2eb54 + LOAD 0 // 2eb97h + ONE + MINUS + STORE 0 + LOAD 0 // 2eb98h + STORE 4 + LOAD 4 + ZERO + EQUAL + JMPTRUE @2eb60 + LOAD 0 // 2eb9ah + ONE + MINUS + STORE 0 + LOAD 0 // 2eb9bh + STORE 4 + LOAD 4 + ZERO + EQUAL + JMPTRUE @2eb8a + LOAD 0 // 2eb9dh + ONE + MINUS + STORE 0 + LOAD 0 // 2eb9eh + STORE 4 + LOAD 4 + ZERO + EQUAL + JMPTRUE @2eb8a +@2eba0: + ZERO + STORE 0 // 2eba0h + LOAD 0 // 2eba3h + DLOAD Scene_activeAnimation + OR + ZERO + NEQUAL + JMPTRUE @2ebac // 2eba7h + JUMP @2ecf1 // 2eba9h +@2ebac: + DLOAD Animation_currentFrame // 2ebach + IMM 6 + LESS + JMPTRUE @2ebed // 2ebb1h + DLOAD $5482 // 2ebb3h + ZERO + NEQUAL + JMPTRUE @2ebed // 2ebb8h + DLOAD $5482 // 2ebbah + ONE + PLUS + DSTORE $5482 + IMM 49 + LIBCALL quotes_get_pointer + ZERO + IMM 240 // 2ebd2h + ZERO + ZERO + DLOAD $5484 // 2ebd9h + STORE 3 + IMM $1110 + LOAD 3 + IMM 63 + LIBCALL KernelMessageList_add + STORE 0 // 2ebe3h + DLOAD $5484 // 2ebe8h + IMM 14 + PLUS + DSTORE $5484 +@2ebed: + DLOAD Animation_currentFrame // 2ebedh + IMM 7 + LESS + JMPTRUE @2ec2e // 2ebf2h + DLOAD $5482 // 2ebf4h + ONE + NEQUAL + JMPTRUE @2ec2e // 2ebf9h + DLOAD $5482 // 2ebfbh + ONE + PLUS + DSTORE $5482 + IMM 54 + LIBCALL quotes_get_pointer + ZERO + IMM 240 // 2ec13h + ZERO + ZERO + DLOAD $5484 // 2ec1ah + STORE 3 + IMM $1110 + LOAD 3 + IMM 63 + LIBCALL KernelMessageList_add + STORE 0 // 2ec24h + DLOAD $5484 // 2ec29h + IMM 14 + PLUS + DSTORE $5484 +@2ec2e: + DLOAD Animation_currentFrame // 2ec2eh + IMM 10 + LESS + JMPTRUE @2ec6f // 2ec33h + DLOAD $5482 // 2ec35h + IMM 2 + NEQUAL + JMPTRUE @2ec6f // 2ec3ah + DLOAD $5482 // 2ec3ch + ONE + PLUS + DSTORE $5482 + IMM 55 + LIBCALL quotes_get_pointer + ZERO + IMM 240 // 2ec54h + ZERO + ZERO + DLOAD $5484 // 2ec5bh + STORE 3 + IMM $1110 + LOAD 3 + IMM 63 + LIBCALL KernelMessageList_add + STORE 0 // 2ec65h + DLOAD $5484 // 2ec6ah + IMM 14 + PLUS + DSTORE $5484 +@2ec6f: + DLOAD Animation_currentFrame // 2ec6fh + IMM 17 + LESS + JMPTRUE @2ecb0 // 2ec74h + DLOAD $5482 // 2ec76h + IMM 3 + NEQUAL + JMPTRUE @2ecb0 // 2ec7bh + DLOAD $5482 // 2ec7dh + ONE + PLUS + DSTORE $5482 + IMM 56 + LIBCALL quotes_get_pointer + ZERO + IMM 240 // 2ec95h + ZERO + ZERO + DLOAD $5484 // 2ec9ch + STORE 3 + IMM $1110 + LOAD 3 + IMM 63 + LIBCALL KernelMessageList_add + STORE 0 // 2eca6h + DLOAD $5484 // 2ecabh + IMM 14 + PLUS + DSTORE $5484 +@2ecb0: + DLOAD Animation_currentFrame // 2ecb0h + IMM 20 + LESS + JMPTRUE @2ecf1 // 2ecb5h + DLOAD $5482 // 2ecb7h + IMM 4 + NEQUAL + JMPTRUE @2ecf1 // 2ecbch + DLOAD $5482 // 2ecbeh + ONE + PLUS + DSTORE $5482 + IMM 50 + LIBCALL quotes_get_pointer + ZERO + IMM 240 // 2ecd6h + ZERO + ZERO + DLOAD $5484 // 2ecddh + STORE 3 + IMM $1110 + LOAD 3 + IMM 63 + LIBCALL KernelMessageList_add + STORE 0 // 2ece7h + DLOAD $5484 // 2ecech + IMM 14 + PLUS + DSTORE $5484 +@2ecf1: + RET +end + + +sub scene101_preaction + ZERO + IMM 384 // 2edd6h + IMM 3 // 2edd9h + LIBCALL Action_isAction + STORE 0 // 2eddbh + LOAD 0 // 2ede3h + ZERO + EQUAL + JMPTRUE @2eded // 2ede5h + MINUSONE + DSTORE $56F2 // 2ede7h +@2eded: + DLOAD $5476 // 2ededh + ZERO + NEQUAL + JMPTRUE @2edf7 // 2edf2h + JUMP @2eea9 // 2edf4h +@2edf7: + ZERO + IMM 3 // 2edf9h + LIBCALL Action_isAction + STORE 0 // 2edfbh + LOAD 0 // 2ee03h + ZERO + NEQUAL + JMPTRUE @2ee44 // 2ee05h + LOAD 0 // 2ee07h + IMM 71 // 2ee08h + LIBCALL Action_isAction + STORE 0 // 2ee0ah + LOAD 0 // 2ee12h + ZERO + NEQUAL + JMPTRUE @2ee44 // 2ee14h + LOAD 0 // 2ee16h + IMM 8 // 2ee17h + LIBCALL Action_isAction + STORE 0 // 2ee19h + LOAD 0 // 2ee21h + ZERO + NEQUAL + JMPTRUE @2ee44 // 2ee23h + LOAD 0 // 2ee25h + IMM 259 // 2ee26h + LIBCALL Action_isAction + STORE 0 // 2ee29h + LOAD 0 // 2ee31h + ZERO + NEQUAL + JMPTRUE @2ee44 // 2ee33h + LOAD 0 // 2ee35h + IMM 125 // 2ee36h + LIBCALL Action_isAction + STORE 0 // 2ee38h + LOAD 0 // 2ee40h + ZERO + EQUAL + JMPTRUE @2ee4a // 2ee42h +@2ee44: + ZERO + DSTORE $56F2 // 2ee44h +@2ee4a: + DLOAD $56F2 // 2ee4ah + ZERO + EQUAL + JMPTRUE @2eea9 // 2ee4fh + DLOAD Scene_abortTimers // 2ee51h + STORE 0 + LOAD 0 // 2ee54h + ZERO + EQUAL + JMPTRUE @2ee60 // 2ee56h + LOAD 0 // 2ee58h + ONE + MINUS + STORE 0 + LOAD 0 // 2ee59h + STORE 4 + LOAD 4 + ZERO + NEQUAL + JMPTRUE @2ee5e + JUMP @2eee0 // 2ee5bh +@2ee5e: + JUMP @2eea9 // 2ee5eh +@2ee60: + ZERO + DSTORE $56F4 // 2ee62h + ZERO + DSTORE Player_stepEnabled // 2ee65h + DLOAD $546E // 2ee68h + STORE 0 + LOAD 0 + LIBCALL SequenceList_remove + ZERO + ZERO + ONE + DLOAD $5450 // 2ee76h + STORE 0 + IMM 3 + ZERO + LOAD 0 + LIBCALL start_sprite_sequence3 + STORE 0 // 2ee7eh + LOAD 0 // 2ee83h + DSTORE $546E + ONE + ZERO + ZERO + LOAD 0 + LIBCALL SequenceList_addSubEntry + STORE 0 // 2ee8ch + DLOAD $546E // 2ee91h + STORE 0 + IMM 17 + ONE + LOAD 0 + LIBCALL SequenceList_setAnimRange + IMM 16 // 2ee9fh + LIBCALL start_sound +@2eea9: + DLOAD $547E // 2eea9h + ZERO + NEQUAL + JMPTRUE @2eeb3 // 2eeaeh + JUMP @2ef9f // 2eeb0h +@2eeb3: + ZERO + IMM 309 // 2eeb5h + LIBCALL Action_isAction + STORE 0 // 2eeb8h + LOAD 0 // 2eec0h + ZERO + EQUAL + JMPTRUE @2eec7 // 2eec2h + JUMP @2ef9f // 2eec4h +@2eec7: + LOAD 0 // 2eec7h + IMM 311 // 2eec8h + LIBCALL Action_isAction + STORE 0 // 2eecbh + LOAD 0 // 2eed3h + ZERO + EQUAL + JMPTRUE @2eeda // 2eed5h + JUMP @2ef9f // 2eed7h +@2eeda: + DLOAD Scene_abortTimers // 2eedah + STORE 0 + JUMP @2ef98 // 2eeddh +@2eee0: + MINUSONE + DSTORE Player_visible // 2eee9h + MINUSONE + DSTORE Player_stepEnabled // 2eeedh + MINUSONE + DSTORE $56F4 // 2eef1h + MINUSONE + IMM 71 + LIBCALL hotspot_activate + DLOAD $5478 // 2eefdh + STORE 0 + LOAD 0 + LIBCALL DynamicHotspots_remove + ZERO + ZERO + ZERO + DLOAD $5452 // 2ef0bh + STORE 0 + IMM 6 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2ef13h + LOAD 0 // 2ef18h + DSTORE $5470 + IMM 4 + LOAD 0 + LIBCALL SequenceList_setDepth + JUMP @2eea9 // 2ef23h +@2ef26: + DLOAD $56F2 // 2ef26h + ZERO + EQUAL + JMPTRUE @2ef9f // 2ef2bh + DLOAD $5472 // 2ef2dh + STORE 0 + LOAD 0 + LIBCALL SequenceList_remove + IMM 24 + LIBCALL object_is_present + STORE 0 // 2ef38h + ONE + STORE 4 // 2ef3dh + LOAD 0 + ONE + EQUAL + JMPFALSE @2ef42 + ZERO + STORE 4 +@2ef42: + LOAD 4 + STORE 0 + LOAD 0 // 2ef45h + IMM 13 + PLUS + STORE 0 + LOAD 0 // 2ef48h + DSTORE $5480 + ZERO + ZERO + ONE + LOAD 0 // 2ef51h + STORE 1 + LOAD 1 // 2ef53h + IMM 2 + MULT + IMM 6 + ZERO + ONE + LIBCALL start_sprite_sequence3 + STORE 0 // 2ef5eh + LOAD 0 // 2ef63h + DSTORE $5472 + ONE + ZERO + ZERO + LOAD 0 + LIBCALL SequenceList_addSubEntry + STORE 0 // 2ef6ch + ZERO + DSTORE Player_stepEnabled // 2ef71h + IMM 20 // 2ef77h + LIBCALL start_sound + RET +@2ef82: + MINUSONE + DSTORE Player_stepEnabled // 2ef82h + ZERO + DSTORE $547E // 2ef8ah + ZERO + IMM 311 + LIBCALL hotspot_activate + RET +@2ef98: + LOAD 0 // 2ef98h + ZERO + EQUAL + JMPTRUE @2ef26 // 2ef9ah + LOAD 0 // 2ef9ch + ONE + MINUS + STORE 0 + LOAD 0 // 2ef9dh + STORE 4 + LOAD 4 + ZERO + EQUAL + JMPTRUE @2ef82 +@2ef9f: + RET +end + + +sub scene101_actions + DLOAD $577A // 2efa0h + ZERO + EQUAL + JMPTRUE @2efae // 2efa5h + DLOAD 0 // 2efaah + STORE 0 + JUMP @2f28f +@2efae: + ZERO + IMM 204 // 2efb0h + IMM 13 // 2efb3h + LIBCALL Action_isAction + STORE 0 // 2efb5h + LOAD 0 // 2efbdh + ZERO + EQUAL + JMPTRUE @2efca // 2efbfh + IMM 102 // 2efc1h + DSTORE Scene_nextScene + JUMP @2f6b4 // 2efc7h +@2efca: + ZERO + IMM 71 // 2efcch + IMM 319 // 2efceh + LIBCALL Action_isAction + STORE 0 // 2efd1h + LOAD 0 // 2efd9h + ZERO + NEQUAL + JMPTRUE @2eff9 // 2efdbh + LOAD 0 // 2efddh + IMM 384 // 2efdeh + IMM 3 // 2efe1h + LIBCALL Action_isAction + STORE 0 // 2efe3h + LOAD 0 // 2efebh + ZERO + NEQUAL + JMPTRUE @2eff2 // 2efedh + JUMP @2f072 // 2efefh +@2eff2: + DLOAD $5476 // 2eff2h + ZERO + NEQUAL + JMPTRUE @2f072 // 2eff7h +@2eff9: + DLOAD $5476 // 2eff9h + ZERO + EQUAL + JMPTRUE @2f003 // 2effeh + JUMP @2f120 // 2f000h +@2f003: + DLOAD Scene_abortTimers // 2f003h + STORE 0 + LOAD 0 // 2f006h + ZERO + EQUAL + JMPTRUE @2f016 // 2f008h + LOAD 0 // 2f00ah + ONE + MINUS + STORE 0 + LOAD 0 // 2f00bh + STORE 4 + LOAD 4 + ZERO + EQUAL + JMPTRUE @2f068 + LOAD 0 // 2f00dh + ONE + MINUS + STORE 0 + LOAD 0 // 2f00eh + STORE 4 + LOAD 4 + ZERO + NEQUAL + JMPTRUE @2f013 + JUMP @2f0b4 // 2f010h +@2f013: + JUMP @2f072 // 2f013h +@2f016: + DLOAD $5470 // 2f016h + STORE 0 + LOAD 0 + LIBCALL SequenceList_remove + ZERO + ZERO + ONE + DLOAD $5450 // 2f024h + STORE 0 + IMM 3 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2f02ch + LOAD 0 // 2f031h + DSTORE $546E + IMM 17 + ONE + LOAD 0 + LIBCALL SequenceList_setAnimRange + ONE + DLOAD $546E // 2f041h + STORE 0 + IMM 10 + IMM 2 + LOAD 0 + LIBCALL SequenceList_addSubEntry + STORE 0 // 2f04ah + IMM 2 // 2f04fh + DLOAD $546E // 2f051h + STORE 0 + ZERO + ZERO + LOAD 0 + LIBCALL SequenceList_addSubEntry + STORE 0 // 2f058h + ZERO + DSTORE Player_stepEnabled // 2f05fh + ZERO + DSTORE Player_visible // 2f062h + DLOAD 0 // 2f065h + STORE 0 + JUMP @2f6b4 +@2f068: + IMM 16 // 2f068h + LIBCALL start_sound +@2f072: + ZERO + IMM 309 // 2f074h + IMM 13 // 2f077h + LIBCALL Action_isAction + STORE 0 // 2f079h + LOAD 0 // 2f081h + ZERO + NEQUAL + JMPTRUE @2f09a // 2f083h + LOAD 0 // 2f085h + IMM 309 // 2f086h + IMM 6 // 2f089h + LIBCALL Action_isAction + STORE 0 // 2f08bh + LOAD 0 // 2f093h + ZERO + NEQUAL + JMPTRUE @2f09a // 2f095h + JUMP @2f1cc // 2f097h +@2f09a: + DLOAD $547E // 2f09ah + ZERO + EQUAL + JMPTRUE @2f0a4 // 2f09fh + JUMP @2f1cc // 2f0a1h +@2f0a4: + DLOAD Scene_abortTimers // 2f0a4h + STORE 0 + LOAD 0 // 2f0a7h + ZERO + EQUAL + JMPTRUE @2f126 // 2f0a9h + LOAD 0 // 2f0abh + ONE + MINUS + STORE 0 + LOAD 0 // 2f0ach + STORE 4 + LOAD 4 + ZERO + NEQUAL + JMPTRUE @2f0b1 + JUMP @2f176 // 2f0aeh +@2f0b1: + JUMP @2f6b4 // 2f0b1h +@2f0b4: + ZERO + ZERO + ZERO + DLOAD $5450 // 2f0bah + STORE 0 + IMM 3 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2f0c2h + LOAD 0 // 2f0c7h + DSTORE $546E + IMM 17 // 2f0cdh + IMM 17 + IMM 17 + LOAD 0 + LIBCALL SequenceList_setAnimRange + MINUSONE + DSTORE Player_stepEnabled // 2f0d7h + ZERO + IMM 71 + LIBCALL hotspot_activate + IMM 159 // 2f0e6h + IMM 84 // 2f0e9h + IMM 33 // 2f0ebh + IMM 36 // 2f0edh + MINUSONE + IMM 319 + IMM 71 + LIBCALL DynamicHotspots_add + STORE 0 // 2f0f8h + LOAD 0 // 2f0fdh + DSTORE $5478 + ZERO + IMM 384 // 2f102h + IMM 3 // 2f105h + LIBCALL Action_isAction + STORE 0 // 2f107h + LOAD 0 // 2f10fh + ZERO + NEQUAL + JMPTRUE @2f116 // 2f111h + JUMP @2f6b4 // 2f113h +@2f116: + ZERO + DSTORE Scene_abortTimers // 2f116h + JUMP @2f072 // 2f11ch +@2f120: + DLOAD 0 // 2f123h + STORE 0 + JUMP @2f28f +@2f126: + IMM 24 + LIBCALL object_is_present + STORE 0 // 2f129h + ONE + STORE 4 // 2f12eh + LOAD 0 + ONE + EQUAL + JMPFALSE @2f133 + ZERO + STORE 4 +@2f133: + LOAD 4 + STORE 0 + LOAD 0 // 2f136h + IMM 13 + PLUS + STORE 0 + LOAD 0 // 2f139h + DSTORE $5480 + ZERO + ZERO + ONE + LOAD 0 // 2f142h + STORE 1 + LOAD 1 // 2f144h + IMM 2 + MULT + IMM 6 + ZERO + ONE + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2f14fh + LOAD 0 // 2f154h + DSTORE $5472 + ONE + ZERO + ZERO + LOAD 0 + LIBCALL SequenceList_addSubEntry + STORE 0 // 2f15dh + ZERO + DSTORE Player_stepEnabled // 2f162h + IMM 20 // 2f168h +@2f16a: + LIBCALL start_sound + JUMP @2f6b4 // 2f172h +@2f176: + DLOAD $5472 // 2f176h + STORE 0 + LOAD 0 + LIBCALL SequenceList_remove + ZERO + ZERO + ZERO + DLOAD $5480 // 2f184h + STORE 1 + LOAD 1 // 2f188h + IMM 2 + MULT + IMM 6 + ZERO + ONE + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2f193h + LOAD 0 // 2f198h + DSTORE $5472 + IMM $FFFE // 2f19eh + IMM $FFFE + IMM $FFFE + LOAD 0 + LIBCALL SequenceList_setAnimRange + MINUSONE + DSTORE Player_stepEnabled // 2f1a8h + MINUSONE + DSTORE $547E // 2f1abh + IMM 24 + LIBCALL object_is_present + STORE 0 // 2f1b1h + LOAD 0 // 2f1b6h + ZERO + NEQUAL + JMPTRUE @2f1bd // 2f1b8h + JUMP @2f6b4 // 2f1bah +@2f1bd: + MINUSONE + IMM 311 + LIBCALL hotspot_activate + JUMP @2f6b4 // 2f1c8h +@2f1cc: + ZERO + IMM 311 // 2f1ceh + IMM 4 // 2f1d1h + LIBCALL Action_isAction + STORE 0 // 2f1d3h + LOAD 0 // 2f1dbh + ZERO + NEQUAL + JMPTRUE @2f1f1 // 2f1ddh + LOAD 0 // 2f1dfh + IMM 311 // 2f1e0h + IMM 10 // 2f1e3h + LIBCALL Action_isAction + STORE 0 // 2f1e5h + LOAD 0 // 2f1edh + ZERO + EQUAL + JMPTRUE @2f248 // 2f1efh +@2f1f1: + IMM 24 + LIBCALL object_is_present + STORE 0 // 2f1f4h + LOAD 0 // 2f1f9h + ZERO + EQUAL + JMPTRUE @2f248 // 2f1fbh + IMM 24 + LIBCALL inventory_add + DLOAD $5472 // 2f205h + STORE 0 + LOAD 0 + LIBCALL SequenceList_remove + ZERO + ZERO + ZERO + DLOAD $5456 // 2f213h + STORE 0 + IMM 6 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2f21bh + LOAD 0 // 2f220h + DSTORE $5472 + IMM $FFFE // 2f226h + IMM $FFFE + IMM $FFFE + LOAD 0 + LIBCALL SequenceList_setAnimRange + ZERO + IMM 311 + LIBCALL hotspot_activate + ZERO + IMM $2788 // 2f238h + LIBCALL dialog_picture_show + IMM 22 // 2f243h + JUMP @2f16a // 2f245h +@2f248: + ZERO + IMM 309 // 2f24ah + IMM 3 // 2f24dh + LIBCALL Action_isAction + STORE 0 // 2f24fh + LOAD 0 // 2f257h + ZERO + NEQUAL + JMPTRUE @2f279 // 2f259h + LOAD 0 // 2f25bh + IMM 311 // 2f25ch + IMM 3 // 2f25fh + LIBCALL Action_isAction + STORE 0 // 2f261h + LOAD 0 // 2f269h + ZERO + EQUAL + JMPTRUE @2f2a6 // 2f26bh + LIBCALL object_is_in_inventory + STORE 0 // 2f270h + LOAD 0 // 2f275h + ZERO + NEQUAL + JMPTRUE @2f2a6 // 2f277h +@2f279: + DLOAD $547E // 2f279h + ZERO + EQUAL + JMPTRUE @2f2a0 // 2f27eh + IMM 24 + LIBCALL object_is_present + STORE 0 // 2f283h + LOAD 0 // 2f288h + ZERO + EQUAL + JMPTRUE @2f29a // 2f28ah +@2f28f: +@2f291: + IMM $2790 + ZERO + LIBCALL dialog_show + JUMP @2f6b4 // 2f296h +@2f29a: +@2f29d: + DLOAD 0 // 2f29eh + STORE 0 + JUMP @2f291 +@2f2a0: + DLOAD 0 // 2f2a3h + STORE 0 + JUMP @2f29d +@2f2a6: + ZERO + IMM 309 // 2f2a8h + IMM 6 // 2f2abh + LIBCALL Action_isAction + STORE 0 // 2f2adh + LOAD 0 // 2f2b5h + ZERO + EQUAL + JMPTRUE @2f2c6 // 2f2b7h + DLOAD $547E // 2f2b9h + ZERO + EQUAL + JMPTRUE @2f2c6 // 2f2beh + DLOAD 0 // 2f2c3h + STORE 0 + JUMP @2f28f +@2f2c6: + ZERO + IMM 384 // 2f2c8h + IMM 3 // 2f2cbh + LIBCALL Action_isAction + STORE 0 // 2f2cdh + LOAD 0 // 2f2d5h + ZERO + NEQUAL + JMPTRUE @2f2dc // 2f2d7h + JUMP @2f3d8 // 2f2d9h +@2f2dc: + DLOAD $5476 // 2f2dch + ZERO + NEQUAL + JMPTRUE @2f2e6 // 2f2e1h + JUMP @2f3d8 // 2f2e3h +@2f2e6: + GLOAD 14 // 2f2e6h + ZERO + EQUAL + JMPTRUE @2f2f4 // 2f2ebh + CALL scene101_sub1 + JUMP @2f6b4 // 2f2f1h +@2f2f4: + DLOAD Scene_abortTimers // 2f2f4h + STORE 0 + LOAD 0 // 2f2f7h + ZERO + EQUAL + JMPTRUE @2f30a // 2f2f9h + LOAD 0 // 2f2fbh + ONE + MINUS + STORE 0 + LOAD 0 // 2f2fch + STORE 4 + LOAD 4 + ZERO + EQUAL + JMPTRUE @2f34c + LOAD 0 // 2f2feh + ONE + MINUS + STORE 0 + LOAD 0 // 2f2ffh + STORE 4 + LOAD 4 + ZERO + EQUAL + JMPTRUE @2f37e + LOAD 0 // 2f301h + ONE + MINUS + STORE 0 + LOAD 0 // 2f302h + STORE 4 + LOAD 4 + ZERO + NEQUAL + JMPTRUE @2f307 + JUMP @2f3c2 // 2f304h +@2f307: + JUMP @2f6b4 // 2f307h +@2f30a: + ZERO + DSTORE Player_stepEnabled // 2f30ah + DLOAD $546E // 2f310h + STORE 0 + LOAD 0 + LIBCALL SequenceList_remove + ZERO + ZERO + ONE + DLOAD $5450 // 2f31eh + STORE 0 + IMM 3 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2f326h + LOAD 0 // 2f32bh + DSTORE $546E + IMM 21 + IMM 17 + LOAD 0 + LIBCALL SequenceList_setAnimRange + ONE + DLOAD $546E // 2f33bh + STORE 0 + ZERO + ZERO + LOAD 0 + LIBCALL SequenceList_addSubEntry + STORE 0 // 2f342h + IMM 17 // 2f347h + JUMP @2f16a // 2f349h +@2f34c: + ZERO + ZERO + ONE + DLOAD $5450 // 2f352h + STORE 0 + IMM 3 + ZERO + LOAD 0 + LIBCALL start_sprite_sequence3 + STORE 0 // 2f35ah + LOAD 0 // 2f35fh + DSTORE $546E + IMM 2 // 2f362h + ZERO + ZERO + LOAD 0 + LIBCALL SequenceList_addSubEntry + STORE 0 // 2f368h + DLOAD $546E // 2f36dh + STORE 0 + IMM 21 + IMM 17 + LOAD 0 + LIBCALL SequenceList_setAnimRange + JUMP @2f6b4 // 2f37bh +@2f37e: + ZERO + ZERO + ZERO + DLOAD $5450 // 2f384h + STORE 0 + IMM 3 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2f38ch + LOAD 0 // 2f391h + DSTORE $546E + IMM 17 // 2f397h + IMM 17 + IMM 17 + LOAD 0 + LIBCALL SequenceList_setAnimRange + ZERO + ZERO + ONE + DLOAD $544A // 2f3a4h + STORE 0 + IMM 3 + ZERO + LOAD 0 + LIBCALL start_cycled_sprite_sequence + STORE 0 // 2f3ach + LOAD 0 // 2f3b1h + DSTORE $5468 + IMM 3 // 2f3b4h + ZERO + ZERO + LOAD 0 + LIBCALL SequenceList_addSubEntry + STORE 0 // 2f3bah + JUMP @2f6b4 // 2f3bfh +@2f3c2: + MINUSONE + DSTORE Player_stepEnabled // 2f3c5h + MINUSONE + GSTORE 14 // 2f3c8h + IMM 112 // 2f3ceh + DSTORE Scene_nextScene + DLOAD 0 // 2f3d4h + STORE 0 + JUMP @2f6b4 +@2f3d8: + ZERO + IMM 71 // 2f3dah + IMM 3 // 2f3dch + LIBCALL Action_isAction + STORE 0 // 2f3deh + LOAD 0 // 2f3e6h + ZERO + EQUAL + JMPTRUE @2f3f0 // 2f3e8h + DLOAD 0 // 2f3edh + STORE 0 + JUMP @2f28f +@2f3f0: + ZERO + IMM 3 // 2f3f2h + LIBCALL Action_isAction + STORE 0 // 2f3f4h + LOAD 0 // 2f3fch + ZERO + NEQUAL + JMPTRUE @2f410 // 2f3feh + LOAD 0 // 2f400h + IMM 259 // 2f401h + LIBCALL Action_isAction + STORE 0 // 2f404h + LOAD 0 // 2f40ch + ZERO + EQUAL + JMPTRUE @2f438 // 2f40eh +@2f410: + ZERO + IMM 142 // 2f412h + LIBCALL Action_isAction + STORE 0 // 2f415h + LOAD 0 // 2f41dh + ZERO + NEQUAL + JMPTRUE @2f431 // 2f41fh + LOAD 0 // 2f421h + IMM 249 // 2f422h + LIBCALL Action_isAction + STORE 0 // 2f425h + LOAD 0 // 2f42dh + ZERO + EQUAL + JMPTRUE @2f438 // 2f42fh +@2f431: + DLOAD 0 // 2f434h + STORE 0 + JUMP @2f28f +@2f438: + ZERO + IMM 168 // 2f43ah + IMM 3 // 2f43dh + LIBCALL Action_isAction + STORE 0 // 2f43fh + LOAD 0 // 2f447h + ZERO + NEQUAL + JMPTRUE @2f481 // 2f449h + LOAD 0 // 2f44bh + IMM 248 // 2f44ch + IMM 3 // 2f44fh + LIBCALL Action_isAction + STORE 0 // 2f451h + LOAD 0 // 2f459h + ZERO + NEQUAL + JMPTRUE @2f481 // 2f45bh + LOAD 0 // 2f45dh + IMM 168 // 2f45eh + IMM 125 // 2f461h + LIBCALL Action_isAction + STORE 0 // 2f463h + LOAD 0 // 2f46bh + ZERO + NEQUAL + JMPTRUE @2f481 // 2f46dh + LOAD 0 // 2f46fh + IMM 248 // 2f470h + IMM 125 // 2f473h + LIBCALL Action_isAction + STORE 0 // 2f475h + LOAD 0 // 2f47dh + ZERO + EQUAL + JMPTRUE @2f488 // 2f47fh +@2f481: + DLOAD 0 // 2f484h + STORE 0 + JUMP @2f28f +@2f488: + ZERO + IMM 145 // 2f48ah + IMM 3 // 2f48dh + LIBCALL Action_isAction + STORE 0 // 2f48fh + LOAD 0 // 2f497h + ZERO + EQUAL + JMPTRUE @2f4a2 // 2f499h + DLOAD 0 // 2f49eh + STORE 0 + JUMP @2f28f +@2f4a2: + ZERO + IMM 225 // 2f4a4h + IMM 3 // 2f4a7h + LIBCALL Action_isAction + STORE 0 // 2f4a9h + LOAD 0 // 2f4b1h + ZERO + NEQUAL + JMPTRUE @2f4c8 // 2f4b3h + LOAD 0 // 2f4b5h + IMM 225 // 2f4b6h + IMM 210 // 2f4b9h + LIBCALL Action_isAction + STORE 0 // 2f4bch + LOAD 0 // 2f4c4h + ZERO + EQUAL + JMPTRUE @2f4ce // 2f4c6h +@2f4c8: + DLOAD 0 // 2f4cbh + STORE 0 + JUMP @2f28f +@2f4ce: + ZERO + IMM 96 // 2f4d0h + IMM 3 // 2f4d2h + LIBCALL Action_isAction + STORE 0 // 2f4d4h + LOAD 0 // 2f4dch + ZERO + EQUAL + JMPTRUE @2f4e6 // 2f4deh + DLOAD 0 // 2f4e3h + STORE 0 + JUMP @2f28f +@2f4e6: + ZERO + IMM 273 // 2f4e8h + IMM 3 // 2f4ebh + LIBCALL Action_isAction + STORE 0 // 2f4edh + LOAD 0 // 2f4f5h + ZERO + EQUAL + JMPTRUE @2f500 // 2f4f7h + DLOAD 0 // 2f4fch + STORE 0 + JUMP @2f28f +@2f500: + ZERO + IMM 123 // 2f502h + IMM 3 // 2f504h + LIBCALL Action_isAction + STORE 0 // 2f506h + LOAD 0 // 2f50eh + ZERO + NEQUAL + JMPTRUE @2f52f // 2f510h + LOAD 0 // 2f512h + IMM 123 // 2f513h + IMM 6 // 2f515h + LIBCALL Action_isAction + STORE 0 // 2f517h + LOAD 0 // 2f51fh + ZERO + EQUAL + JMPTRUE @2f536 // 2f521h + LIBCALL object_is_in_inventory + STORE 0 // 2f526h + LOAD 0 // 2f52bh + ZERO + NEQUAL + JMPTRUE @2f536 // 2f52dh +@2f52f: + DLOAD 0 // 2f532h + STORE 0 + JUMP @2f28f +@2f536: + ZERO + IMM 123 // 2f538h + IMM 6 // 2f53ah + LIBCALL Action_isAction + STORE 0 // 2f53ch + LOAD 0 // 2f544h + ZERO + EQUAL + JMPTRUE @2f54e // 2f546h + DLOAD 0 // 2f54bh + STORE 0 + JUMP @2f28f +@2f54e: + ZERO + IMM 358 // 2f550h + IMM 3 // 2f553h + LIBCALL Action_isAction + STORE 0 // 2f555h + LOAD 0 // 2f55dh + ZERO + EQUAL + JMPTRUE @2f568 // 2f55fh + DLOAD 0 // 2f564h + STORE 0 + JUMP @2f28f +@2f568: + ZERO + IMM 202 // 2f56ah + IMM 3 // 2f56dh + LIBCALL Action_isAction + STORE 0 // 2f56fh + LOAD 0 // 2f577h + ZERO + EQUAL + JMPTRUE @2f582 // 2f579h + DLOAD 0 // 2f57eh + STORE 0 + JUMP @2f28f +@2f582: + ZERO + IMM 99 // 2f584h + IMM 3 // 2f586h + LIBCALL Action_isAction + STORE 0 // 2f588h + LOAD 0 // 2f590h + ZERO + EQUAL + JMPTRUE @2f59a // 2f592h + DLOAD 0 // 2f597h + STORE 0 + JUMP @2f28f +@2f59a: + ZERO + IMM 235 // 2f59ch + IMM 3 // 2f59fh + LIBCALL Action_isAction + STORE 0 // 2f5a1h + LOAD 0 // 2f5a9h + ZERO + EQUAL + JMPTRUE @2f5b4 // 2f5abh + DLOAD 0 // 2f5b0h + STORE 0 + JUMP @2f28f +@2f5b4: + ZERO + IMM 120 // 2f5b6h + IMM 3 // 2f5b8h + LIBCALL Action_isAction + STORE 0 // 2f5bah + LOAD 0 // 2f5c2h + ZERO + EQUAL + JMPTRUE @2f5cc // 2f5c4h + DLOAD 0 // 2f5c9h + STORE 0 + JUMP @2f28f +@2f5cc: + ZERO + IMM 400 // 2f5ceh + IMM 3 // 2f5d1h + LIBCALL Action_isAction + STORE 0 // 2f5d3h + LOAD 0 // 2f5dbh + ZERO + EQUAL + JMPTRUE @2f5e6 // 2f5ddh + DLOAD 0 // 2f5e2h + STORE 0 + JUMP @2f28f +@2f5e6: + ZERO + IMM 312 // 2f5e8h + IMM 3 // 2f5ebh + LIBCALL Action_isAction + STORE 0 // 2f5edh + LOAD 0 // 2f5f5h + ZERO + EQUAL + JMPTRUE @2f600 // 2f5f7h + DLOAD 0 // 2f5fch + STORE 0 + JUMP @2f28f +@2f600: + ZERO + IMM 273 // 2f602h + IMM 4 // 2f605h + LIBCALL Action_isAction + STORE 0 // 2f607h + LOAD 0 // 2f60fh + ZERO + EQUAL + JMPTRUE @2f61a // 2f611h + DLOAD 0 // 2f616h + STORE 0 + JUMP @2f28f +@2f61a: + ZERO + IMM 145 // 2f61ch + IMM 4 // 2f61fh + LIBCALL Action_isAction + STORE 0 // 2f621h + LOAD 0 // 2f629h + ZERO + EQUAL + JMPTRUE @2f634 // 2f62bh + DLOAD 0 // 2f630h + STORE 0 + JUMP @2f28f +@2f634: + ZERO + IMM 99 // 2f636h + IMM 6 // 2f638h + LIBCALL Action_isAction + STORE 0 // 2f63ah + LOAD 0 // 2f642h + ZERO + EQUAL + JMPTRUE @2f64c // 2f644h + DLOAD 0 // 2f649h + STORE 0 + JUMP @2f28f +@2f64c: + ZERO + IMM 96 // 2f64eh + IMM 6 // 2f650h + LIBCALL Action_isAction + STORE 0 // 2f652h + LOAD 0 // 2f65ah + ZERO + EQUAL + JMPTRUE @2f664 // 2f65ch + DLOAD 0 // 2f661h + STORE 0 + JUMP @2f28f +@2f664: + ZERO + IMM 96 // 2f666h + IMM 11 // 2f668h + LIBCALL Action_isAction + STORE 0 // 2f66ah + LOAD 0 // 2f672h + ZERO + EQUAL + JMPTRUE @2f67c // 2f674h + DLOAD 0 // 2f679h + STORE 0 + JUMP @2f28f +@2f67c: + ZERO + IMM 3 // 2f67eh + LIBCALL Action_isAction + STORE 0 // 2f680h + LOAD 0 // 2f688h + ZERO + NEQUAL + JMPTRUE @2f69c // 2f68ah + LOAD 0 // 2f68ch + IMM 274 // 2f68dh + LIBCALL Action_isAction + STORE 0 // 2f690h + LOAD 0 // 2f698h + ZERO + EQUAL + JMPTRUE @2f6ba // 2f69ah +@2f69c: + ZERO + IMM 382 // 2f69eh + LIBCALL Action_isAction + STORE 0 // 2f6a1h + LOAD 0 // 2f6a9h + ZERO + EQUAL + JMPTRUE @2f6ba // 2f6abh + DLOAD 0 // 2f6b0h + STORE 0 + JUMP @2f28f +@2f6b4: + ZERO + DSTORE $5768 // 2f6b4h +@2f6ba: + RET +end + + |